ducheng678 commited on
Commit
093b0a5
·
0 Parent(s):

Initial WaveLSFromer project

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +1 -0
  2. .gitignore +25 -0
  3. LICENSE +201 -0
  4. README.md +26 -0
  5. Stockformer.py +146 -0
  6. clean_ipynb.sh +20 -0
  7. configs/lstm/basic_PEMSBAY.yaml +368 -0
  8. configs/mlp/basic.yaml +58 -0
  9. configs/mlp/basic_PEMSBAY.yaml +366 -0
  10. configs/stockformer/OneCycleLRSchedule.yaml +59 -0
  11. configs/stockformer/basic.yaml +62 -0
  12. configs/stockformer/basic_PEMSBAY.yaml +374 -0
  13. configs/stockformer/basic_PEMSBAY_small.yaml +373 -0
  14. configs/stockformer/basic_WTH.yaml +60 -0
  15. configs/stockformer/basic_material.yaml +48 -0
  16. configs/stockformer/general.yaml +61 -0
  17. configs/stockformer/general_PEMSBAY.yaml +373 -0
  18. d.sh +94 -0
  19. data_collect.ipynb +536 -0
  20. data_collect.py +369 -0
  21. data_loader.py +652 -0
  22. data_prepare.ipynb +311 -0
  23. data_prepare.py +214 -0
  24. data_provider/__init__.py +0 -0
  25. data_provider/data_factory.py +55 -0
  26. data_provider/data_loader.py +652 -0
  27. data_provider/data_module.py +135 -0
  28. embed.py +228 -0
  29. exp/__init__.py +0 -0
  30. exp/exp_basic.py +38 -0
  31. exp/exp_informer.py +370 -0
  32. exp/exp_timeseries.py +368 -0
  33. exp_timeseries.py +466 -0
  34. general_Banks_Diversified.yaml +57 -0
  35. general_Life_Insurance.yaml +53 -0
  36. general_Semiconductors_Equipment.yaml +48 -0
  37. layers/__init__.py +0 -0
  38. layers/attn.py +184 -0
  39. layers/decoder.py +56 -0
  40. layers/embed.py +228 -0
  41. layers/encoder.py +216 -0
  42. models/Basic.py +63 -0
  43. models/DLinear.py +104 -0
  44. models/Informer.py +242 -0
  45. models/Lstm.py +84 -0
  46. models/Stockformer.py +131 -0
  47. models/__init__.py +0 -0
  48. old_stuff/Dockerfile +8 -0
  49. old_stuff/Informer.ipynb +698 -0
  50. old_stuff/Makefile +38 -0
.gitattributes ADDED
@@ -0,0 +1 @@
 
 
1
+ *.png filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ **/__pycache__/
2
+ *.pyc
3
+ .venv/
4
+ .env
5
+ .vscode
6
+ .codex
7
+ .tmux.conf
8
+
9
+ # Notebook/editor artifacts
10
+ **/.ipynb_checkpoints/
11
+ *~
12
+ *.un~
13
+ :w
14
+ '
15
+
16
+ checkpoints
17
+ data
18
+ results
19
+
20
+ # Pytorch Lightning
21
+ lightning_logs
22
+ .lr_find_*
23
+ .scale_batch_size_*
24
+
25
+ bbtest_logs
LICENSE ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
README.md ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ![Python 3.10](https://img.shields.io/badge/python-3.10-green.svg?style=plastic)
2
+ ![PyTorch 1.13](https://img.shields.io/badge/pytorch-1.13-green.svg?style=plastic)
3
+ ![PyTorch Lightning 1.8](https://img.shields.io/badge/pytorch%20lightning-1.8-green.svg?style=plastic)
4
+
5
+ # WaveLSFromer
6
+
7
+ WaveLSFromer is a research codebase for long-sequence financial time-series
8
+ forecasting. It extends the Informer/Stockformer style transformer stack with
9
+ stock-specific training objectives, PyTorch Lightning experiment loops,
10
+ config-driven model runs, and learnable wavelet front-end components for
11
+ low/high frequency feature extraction.
12
+
13
+ The repository includes:
14
+
15
+ - transformer, Informer, DLinear, LSTM, and MLP model baselines;
16
+ - learnable 1D wavelet filters with frequency-domain regularization;
17
+ - PyTorch Lightning training, validation, prediction, and checkpoint workflows;
18
+ - stock-return metrics and differentiable trading-oriented loss functions;
19
+ - YAML experiment configs for financial and benchmark time-series datasets;
20
+ - notebooks and scripts for data collection, preparation, and result analysis.
21
+
22
+ Initially forked from the [Informer: Beyond Efficient Transformer for Long Sequence Time-Series Forecasting repo](https://github.com/zhouhaoyi/Informer2020).
23
+
24
+ Thanks to [polygon.io](http://polygon.io/) for being our financial data provider.
25
+
26
+ Contributors: [Zac Schulwolf](https://github.com/zacswolf) and [Shuozhe Li](https://github.com/ShuoZheLi)
Stockformer.py ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import torch
3
+ import torch.nn as nn
4
+
5
+ from layers.encoder import Encoder, EncoderLayer, ConvLayer
6
+ from layers.attn import FullAttention, AttentionLayer, ProbAttention
7
+ from layers.embed import DataEmbedding
8
+ from utils.masking import QuestionMask
9
+ from .wavelet import WaveletFront
10
+
11
+
12
+ class Stockformer(nn.Module):
13
+ def __init__(self, config):
14
+ super(Stockformer, self).__init__()
15
+ self.pred_len = config.pred_len
16
+ assert self.pred_len == 1, "Stockformer needs pred_len to be 1"
17
+ self.attn = config.attn
18
+ self.output_attention = config.output_attention
19
+ self.seq_len = config.seq_len
20
+ self.final_mode = config.final_mode
21
+
22
+ self.wave_model = WaveletFront(in_channels=config.enc_in,
23
+ d_model=config.d_model-config.emb_t2v_app_dim,
24
+ kernel_size=31,
25
+ n_fft=128)
26
+
27
+ # Embedding
28
+ self.enc_embedding = DataEmbedding(
29
+ config.d_model-config.emb_t2v_app_dim,
30
+ # config.enc_in,
31
+ config.d_model,
32
+ config.t_embed,
33
+ config.freq,
34
+ config.dropout_emb,
35
+ emb_t2v_app_dim=config.emb_t2v_app_dim,
36
+ tok_emb=config.tok_emb,
37
+ )
38
+ # Attention
39
+ Attn = ProbAttention if config.attn == "prob" else FullAttention
40
+ # Encoder
41
+ self.encoder = Encoder(
42
+ [
43
+ EncoderLayer(
44
+ AttentionLayer(
45
+ Attn(
46
+ True if config.final_mode == "mode3" else False,
47
+ config.factor,
48
+ attention_dropout=config.dropout,
49
+ output_attention=config.output_attention,
50
+ ),
51
+ config.d_model,
52
+ config.n_heads,
53
+ mix=False,
54
+ ),
55
+ config.d_model,
56
+ config.d_ff,
57
+ dropout=config.dropout,
58
+ activation=config.activation,
59
+ ln_mode=config.ln_mode,
60
+ )
61
+ for l in range(config.e_layers)
62
+ ],
63
+ [ConvLayer(config.d_model) for l in range(config.e_layers - 1)]
64
+ if config.distil
65
+ else None,
66
+ # norm_layer=torch.nn.LayerNorm(config.d_model),
67
+ norm_layer=torch.nn.RMSNorm(config.d_model),
68
+ )
69
+
70
+ if config.final_mode == "mode1":
71
+ self.final = nn.Linear(
72
+ config.d_model * config.seq_len, config.c_out, bias=True
73
+ )
74
+ elif config.final_mode == "mode2" or config.final_mode == "mode3":
75
+ self.final = nn.Linear(config.d_model, config.c_out, bias=True)
76
+ else:
77
+ raise Exception(f"Invalid final_mode: {config.final_mode}")
78
+ # nn.init.xavier_normal_(self.final.weight, gain=nn.init.calculate_gain("tanh"))
79
+
80
+ # self.final = nn.Sequential(*[
81
+ # nn.Linear(config.d_model * config.seq_len, config.d_model * 4, bias=True),
82
+ # nn.GELU(),
83
+ # nn.Linear(config.d_model * 4, config.c_out, bias=True)
84
+ # ])
85
+
86
+ # Load pre-trained model
87
+ if config.load_model_path is not None:
88
+ path = os.path.join(config.checkpoints, config.load_model_path)
89
+ print(f"Loading Model from {path}")
90
+ self.load_state_dict(torch.load(path))
91
+
92
+ def forward(
93
+ self,
94
+ x_enc,
95
+ x_mark_enc,
96
+ x_dec,
97
+ x_mark_dec,
98
+ enc_self_mask=None,
99
+ dec_self_mask=None,
100
+ dec_enc_mask=None,
101
+ pre_train=False,
102
+ ):
103
+ # x_enc is (batch_size / num gpus, seq_len, enc_in)
104
+ # x_mark_enc is (batch_size / num gpus, seq_len, date-representation (7forhours)
105
+ assert len(x_enc.shape) == 3
106
+ assert x_enc.shape[1] == self.seq_len
107
+
108
+ x_enc, reg, _ = self.wave_model(x_enc.permute(0, 2, 1))
109
+
110
+ # print(reg)
111
+ lambda_low=100; lambda_high=100; lambda_overlap=100; lambda_parse=1e-2; lambda_shape=10
112
+ loss_reg = (lambda_low*reg["L_low"] + lambda_high*reg["L_high"]
113
+ + lambda_overlap*reg["L_overlap"]
114
+ + lambda_parse*reg["L_parseval"]
115
+ + lambda_shape*reg["L_shape"]
116
+ )
117
+
118
+ if self.final_mode == "mode3":
119
+ # This gives the encoder a question input as the last token
120
+ # TODO: Maybe this should be initialized differently, like to the mean of x_enc, random, mean of dataset?
121
+ zeros = torch.zeros([x_enc.shape[0], 1, x_enc.shape[2]]).to(x_enc)
122
+ x_enc = torch.cat([x_enc, zeros], 1)
123
+ x_mark_enc = torch.cat([x_mark_enc, x_mark_dec], 1)
124
+ assert enc_self_mask is None
125
+ enc_self_mask = QuestionMask(
126
+ x_enc.shape[0], x_enc.shape[1], device=x_enc.device
127
+ )
128
+
129
+ # emb_out is (batch_size / num gpus, seq_len, d_model)
130
+ emb_out = self.enc_embedding(x_enc, x_mark_enc)
131
+
132
+ # enc_out is (batch_size / num gpus, seq_len, d_model) but seq_len will change if distil
133
+ enc_out, attns = self.encoder(emb_out, attn_mask=enc_self_mask)
134
+
135
+ if self.final_mode == "mode1":
136
+ out = self.final(enc_out.flatten(start_dim=1))
137
+ elif self.final_mode == "mode2" or self.final_mode == "mode3":
138
+ out = self.final(enc_out[:, -1, :])
139
+ else:
140
+ assert False, f"Forward missing valid final mode {self.final_mode}"
141
+
142
+ # The None below is just adding a dummy dimension
143
+ if self.output_attention:
144
+ return out[:, None, :], attns
145
+ else:
146
+ return out[:, None, :], loss_reg # (batch_size, 1, c_out)
clean_ipynb.sh ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ # This script removes all output from a Jupyter notebook
3
+ # Generated using copilot
4
+ # Usage: source clean_ipynb.sh notebook.ipynb
5
+
6
+ # Check if the file exists
7
+ if [ ! -f $1 ]; then
8
+ echo "File $1 does not exist"
9
+ exit 1
10
+ fi
11
+
12
+ # Check if the file is a Jupyter notebook
13
+ if [ "${1: -6}" != ".ipynb" ]; then
14
+ echo "File $1 is not a Jupyter notebook"
15
+ exit 1
16
+ fi
17
+
18
+ # Remove all output from the notebook
19
+ python -m nbconvert --clear-output --inplace $1
20
+ # jupyter nbconvert --ClearOutputPreprocessor.enabled=True --inplace $1
configs/lstm/basic_PEMSBAY.yaml ADDED
@@ -0,0 +1,368 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ activation: gelu
2
+ attn: full
3
+ batch_size: 256
4
+ c_out: 1
5
+ cols:
6
+ - 400001_logpctchange
7
+ - 400017_logpctchange
8
+ - 400030_logpctchange
9
+ - 400040_logpctchange
10
+ - 400045_logpctchange
11
+ - 400052_logpctchange
12
+ - 400057_logpctchange
13
+ - 400059_logpctchange
14
+ - 400065_logpctchange
15
+ - 400069_logpctchange
16
+ - 400073_logpctchange
17
+ - 400084_logpctchange
18
+ - 400085_logpctchange
19
+ - 400088_logpctchange
20
+ - 400096_logpctchange
21
+ - 400097_logpctchange
22
+ - 400100_logpctchange
23
+ - 400104_logpctchange
24
+ - 400109_logpctchange
25
+ - 400122_logpctchange
26
+ - 400147_logpctchange
27
+ - 400148_logpctchange
28
+ - 400149_logpctchange
29
+ - 400158_logpctchange
30
+ - 400160_logpctchange
31
+ - 400168_logpctchange
32
+ - 400172_logpctchange
33
+ - 400174_logpctchange
34
+ - 400178_logpctchange
35
+ - 400185_logpctchange
36
+ - 400201_logpctchange
37
+ - 400206_logpctchange
38
+ - 400209_logpctchange
39
+ - 400213_logpctchange
40
+ - 400221_logpctchange
41
+ - 400222_logpctchange
42
+ - 400227_logpctchange
43
+ - 400236_logpctchange
44
+ - 400238_logpctchange
45
+ - 400240_logpctchange
46
+ - 400246_logpctchange
47
+ - 400253_logpctchange
48
+ - 400257_logpctchange
49
+ - 400258_logpctchange
50
+ - 400268_logpctchange
51
+ - 400274_logpctchange
52
+ - 400278_logpctchange
53
+ - 400280_logpctchange
54
+ - 400292_logpctchange
55
+ - 400296_logpctchange
56
+ - 400298_logpctchange
57
+ - 400330_logpctchange
58
+ - 400336_logpctchange
59
+ - 400343_logpctchange
60
+ - 400353_logpctchange
61
+ - 400372_logpctchange
62
+ - 400394_logpctchange
63
+ - 400400_logpctchange
64
+ - 400414_logpctchange
65
+ - 400418_logpctchange
66
+ - 400429_logpctchange
67
+ - 400435_logpctchange
68
+ - 400436_logpctchange
69
+ - 400440_logpctchange
70
+ - 400449_logpctchange
71
+ - 400457_logpctchange
72
+ - 400461_logpctchange
73
+ - 400464_logpctchange
74
+ - 400479_logpctchange
75
+ - 400485_logpctchange
76
+ - 400499_logpctchange
77
+ - 400507_logpctchange
78
+ - 400508_logpctchange
79
+ - 400514_logpctchange
80
+ - 400519_logpctchange
81
+ - 400528_logpctchange
82
+ - 400545_logpctchange
83
+ - 400560_logpctchange
84
+ - 400563_logpctchange
85
+ - 400567_logpctchange
86
+ - 400581_logpctchange
87
+ - 400582_logpctchange
88
+ - 400586_logpctchange
89
+ - 400637_logpctchange
90
+ - 400643_logpctchange
91
+ - 400648_logpctchange
92
+ - 400649_logpctchange
93
+ - 400654_logpctchange
94
+ - 400664_logpctchange
95
+ - 400665_logpctchange
96
+ - 400668_logpctchange
97
+ - 400673_logpctchange
98
+ - 400677_logpctchange
99
+ - 400687_logpctchange
100
+ - 400688_logpctchange
101
+ - 400690_logpctchange
102
+ - 400700_logpctchange
103
+ - 400709_logpctchange
104
+ - 400713_logpctchange
105
+ - 400714_logpctchange
106
+ - 400715_logpctchange
107
+ - 400717_logpctchange
108
+ - 400723_logpctchange
109
+ - 400743_logpctchange
110
+ - 400750_logpctchange
111
+ - 400760_logpctchange
112
+ - 400772_logpctchange
113
+ - 400790_logpctchange
114
+ - 400792_logpctchange
115
+ - 400794_logpctchange
116
+ - 400799_logpctchange
117
+ - 400804_logpctchange
118
+ - 400822_logpctchange
119
+ - 400823_logpctchange
120
+ - 400828_logpctchange
121
+ - 400832_logpctchange
122
+ - 400837_logpctchange
123
+ - 400842_logpctchange
124
+ - 400863_logpctchange
125
+ - 400869_logpctchange
126
+ - 400873_logpctchange
127
+ - 400895_logpctchange
128
+ - 400904_logpctchange
129
+ - 400907_logpctchange
130
+ - 400911_logpctchange
131
+ - 400916_logpctchange
132
+ - 400922_logpctchange
133
+ - 400934_logpctchange
134
+ - 400951_logpctchange
135
+ - 400952_logpctchange
136
+ - 400953_logpctchange
137
+ - 400964_logpctchange
138
+ - 400965_logpctchange
139
+ - 400970_logpctchange
140
+ - 400971_logpctchange
141
+ - 400973_logpctchange
142
+ - 400995_logpctchange
143
+ - 400996_logpctchange
144
+ - 401014_logpctchange
145
+ - 401129_logpctchange
146
+ - 401154_logpctchange
147
+ - 401163_logpctchange
148
+ - 401167_logpctchange
149
+ - 401210_logpctchange
150
+ - 401224_logpctchange
151
+ - 401327_logpctchange
152
+ - 401351_logpctchange
153
+ - 401388_logpctchange
154
+ - 401391_logpctchange
155
+ - 401400_logpctchange
156
+ - 401403_logpctchange
157
+ - 401440_logpctchange
158
+ - 401457_logpctchange
159
+ - 401464_logpctchange
160
+ - 401489_logpctchange
161
+ - 401495_logpctchange
162
+ - 401507_logpctchange
163
+ - 401534_logpctchange
164
+ - 401541_logpctchange
165
+ - 401555_logpctchange
166
+ - 401560_logpctchange
167
+ - 401567_logpctchange
168
+ - 401597_logpctchange
169
+ - 401606_logpctchange
170
+ - 401611_logpctchange
171
+ - 401655_logpctchange
172
+ - 401808_logpctchange
173
+ - 401809_logpctchange
174
+ - 401810_logpctchange
175
+ - 401811_logpctchange
176
+ - 401816_logpctchange
177
+ - 401817_logpctchange
178
+ - 401845_logpctchange
179
+ - 401846_logpctchange
180
+ - 401890_logpctchange
181
+ - 401891_logpctchange
182
+ - 401906_logpctchange
183
+ - 401908_logpctchange
184
+ - 401926_logpctchange
185
+ - 401936_logpctchange
186
+ - 401937_logpctchange
187
+ - 401942_logpctchange
188
+ - 401943_logpctchange
189
+ - 401948_logpctchange
190
+ - 401957_logpctchange
191
+ - 401958_logpctchange
192
+ - 401994_logpctchange
193
+ - 401996_logpctchange
194
+ - 401997_logpctchange
195
+ - 401998_logpctchange
196
+ - 402056_logpctchange
197
+ - 402057_logpctchange
198
+ - 402058_logpctchange
199
+ - 402059_logpctchange
200
+ - 402060_logpctchange
201
+ - 402061_logpctchange
202
+ - 402067_logpctchange
203
+ - 402117_logpctchange
204
+ - 402118_logpctchange
205
+ - 402119_logpctchange
206
+ - 402120_logpctchange
207
+ - 402121_logpctchange
208
+ - 402281_logpctchange
209
+ - 402282_logpctchange
210
+ - 402283_logpctchange
211
+ - 402284_logpctchange
212
+ - 402285_logpctchange
213
+ - 402286_logpctchange
214
+ - 402287_logpctchange
215
+ - 402288_logpctchange
216
+ - 402289_logpctchange
217
+ - 402359_logpctchange
218
+ - 402360_logpctchange
219
+ - 402361_logpctchange
220
+ - 402362_logpctchange
221
+ - 402363_logpctchange
222
+ - 402364_logpctchange
223
+ - 402365_logpctchange
224
+ - 402366_logpctchange
225
+ - 402367_logpctchange
226
+ - 402368_logpctchange
227
+ - 402369_logpctchange
228
+ - 402370_logpctchange
229
+ - 402371_logpctchange
230
+ - 402372_logpctchange
231
+ - 402373_logpctchange
232
+ - 403225_logpctchange
233
+ - 403265_logpctchange
234
+ - 403329_logpctchange
235
+ - 403401_logpctchange
236
+ - 403402_logpctchange
237
+ - 403404_logpctchange
238
+ - 403406_logpctchange
239
+ - 403409_logpctchange
240
+ - 403412_logpctchange
241
+ - 403414_logpctchange
242
+ - 403419_logpctchange
243
+ - 404370_logpctchange
244
+ - 404434_logpctchange
245
+ - 404435_logpctchange
246
+ - 404444_logpctchange
247
+ - 404451_logpctchange
248
+ - 404452_logpctchange
249
+ - 404453_logpctchange
250
+ - 404461_logpctchange
251
+ - 404462_logpctchange
252
+ - 404521_logpctchange
253
+ - 404522_logpctchange
254
+ - 404553_logpctchange
255
+ - 404554_logpctchange
256
+ - 404585_logpctchange
257
+ - 404586_logpctchange
258
+ - 404640_logpctchange
259
+ - 404753_logpctchange
260
+ - 404759_logpctchange
261
+ - 405613_logpctchange
262
+ - 405619_logpctchange
263
+ - 405701_logpctchange
264
+ - 407150_logpctchange
265
+ - 407151_logpctchange
266
+ - 407152_logpctchange
267
+ - 407153_logpctchange
268
+ - 407155_logpctchange
269
+ - 407157_logpctchange
270
+ - 407161_logpctchange
271
+ - 407165_logpctchange
272
+ - 407172_logpctchange
273
+ - 407173_logpctchange
274
+ - 407174_logpctchange
275
+ - 407176_logpctchange
276
+ - 407177_logpctchange
277
+ - 407179_logpctchange
278
+ - 407180_logpctchange
279
+ - 407181_logpctchange
280
+ - 407184_logpctchange
281
+ - 407185_logpctchange
282
+ - 407186_logpctchange
283
+ - 407187_logpctchange
284
+ - 407190_logpctchange
285
+ - 407191_logpctchange
286
+ - 407194_logpctchange
287
+ - 407200_logpctchange
288
+ - 407202_logpctchange
289
+ - 407204_logpctchange
290
+ - 407206_logpctchange
291
+ - 407207_logpctchange
292
+ - 407321_logpctchange
293
+ - 407323_logpctchange
294
+ - 407325_logpctchange
295
+ - 407328_logpctchange
296
+ - 407331_logpctchange
297
+ - 407332_logpctchange
298
+ - 407335_logpctchange
299
+ - 407336_logpctchange
300
+ - 407337_logpctchange
301
+ - 407339_logpctchange
302
+ - 407341_logpctchange
303
+ - 407342_logpctchange
304
+ - 407344_logpctchange
305
+ - 407348_logpctchange
306
+ - 407352_logpctchange
307
+ - 407359_logpctchange
308
+ - 407360_logpctchange
309
+ - 407361_logpctchange
310
+ - 407364_logpctchange
311
+ - 407367_logpctchange
312
+ - 407370_logpctchange
313
+ - 407372_logpctchange
314
+ - 407373_logpctchange
315
+ - 407374_logpctchange
316
+ - 407710_logpctchange
317
+ - 407711_logpctchange
318
+ - 408907_logpctchange
319
+ - 408911_logpctchange
320
+ - 409524_logpctchange
321
+ - 409525_logpctchange
322
+ - 409526_logpctchange
323
+ - 409528_logpctchange
324
+ - 409529_logpctchange
325
+ - 413026_logpctchange
326
+ - 413845_logpctchange
327
+ - 413877_logpctchange
328
+ - 413878_logpctchange
329
+ - 414284_logpctchange
330
+ - 414694_logpctchange
331
+ d_ff: 512
332
+ d_model: 512
333
+ data_path: PEMSBAY.csv
334
+ # date_end: '2020-01-01'
335
+ # date_start: '2012-01-01'
336
+ # date_test: '2019-06-01'
337
+ des: lstmPEMs
338
+ distil: false
339
+ dont_shuffle_train: false
340
+ dropout: 0.5
341
+ dropout_emb: 0.0
342
+ e_layers: 1
343
+ emb_t2v_app_dim: 16
344
+ enc_in: 325
345
+ features: MS
346
+ final_mode: mode1
347
+ freq: m
348
+ inverse_output: false
349
+ inverse_pred: true
350
+ label_len: 0
351
+ learning_rate: 1.0e-04
352
+ loss: stock_tanhv1
353
+ lradj: null
354
+ max_epochs: 50
355
+ model: lstm
356
+ no_early_stop: false
357
+ no_scale_mean: true
358
+ optim: Adam
359
+ patience: 1000
360
+ pre_loss: null
361
+ pred_len: 1
362
+ pre_epochs: 0
363
+ root_path: ./data/other/
364
+ scale: true
365
+ seed: 2
366
+ seq_len: 16
367
+ # t_embed: time2vec_add
368
+ target: 400001_logpctchange
configs/mlp/basic.yaml ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ activation: gelu
2
+ attn: full
3
+ batch_size: 256
4
+ c_out: 1
5
+ cols:
6
+ - XOM_logpctchange
7
+ - CVX_logpctchange
8
+ - COP_logpctchange
9
+ - BP_logpctchange
10
+ - PBR_logpctchange
11
+ - WTI_logpctchange
12
+ - EOG_logpctchange
13
+ - ENB_logpctchange
14
+ - SLB_logpctchange
15
+ d_ff: 4096
16
+ d_model: 512
17
+ data_path: full_1h.csv
18
+ # date_end: '2020-01-01'
19
+ # date_start: '2012-01-01'
20
+ # date_test: '2019-06-01'
21
+ des: full_1h
22
+ distil: false
23
+ dont_shuffle_train: false
24
+ dropout: 0.5
25
+ dropout_emb: 0.0
26
+ e_layers: 4
27
+ emb_t2v_app_dim: 16
28
+ enc_in: 9
29
+ factor: 5
30
+ features: MS
31
+ final_mode: mode1
32
+ freq: m
33
+ inverse_output: false
34
+ inverse_pred: true
35
+ label_len: 0
36
+ learning_rate: 1.0e-05
37
+ # ln_mode: post
38
+ loss: stock_tanhv1
39
+ lradj: null
40
+ max_epochs: 50
41
+ # mix: false
42
+ model: mlp
43
+ # n_heads: 16
44
+ no_early_stop: false
45
+ no_scale_mean: true
46
+ optim: Adam
47
+ # output_attention: false
48
+ patience: 1000
49
+ pre_loss: null #stock_tanhv4
50
+ pred_len: 1
51
+ pre_epochs: 0
52
+ root_path: ./data/stock/
53
+ scale: true
54
+ seed: 2
55
+ seq_len: 32
56
+ # t_embed: time2vec_add
57
+ target: WTI_logpctchange
58
+
configs/mlp/basic_PEMSBAY.yaml ADDED
@@ -0,0 +1,366 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ activation: gelu
2
+ attn: full
3
+ batch_size: 256
4
+ c_out: 1
5
+ cols:
6
+ - 400001_logpctchange
7
+ - 400017_logpctchange
8
+ - 400030_logpctchange
9
+ - 400040_logpctchange
10
+ - 400045_logpctchange
11
+ - 400052_logpctchange
12
+ - 400057_logpctchange
13
+ - 400059_logpctchange
14
+ - 400065_logpctchange
15
+ - 400069_logpctchange
16
+ - 400073_logpctchange
17
+ - 400084_logpctchange
18
+ - 400085_logpctchange
19
+ - 400088_logpctchange
20
+ - 400096_logpctchange
21
+ - 400097_logpctchange
22
+ - 400100_logpctchange
23
+ - 400104_logpctchange
24
+ - 400109_logpctchange
25
+ - 400122_logpctchange
26
+ - 400147_logpctchange
27
+ - 400148_logpctchange
28
+ - 400149_logpctchange
29
+ - 400158_logpctchange
30
+ - 400160_logpctchange
31
+ - 400168_logpctchange
32
+ - 400172_logpctchange
33
+ - 400174_logpctchange
34
+ - 400178_logpctchange
35
+ - 400185_logpctchange
36
+ - 400201_logpctchange
37
+ - 400206_logpctchange
38
+ - 400209_logpctchange
39
+ - 400213_logpctchange
40
+ - 400221_logpctchange
41
+ - 400222_logpctchange
42
+ - 400227_logpctchange
43
+ - 400236_logpctchange
44
+ - 400238_logpctchange
45
+ - 400240_logpctchange
46
+ - 400246_logpctchange
47
+ - 400253_logpctchange
48
+ - 400257_logpctchange
49
+ - 400258_logpctchange
50
+ - 400268_logpctchange
51
+ - 400274_logpctchange
52
+ - 400278_logpctchange
53
+ - 400280_logpctchange
54
+ - 400292_logpctchange
55
+ - 400296_logpctchange
56
+ - 400298_logpctchange
57
+ - 400330_logpctchange
58
+ - 400336_logpctchange
59
+ - 400343_logpctchange
60
+ - 400353_logpctchange
61
+ - 400372_logpctchange
62
+ - 400394_logpctchange
63
+ - 400400_logpctchange
64
+ - 400414_logpctchange
65
+ - 400418_logpctchange
66
+ - 400429_logpctchange
67
+ - 400435_logpctchange
68
+ - 400436_logpctchange
69
+ - 400440_logpctchange
70
+ - 400449_logpctchange
71
+ - 400457_logpctchange
72
+ - 400461_logpctchange
73
+ - 400464_logpctchange
74
+ - 400479_logpctchange
75
+ - 400485_logpctchange
76
+ - 400499_logpctchange
77
+ - 400507_logpctchange
78
+ - 400508_logpctchange
79
+ - 400514_logpctchange
80
+ - 400519_logpctchange
81
+ - 400528_logpctchange
82
+ - 400545_logpctchange
83
+ - 400560_logpctchange
84
+ - 400563_logpctchange
85
+ - 400567_logpctchange
86
+ - 400581_logpctchange
87
+ - 400582_logpctchange
88
+ - 400586_logpctchange
89
+ - 400637_logpctchange
90
+ - 400643_logpctchange
91
+ - 400648_logpctchange
92
+ - 400649_logpctchange
93
+ - 400654_logpctchange
94
+ - 400664_logpctchange
95
+ - 400665_logpctchange
96
+ - 400668_logpctchange
97
+ - 400673_logpctchange
98
+ - 400677_logpctchange
99
+ - 400687_logpctchange
100
+ - 400688_logpctchange
101
+ - 400690_logpctchange
102
+ - 400700_logpctchange
103
+ - 400709_logpctchange
104
+ - 400713_logpctchange
105
+ - 400714_logpctchange
106
+ - 400715_logpctchange
107
+ - 400717_logpctchange
108
+ - 400723_logpctchange
109
+ - 400743_logpctchange
110
+ - 400750_logpctchange
111
+ - 400760_logpctchange
112
+ - 400772_logpctchange
113
+ - 400790_logpctchange
114
+ - 400792_logpctchange
115
+ - 400794_logpctchange
116
+ - 400799_logpctchange
117
+ - 400804_logpctchange
118
+ - 400822_logpctchange
119
+ - 400823_logpctchange
120
+ - 400828_logpctchange
121
+ - 400832_logpctchange
122
+ - 400837_logpctchange
123
+ - 400842_logpctchange
124
+ - 400863_logpctchange
125
+ - 400869_logpctchange
126
+ - 400873_logpctchange
127
+ - 400895_logpctchange
128
+ - 400904_logpctchange
129
+ - 400907_logpctchange
130
+ - 400911_logpctchange
131
+ - 400916_logpctchange
132
+ - 400922_logpctchange
133
+ - 400934_logpctchange
134
+ - 400951_logpctchange
135
+ - 400952_logpctchange
136
+ - 400953_logpctchange
137
+ - 400964_logpctchange
138
+ - 400965_logpctchange
139
+ - 400970_logpctchange
140
+ - 400971_logpctchange
141
+ - 400973_logpctchange
142
+ - 400995_logpctchange
143
+ - 400996_logpctchange
144
+ - 401014_logpctchange
145
+ - 401129_logpctchange
146
+ - 401154_logpctchange
147
+ - 401163_logpctchange
148
+ - 401167_logpctchange
149
+ - 401210_logpctchange
150
+ - 401224_logpctchange
151
+ - 401327_logpctchange
152
+ - 401351_logpctchange
153
+ - 401388_logpctchange
154
+ - 401391_logpctchange
155
+ - 401400_logpctchange
156
+ - 401403_logpctchange
157
+ - 401440_logpctchange
158
+ - 401457_logpctchange
159
+ - 401464_logpctchange
160
+ - 401489_logpctchange
161
+ - 401495_logpctchange
162
+ - 401507_logpctchange
163
+ - 401534_logpctchange
164
+ - 401541_logpctchange
165
+ - 401555_logpctchange
166
+ - 401560_logpctchange
167
+ - 401567_logpctchange
168
+ - 401597_logpctchange
169
+ - 401606_logpctchange
170
+ - 401611_logpctchange
171
+ - 401655_logpctchange
172
+ - 401808_logpctchange
173
+ - 401809_logpctchange
174
+ - 401810_logpctchange
175
+ - 401811_logpctchange
176
+ - 401816_logpctchange
177
+ - 401817_logpctchange
178
+ - 401845_logpctchange
179
+ - 401846_logpctchange
180
+ - 401890_logpctchange
181
+ - 401891_logpctchange
182
+ - 401906_logpctchange
183
+ - 401908_logpctchange
184
+ - 401926_logpctchange
185
+ - 401936_logpctchange
186
+ - 401937_logpctchange
187
+ - 401942_logpctchange
188
+ - 401943_logpctchange
189
+ - 401948_logpctchange
190
+ - 401957_logpctchange
191
+ - 401958_logpctchange
192
+ - 401994_logpctchange
193
+ - 401996_logpctchange
194
+ - 401997_logpctchange
195
+ - 401998_logpctchange
196
+ - 402056_logpctchange
197
+ - 402057_logpctchange
198
+ - 402058_logpctchange
199
+ - 402059_logpctchange
200
+ - 402060_logpctchange
201
+ - 402061_logpctchange
202
+ - 402067_logpctchange
203
+ - 402117_logpctchange
204
+ - 402118_logpctchange
205
+ - 402119_logpctchange
206
+ - 402120_logpctchange
207
+ - 402121_logpctchange
208
+ - 402281_logpctchange
209
+ - 402282_logpctchange
210
+ - 402283_logpctchange
211
+ - 402284_logpctchange
212
+ - 402285_logpctchange
213
+ - 402286_logpctchange
214
+ - 402287_logpctchange
215
+ - 402288_logpctchange
216
+ - 402289_logpctchange
217
+ - 402359_logpctchange
218
+ - 402360_logpctchange
219
+ - 402361_logpctchange
220
+ - 402362_logpctchange
221
+ - 402363_logpctchange
222
+ - 402364_logpctchange
223
+ - 402365_logpctchange
224
+ - 402366_logpctchange
225
+ - 402367_logpctchange
226
+ - 402368_logpctchange
227
+ - 402369_logpctchange
228
+ - 402370_logpctchange
229
+ - 402371_logpctchange
230
+ - 402372_logpctchange
231
+ - 402373_logpctchange
232
+ - 403225_logpctchange
233
+ - 403265_logpctchange
234
+ - 403329_logpctchange
235
+ - 403401_logpctchange
236
+ - 403402_logpctchange
237
+ - 403404_logpctchange
238
+ - 403406_logpctchange
239
+ - 403409_logpctchange
240
+ - 403412_logpctchange
241
+ - 403414_logpctchange
242
+ - 403419_logpctchange
243
+ - 404370_logpctchange
244
+ - 404434_logpctchange
245
+ - 404435_logpctchange
246
+ - 404444_logpctchange
247
+ - 404451_logpctchange
248
+ - 404452_logpctchange
249
+ - 404453_logpctchange
250
+ - 404461_logpctchange
251
+ - 404462_logpctchange
252
+ - 404521_logpctchange
253
+ - 404522_logpctchange
254
+ - 404553_logpctchange
255
+ - 404554_logpctchange
256
+ - 404585_logpctchange
257
+ - 404586_logpctchange
258
+ - 404640_logpctchange
259
+ - 404753_logpctchange
260
+ - 404759_logpctchange
261
+ - 405613_logpctchange
262
+ - 405619_logpctchange
263
+ - 405701_logpctchange
264
+ - 407150_logpctchange
265
+ - 407151_logpctchange
266
+ - 407152_logpctchange
267
+ - 407153_logpctchange
268
+ - 407155_logpctchange
269
+ - 407157_logpctchange
270
+ - 407161_logpctchange
271
+ - 407165_logpctchange
272
+ - 407172_logpctchange
273
+ - 407173_logpctchange
274
+ - 407174_logpctchange
275
+ - 407176_logpctchange
276
+ - 407177_logpctchange
277
+ - 407179_logpctchange
278
+ - 407180_logpctchange
279
+ - 407181_logpctchange
280
+ - 407184_logpctchange
281
+ - 407185_logpctchange
282
+ - 407186_logpctchange
283
+ - 407187_logpctchange
284
+ - 407190_logpctchange
285
+ - 407191_logpctchange
286
+ - 407194_logpctchange
287
+ - 407200_logpctchange
288
+ - 407202_logpctchange
289
+ - 407204_logpctchange
290
+ - 407206_logpctchange
291
+ - 407207_logpctchange
292
+ - 407321_logpctchange
293
+ - 407323_logpctchange
294
+ - 407325_logpctchange
295
+ - 407328_logpctchange
296
+ - 407331_logpctchange
297
+ - 407332_logpctchange
298
+ - 407335_logpctchange
299
+ - 407336_logpctchange
300
+ - 407337_logpctchange
301
+ - 407339_logpctchange
302
+ - 407341_logpctchange
303
+ - 407342_logpctchange
304
+ - 407344_logpctchange
305
+ - 407348_logpctchange
306
+ - 407352_logpctchange
307
+ - 407359_logpctchange
308
+ - 407360_logpctchange
309
+ - 407361_logpctchange
310
+ - 407364_logpctchange
311
+ - 407367_logpctchange
312
+ - 407370_logpctchange
313
+ - 407372_logpctchange
314
+ - 407373_logpctchange
315
+ - 407374_logpctchange
316
+ - 407710_logpctchange
317
+ - 407711_logpctchange
318
+ - 408907_logpctchange
319
+ - 408911_logpctchange
320
+ - 409524_logpctchange
321
+ - 409525_logpctchange
322
+ - 409526_logpctchange
323
+ - 409528_logpctchange
324
+ - 409529_logpctchange
325
+ - 413026_logpctchange
326
+ - 413845_logpctchange
327
+ - 413877_logpctchange
328
+ - 413878_logpctchange
329
+ - 414284_logpctchange
330
+ - 414694_logpctchange
331
+ d_model: 256
332
+ data_path: PEMSBAY.csv
333
+ # date_end: '2020-01-01'
334
+ # date_start: '2012-01-01'
335
+ # date_test: '2019-06-01'
336
+ des: mlpPEMs
337
+ dont_shuffle_train: false
338
+ dropout: 0.75
339
+ dropout_emb: 0.0
340
+ e_layers: 4
341
+ emb_t2v_app_dim: 16
342
+ enc_in: 325
343
+ features: MS
344
+ final_mode: mode1
345
+ freq: m
346
+ inverse_output: false
347
+ inverse_pred: true
348
+ label_len: 0
349
+ learning_rate: 1.0e-05
350
+ loss: stock_tanhv1
351
+ lradj: null
352
+ max_epochs: 100
353
+ model: mlp
354
+ no_early_stop: false
355
+ no_scale_mean: true
356
+ optim: Adam
357
+ patience: 1000
358
+ pre_loss: null
359
+ pred_len: 1
360
+ pre_epochs: 0
361
+ root_path: ./data/other/
362
+ scale: true
363
+ seed: 2
364
+ seq_len: 16
365
+ t_embed: null
366
+ target: 400001_logpctchange
configs/stockformer/OneCycleLRSchedule.yaml ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ activation: gelu
2
+ attn: full
3
+ batch_size: 128
4
+ c_out: 1
5
+ cols:
6
+ - XOM_logpctchange
7
+ - CVX_logpctchange
8
+ - COP_logpctchange
9
+ - BP_logpctchange
10
+ - PBR_logpctchange
11
+ - WTI_logpctchange
12
+ - EOG_logpctchange
13
+ # - ENB_logpctchange
14
+ # - SLB_logpctchange
15
+ d_ff: 4096 #2048
16
+ d_model: 512
17
+ # data_path: full_1h.csv
18
+ data_path: material_1h.csv
19
+ # date_end: '2020-01-01'
20
+ # date_start: '2012-01-01'
21
+ # date_test: '2019-06-01'
22
+ date_end: '2025-10-23'
23
+ date_start: '2020-10-26'
24
+ date_test: '2025-06-26'
25
+ des: full_1h
26
+ distil: false
27
+ dont_shuffle_train: true
28
+ dropout: 0.5
29
+ dropout_emb: 0.0
30
+ e_layers: 12
31
+ emb_t2v_app_dim: 16
32
+ t_embed: time2vec_app
33
+ enc_in: 7
34
+ factor: 5
35
+ features: MS
36
+ final_mode: mode1
37
+ freq: h
38
+ inverse_output: false
39
+ inverse_pred: true
40
+ label_len: 0
41
+ learning_rate: 1.0e-05
42
+ ln_mode: post
43
+ loss: stock_tanhv1
44
+ lradj: type3
45
+ mix: false
46
+ model: stockformer
47
+ n_heads: 512
48
+ no_early_stop: false
49
+ no_scale_mean: true
50
+ optim: AdamW
51
+ output_attention: false
52
+ patience: 100
53
+ pred_len: 1
54
+ root_path: ./data/stock/
55
+ scale: true
56
+ seed: null
57
+ seq_len: 16
58
+ target: WTI_logpctchange
59
+ max_epochs: 20
configs/stockformer/basic.yaml ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ activation: gelu
2
+ attn: full
3
+ batch_size: 256
4
+ c_out: 1
5
+ cols:
6
+ - XOM_logpctchange
7
+ - CVX_logpctchange
8
+ - COP_logpctchange
9
+ - BP_logpctchange
10
+ - PBR_logpctchange
11
+ - WTI_logpctchange
12
+ - EOG_logpctchange
13
+ - ENB_logpctchange
14
+ - SLB_logpctchange
15
+ d_ff: 4096 #2048
16
+ d_model: 512
17
+ data_path: full_1h.csv
18
+ # date_end: '2020-01-01'
19
+ # date_start: '2012-01-01'
20
+ # date_test: '2019-06-01'
21
+ # date_test: '2020-11-01'
22
+ # date_val: '2019-11-01'
23
+ date_end: '2022-11-01'
24
+ date_test: '2022-09-01'
25
+ date_val: '2022-08-01'
26
+ des: full_1h
27
+ distil: false
28
+ dont_shuffle_train: false
29
+ dropout: 0.2
30
+ dropout_emb: 0.0
31
+ e_layers: 4
32
+ emb_t2v_app_dim: 16
33
+ enc_in: 9
34
+ factor: 5
35
+ features: MS
36
+ final_mode: mode3
37
+ freq: h
38
+ inverse_output: false
39
+ inverse_pred: true
40
+ label_len: 0
41
+ learning_rate: 1.0e-05
42
+ ln_mode: post
43
+ loss: stock_tanhv1
44
+ lradj: null
45
+ max_epochs: 100
46
+ mix: false
47
+ model: stockformer
48
+ n_heads: 8
49
+ no_early_stop: false
50
+ no_scale_mean: true
51
+ optim: Adam #Ranger
52
+ output_attention: false
53
+ patience: 1000
54
+ pred_len: 1
55
+ pre_loss: stock_tanhv4
56
+ pre_epochs: 60
57
+ root_path: ./data/stock/
58
+ scale: true
59
+ seed: 1
60
+ seq_len: 32
61
+ t_embed: time2vec_app
62
+ target: WTI_logpctchange
configs/stockformer/basic_PEMSBAY.yaml ADDED
@@ -0,0 +1,374 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ activation: gelu
2
+ attn: full
3
+ batch_size: 256
4
+ c_out: 1
5
+ cols:
6
+ - 400001_logpctchange
7
+ - 400017_logpctchange
8
+ - 400030_logpctchange
9
+ - 400040_logpctchange
10
+ - 400045_logpctchange
11
+ - 400052_logpctchange
12
+ - 400057_logpctchange
13
+ - 400059_logpctchange
14
+ - 400065_logpctchange
15
+ - 400069_logpctchange
16
+ - 400073_logpctchange
17
+ - 400084_logpctchange
18
+ - 400085_logpctchange
19
+ - 400088_logpctchange
20
+ - 400096_logpctchange
21
+ - 400097_logpctchange
22
+ - 400100_logpctchange
23
+ - 400104_logpctchange
24
+ - 400109_logpctchange
25
+ - 400122_logpctchange
26
+ - 400147_logpctchange
27
+ - 400148_logpctchange
28
+ - 400149_logpctchange
29
+ - 400158_logpctchange
30
+ - 400160_logpctchange
31
+ - 400168_logpctchange
32
+ - 400172_logpctchange
33
+ - 400174_logpctchange
34
+ - 400178_logpctchange
35
+ - 400185_logpctchange
36
+ - 400201_logpctchange
37
+ - 400206_logpctchange
38
+ - 400209_logpctchange
39
+ - 400213_logpctchange
40
+ - 400221_logpctchange
41
+ - 400222_logpctchange
42
+ - 400227_logpctchange
43
+ - 400236_logpctchange
44
+ - 400238_logpctchange
45
+ - 400240_logpctchange
46
+ - 400246_logpctchange
47
+ - 400253_logpctchange
48
+ - 400257_logpctchange
49
+ - 400258_logpctchange
50
+ - 400268_logpctchange
51
+ - 400274_logpctchange
52
+ - 400278_logpctchange
53
+ - 400280_logpctchange
54
+ - 400292_logpctchange
55
+ - 400296_logpctchange
56
+ - 400298_logpctchange
57
+ - 400330_logpctchange
58
+ - 400336_logpctchange
59
+ - 400343_logpctchange
60
+ - 400353_logpctchange
61
+ - 400372_logpctchange
62
+ - 400394_logpctchange
63
+ - 400400_logpctchange
64
+ - 400414_logpctchange
65
+ - 400418_logpctchange
66
+ - 400429_logpctchange
67
+ - 400435_logpctchange
68
+ - 400436_logpctchange
69
+ - 400440_logpctchange
70
+ - 400449_logpctchange
71
+ - 400457_logpctchange
72
+ - 400461_logpctchange
73
+ - 400464_logpctchange
74
+ - 400479_logpctchange
75
+ - 400485_logpctchange
76
+ - 400499_logpctchange
77
+ - 400507_logpctchange
78
+ - 400508_logpctchange
79
+ - 400514_logpctchange
80
+ - 400519_logpctchange
81
+ - 400528_logpctchange
82
+ - 400545_logpctchange
83
+ - 400560_logpctchange
84
+ - 400563_logpctchange
85
+ - 400567_logpctchange
86
+ - 400581_logpctchange
87
+ - 400582_logpctchange
88
+ - 400586_logpctchange
89
+ - 400637_logpctchange
90
+ - 400643_logpctchange
91
+ - 400648_logpctchange
92
+ - 400649_logpctchange
93
+ - 400654_logpctchange
94
+ - 400664_logpctchange
95
+ - 400665_logpctchange
96
+ - 400668_logpctchange
97
+ - 400673_logpctchange
98
+ - 400677_logpctchange
99
+ - 400687_logpctchange
100
+ - 400688_logpctchange
101
+ - 400690_logpctchange
102
+ - 400700_logpctchange
103
+ - 400709_logpctchange
104
+ - 400713_logpctchange
105
+ - 400714_logpctchange
106
+ - 400715_logpctchange
107
+ - 400717_logpctchange
108
+ - 400723_logpctchange
109
+ - 400743_logpctchange
110
+ - 400750_logpctchange
111
+ - 400760_logpctchange
112
+ - 400772_logpctchange
113
+ - 400790_logpctchange
114
+ - 400792_logpctchange
115
+ - 400794_logpctchange
116
+ - 400799_logpctchange
117
+ - 400804_logpctchange
118
+ - 400822_logpctchange
119
+ - 400823_logpctchange
120
+ - 400828_logpctchange
121
+ - 400832_logpctchange
122
+ - 400837_logpctchange
123
+ - 400842_logpctchange
124
+ - 400863_logpctchange
125
+ - 400869_logpctchange
126
+ - 400873_logpctchange
127
+ - 400895_logpctchange
128
+ - 400904_logpctchange
129
+ - 400907_logpctchange
130
+ - 400911_logpctchange
131
+ - 400916_logpctchange
132
+ - 400922_logpctchange
133
+ - 400934_logpctchange
134
+ - 400951_logpctchange
135
+ - 400952_logpctchange
136
+ - 400953_logpctchange
137
+ - 400964_logpctchange
138
+ - 400965_logpctchange
139
+ - 400970_logpctchange
140
+ - 400971_logpctchange
141
+ - 400973_logpctchange
142
+ - 400995_logpctchange
143
+ - 400996_logpctchange
144
+ - 401014_logpctchange
145
+ - 401129_logpctchange
146
+ - 401154_logpctchange
147
+ - 401163_logpctchange
148
+ - 401167_logpctchange
149
+ - 401210_logpctchange
150
+ - 401224_logpctchange
151
+ - 401327_logpctchange
152
+ - 401351_logpctchange
153
+ - 401388_logpctchange
154
+ - 401391_logpctchange
155
+ - 401400_logpctchange
156
+ - 401403_logpctchange
157
+ - 401440_logpctchange
158
+ - 401457_logpctchange
159
+ - 401464_logpctchange
160
+ - 401489_logpctchange
161
+ - 401495_logpctchange
162
+ - 401507_logpctchange
163
+ - 401534_logpctchange
164
+ - 401541_logpctchange
165
+ - 401555_logpctchange
166
+ - 401560_logpctchange
167
+ - 401567_logpctchange
168
+ - 401597_logpctchange
169
+ - 401606_logpctchange
170
+ - 401611_logpctchange
171
+ - 401655_logpctchange
172
+ - 401808_logpctchange
173
+ - 401809_logpctchange
174
+ - 401810_logpctchange
175
+ - 401811_logpctchange
176
+ - 401816_logpctchange
177
+ - 401817_logpctchange
178
+ - 401845_logpctchange
179
+ - 401846_logpctchange
180
+ - 401890_logpctchange
181
+ - 401891_logpctchange
182
+ - 401906_logpctchange
183
+ - 401908_logpctchange
184
+ - 401926_logpctchange
185
+ - 401936_logpctchange
186
+ - 401937_logpctchange
187
+ - 401942_logpctchange
188
+ - 401943_logpctchange
189
+ - 401948_logpctchange
190
+ - 401957_logpctchange
191
+ - 401958_logpctchange
192
+ - 401994_logpctchange
193
+ - 401996_logpctchange
194
+ - 401997_logpctchange
195
+ - 401998_logpctchange
196
+ - 402056_logpctchange
197
+ - 402057_logpctchange
198
+ - 402058_logpctchange
199
+ - 402059_logpctchange
200
+ - 402060_logpctchange
201
+ - 402061_logpctchange
202
+ - 402067_logpctchange
203
+ - 402117_logpctchange
204
+ - 402118_logpctchange
205
+ - 402119_logpctchange
206
+ - 402120_logpctchange
207
+ - 402121_logpctchange
208
+ - 402281_logpctchange
209
+ - 402282_logpctchange
210
+ - 402283_logpctchange
211
+ - 402284_logpctchange
212
+ - 402285_logpctchange
213
+ - 402286_logpctchange
214
+ - 402287_logpctchange
215
+ - 402288_logpctchange
216
+ - 402289_logpctchange
217
+ - 402359_logpctchange
218
+ - 402360_logpctchange
219
+ - 402361_logpctchange
220
+ - 402362_logpctchange
221
+ - 402363_logpctchange
222
+ - 402364_logpctchange
223
+ - 402365_logpctchange
224
+ - 402366_logpctchange
225
+ - 402367_logpctchange
226
+ - 402368_logpctchange
227
+ - 402369_logpctchange
228
+ - 402370_logpctchange
229
+ - 402371_logpctchange
230
+ - 402372_logpctchange
231
+ - 402373_logpctchange
232
+ - 403225_logpctchange
233
+ - 403265_logpctchange
234
+ - 403329_logpctchange
235
+ - 403401_logpctchange
236
+ - 403402_logpctchange
237
+ - 403404_logpctchange
238
+ - 403406_logpctchange
239
+ - 403409_logpctchange
240
+ - 403412_logpctchange
241
+ - 403414_logpctchange
242
+ - 403419_logpctchange
243
+ - 404370_logpctchange
244
+ - 404434_logpctchange
245
+ - 404435_logpctchange
246
+ - 404444_logpctchange
247
+ - 404451_logpctchange
248
+ - 404452_logpctchange
249
+ - 404453_logpctchange
250
+ - 404461_logpctchange
251
+ - 404462_logpctchange
252
+ - 404521_logpctchange
253
+ - 404522_logpctchange
254
+ - 404553_logpctchange
255
+ - 404554_logpctchange
256
+ - 404585_logpctchange
257
+ - 404586_logpctchange
258
+ - 404640_logpctchange
259
+ - 404753_logpctchange
260
+ - 404759_logpctchange
261
+ - 405613_logpctchange
262
+ - 405619_logpctchange
263
+ - 405701_logpctchange
264
+ - 407150_logpctchange
265
+ - 407151_logpctchange
266
+ - 407152_logpctchange
267
+ - 407153_logpctchange
268
+ - 407155_logpctchange
269
+ - 407157_logpctchange
270
+ - 407161_logpctchange
271
+ - 407165_logpctchange
272
+ - 407172_logpctchange
273
+ - 407173_logpctchange
274
+ - 407174_logpctchange
275
+ - 407176_logpctchange
276
+ - 407177_logpctchange
277
+ - 407179_logpctchange
278
+ - 407180_logpctchange
279
+ - 407181_logpctchange
280
+ - 407184_logpctchange
281
+ - 407185_logpctchange
282
+ - 407186_logpctchange
283
+ - 407187_logpctchange
284
+ - 407190_logpctchange
285
+ - 407191_logpctchange
286
+ - 407194_logpctchange
287
+ - 407200_logpctchange
288
+ - 407202_logpctchange
289
+ - 407204_logpctchange
290
+ - 407206_logpctchange
291
+ - 407207_logpctchange
292
+ - 407321_logpctchange
293
+ - 407323_logpctchange
294
+ - 407325_logpctchange
295
+ - 407328_logpctchange
296
+ - 407331_logpctchange
297
+ - 407332_logpctchange
298
+ - 407335_logpctchange
299
+ - 407336_logpctchange
300
+ - 407337_logpctchange
301
+ - 407339_logpctchange
302
+ - 407341_logpctchange
303
+ - 407342_logpctchange
304
+ - 407344_logpctchange
305
+ - 407348_logpctchange
306
+ - 407352_logpctchange
307
+ - 407359_logpctchange
308
+ - 407360_logpctchange
309
+ - 407361_logpctchange
310
+ - 407364_logpctchange
311
+ - 407367_logpctchange
312
+ - 407370_logpctchange
313
+ - 407372_logpctchange
314
+ - 407373_logpctchange
315
+ - 407374_logpctchange
316
+ - 407710_logpctchange
317
+ - 407711_logpctchange
318
+ - 408907_logpctchange
319
+ - 408911_logpctchange
320
+ - 409524_logpctchange
321
+ - 409525_logpctchange
322
+ - 409526_logpctchange
323
+ - 409528_logpctchange
324
+ - 409529_logpctchange
325
+ - 413026_logpctchange
326
+ - 413845_logpctchange
327
+ - 413877_logpctchange
328
+ - 413878_logpctchange
329
+ - 414284_logpctchange
330
+ # - 414694_logpctchange
331
+ d_ff: 4096 #2048
332
+ d_model: 512
333
+ data_path: PEMSBAY.csv
334
+ # date_end: '2020-01-01'
335
+ # date_start: '2012-01-01'
336
+ # date_test: '2019-06-01'
337
+ des: stockPEMS
338
+ distil: false
339
+ dont_shuffle_train: false
340
+ dropout: 0.5
341
+ dropout_emb: 0.0
342
+ e_layers: 4
343
+ emb_t2v_app_dim: 16
344
+ enc_in: 325
345
+ factor: 5
346
+ features: MS
347
+ final_mode: mode3
348
+ freq: m
349
+ inverse_output: false
350
+ inverse_pred: true
351
+ label_len: 0
352
+ learning_rate: 1.0e-04
353
+ ln_mode: post
354
+ loss: stock_tanhv1
355
+ lradj: null
356
+ max_epochs: 30
357
+ mix: false
358
+ model: stockformer
359
+ n_heads: 8
360
+ no_early_stop: false
361
+ no_scale_mean: true
362
+ optim: Adam #Ranger
363
+ output_attention: false
364
+ patience: 1000
365
+ pred_len: 1
366
+ pre_loss: null
367
+ pre_epochs: 0
368
+ root_path: ./data/other/
369
+ scale: true
370
+ seed: 2
371
+ seq_len: 16
372
+ t_embed: null
373
+ tok_emb: default
374
+ target: 400001_logpctchange
configs/stockformer/basic_PEMSBAY_small.yaml ADDED
@@ -0,0 +1,373 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ activation: gelu
2
+ attn: full
3
+ batch_size: 256
4
+ c_out: 1
5
+ cols:
6
+ - 400001_logpctchange
7
+ - 400017_logpctchange
8
+ - 400030_logpctchange
9
+ - 400040_logpctchange
10
+ - 400045_logpctchange
11
+ - 400052_logpctchange
12
+ - 400057_logpctchange
13
+ - 400059_logpctchange
14
+ - 400065_logpctchange
15
+ - 400069_logpctchange
16
+ # - 400073_logpctchange
17
+ # - 400084_logpctchange
18
+ # - 400085_logpctchange
19
+ # - 400088_logpctchange
20
+ # - 400096_logpctchange
21
+ # - 400097_logpctchange
22
+ # - 400100_logpctchange
23
+ # - 400104_logpctchange
24
+ # - 400109_logpctchange
25
+ # - 400122_logpctchange
26
+ # - 400147_logpctchange
27
+ # - 400148_logpctchange
28
+ # - 400149_logpctchange
29
+ # - 400158_logpctchange
30
+ # - 400160_logpctchange
31
+ # - 400168_logpctchange
32
+ # - 400172_logpctchange
33
+ # - 400174_logpctchange
34
+ # - 400178_logpctchange
35
+ # - 400185_logpctchange
36
+ # - 400201_logpctchange
37
+ # - 400206_logpctchange
38
+ # - 400209_logpctchange
39
+ # - 400213_logpctchange
40
+ # - 400221_logpctchange
41
+ # - 400222_logpctchange
42
+ # - 400227_logpctchange
43
+ # - 400236_logpctchange
44
+ # - 400238_logpctchange
45
+ # - 400240_logpctchange
46
+ # - 400246_logpctchange
47
+ # - 400253_logpctchange
48
+ # - 400257_logpctchange
49
+ # - 400258_logpctchange
50
+ # - 400268_logpctchange
51
+ # - 400274_logpctchange
52
+ # - 400278_logpctchange
53
+ # - 400280_logpctchange
54
+ # - 400292_logpctchange
55
+ # - 400296_logpctchange
56
+ # - 400298_logpctchange
57
+ # - 400330_logpctchange
58
+ # - 400336_logpctchange
59
+ # - 400343_logpctchange
60
+ # - 400353_logpctchange
61
+ # - 400372_logpctchange
62
+ # - 400394_logpctchange
63
+ # - 400400_logpctchange
64
+ # - 400414_logpctchange
65
+ # - 400418_logpctchange
66
+ # - 400429_logpctchange
67
+ # - 400435_logpctchange
68
+ # - 400436_logpctchange
69
+ # - 400440_logpctchange
70
+ # - 400449_logpctchange
71
+ # - 400457_logpctchange
72
+ # - 400461_logpctchange
73
+ # - 400464_logpctchange
74
+ # - 400479_logpctchange
75
+ # - 400485_logpctchange
76
+ # - 400499_logpctchange
77
+ # - 400507_logpctchange
78
+ # - 400508_logpctchange
79
+ # - 400514_logpctchange
80
+ # - 400519_logpctchange
81
+ # - 400528_logpctchange
82
+ # - 400545_logpctchange
83
+ # - 400560_logpctchange
84
+ # - 400563_logpctchange
85
+ # - 400567_logpctchange
86
+ # - 400581_logpctchange
87
+ # - 400582_logpctchange
88
+ # - 400586_logpctchange
89
+ # - 400637_logpctchange
90
+ # - 400643_logpctchange
91
+ # - 400648_logpctchange
92
+ # - 400649_logpctchange
93
+ # - 400654_logpctchange
94
+ # - 400664_logpctchange
95
+ # - 400665_logpctchange
96
+ # - 400668_logpctchange
97
+ # - 400673_logpctchange
98
+ # - 400677_logpctchange
99
+ # - 400687_logpctchange
100
+ # - 400688_logpctchange
101
+ # - 400690_logpctchange
102
+ # - 400700_logpctchange
103
+ # - 400709_logpctchange
104
+ # - 400713_logpctchange
105
+ # - 400714_logpctchange
106
+ # - 400715_logpctchange
107
+ # - 400717_logpctchange
108
+ # - 400723_logpctchange
109
+ # - 400743_logpctchange
110
+ # - 400750_logpctchange
111
+ # - 400760_logpctchange
112
+ # - 400772_logpctchange
113
+ # - 400790_logpctchange
114
+ # - 400792_logpctchange
115
+ # - 400794_logpctchange
116
+ # - 400799_logpctchange
117
+ # - 400804_logpctchange
118
+ # - 400822_logpctchange
119
+ # - 400823_logpctchange
120
+ # - 400828_logpctchange
121
+ # - 400832_logpctchange
122
+ # - 400837_logpctchange
123
+ # - 400842_logpctchange
124
+ # - 400863_logpctchange
125
+ # - 400869_logpctchange
126
+ # - 400873_logpctchange
127
+ # - 400895_logpctchange
128
+ # - 400904_logpctchange
129
+ # - 400907_logpctchange
130
+ # - 400911_logpctchange
131
+ # - 400916_logpctchange
132
+ # - 400922_logpctchange
133
+ # - 400934_logpctchange
134
+ # - 400951_logpctchange
135
+ # - 400952_logpctchange
136
+ # - 400953_logpctchange
137
+ # - 400964_logpctchange
138
+ # - 400965_logpctchange
139
+ # - 400970_logpctchange
140
+ # - 400971_logpctchange
141
+ # - 400973_logpctchange
142
+ # - 400995_logpctchange
143
+ # - 400996_logpctchange
144
+ # - 401014_logpctchange
145
+ # - 401129_logpctchange
146
+ # - 401154_logpctchange
147
+ # - 401163_logpctchange
148
+ # - 401167_logpctchange
149
+ # - 401210_logpctchange
150
+ # - 401224_logpctchange
151
+ # - 401327_logpctchange
152
+ # - 401351_logpctchange
153
+ # - 401388_logpctchange
154
+ # - 401391_logpctchange
155
+ # - 401400_logpctchange
156
+ # - 401403_logpctchange
157
+ # - 401440_logpctchange
158
+ # - 401457_logpctchange
159
+ # - 401464_logpctchange
160
+ # - 401489_logpctchange
161
+ # - 401495_logpctchange
162
+ # - 401507_logpctchange
163
+ # - 401534_logpctchange
164
+ # - 401541_logpctchange
165
+ # - 401555_logpctchange
166
+ # - 401560_logpctchange
167
+ # - 401567_logpctchange
168
+ # - 401597_logpctchange
169
+ # - 401606_logpctchange
170
+ # - 401611_logpctchange
171
+ # - 401655_logpctchange
172
+ # - 401808_logpctchange
173
+ # - 401809_logpctchange
174
+ # - 401810_logpctchange
175
+ # - 401811_logpctchange
176
+ # - 401816_logpctchange
177
+ # - 401817_logpctchange
178
+ # - 401845_logpctchange
179
+ # - 401846_logpctchange
180
+ # - 401890_logpctchange
181
+ # - 401891_logpctchange
182
+ # - 401906_logpctchange
183
+ # - 401908_logpctchange
184
+ # - 401926_logpctchange
185
+ # - 401936_logpctchange
186
+ # - 401937_logpctchange
187
+ # - 401942_logpctchange
188
+ # - 401943_logpctchange
189
+ # - 401948_logpctchange
190
+ # - 401957_logpctchange
191
+ # - 401958_logpctchange
192
+ # - 401994_logpctchange
193
+ # - 401996_logpctchange
194
+ # - 401997_logpctchange
195
+ # - 401998_logpctchange
196
+ # - 402056_logpctchange
197
+ # - 402057_logpctchange
198
+ # - 402058_logpctchange
199
+ # - 402059_logpctchange
200
+ # - 402060_logpctchange
201
+ # - 402061_logpctchange
202
+ # - 402067_logpctchange
203
+ # - 402117_logpctchange
204
+ # - 402118_logpctchange
205
+ # - 402119_logpctchange
206
+ # - 402120_logpctchange
207
+ # - 402121_logpctchange
208
+ # - 402281_logpctchange
209
+ # - 402282_logpctchange
210
+ # - 402283_logpctchange
211
+ # - 402284_logpctchange
212
+ # - 402285_logpctchange
213
+ # - 402286_logpctchange
214
+ # - 402287_logpctchange
215
+ # - 402288_logpctchange
216
+ # - 402289_logpctchange
217
+ # - 402359_logpctchange
218
+ # - 402360_logpctchange
219
+ # - 402361_logpctchange
220
+ # - 402362_logpctchange
221
+ # - 402363_logpctchange
222
+ # - 402364_logpctchange
223
+ # - 402365_logpctchange
224
+ # - 402366_logpctchange
225
+ # - 402367_logpctchange
226
+ # - 402368_logpctchange
227
+ # - 402369_logpctchange
228
+ # - 402370_logpctchange
229
+ # - 402371_logpctchange
230
+ # - 402372_logpctchange
231
+ # - 402373_logpctchange
232
+ # - 403225_logpctchange
233
+ # - 403265_logpctchange
234
+ # - 403329_logpctchange
235
+ # - 403401_logpctchange
236
+ # - 403402_logpctchange
237
+ # - 403404_logpctchange
238
+ # - 403406_logpctchange
239
+ # - 403409_logpctchange
240
+ # - 403412_logpctchange
241
+ # - 403414_logpctchange
242
+ # - 403419_logpctchange
243
+ # - 404370_logpctchange
244
+ # - 404434_logpctchange
245
+ # - 404435_logpctchange
246
+ # - 404444_logpctchange
247
+ # - 404451_logpctchange
248
+ # - 404452_logpctchange
249
+ # - 404453_logpctchange
250
+ # - 404461_logpctchange
251
+ # - 404462_logpctchange
252
+ # - 404521_logpctchange
253
+ # - 404522_logpctchange
254
+ # - 404553_logpctchange
255
+ # - 404554_logpctchange
256
+ # - 404585_logpctchange
257
+ # - 404586_logpctchange
258
+ # - 404640_logpctchange
259
+ # - 404753_logpctchange
260
+ # - 404759_logpctchange
261
+ # - 405613_logpctchange
262
+ # - 405619_logpctchange
263
+ # - 405701_logpctchange
264
+ # - 407150_logpctchange
265
+ # - 407151_logpctchange
266
+ # - 407152_logpctchange
267
+ # - 407153_logpctchange
268
+ # - 407155_logpctchange
269
+ # - 407157_logpctchange
270
+ # - 407161_logpctchange
271
+ # - 407165_logpctchange
272
+ # - 407172_logpctchange
273
+ # - 407173_logpctchange
274
+ # - 407174_logpctchange
275
+ # - 407176_logpctchange
276
+ # - 407177_logpctchange
277
+ # - 407179_logpctchange
278
+ # - 407180_logpctchange
279
+ # - 407181_logpctchange
280
+ # - 407184_logpctchange
281
+ # - 407185_logpctchange
282
+ # - 407186_logpctchange
283
+ # - 407187_logpctchange
284
+ # - 407190_logpctchange
285
+ # - 407191_logpctchange
286
+ # - 407194_logpctchange
287
+ # - 407200_logpctchange
288
+ # - 407202_logpctchange
289
+ # - 407204_logpctchange
290
+ # - 407206_logpctchange
291
+ # - 407207_logpctchange
292
+ # - 407321_logpctchange
293
+ # - 407323_logpctchange
294
+ # - 407325_logpctchange
295
+ # - 407328_logpctchange
296
+ # - 407331_logpctchange
297
+ # - 407332_logpctchange
298
+ # - 407335_logpctchange
299
+ # - 407336_logpctchange
300
+ # - 407337_logpctchange
301
+ # - 407339_logpctchange
302
+ # - 407341_logpctchange
303
+ # - 407342_logpctchange
304
+ # - 407344_logpctchange
305
+ # - 407348_logpctchange
306
+ # - 407352_logpctchange
307
+ # - 407359_logpctchange
308
+ # - 407360_logpctchange
309
+ # - 407361_logpctchange
310
+ # - 407364_logpctchange
311
+ # - 407367_logpctchange
312
+ # - 407370_logpctchange
313
+ # - 407372_logpctchange
314
+ # - 407373_logpctchange
315
+ # - 407374_logpctchange
316
+ # - 407710_logpctchange
317
+ # - 407711_logpctchange
318
+ # - 408907_logpctchange
319
+ # - 408911_logpctchange
320
+ # - 409524_logpctchange
321
+ # - 409525_logpctchange
322
+ # - 409526_logpctchange
323
+ # - 409528_logpctchange
324
+ # - 409529_logpctchange
325
+ # - 413026_logpctchange
326
+ # - 413845_logpctchange
327
+ # - 413877_logpctchange
328
+ # - 413878_logpctchange
329
+ # - 414284_logpctchange
330
+ # - 414694_logpctchange
331
+ d_ff: 4096 #2048
332
+ d_model: 512
333
+ data_path: PEMSBAY.csv
334
+ # date_end: '2020-01-01'
335
+ # date_start: '2012-01-01'
336
+ # date_test: '2019-06-01'
337
+ des: full_1h
338
+ distil: false
339
+ dont_shuffle_train: false
340
+ dropout: 0.5
341
+ dropout_emb: 0.05
342
+ e_layers: 3
343
+ emb_t2v_app_dim: 16
344
+ enc_in: 10
345
+ factor: 5
346
+ features: MS
347
+ final_mode: mode3
348
+ freq: m
349
+ inverse_output: false
350
+ inverse_pred: true
351
+ label_len: 0
352
+ learning_rate: 1.0e-04
353
+ ln_mode: post
354
+ loss: stock_tanhv1
355
+ lradj: null
356
+ max_epochs: 30
357
+ mix: false
358
+ model: stockformer
359
+ n_heads: 8
360
+ no_early_stop: false
361
+ no_scale_mean: true
362
+ optim: Adam #Ranger
363
+ output_attention: false
364
+ patience: 1000
365
+ pred_len: 1
366
+ pre_loss: null
367
+ pre_epochs: 0
368
+ root_path: ./data/other/
369
+ scale: true
370
+ seed: 2
371
+ seq_len: 16
372
+ t_embed: time2vec_add
373
+ target: 400001_logpctchange
configs/stockformer/basic_WTH.yaml ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ activation: gelu
2
+ attn: full
3
+ batch_size: 256
4
+ c_out: 1
5
+ cols:
6
+ - Visibility_logpctchange
7
+ - DryBulbFarenheit_logpctchange
8
+ - DryBulbCelsius_logpctchange
9
+ - WetBulbFarenheit_logpctchange
10
+ - DewPointFarenheit_logpctchange
11
+ - DewPointCelsius_logpctchange
12
+ - RelativeHumidity_logpctchange
13
+ - WindSpeed_logpctchange
14
+ - WindDirection_logpctchange
15
+ - StationPressure_logpctchange
16
+ - Altimeter_logpctchange
17
+ - WetBulbCelsius_logpctchange
18
+ d_ff: 4096 #2048
19
+ d_model: 512
20
+ data_path: WTH.csv
21
+ # date_end: '2020-01-01'
22
+ # date_start: '2012-01-01'
23
+ # date_test: '2019-06-01'
24
+ des: full_1h
25
+ distil: false
26
+ dont_shuffle_train: false
27
+ dropout: 0.5
28
+ dropout_emb: 0.0
29
+ e_layers: 4
30
+ emb_t2v_app_dim: 16
31
+ enc_in: 12
32
+ factor: 5
33
+ features: MS
34
+ final_mode: mode3
35
+ freq: h
36
+ inverse_output: false
37
+ inverse_pred: true
38
+ label_len: 0
39
+ learning_rate: 1.0e-05
40
+ ln_mode: post
41
+ loss: stock_tanhv1
42
+ lradj: null
43
+ max_epochs: 30
44
+ mix: false
45
+ model: stockformer
46
+ n_heads: 32
47
+ no_early_stop: false
48
+ no_scale_mean: true
49
+ optim: Adam #Ranger
50
+ output_attention: false
51
+ patience: 1000
52
+ pred_len: 1
53
+ pre_loss: stock_tanhv4
54
+ pre_epochs: 15
55
+ root_path: ./data/other/
56
+ scale: true
57
+ seed: 5
58
+ seq_len: 16
59
+ t_embed: null
60
+ target: WetBulbFarenheit_logpctchange
configs/stockformer/basic_material.yaml ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ activation: gelu
2
+ attn: full
3
+ batch_size: 256
4
+ c_out: 1
5
+ cols: null
6
+ d_ff: 4096 #2048
7
+ d_model: 512
8
+ data_path: material_1h.csv
9
+ # date_end: '2020-01-01'
10
+ # date_start: '2012-01-01'
11
+ # date_test: '2019-06-01'
12
+ des: full_1h
13
+ distil: false
14
+ dont_shuffle_train: false
15
+ dropout: 0.5
16
+ dropout_emb: 0.0
17
+ e_layers: 4
18
+ emb_t2v_app_dim: 16
19
+ enc_in: 9
20
+ factor: 5
21
+ features: MS
22
+ final_mode: mode3
23
+ freq: h
24
+ inverse_output: false
25
+ inverse_pred: true
26
+ label_len: 0
27
+ learning_rate: 1.0e-05
28
+ ln_mode: post
29
+ loss: stock_tanhv1
30
+ lradj: null
31
+ max_epochs: 50
32
+ mix: false
33
+ model: stockformer
34
+ n_heads: 16
35
+ no_early_stop: false
36
+ no_scale_mean: true
37
+ optim: Adam #Ranger
38
+ output_attention: false
39
+ patience: 1000
40
+ pred_len: 1
41
+ pre_loss: stock_tanhv4
42
+ pre_epochs: 30
43
+ root_path: ./data/stock/
44
+ scale: true
45
+ seed: 1
46
+ seq_len: 32
47
+ t_embed: time2vec_add
48
+ target: FCX_logpctchange
configs/stockformer/general.yaml ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ activation: gelu
2
+ attn: full
3
+ batch_size: 208
4
+ c_out: 1
5
+ cols:
6
+ - XOM_logpctchange
7
+ - CVX_logpctchange
8
+ - COP_logpctchange
9
+ - BP_logpctchange
10
+ - PBR_logpctchange
11
+ - EOG_logpctchange
12
+ - WTI_logpctchange
13
+ # - ENB_logpctchange
14
+ # - SLB_logpctchange
15
+ d_ff: 4096 #2048
16
+ d_model: 512
17
+ data_path: material_1h.csv
18
+ # date_end: '2020-01-01'
19
+ # date_start: '2012-01-01'
20
+ # date_test: '2019-06-01'
21
+ date_end: '2025-10-23'
22
+ date_start: '2020-10-26'
23
+ date_test: '2025-06-26'
24
+ des: full_1h
25
+ distil: false
26
+ dont_shuffle_train: false
27
+ dropout: 0.5
28
+ dropout_emb: 0.0
29
+ t_embed: time2vec_app
30
+ enc_in: 7
31
+ factor: 5
32
+ features: MS
33
+ freq: h
34
+ inverse_pred: true
35
+ # inverse_output: false
36
+ loss: stock_tanhv1
37
+ # inverse_output: true
38
+ # loss: stock_tanhv1+mae
39
+ final_mode: mode3
40
+ label_len: 0
41
+ learning_rate: 1.0e-05
42
+ seq_len: 64
43
+ e_layers: 12
44
+ emb_t2v_app_dim: 16
45
+ ln_mode: post
46
+ lradj: null
47
+ mix: false
48
+ model: stockformer
49
+ n_heads: 512
50
+ no_early_stop: true
51
+ no_scale_mean: true
52
+ # optim: Ranger
53
+ optim: AdamW
54
+ output_attention: false
55
+ patience: 100
56
+ pred_len: 1
57
+ root_path: ./data/stock/
58
+ scale: true
59
+ seed: 4
60
+ target: WTI_logpctchange
61
+ max_epochs: 100
configs/stockformer/general_PEMSBAY.yaml ADDED
@@ -0,0 +1,373 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ activation: gelu
2
+ attn: full
3
+ batch_size: 256
4
+ c_out: 1
5
+ cols:
6
+ - 400001_logpctchange
7
+ - 400017_logpctchange
8
+ - 400030_logpctchange
9
+ - 400040_logpctchange
10
+ - 400045_logpctchange
11
+ - 400052_logpctchange
12
+ - 400057_logpctchange
13
+ - 400059_logpctchange
14
+ - 400065_logpctchange
15
+ - 400069_logpctchange
16
+ # - 400073_logpctchange
17
+ # - 400084_logpctchange
18
+ # - 400085_logpctchange
19
+ # - 400088_logpctchange
20
+ # - 400096_logpctchange
21
+ # - 400097_logpctchange
22
+ # - 400100_logpctchange
23
+ # - 400104_logpctchange
24
+ # - 400109_logpctchange
25
+ # - 400122_logpctchange
26
+ # - 400147_logpctchange
27
+ # - 400148_logpctchange
28
+ # - 400149_logpctchange
29
+ # - 400158_logpctchange
30
+ # - 400160_logpctchange
31
+ # - 400168_logpctchange
32
+ # - 400172_logpctchange
33
+ # - 400174_logpctchange
34
+ # - 400178_logpctchange
35
+ # - 400185_logpctchange
36
+ # - 400201_logpctchange
37
+ # - 400206_logpctchange
38
+ # - 400209_logpctchange
39
+ # - 400213_logpctchange
40
+ # - 400221_logpctchange
41
+ # - 400222_logpctchange
42
+ # - 400227_logpctchange
43
+ # - 400236_logpctchange
44
+ # - 400238_logpctchange
45
+ # - 400240_logpctchange
46
+ # - 400246_logpctchange
47
+ # - 400253_logpctchange
48
+ # - 400257_logpctchange
49
+ # - 400258_logpctchange
50
+ # - 400268_logpctchange
51
+ # - 400274_logpctchange
52
+ # - 400278_logpctchange
53
+ # - 400280_logpctchange
54
+ # - 400292_logpctchange
55
+ # - 400296_logpctchange
56
+ # - 400298_logpctchange
57
+ # - 400330_logpctchange
58
+ # - 400336_logpctchange
59
+ # - 400343_logpctchange
60
+ # - 400353_logpctchange
61
+ # - 400372_logpctchange
62
+ # - 400394_logpctchange
63
+ # - 400400_logpctchange
64
+ # - 400414_logpctchange
65
+ # - 400418_logpctchange
66
+ # - 400429_logpctchange
67
+ # - 400435_logpctchange
68
+ # - 400436_logpctchange
69
+ # - 400440_logpctchange
70
+ # - 400449_logpctchange
71
+ # - 400457_logpctchange
72
+ # - 400461_logpctchange
73
+ # - 400464_logpctchange
74
+ # - 400479_logpctchange
75
+ # - 400485_logpctchange
76
+ # - 400499_logpctchange
77
+ # - 400507_logpctchange
78
+ # - 400508_logpctchange
79
+ # - 400514_logpctchange
80
+ # - 400519_logpctchange
81
+ # - 400528_logpctchange
82
+ # - 400545_logpctchange
83
+ # - 400560_logpctchange
84
+ # - 400563_logpctchange
85
+ # - 400567_logpctchange
86
+ # - 400581_logpctchange
87
+ # - 400582_logpctchange
88
+ # - 400586_logpctchange
89
+ # - 400637_logpctchange
90
+ # - 400643_logpctchange
91
+ # - 400648_logpctchange
92
+ # - 400649_logpctchange
93
+ # - 400654_logpctchange
94
+ # - 400664_logpctchange
95
+ # - 400665_logpctchange
96
+ # - 400668_logpctchange
97
+ # - 400673_logpctchange
98
+ # - 400677_logpctchange
99
+ # - 400687_logpctchange
100
+ # - 400688_logpctchange
101
+ # - 400690_logpctchange
102
+ # - 400700_logpctchange
103
+ # - 400709_logpctchange
104
+ # - 400713_logpctchange
105
+ # - 400714_logpctchange
106
+ # - 400715_logpctchange
107
+ # - 400717_logpctchange
108
+ # - 400723_logpctchange
109
+ # - 400743_logpctchange
110
+ # - 400750_logpctchange
111
+ # - 400760_logpctchange
112
+ # - 400772_logpctchange
113
+ # - 400790_logpctchange
114
+ # - 400792_logpctchange
115
+ # - 400794_logpctchange
116
+ # - 400799_logpctchange
117
+ # - 400804_logpctchange
118
+ # - 400822_logpctchange
119
+ # - 400823_logpctchange
120
+ # - 400828_logpctchange
121
+ # - 400832_logpctchange
122
+ # - 400837_logpctchange
123
+ # - 400842_logpctchange
124
+ # - 400863_logpctchange
125
+ # - 400869_logpctchange
126
+ # - 400873_logpctchange
127
+ # - 400895_logpctchange
128
+ # - 400904_logpctchange
129
+ # - 400907_logpctchange
130
+ # - 400911_logpctchange
131
+ # - 400916_logpctchange
132
+ # - 400922_logpctchange
133
+ # - 400934_logpctchange
134
+ # - 400951_logpctchange
135
+ # - 400952_logpctchange
136
+ # - 400953_logpctchange
137
+ # - 400964_logpctchange
138
+ # - 400965_logpctchange
139
+ # - 400970_logpctchange
140
+ # - 400971_logpctchange
141
+ # - 400973_logpctchange
142
+ # - 400995_logpctchange
143
+ # - 400996_logpctchange
144
+ # - 401014_logpctchange
145
+ # - 401129_logpctchange
146
+ # - 401154_logpctchange
147
+ # - 401163_logpctchange
148
+ # - 401167_logpctchange
149
+ # - 401210_logpctchange
150
+ # - 401224_logpctchange
151
+ # - 401327_logpctchange
152
+ # - 401351_logpctchange
153
+ # - 401388_logpctchange
154
+ # - 401391_logpctchange
155
+ # - 401400_logpctchange
156
+ # - 401403_logpctchange
157
+ # - 401440_logpctchange
158
+ # - 401457_logpctchange
159
+ # - 401464_logpctchange
160
+ # - 401489_logpctchange
161
+ # - 401495_logpctchange
162
+ # - 401507_logpctchange
163
+ # - 401534_logpctchange
164
+ # - 401541_logpctchange
165
+ # - 401555_logpctchange
166
+ # - 401560_logpctchange
167
+ # - 401567_logpctchange
168
+ # - 401597_logpctchange
169
+ # - 401606_logpctchange
170
+ # - 401611_logpctchange
171
+ # - 401655_logpctchange
172
+ # - 401808_logpctchange
173
+ # - 401809_logpctchange
174
+ # - 401810_logpctchange
175
+ # - 401811_logpctchange
176
+ # - 401816_logpctchange
177
+ # - 401817_logpctchange
178
+ # - 401845_logpctchange
179
+ # - 401846_logpctchange
180
+ # - 401890_logpctchange
181
+ # - 401891_logpctchange
182
+ # - 401906_logpctchange
183
+ # - 401908_logpctchange
184
+ # - 401926_logpctchange
185
+ # - 401936_logpctchange
186
+ # - 401937_logpctchange
187
+ # - 401942_logpctchange
188
+ # - 401943_logpctchange
189
+ # - 401948_logpctchange
190
+ # - 401957_logpctchange
191
+ # - 401958_logpctchange
192
+ # - 401994_logpctchange
193
+ # - 401996_logpctchange
194
+ # - 401997_logpctchange
195
+ # - 401998_logpctchange
196
+ # - 402056_logpctchange
197
+ # - 402057_logpctchange
198
+ # - 402058_logpctchange
199
+ # - 402059_logpctchange
200
+ # - 402060_logpctchange
201
+ # - 402061_logpctchange
202
+ # - 402067_logpctchange
203
+ # - 402117_logpctchange
204
+ # - 402118_logpctchange
205
+ # - 402119_logpctchange
206
+ # - 402120_logpctchange
207
+ # - 402121_logpctchange
208
+ # - 402281_logpctchange
209
+ # - 402282_logpctchange
210
+ # - 402283_logpctchange
211
+ # - 402284_logpctchange
212
+ # - 402285_logpctchange
213
+ # - 402286_logpctchange
214
+ # - 402287_logpctchange
215
+ # - 402288_logpctchange
216
+ # - 402289_logpctchange
217
+ # - 402359_logpctchange
218
+ # - 402360_logpctchange
219
+ # - 402361_logpctchange
220
+ # - 402362_logpctchange
221
+ # - 402363_logpctchange
222
+ # - 402364_logpctchange
223
+ # - 402365_logpctchange
224
+ # - 402366_logpctchange
225
+ # - 402367_logpctchange
226
+ # - 402368_logpctchange
227
+ # - 402369_logpctchange
228
+ # - 402370_logpctchange
229
+ # - 402371_logpctchange
230
+ # - 402372_logpctchange
231
+ # - 402373_logpctchange
232
+ # - 403225_logpctchange
233
+ # - 403265_logpctchange
234
+ # - 403329_logpctchange
235
+ # - 403401_logpctchange
236
+ # - 403402_logpctchange
237
+ # - 403404_logpctchange
238
+ # - 403406_logpctchange
239
+ # - 403409_logpctchange
240
+ # - 403412_logpctchange
241
+ # - 403414_logpctchange
242
+ # - 403419_logpctchange
243
+ # - 404370_logpctchange
244
+ # - 404434_logpctchange
245
+ # - 404435_logpctchange
246
+ # - 404444_logpctchange
247
+ # - 404451_logpctchange
248
+ # - 404452_logpctchange
249
+ # - 404453_logpctchange
250
+ # - 404461_logpctchange
251
+ # - 404462_logpctchange
252
+ # - 404521_logpctchange
253
+ # - 404522_logpctchange
254
+ # - 404553_logpctchange
255
+ # - 404554_logpctchange
256
+ # - 404585_logpctchange
257
+ # - 404586_logpctchange
258
+ # - 404640_logpctchange
259
+ # - 404753_logpctchange
260
+ # - 404759_logpctchange
261
+ # - 405613_logpctchange
262
+ # - 405619_logpctchange
263
+ # - 405701_logpctchange
264
+ # - 407150_logpctchange
265
+ # - 407151_logpctchange
266
+ # - 407152_logpctchange
267
+ # - 407153_logpctchange
268
+ # - 407155_logpctchange
269
+ # - 407157_logpctchange
270
+ # - 407161_logpctchange
271
+ # - 407165_logpctchange
272
+ # - 407172_logpctchange
273
+ # - 407173_logpctchange
274
+ # - 407174_logpctchange
275
+ # - 407176_logpctchange
276
+ # - 407177_logpctchange
277
+ # - 407179_logpctchange
278
+ # - 407180_logpctchange
279
+ # - 407181_logpctchange
280
+ # - 407184_logpctchange
281
+ # - 407185_logpctchange
282
+ # - 407186_logpctchange
283
+ # - 407187_logpctchange
284
+ # - 407190_logpctchange
285
+ # - 407191_logpctchange
286
+ # - 407194_logpctchange
287
+ # - 407200_logpctchange
288
+ # - 407202_logpctchange
289
+ # - 407204_logpctchange
290
+ # - 407206_logpctchange
291
+ # - 407207_logpctchange
292
+ # - 407321_logpctchange
293
+ # - 407323_logpctchange
294
+ # - 407325_logpctchange
295
+ # - 407328_logpctchange
296
+ # - 407331_logpctchange
297
+ # - 407332_logpctchange
298
+ # - 407335_logpctchange
299
+ # - 407336_logpctchange
300
+ # - 407337_logpctchange
301
+ # - 407339_logpctchange
302
+ # - 407341_logpctchange
303
+ # - 407342_logpctchange
304
+ # - 407344_logpctchange
305
+ # - 407348_logpctchange
306
+ # - 407352_logpctchange
307
+ # - 407359_logpctchange
308
+ # - 407360_logpctchange
309
+ # - 407361_logpctchange
310
+ # - 407364_logpctchange
311
+ # - 407367_logpctchange
312
+ # - 407370_logpctchange
313
+ # - 407372_logpctchange
314
+ # - 407373_logpctchange
315
+ # - 407374_logpctchange
316
+ # - 407710_logpctchange
317
+ # - 407711_logpctchange
318
+ # - 408907_logpctchange
319
+ # - 408911_logpctchange
320
+ # - 409524_logpctchange
321
+ # - 409525_logpctchange
322
+ # - 409526_logpctchange
323
+ # - 409528_logpctchange
324
+ # - 409529_logpctchange
325
+ # - 413026_logpctchange
326
+ # - 413845_logpctchange
327
+ # - 413877_logpctchange
328
+ # - 413878_logpctchange
329
+ # - 414284_logpctchange
330
+ # - 414694_logpctchange
331
+ d_ff: 4096 #2048
332
+ d_model: 512
333
+ data_path: PEMSBAY.csv
334
+ # date_end: '2020-01-01'
335
+ # date_start: '2012-01-01'
336
+ # date_test: '2019-06-01'
337
+ des: full_1h
338
+ distil: false
339
+ dont_shuffle_train: false
340
+ dropout: 0.5
341
+ dropout_emb: 0.0
342
+ e_layers: 12
343
+ emb_t2v_app_dim: 16
344
+ enc_in: 10 #325
345
+ factor: 5
346
+ features: MS
347
+ final_mode: mode3
348
+ freq: m
349
+ inverse_output: false
350
+ inverse_pred: true
351
+ label_len: 0
352
+ learning_rate: 1.0e-05
353
+ ln_mode: post
354
+ loss: stock_tanhv1
355
+ lradj: null
356
+ max_epochs: 30
357
+ mix: false
358
+ model: stockformer
359
+ n_heads: 512
360
+ no_early_stop: false
361
+ no_scale_mean: true
362
+ optim: Adam #Ranger
363
+ output_attention: false
364
+ patience: 1000
365
+ pred_len: 1
366
+ pre_loss: null #stock_tanhv4
367
+ pre_epochs: 0 #15
368
+ root_path: ./data/other/
369
+ scale: true
370
+ seed: 2
371
+ seq_len: 16
372
+ t_embed: time2vec_add
373
+ target: 400001_logpctchange
d.sh ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ mkdir -p stock_transformer_back
3
+ cd stock_transformer_back
4
+
5
+
6
+ STUDIO="hallucination/slow-rose-kq8y"
7
+
8
+ ########################
9
+ # 1. 目录:先 mkdir,再下载
10
+ ########################
11
+
12
+ # configs/
13
+ mkdir -p configs
14
+ lightning download folder stock_transformer_back/configs \
15
+ --studio "$STUDIO" \
16
+ --local-path ./configs
17
+
18
+ # data/
19
+ mkdir -p data
20
+ lightning download folder stock_transformer_back/data \
21
+ --studio "$STUDIO" \
22
+ --local-path ./data
23
+
24
+ # data_provider/
25
+ mkdir -p data_provider
26
+ lightning download folder stock_transformer_back/data_provider \
27
+ --studio "$STUDIO" \
28
+ --local-path ./data_provider
29
+
30
+ # exp/
31
+ mkdir -p exp
32
+ lightning download folder stock_transformer_back/exp \
33
+ --studio "$STUDIO" \
34
+ --local-path ./exp
35
+
36
+ # layers/
37
+ mkdir -p layers
38
+ lightning download folder stock_transformer_back/layers \
39
+ --studio "$STUDIO" \
40
+ --local-path ./layers
41
+
42
+ # models/
43
+ mkdir -p models
44
+ lightning download folder stock_transformer_back/models \
45
+ --studio "$STUDIO" \
46
+ --local-path ./models
47
+
48
+ # old_stuff/
49
+ mkdir -p old_stuff
50
+ lightning download folder stock_transformer_back/old_stuff \
51
+ --studio "$STUDIO" \
52
+ --local-path ./old_stuff
53
+
54
+ # utils/
55
+ mkdir -p utils
56
+ lightning download folder stock_transformer_back/utils \
57
+ --studio "$STUDIO" \
58
+ --local-path ./utils
59
+
60
+ # 注意:不下 lightning_logs,所以这里不写它
61
+
62
+
63
+ ########################
64
+ # 2. 单个文件:直接下到当前目录
65
+ ########################
66
+
67
+ lightning download file stock_transformer_back/.gitignore --studio "$STUDIO"
68
+ lightning download file stock_transformer_back/.tmux.conf --studio "$STUDIO"
69
+ lightning download file stock_transformer_back/LICENSE --studio "$STUDIO"
70
+ lightning download file stock_transformer_back/README.md --studio "$STUDIO"
71
+ lightning download file stock_transformer_back/Stockformer.py --studio "$STUDIO"
72
+ lightning download file stock_transformer_back/clean_ipynb.sh --studio "$STUDIO"
73
+
74
+ lightning download file stock_transformer_back/data_collect.ipynb --studio "$STUDIO"
75
+ lightning download file stock_transformer_back/data_collect.py --studio "$STUDIO"
76
+ lightning download file stock_transformer_back/data_loader.py --studio "$STUDIO"
77
+ lightning download file stock_transformer_back/data_prepare.ipynb --studio "$STUDIO"
78
+ lightning download file stock_transformer_back/data_prepare.py --studio "$STUDIO"
79
+
80
+ lightning download file stock_transformer_back/embed.py --studio "$STUDIO"
81
+ lightning download file stock_transformer_back/exp_timeseries.py --studio "$STUDIO"
82
+
83
+ lightning download file stock_transformer_back/run_bbtest.py --studio "$STUDIO"
84
+ lightning download file stock_transformer_back/run_hypopt.py --studio "$STUDIO"
85
+ lightning download file stock_transformer_back/run_once.py --studio "$STUDIO"
86
+
87
+ lightning download file stock_transformer_back/stock_metrics.py --studio "$STUDIO"
88
+ lightning download file stock_transformer_back/tools.py --studio "$STUDIO"
89
+
90
+ lightning download file stock_transformer_back/vis_data.ipynb --studio "$STUDIO"
91
+ lightning download file stock_transformer_back/vis_results.ipynb --studio "$STUDIO"
92
+
93
+ lightning download file stock_transformer_back/wavelet.py --studio "$STUDIO"
94
+
data_collect.ipynb ADDED
@@ -0,0 +1,536 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": 1,
6
+ "metadata": {},
7
+ "outputs": [],
8
+ "source": [
9
+ "import pandas as pd\n",
10
+ "from time import sleep\n",
11
+ "import datetime\n",
12
+ "import os\n",
13
+ "from utils.ipynb_helpers import read_data, write_df, convert_tz, add_tz\n",
14
+ "from dotenv import load_dotenv\n",
15
+ "\n",
16
+ "# Create a .env file and add your keys\n",
17
+ "load_dotenv()\n",
18
+ "\n",
19
+ "# Location to save raw data from data providers\n",
20
+ "DATA_RAW = \"data/raw\"\n",
21
+ "\n",
22
+ "\n",
23
+ "equities = [\"XOM\", \"CVX\", \"COP\", \"BP\", \"PBR\", \"WTI\", \"TTE\", \"EQNR\", \"EOG\", \"ENB\", \"SLB\"]\n",
24
+ "more_equities = []\n",
25
+ "\n",
26
+ "crude_oil = [\"CL=F\", \"BZ=F\"] # wti, brent,\n",
27
+ "random = [\"TSLA\", \"AAPL\"]\n",
28
+ "\n",
29
+ "materials_equities = [\"BHP\", \"LIN\", \"RIO\", \"VALE\", \"APD\", \"FCX\", \"SHW\", \"SCCO\", \"CTVA\", \"ECL\", \"NUE\", \"NTR\"]\n",
30
+ "\n",
31
+ "\n",
32
+ "# https://en.wikipedia.org/wiki/List_of_countries_by_oil_production\n",
33
+ "# https://www.weforum.org/agenda/2016/05/which-economies-are-most-reliant-on-oil/\n",
34
+ "# OPEC: Iran, Iraq, Kuwait, Saudi Arabia, Venezuela\n",
35
+ "# fx_opec = [_, \"C:USDIQD\", \"C:USDKWD\", \"C:USDSAR\", \"C:USDVEF\"]\n",
36
+ "\n",
37
+ "# OPEC+: Algeria, Angola, Congo, Equatorial Guinea, Gabon, Libya, Nigeria, United Arab Emirates\n",
38
+ "# fx_opec_pp = [\"C:USDDZD\",_, \"C:USDCDF\", \"C:USDGNF\", _, \"C:USDLYD\", \"C:USDNGN\", \"C:USDAED\"]\n",
39
+ "\n",
40
+ "# Large: US, Russia, China, Canada, Norway\n",
41
+ "# Other important: Qatar, Kazakhstan\n",
42
+ "# fx_other= [\"C:USDQAR\", \"C:USDKZT\"]\n",
43
+ "\n",
44
+ "fx = [\"C:USDSAR\", \"C:USDAED\"]\n",
45
+ "\n",
46
+ "tickers = equities # + crude_oil"
47
+ ]
48
+ },
49
+ {
50
+ "cell_type": "markdown",
51
+ "metadata": {},
52
+ "source": [
53
+ "##### Get Data From Data Provider"
54
+ ]
55
+ },
56
+ {
57
+ "cell_type": "code",
58
+ "execution_count": 2,
59
+ "metadata": {},
60
+ "outputs": [],
61
+ "source": [
62
+ "# Y Finance\n",
63
+ "\n",
64
+ "import yfinance as yf\n",
65
+ "\n",
66
+ "\n",
67
+ "def use_yfinance(\n",
68
+ " tickers, out_file, timeframe=\"day\", start=\"2000-01-01\", end=\"2023-01-01\"\n",
69
+ "):\n",
70
+ " assert timeframe == \"day\", \"Use day timeframe for day\"\n",
71
+ "\n",
72
+ " data = yf.download(tickers, start=start, end=end, group_by=\"ticker\")\n",
73
+ "\n",
74
+ " if len(tickers) == 1:\n",
75
+ " data = pd.concat([data], axis=1, keys=[tickers[0]])\n",
76
+ "\n",
77
+ " data.index.rename(\"date\", inplace=True)\n",
78
+ " data.rename(columns=lambda x: str.lower(x), level=1, inplace=True)\n",
79
+ "\n",
80
+ " if data.index.to_series().dt.tz is None:\n",
81
+ " print(\"Adding time\")\n",
82
+ " data = add_tz(data, time_zone=\"UTC\")\n",
83
+ "\n",
84
+ " if out_file is not None:\n",
85
+ " write_df(data, out_file)\n",
86
+ "\n",
87
+ " return data"
88
+ ]
89
+ },
90
+ {
91
+ "cell_type": "code",
92
+ "execution_count": 22,
93
+ "metadata": {},
94
+ "outputs": [],
95
+ "source": [
96
+ "# Alpha Vantage\n",
97
+ "\n",
98
+ "\n",
99
+ "def csv_str_to_df(decoded_content, ticker):\n",
100
+ " \"\"\"CSV string to df\"\"\"\n",
101
+ " print(decoded_content[:1000])\n",
102
+ " lines = decoded_content.splitlines()\n",
103
+ " print(len(lines), lines[0].split(\",\")[1:])\n",
104
+ " print(lines[2])\n",
105
+ " #while(1):pass\n",
106
+ " data = pd.DataFrame(\n",
107
+ " [row.split(\",\") for row in lines[1:]],\n",
108
+ " columns=[\"date\", *lines[0].split(\",\")[1:]],\n",
109
+ " )\n",
110
+ " \n",
111
+ "\n",
112
+ " data = data.reset_index(drop=True).set_index(\"date\")\n",
113
+ " data.index = pd.to_datetime(data.index)\n",
114
+ "\n",
115
+ " # Add timezome -- we assume it is sent in with unlabled eastern time\n",
116
+ " if data.index.to_series().dt.tz is None:\n",
117
+ " print(\"CONVERTING TIME\")\n",
118
+ " data = add_tz(data, time_zone=\"US/Eastern\")\n",
119
+ " data = convert_tz(data, time_zone=\"UTC\")\n",
120
+ " data = pd.concat([data], axis=1, keys=[ticker])\n",
121
+ " return data\n",
122
+ "\n",
123
+ "\n",
124
+ "def alpha_vantage_get_ticker_data(ticker, time=\"1min\", year=1, month=1):\n",
125
+ " \"\"\"Function to get (ticker, year, month) data using alpha vantage's time series intraday extended API\"\"\"\n",
126
+ " ALPHA_VANTAGE_API_KEY = os.environ.get(\"ALPHA_VANTAGE_API_KEY\")\n",
127
+ " import requests\n",
128
+ "\n",
129
+ " CSV_URL = f\"https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol={ticker}&interval={time}&month={2026-year}-{11-month:02d}&outputsize=full&apikey={ALPHA_VANTAGE_API_KEY}\"\n",
130
+ "\n",
131
+ " while True:\n",
132
+ " with requests.Session() as s:\n",
133
+ " download = s.get(CSV_URL)\n",
134
+ " decoded_content = download.content.decode(\"utf-8\")\n",
135
+ " print(\n",
136
+ " f\"ticker: {ticker}, y{year} m{month}; response length: {len(decoded_content)}\"\n",
137
+ " )\n",
138
+ "\n",
139
+ " if len(decoded_content) == 236:\n",
140
+ " # API too many requests\n",
141
+ " sleep(60)\n",
142
+ " elif len(decoded_content) <= 243:\n",
143
+ " # Token doesn't exist or something\n",
144
+ " print(f\"Error getting {ticker}, y{year}, m{month}. We are skipping\")\n",
145
+ " print(decoded_content)\n",
146
+ " return None\n",
147
+ " else:\n",
148
+ " return csv_str_to_df(decoded_content, ticker)\n",
149
+ "\n",
150
+ "\n",
151
+ "def use_alpha_vantage(tickers, out_file, time=\"1min\"):\n",
152
+ " \"\"\"Function to get multiple full tickers data using alpha vantage's time series intraday extended API\"\"\"\n",
153
+ "\n",
154
+ " dfs = []\n",
155
+ " for ticker in tickers:\n",
156
+ " t_dfs = []\n",
157
+ " for year in range(1, 3):\n",
158
+ " for month in range(1, 13):\n",
159
+ " df_temp = alpha_vantage_get_ticker_data(\n",
160
+ " ticker, time=time, year=year, month=month\n",
161
+ " )\n",
162
+ " if df_temp is not None:\n",
163
+ " t_dfs.append(df_temp)\n",
164
+ "\n",
165
+ " if len(t_dfs):\n",
166
+ " dfs.append(pd.concat(t_dfs, axis=0))\n",
167
+ " else:\n",
168
+ " print(f\"Skipped {ticker}.\")\n",
169
+ " df = pd.concat(dfs, axis=1, sort=True)\n",
170
+ " df.index.rename(\"date\", inplace=True)\n",
171
+ "\n",
172
+ " write_df(df, out_file)\n",
173
+ "\n",
174
+ " return df"
175
+ ]
176
+ },
177
+ {
178
+ "cell_type": "code",
179
+ "execution_count": 23,
180
+ "metadata": {},
181
+ "outputs": [],
182
+ "source": [
183
+ "# Alpaca\n",
184
+ "\n",
185
+ "\n",
186
+ "def use_alpaca(tickers, out_file, timeframe=\"1Minute\", start=\"2017-01-01\"):\n",
187
+ " APCA_API_BASE_URL = os.environ.get(\"APCA_API_BASE_URL\")\n",
188
+ " APCA_API_KEY_ID = os.environ.get(\"APCA_API_KEY_ID\")\n",
189
+ " APCA_API_SECRET_KEY = os.environ.get(\"APCA_API_SECRET_KEY\")\n",
190
+ " import alpaca_trade_api as tradeapi\n",
191
+ "\n",
192
+ " alpaca = tradeapi.REST(\n",
193
+ " key_id=APCA_API_KEY_ID,\n",
194
+ " secret_key=APCA_API_SECRET_KEY,\n",
195
+ " base_url=APCA_API_BASE_URL,\n",
196
+ " )\n",
197
+ " account = alpaca.get_account()\n",
198
+ " print(account.status)\n",
199
+ "\n",
200
+ " dfs = []\n",
201
+ " for ticker in tickers:\n",
202
+ " print(\"Getting\", ticker)\n",
203
+ " df = alpaca.get_bars(ticker, timeframe, start).df\n",
204
+ " print(\"Recieved\", ticker)\n",
205
+ " df.index.name = \"date\"\n",
206
+ " df = pd.concat([df], axis=1, keys=[ticker])\n",
207
+ " dfs.append(df)\n",
208
+ " df = pd.concat(dfs, axis=1, sort=True)\n",
209
+ " df.index.rename(\"date\", inplace=True)\n",
210
+ "\n",
211
+ " if out_file is not None:\n",
212
+ " write_df(df, out_file)\n",
213
+ "\n",
214
+ " return df"
215
+ ]
216
+ },
217
+ {
218
+ "cell_type": "code",
219
+ "execution_count": 24,
220
+ "metadata": {},
221
+ "outputs": [],
222
+ "source": [
223
+ "# Polygon\n",
224
+ "\n",
225
+ "\n",
226
+ "def use_polygon(tickers, out_file, multiplier=1, timespan=\"minute\", start=\"2000-01-01\"):\n",
227
+ " POLYGON_API_KEY = os.environ.get(\"POLYGON_API_KEY\")\n",
228
+ " from polygon import RESTClient\n",
229
+ "\n",
230
+ " client = RESTClient(POLYGON_API_KEY)\n",
231
+ " dfs = []\n",
232
+ " end = datetime.datetime.utcnow()\n",
233
+ " start_og = start\n",
234
+ " for ticker in tickers:\n",
235
+ " start = start_og\n",
236
+ " df_agg = None\n",
237
+ " response_len = None\n",
238
+ " i = 0\n",
239
+ " print(\"Getting\", ticker)\n",
240
+ " while response_len != 1:\n",
241
+ " i += 1\n",
242
+ " aggs = client.get_aggs(\n",
243
+ " ticker,\n",
244
+ " multiplier,\n",
245
+ " timespan,\n",
246
+ " start,\n",
247
+ " end,\n",
248
+ " adjusted=True,\n",
249
+ " sort=\"asc\",\n",
250
+ " limit=50000,\n",
251
+ " )\n",
252
+ " df = pd.DataFrame(aggs)\n",
253
+ " df.index = pd.DatetimeIndex(\n",
254
+ " pd.to_datetime(df[\"timestamp\"], unit=\"ms\", utc=True)\n",
255
+ " )\n",
256
+ " df.index.name = \"date\"\n",
257
+ " df = df.filter([\"open\", \"high\", \"low\", \"close\", \"volume\", \"vwap\"], axis=1)\n",
258
+ " response_len = len(df.index)\n",
259
+ " start = df.last_valid_index()\n",
260
+ " print(i, response_len)\n",
261
+ " if df_agg is not None:\n",
262
+ " df_agg.drop(index=df_agg.index[-1], axis=0, inplace=True)\n",
263
+ " df_agg = pd.merge(df_agg.reset_index(), df.reset_index(), how=\"outer\")\n",
264
+ " df_agg = df_agg.set_index(\"date\")\n",
265
+ " else:\n",
266
+ " df_agg = df\n",
267
+ " sleep(1) # Attempt to be nice\n",
268
+ " df_agg = pd.concat([df_agg], axis=1, keys=[ticker])\n",
269
+ " dfs.append(df_agg)\n",
270
+ " print(\"Recieved\", ticker)\n",
271
+ "\n",
272
+ " df = pd.concat(dfs, axis=1, sort=True)\n",
273
+ " df.index.rename(\"date\", inplace=True)\n",
274
+ "\n",
275
+ " if out_file is not None:\n",
276
+ " write_df(df, out_file)\n",
277
+ "\n",
278
+ " return df"
279
+ ]
280
+ },
281
+ {
282
+ "cell_type": "code",
283
+ "execution_count": 6,
284
+ "metadata": {
285
+ "scrolled": true
286
+ },
287
+ "outputs": [
288
+ {
289
+ "name": "stderr",
290
+ "output_type": "stream",
291
+ "text": [
292
+ "/tmp/ipykernel_7521/3255818553.py:11: FutureWarning: YF.download() has changed argument auto_adjust default to True\n",
293
+ " data = yf.download(tickers, start=start, end=end, group_by=\"ticker\")\n",
294
+ "[*********************100%***********************] 2 of 2 completed"
295
+ ]
296
+ },
297
+ {
298
+ "name": "stdout",
299
+ "output_type": "stream",
300
+ "text": [
301
+ "Adding time\n"
302
+ ]
303
+ },
304
+ {
305
+ "name": "stderr",
306
+ "output_type": "stream",
307
+ "text": [
308
+ "\n"
309
+ ]
310
+ }
311
+ ],
312
+ "source": [
313
+ "# Yahoo Finance\n",
314
+ "df = use_yfinance(\n",
315
+ " [\"AAPL\", \"TSLA\"], os.path.join(DATA_RAW, \"aapl_day_full.csv\"), start=\"1970-01-01\"\n",
316
+ ")"
317
+ ]
318
+ },
319
+ {
320
+ "cell_type": "code",
321
+ "execution_count": 25,
322
+ "metadata": {
323
+ "scrolled": true
324
+ },
325
+ "outputs": [
326
+ {
327
+ "name": "stdout",
328
+ "output_type": "stream",
329
+ "text": [
330
+ "ticker: XOM, y1 m1; response length: 2481441\n",
331
+ "{\n",
332
+ " \"Meta Data\": {\n",
333
+ " \"1. Information\": \"Intraday (1min) open, high, low, close prices and volume\",\n",
334
+ " \"2. Symbol\": \"XOM\",\n",
335
+ " \"3. Last Refreshed\": \"2025-10-22 19:59:00\",\n",
336
+ " \"4. Interval\": \"1min\",\n",
337
+ " \"5. Output Size\": \"Full size\",\n",
338
+ " \"6. Time Zone\": \"US/Eastern\"\n",
339
+ " },\n",
340
+ " \"Time Series (1min)\": {\n",
341
+ " \"2025-10-22 19:59:00\": {\n",
342
+ " \"1. open\": \"115.2100\",\n",
343
+ " \"2. high\": \"115.3900\",\n",
344
+ " \"3. low\": \"115.2100\",\n",
345
+ " \"4. close\": \"115.3900\",\n",
346
+ " \"5. volume\": \"105\"\n",
347
+ " },\n",
348
+ " \"2025-10-22 19:58:00\": {\n",
349
+ " \"1. open\": \"115.4800\",\n",
350
+ " \"2. high\": \"115.4800\",\n",
351
+ " \"3. low\": \"115.2000\",\n",
352
+ " \"4. close\": \"115.2000\",\n",
353
+ " \"5. volume\": \"6\"\n",
354
+ " },\n",
355
+ " \"2025-10-22 19:57:00\": {\n",
356
+ " \"1. open\": \"115.4800\",\n",
357
+ " \"2. high\": \"115.4800\",\n",
358
+ " \"3. low\": \"115.3800\",\n",
359
+ " \"4. close\": \"115.3800\",\n",
360
+ " \"5. volume\": \"170\"\n",
361
+ " },\n",
362
+ " \"2025-10-22 19:56:00\n",
363
+ "80589 []\n",
364
+ " \"1. Information\": \"Intraday (1min) open, high, low, close prices and volume\",\n"
365
+ ]
366
+ },
367
+ {
368
+ "ename": "ValueError",
369
+ "evalue": "1 columns passed, passed data had 5 columns",
370
+ "output_type": "error",
371
+ "traceback": [
372
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
373
+ "\u001b[0;31mAssertionError\u001b[0m Traceback (most recent call last)",
374
+ "File \u001b[0;32m~/.local/lib/python3.10/site-packages/pandas/core/internals/construction.py:939\u001b[0m, in \u001b[0;36m_finalize_columns_and_data\u001b[0;34m(content, columns, dtype)\u001b[0m\n\u001b[1;32m 938\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 939\u001b[0m columns \u001b[38;5;241m=\u001b[39m \u001b[43m_validate_or_indexify_columns\u001b[49m\u001b[43m(\u001b[49m\u001b[43mcontents\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcolumns\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 940\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mAssertionError\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m err:\n\u001b[1;32m 941\u001b[0m \u001b[38;5;66;03m# GH#26429 do not raise user-facing AssertionError\u001b[39;00m\n",
375
+ "File \u001b[0;32m~/.local/lib/python3.10/site-packages/pandas/core/internals/construction.py:986\u001b[0m, in \u001b[0;36m_validate_or_indexify_columns\u001b[0;34m(content, columns)\u001b[0m\n\u001b[1;32m 984\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m is_mi_list \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(columns) \u001b[38;5;241m!=\u001b[39m \u001b[38;5;28mlen\u001b[39m(content): \u001b[38;5;66;03m# pragma: no cover\u001b[39;00m\n\u001b[1;32m 985\u001b[0m \u001b[38;5;66;03m# caller's responsibility to check for this...\u001b[39;00m\n\u001b[0;32m--> 986\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mAssertionError\u001b[39;00m(\n\u001b[1;32m 987\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28mlen\u001b[39m(columns)\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m columns passed, passed data had \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 988\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28mlen\u001b[39m(content)\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m columns\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 989\u001b[0m )\n\u001b[1;32m 990\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m is_mi_list:\n\u001b[1;32m 991\u001b[0m \u001b[38;5;66;03m# check if nested list column, length of each sub-list should be equal\u001b[39;00m\n",
376
+ "\u001b[0;31mAssertionError\u001b[0m: 1 columns passed, passed data had 5 columns",
377
+ "\nThe above exception was the direct cause of the following exception:\n",
378
+ "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
379
+ "Cell \u001b[0;32mIn[25], line 2\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;66;03m# Alpha Vantage\u001b[39;00m\n\u001b[0;32m----> 2\u001b[0m df \u001b[38;5;241m=\u001b[39m \u001b[43muse_alpha_vantage\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtickers\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mos\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mpath\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mjoin\u001b[49m\u001b[43m(\u001b[49m\u001b[43mDATA_RAW\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mrealdata.csv\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\u001b[43m)\u001b[49m\n",
380
+ "Cell \u001b[0;32mIn[22], line 64\u001b[0m, in \u001b[0;36muse_alpha_vantage\u001b[0;34m(tickers, out_file, time)\u001b[0m\n\u001b[1;32m 62\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m year \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mrange\u001b[39m(\u001b[38;5;241m1\u001b[39m, \u001b[38;5;241m3\u001b[39m):\n\u001b[1;32m 63\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m month \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mrange\u001b[39m(\u001b[38;5;241m1\u001b[39m, \u001b[38;5;241m13\u001b[39m):\n\u001b[0;32m---> 64\u001b[0m df_temp \u001b[38;5;241m=\u001b[39m \u001b[43malpha_vantage_get_ticker_data\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 65\u001b[0m \u001b[43m \u001b[49m\u001b[43mticker\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtime\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtime\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43myear\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43myear\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmonth\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmonth\u001b[49m\n\u001b[1;32m 66\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 67\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m df_temp \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 68\u001b[0m t_dfs\u001b[38;5;241m.\u001b[39mappend(df_temp)\n",
381
+ "Cell \u001b[0;32mIn[22], line 53\u001b[0m, in \u001b[0;36malpha_vantage_get_ticker_data\u001b[0;34m(ticker, time, year, month)\u001b[0m\n\u001b[1;32m 51\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[1;32m 52\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m---> 53\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mcsv_str_to_df\u001b[49m\u001b[43m(\u001b[49m\u001b[43mdecoded_content\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mticker\u001b[49m\u001b[43m)\u001b[49m\n",
382
+ "Cell \u001b[0;32mIn[22], line 11\u001b[0m, in \u001b[0;36mcsv_str_to_df\u001b[0;34m(decoded_content, ticker)\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[38;5;28mprint\u001b[39m(lines[\u001b[38;5;241m2\u001b[39m])\n\u001b[1;32m 10\u001b[0m \u001b[38;5;66;03m#while(1):pass\u001b[39;00m\n\u001b[0;32m---> 11\u001b[0m data \u001b[38;5;241m=\u001b[39m \u001b[43mpd\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mDataFrame\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 12\u001b[0m \u001b[43m \u001b[49m\u001b[43m[\u001b[49m\u001b[43mrow\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msplit\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m,\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mfor\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mrow\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01min\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mlines\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m]\u001b[49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 13\u001b[0m \u001b[43m \u001b[49m\u001b[43mcolumns\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mdate\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mlines\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m]\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msplit\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m,\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m]\u001b[49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 14\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 17\u001b[0m data \u001b[38;5;241m=\u001b[39m data\u001b[38;5;241m.\u001b[39mreset_index(drop\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m)\u001b[38;5;241m.\u001b[39mset_index(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mdate\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 18\u001b[0m data\u001b[38;5;241m.\u001b[39mindex \u001b[38;5;241m=\u001b[39m pd\u001b[38;5;241m.\u001b[39mto_datetime(data\u001b[38;5;241m.\u001b[39mindex)\n",
383
+ "File \u001b[0;32m~/.local/lib/python3.10/site-packages/pandas/core/frame.py:851\u001b[0m, in \u001b[0;36mDataFrame.__init__\u001b[0;34m(self, data, index, columns, dtype, copy)\u001b[0m\n\u001b[1;32m 849\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m columns \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 850\u001b[0m columns \u001b[38;5;241m=\u001b[39m ensure_index(columns)\n\u001b[0;32m--> 851\u001b[0m arrays, columns, index \u001b[38;5;241m=\u001b[39m \u001b[43mnested_data_to_arrays\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 852\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;66;43;03m# error: Argument 3 to \"nested_data_to_arrays\" has incompatible\u001b[39;49;00m\n\u001b[1;32m 853\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;66;43;03m# type \"Optional[Collection[Any]]\"; expected \"Optional[Index]\"\u001b[39;49;00m\n\u001b[1;32m 854\u001b[0m \u001b[43m \u001b[49m\u001b[43mdata\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 855\u001b[0m \u001b[43m \u001b[49m\u001b[43mcolumns\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 856\u001b[0m \u001b[43m \u001b[49m\u001b[43mindex\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;66;43;03m# type: ignore[arg-type]\u001b[39;49;00m\n\u001b[1;32m 857\u001b[0m \u001b[43m \u001b[49m\u001b[43mdtype\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 858\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 859\u001b[0m mgr \u001b[38;5;241m=\u001b[39m arrays_to_mgr(\n\u001b[1;32m 860\u001b[0m arrays,\n\u001b[1;32m 861\u001b[0m columns,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 864\u001b[0m typ\u001b[38;5;241m=\u001b[39mmanager,\n\u001b[1;32m 865\u001b[0m )\n\u001b[1;32m 866\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n",
384
+ "File \u001b[0;32m~/.local/lib/python3.10/site-packages/pandas/core/internals/construction.py:520\u001b[0m, in \u001b[0;36mnested_data_to_arrays\u001b[0;34m(data, columns, index, dtype)\u001b[0m\n\u001b[1;32m 517\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m is_named_tuple(data[\u001b[38;5;241m0\u001b[39m]) \u001b[38;5;129;01mand\u001b[39;00m columns \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 518\u001b[0m columns \u001b[38;5;241m=\u001b[39m ensure_index(data[\u001b[38;5;241m0\u001b[39m]\u001b[38;5;241m.\u001b[39m_fields)\n\u001b[0;32m--> 520\u001b[0m arrays, columns \u001b[38;5;241m=\u001b[39m \u001b[43mto_arrays\u001b[49m\u001b[43m(\u001b[49m\u001b[43mdata\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcolumns\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdtype\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mdtype\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 521\u001b[0m columns \u001b[38;5;241m=\u001b[39m ensure_index(columns)\n\u001b[1;32m 523\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m index \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n",
385
+ "File \u001b[0;32m~/.local/lib/python3.10/site-packages/pandas/core/internals/construction.py:845\u001b[0m, in \u001b[0;36mto_arrays\u001b[0;34m(data, columns, dtype)\u001b[0m\n\u001b[1;32m 842\u001b[0m data \u001b[38;5;241m=\u001b[39m [\u001b[38;5;28mtuple\u001b[39m(x) \u001b[38;5;28;01mfor\u001b[39;00m x \u001b[38;5;129;01min\u001b[39;00m data]\n\u001b[1;32m 843\u001b[0m arr \u001b[38;5;241m=\u001b[39m _list_to_arrays(data)\n\u001b[0;32m--> 845\u001b[0m content, columns \u001b[38;5;241m=\u001b[39m \u001b[43m_finalize_columns_and_data\u001b[49m\u001b[43m(\u001b[49m\u001b[43marr\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcolumns\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdtype\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 846\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m content, columns\n",
386
+ "File \u001b[0;32m~/.local/lib/python3.10/site-packages/pandas/core/internals/construction.py:942\u001b[0m, in \u001b[0;36m_finalize_columns_and_data\u001b[0;34m(content, columns, dtype)\u001b[0m\n\u001b[1;32m 939\u001b[0m columns \u001b[38;5;241m=\u001b[39m _validate_or_indexify_columns(contents, columns)\n\u001b[1;32m 940\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mAssertionError\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m err:\n\u001b[1;32m 941\u001b[0m \u001b[38;5;66;03m# GH#26429 do not raise user-facing AssertionError\u001b[39;00m\n\u001b[0;32m--> 942\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(err) \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01merr\u001b[39;00m\n\u001b[1;32m 944\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(contents) \u001b[38;5;129;01mand\u001b[39;00m contents[\u001b[38;5;241m0\u001b[39m]\u001b[38;5;241m.\u001b[39mdtype \u001b[38;5;241m==\u001b[39m np\u001b[38;5;241m.\u001b[39mobject_:\n\u001b[1;32m 945\u001b[0m contents \u001b[38;5;241m=\u001b[39m convert_object_array(contents, dtype\u001b[38;5;241m=\u001b[39mdtype)\n",
387
+ "\u001b[0;31mValueError\u001b[0m: 1 columns passed, passed data had 5 columns"
388
+ ]
389
+ }
390
+ ],
391
+ "source": [
392
+ "# Alpha Vantage\n",
393
+ "df = use_alpha_vantage(tickers, os.path.join(DATA_RAW, \"realdata.csv\"))"
394
+ ]
395
+ },
396
+ {
397
+ "cell_type": "code",
398
+ "execution_count": null,
399
+ "metadata": {},
400
+ "outputs": [],
401
+ "source": [
402
+ "# Alpaca\n",
403
+ "df = use_alpaca(\n",
404
+ " tickers + random, os.path.join(DATA_RAW, \"realdata_alp_1h.csv\"), timeframe=\"1Hour\"\n",
405
+ ")"
406
+ ]
407
+ },
408
+ {
409
+ "cell_type": "code",
410
+ "execution_count": null,
411
+ "metadata": {},
412
+ "outputs": [],
413
+ "source": [
414
+ "# Polygon\n",
415
+ "df = use_polygon(\n",
416
+ " materials_equities,\n",
417
+ " os.path.join(DATA_RAW, \"materials_1h.csv\"),\n",
418
+ " multiplier=1,\n",
419
+ " timespan=\"hour\",\n",
420
+ " start=\"2000-01-01\",\n",
421
+ ")"
422
+ ]
423
+ },
424
+ {
425
+ "cell_type": "code",
426
+ "execution_count": null,
427
+ "metadata": {},
428
+ "outputs": [],
429
+ "source": [
430
+ "df.head()"
431
+ ]
432
+ },
433
+ {
434
+ "cell_type": "markdown",
435
+ "metadata": {},
436
+ "source": [
437
+ "## Extras"
438
+ ]
439
+ },
440
+ {
441
+ "cell_type": "markdown",
442
+ "metadata": {},
443
+ "source": [
444
+ "##### Read Data From All-Data CSV (Multi Index Columns)"
445
+ ]
446
+ },
447
+ {
448
+ "cell_type": "code",
449
+ "execution_count": null,
450
+ "metadata": {},
451
+ "outputs": [],
452
+ "source": [
453
+ "df_all = read_data(os.path.join(DATA_RAW, \"realdata.csv\"))\n",
454
+ "# df = read_data(\"tsla_aapl.csv\")\n",
455
+ "print(df_all.head())\n",
456
+ "print(df.head())\n",
457
+ "print(df_all.columns)\n",
458
+ "print(df.columns)"
459
+ ]
460
+ },
461
+ {
462
+ "cell_type": "markdown",
463
+ "metadata": {},
464
+ "source": [
465
+ "##### Concatenate two datasets"
466
+ ]
467
+ },
468
+ {
469
+ "cell_type": "code",
470
+ "execution_count": null,
471
+ "metadata": {},
472
+ "outputs": [],
473
+ "source": [
474
+ "run = False\n",
475
+ "if run and not df.columns.equals(df_all.columns):\n",
476
+ " df_new = write_df(\n",
477
+ " pd.concat([df_all, df], axis=1), os.path.join(DATA_RAW, \"realdata.csv\")\n",
478
+ " )"
479
+ ]
480
+ },
481
+ {
482
+ "cell_type": "markdown",
483
+ "metadata": {},
484
+ "source": [
485
+ "### Remove rows with a lot of NANs\n",
486
+ "This is important when using FX data"
487
+ ]
488
+ },
489
+ {
490
+ "cell_type": "code",
491
+ "execution_count": null,
492
+ "metadata": {},
493
+ "outputs": [],
494
+ "source": [
495
+ "df_f = df.copy()\n",
496
+ "df_f = df_f.dropna(axis=0, thresh=50) #80\n",
497
+ "write_df(df_f, os.path.join(DATA_RAW, \"realdata_pol_1h.csv\"))"
498
+ ]
499
+ },
500
+ {
501
+ "cell_type": "code",
502
+ "execution_count": null,
503
+ "metadata": {},
504
+ "outputs": [],
505
+ "source": [
506
+ "df.tail(80)"
507
+ ]
508
+ }
509
+ ],
510
+ "metadata": {
511
+ "kernelspec": {
512
+ "display_name": "Python 3 (ipykernel)",
513
+ "language": "python",
514
+ "name": "python3"
515
+ },
516
+ "language_info": {
517
+ "codemirror_mode": {
518
+ "name": "ipython",
519
+ "version": 3
520
+ },
521
+ "file_extension": ".py",
522
+ "mimetype": "text/x-python",
523
+ "name": "python",
524
+ "nbconvert_exporter": "python",
525
+ "pygments_lexer": "ipython3",
526
+ "version": "3.10.14"
527
+ },
528
+ "vscode": {
529
+ "interpreter": {
530
+ "hash": "51980e48e269f7c05efac26b22569386591d7f1d45336266d53ed7fc3ab7efc6"
531
+ }
532
+ }
533
+ },
534
+ "nbformat": 4,
535
+ "nbformat_minor": 4
536
+ }
data_collect.py ADDED
@@ -0,0 +1,369 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+ # coding: utf-8
3
+
4
+ # In[1]:
5
+
6
+
7
+ import pandas as pd
8
+ from time import sleep
9
+ import datetime
10
+ import os
11
+ from utils.ipynb_helpers import read_data, write_df, convert_tz, add_tz
12
+ from dotenv import load_dotenv
13
+ import traceback
14
+
15
+ # Create a .env file and add your keys
16
+ load_dotenv()
17
+
18
+ # Location to save raw data from data providers
19
+ DATA_RAW = "data/raw"
20
+
21
+
22
+ equities = ["XOM", "CVX", "COP", "BP", "PBR", "WTI", "TTE", "EQNR", "EOG", "ENB", "SLB"]
23
+ more_equities = []
24
+
25
+ crude_oil = ["CL=F", "BZ=F"] # wti, brent,
26
+ random = ["TSLA", "AAPL"]
27
+
28
+ materials_equities = ["BHP", "LIN", "RIO", "VALE", "APD", "FCX", "SHW", "SCCO", "CTVA", "ECL", "NUE", "NTR"]
29
+
30
+
31
+ # https://en.wikipedia.org/wiki/List_of_countries_by_oil_production
32
+ # https://www.weforum.org/agenda/2016/05/which-economies-are-most-reliant-on-oil/
33
+ # OPEC: Iran, Iraq, Kuwait, Saudi Arabia, Venezuela
34
+ # fx_opec = [_, "C:USDIQD", "C:USDKWD", "C:USDSAR", "C:USDVEF"]
35
+
36
+ # OPEC+: Algeria, Angola, Congo, Equatorial Guinea, Gabon, Libya, Nigeria, United Arab Emirates
37
+ # fx_opec_pp = ["C:USDDZD",_, "C:USDCDF", "C:USDGNF", _, "C:USDLYD", "C:USDNGN", "C:USDAED"]
38
+
39
+ # Large: US, Russia, China, Canada, Norway
40
+ # Other important: Qatar, Kazakhstan
41
+ # fx_other= ["C:USDQAR", "C:USDKZT"]
42
+
43
+ fx = ["C:USDSAR", "C:USDAED"]
44
+
45
+ tickers = equities # + crude_oil
46
+
47
+
48
+ # ##### Get Data From Data Provider
49
+
50
+ # In[2]:
51
+
52
+
53
+ # Y Finance
54
+
55
+ import yfinance as yf
56
+
57
+
58
+ def use_yfinance(
59
+ tickers, out_file, timeframe="day", start="2000-01-01", end="2023-01-01"
60
+ ):
61
+ assert timeframe == "day", "Use day timeframe for day"
62
+
63
+ data = yf.download(tickers, start=start, end=end, group_by="ticker", threads=False)
64
+
65
+ if len(tickers) == 1:
66
+ data = pd.concat([data], axis=1, keys=[tickers[0]])
67
+
68
+ data.index.rename("date", inplace=True)
69
+ data.rename(columns=lambda x: str.lower(x), level=1, inplace=True)
70
+
71
+ if data.index.to_series().dt.tz is None:
72
+ print("Adding time")
73
+ data = add_tz(data, time_zone="UTC")
74
+
75
+ if out_file is not None:
76
+ write_df(data, out_file)
77
+
78
+ return data
79
+
80
+
81
+ # In[22]:
82
+
83
+
84
+ # Alpha Vantage
85
+
86
+
87
+ def csv_str_to_df(decoded_content, ticker):
88
+ """CSV string to df"""
89
+ lines = decoded_content.splitlines()
90
+ print(lines[-20:])
91
+ lines = [ "".join([ lines[i+j][8:-3] if j//6==0 else lines[i+j][12:-1] for j in range(6) ]) for i in range(10, len(lines), 6)]
92
+ print(len(lines))
93
+ print(lines[-20:])
94
+ while(1):pass
95
+ data = pd.DataFrame(
96
+ [row.split(",") for row in lines[1:]],
97
+ columns=["date", "open", "high", "low", "close", "volume"],
98
+ )
99
+
100
+
101
+ data = data.reset_index(drop=True).set_index("date")
102
+ data.index = pd.to_datetime(data.index)
103
+
104
+ # Add timezome -- we assume it is sent in with unlabled eastern time
105
+ if data.index.to_series().dt.tz is None:
106
+ print("CONVERTING TIME")
107
+ data = add_tz(data, time_zone="US/Eastern")
108
+ data = convert_tz(data, time_zone="UTC")
109
+ data = pd.concat([data], axis=1, keys=[ticker])
110
+ return data
111
+
112
+
113
+ def alpha_vantage_get_ticker_data(ticker, time="1min", year=1, month=1):
114
+ """Function to get (ticker, year, month) data using alpha vantage's time series intraday extended API"""
115
+ ALPHA_VANTAGE_API_KEY = "VGRS7MNEHU6K8FAZ"
116
+ import requests
117
+
118
+ CSV_URL = f"https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol={ticker}&interval={time}&month={2026-year}-{11-month:02d}&outputsize=full&apikey={ALPHA_VANTAGE_API_KEY}"
119
+
120
+ while True:
121
+ with requests.Session() as s:
122
+ download = s.get(CSV_URL)
123
+ # save to local file
124
+ decoded_content = download.content.decode("utf-8")
125
+ print(
126
+ f"ticker: {ticker}, y{year} m{month}; response length: {len(decoded_content)}"
127
+ )
128
+
129
+ if len(decoded_content) == 236:
130
+ # API too many requests
131
+ sleep(60)
132
+ elif len(decoded_content) <= 243:
133
+ # Token doesn't exist or something
134
+ print(f"Error getting {ticker}, y{year}, m{month}. We are skipping")
135
+ print(decoded_content)
136
+ return None
137
+ else:
138
+ return csv_str_to_df(decoded_content, ticker)
139
+
140
+
141
+ def use_alpha_vantage(tickers, out_file, time="1min"):
142
+ """Function to get multiple full tickers data using alpha vantage's time series intraday extended API"""
143
+
144
+ dfs = []
145
+ for ticker in tickers:
146
+ t_dfs = []
147
+ for year in range(1, 3):
148
+ for month in range(1, 13):
149
+ df_temp = alpha_vantage_get_ticker_data(
150
+ ticker, time=time, year=year, month=month
151
+ )
152
+ if df_temp is not None:
153
+ t_dfs.append(df_temp)
154
+
155
+ if len(t_dfs):
156
+ dfs.append(pd.concat(t_dfs, axis=0))
157
+ else:
158
+ print(f"Skipped {ticker}.")
159
+ df = pd.concat(dfs, axis=1, sort=True)
160
+ while(1):pass
161
+ df.index.rename("date", inplace=True)
162
+
163
+ write_df(df, out_file)
164
+
165
+ return df
166
+
167
+
168
+ # In[23]:
169
+
170
+
171
+ # Alpaca
172
+
173
+
174
+ def use_alpaca(tickers, out_file, timeframe="1Minute", start="2017-01-01"):
175
+ APCA_API_BASE_URL = os.environ.get("APCA_API_BASE_URL")
176
+ APCA_API_KEY_ID = os.environ.get("APCA_API_KEY_ID")
177
+ APCA_API_SECRET_KEY = os.environ.get("APCA_API_SECRET_KEY")
178
+ import alpaca_trade_api as tradeapi
179
+
180
+ alpaca = tradeapi.REST(
181
+ key_id=APCA_API_KEY_ID,
182
+ secret_key=APCA_API_SECRET_KEY,
183
+ base_url=APCA_API_BASE_URL,
184
+ )
185
+ account = alpaca.get_account()
186
+ print(account.status)
187
+
188
+ dfs = []
189
+ for ticker in tickers:
190
+ print("Getting", ticker)
191
+ df = alpaca.get_bars(ticker, timeframe, start).df
192
+ print("Recieved", ticker)
193
+ df.index.name = "date"
194
+ df = pd.concat([df], axis=1, keys=[ticker])
195
+ dfs.append(df)
196
+ df = pd.concat(dfs, axis=1, sort=True)
197
+ df.index.rename("date", inplace=True)
198
+
199
+ if out_file is not None:
200
+ write_df(df, out_file)
201
+
202
+ return df
203
+
204
+
205
+ # In[24]:
206
+
207
+
208
+ # Polygon
209
+
210
+ def try_until_suc(request_func, *args, **kwargs):
211
+ while True:
212
+ try:
213
+ res = request_func(*args, **kwargs)
214
+ except Exception as e:
215
+ print("Error Message:", e)
216
+ print(f"Traceback Details: {traceback.format_exc()}") # Get full traceback as a string
217
+ print("retry sending request...")
218
+ sleep(5)
219
+ else:
220
+ break
221
+ return res
222
+
223
+
224
+ def use_polygon(tickers, out_file, multiplier=1, timespan="minute", start="2000-01-01"):
225
+ POLYGON_API_KEY = "i0tmf9psII0FV_W7cAHs5PSKSVlqns72"
226
+ from polygon import RESTClient
227
+
228
+ client = RESTClient(POLYGON_API_KEY)
229
+ # aggs = client.get_aggs("AAPL", 1, "day", "2000-01-01", "2001-01-01")
230
+ # print(aggs[0].timestamp)
231
+ # while(1):pass
232
+ dfs = []
233
+ end = datetime.datetime.utcnow()
234
+ start_og = start
235
+ for ticker in tickers:
236
+ start = start_og
237
+ df_agg = None
238
+ response_len = None
239
+ i = 0
240
+ print("Getting", ticker)
241
+ while response_len != 1:
242
+ i += 1
243
+ aggs = try_until_suc(
244
+ client.get_aggs,
245
+ ticker,
246
+ multiplier,
247
+ timespan,
248
+ start,
249
+ end,
250
+ adjusted=True,
251
+ sort="asc",
252
+ limit=50000,
253
+ )
254
+ df = pd.DataFrame(aggs)
255
+ df.index = pd.DatetimeIndex(
256
+ pd.to_datetime(df["timestamp"], unit="ms", utc=True)
257
+ )
258
+ df.index.name = "date"
259
+ df = df.filter(["open", "high", "low", "close", "volume", "vwap"], axis=1)
260
+ response_len = len(df.index)
261
+ start = df.last_valid_index()
262
+ print(i, response_len)
263
+ if df_agg is not None:
264
+ df_agg.drop(index=df_agg.index[-1], axis=0, inplace=True)
265
+ df_agg = pd.merge(df_agg.reset_index(), df.reset_index(), how="outer")
266
+ df_agg = df_agg.set_index("date")
267
+ else:
268
+ df_agg = df
269
+ sleep(12) # Attempt to be nice
270
+ df_agg = pd.concat([df_agg], axis=1, keys=[ticker])
271
+ dfs.append(df_agg)
272
+ print("Recieved", ticker)
273
+
274
+ df = pd.concat(dfs, axis=1, sort=True)
275
+ df.index.rename("date", inplace=True)
276
+
277
+ if out_file is not None:
278
+ write_df(df, out_file)
279
+
280
+ return df
281
+
282
+
283
+ # In[6]:
284
+
285
+
286
+ # Yahoo Finance
287
+ # df = use_yfinance(
288
+ # random, os.path.join(DATA_RAW, "aapl_day_full.csv"), start="1970-01-01",
289
+ # )
290
+
291
+
292
+ # In[25]:
293
+
294
+
295
+ # Alpha Vantage
296
+ # df = use_alpha_vantage(tickers, os.path.join(DATA_RAW, "realdata.csv"), time="1h")
297
+
298
+
299
+ # In[ ]:
300
+
301
+
302
+ # # Alpaca
303
+ # df = use_alpaca(
304
+ # tickers + random, os.path.join(DATA_RAW, "realdata_alp_1h.csv"), timeframe="1Hour"
305
+ # )
306
+
307
+
308
+ # # In[ ]:
309
+
310
+
311
+ # Polygon
312
+ df = use_polygon(
313
+ tickers,
314
+ os.path.join(DATA_RAW, "realdata.csv"),
315
+ multiplier=1,
316
+ timespan="hour",
317
+ start="2000-01-01",
318
+ )
319
+
320
+
321
+ # In[ ]:
322
+
323
+
324
+ df.head()
325
+
326
+
327
+ # ## Extras
328
+
329
+ # ##### Read Data From All-Data CSV (Multi Index Columns)
330
+
331
+ # In[ ]:
332
+
333
+
334
+ df_all = read_data(os.path.join(DATA_RAW, "realdata.csv"))
335
+ # df = read_data("tsla_aapl.csv")
336
+ print(df_all.head())
337
+ print(df.head())
338
+ print(df_all.columns)
339
+ print(df.columns)
340
+
341
+
342
+ # ##### Concatenate two datasets
343
+
344
+ # In[ ]:
345
+
346
+
347
+ run = False
348
+ if run and not df.columns.equals(df_all.columns):
349
+ df_new = write_df(
350
+ pd.concat([df_all, df], axis=1), os.path.join(DATA_RAW, "realdata.csv")
351
+ )
352
+
353
+
354
+ # ### Remove rows with a lot of NANs
355
+ # This is important when using FX data
356
+
357
+ # In[ ]:
358
+
359
+
360
+ df_f = df.copy()
361
+ df_f = df_f.dropna(axis=0, thresh=50) #80
362
+ write_df(df_f, os.path.join(DATA_RAW, "realdata_pol_1h.csv"))
363
+
364
+
365
+ # In[ ]:
366
+
367
+
368
+ df.tail(80)
369
+
data_loader.py ADDED
@@ -0,0 +1,652 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import numpy as np
3
+ import pandas as pd
4
+
5
+ import torch
6
+ from torch.utils.data import Dataset
7
+
8
+ # from sklearn.preprocessing import StandardScaler
9
+
10
+ from utils.tools import StandardScaler, dotdict
11
+ from utils.timefeatures import time_features
12
+
13
+ import warnings
14
+
15
+ warnings.filterwarnings("ignore")
16
+
17
+
18
+ class Dataset_ETT_hour(Dataset):
19
+ def __init__(
20
+ self,
21
+ root_path,
22
+ flag="train",
23
+ size=None,
24
+ features="S",
25
+ data_path="ETTh1.csv",
26
+ target="OT",
27
+ scale=True,
28
+ inverse=False,
29
+ timeenc=0,
30
+ freq="h",
31
+ cols=None,
32
+ ):
33
+ # size [seq_len, label_len, pred_len]
34
+ # info
35
+ if size == None:
36
+ self.seq_len = 24 * 4 * 4
37
+ self.label_len = 24 * 4
38
+ self.pred_len = 24 * 4
39
+ else:
40
+ self.seq_len = size[0]
41
+ self.label_len = size[1]
42
+ self.pred_len = size[2]
43
+ # init
44
+ assert flag in ["train", "test", "val"]
45
+ type_map = {"train": 0, "val": 1, "test": 2}
46
+ self.set_type = type_map[flag]
47
+
48
+ self.features = features
49
+ self.target = target
50
+ self.scale = scale
51
+ self.inverse = inverse
52
+ self.timeenc = timeenc
53
+ self.freq = freq
54
+
55
+ self.root_path = root_path
56
+ self.data_path = data_path
57
+ self.__read_data__()
58
+
59
+ def __read_data__(self):
60
+ self.scaler = StandardScaler()
61
+ df_raw = pd.read_csv(os.path.join(self.root_path, self.data_path))
62
+
63
+ border1s = [
64
+ 0,
65
+ 12 * 30 * 24 - self.seq_len,
66
+ 12 * 30 * 24 + 4 * 30 * 24 - self.seq_len,
67
+ ]
68
+ border2s = [
69
+ 12 * 30 * 24,
70
+ 12 * 30 * 24 + 4 * 30 * 24,
71
+ 12 * 30 * 24 + 8 * 30 * 24,
72
+ ]
73
+ border1 = border1s[self.set_type]
74
+ border2 = border2s[self.set_type]
75
+
76
+ if self.features == "M" or self.features == "MS":
77
+ cols_data = df_raw.columns[1:]
78
+ df_data = df_raw[cols_data]
79
+ elif self.features == "S":
80
+ df_data = df_raw[[self.target]]
81
+
82
+ if self.scale:
83
+ train_data = df_data[border1s[0] : border2s[0]]
84
+ self.scaler.fit(train_data.values, scale_mean=not self.config.no_scale_mean)
85
+ data = self.scaler.transform(df_data.values)
86
+ else:
87
+ data = df_data.values
88
+
89
+ df_stamp = df_raw[["date"]][border1:border2]
90
+ df_stamp["date"] = pd.to_datetime(df_stamp.date)
91
+ self.raw_dates = df_stamp.date.to_numpy(dtype=np.datetime64)
92
+ data_stamp = time_features(df_stamp, timeenc=self.timeenc, freq=self.freq)
93
+
94
+ self.data_x = data[border1:border2]
95
+ if self.inverse:
96
+ self.data_y = df_data.values[border1:border2]
97
+ else:
98
+ self.data_y = data[border1:border2]
99
+ self.data_stamp = data_stamp
100
+
101
+ def __getitem__(self, index):
102
+ s_begin = index
103
+ s_end = s_begin + self.seq_len
104
+ r_begin = s_end - self.label_len
105
+ r_end = r_begin + self.label_len + self.pred_len
106
+
107
+ seq_x = self.data_x[s_begin:s_end]
108
+ if self.inverse:
109
+ seq_y = np.concatenate(
110
+ [
111
+ self.data_x[r_begin : r_begin + self.label_len],
112
+ self.data_y[r_begin + self.label_len : r_end],
113
+ ],
114
+ 0,
115
+ )
116
+ else:
117
+ seq_y = self.data_y[r_begin:r_end]
118
+ seq_x_mark = self.data_stamp[s_begin:s_end]
119
+ seq_y_mark = self.data_stamp[r_begin:r_end]
120
+
121
+ return seq_x, seq_y, seq_x_mark, seq_y_mark, index
122
+
123
+ def index_to_dates(self, index):
124
+ # index is of length batch_size
125
+ s_begin = index
126
+ s_end = s_begin + self.config.seq_len
127
+ r_begin = s_end - self.config.label_len
128
+ r_end = r_begin + self.config.label_len + self.config.pred_len
129
+
130
+ seq_x_raw_dates = self.raw_dates[
131
+ np.add.outer(s_begin, np.arange(self.config.seq_len))
132
+ ]
133
+ seq_y_raw_dates = self.raw_dates[
134
+ np.add.outer(
135
+ r_begin, np.arange(self.config.label_len + self.config.pred_len)
136
+ )
137
+ ]
138
+
139
+ return seq_x_raw_dates, seq_y_raw_dates
140
+
141
+ def __len__(self):
142
+ return len(self.data_x) - self.seq_len - self.pred_len + 1
143
+
144
+ def inverse_transform(self, data):
145
+ return self.scaler.inverse_transform(data)
146
+
147
+
148
+ class Dataset_ETT_minute(Dataset):
149
+ def __init__(
150
+ self,
151
+ root_path,
152
+ flag="train",
153
+ size=None,
154
+ features="S",
155
+ data_path="ETTm1.csv",
156
+ target="OT",
157
+ scale=True,
158
+ inverse=False,
159
+ timeenc=0,
160
+ freq="t",
161
+ cols=None,
162
+ ):
163
+ # size [seq_len, label_len, pred_len]
164
+ # info
165
+ if size == None:
166
+ self.seq_len = 24 * 4 * 4
167
+ self.label_len = 24 * 4
168
+ self.pred_len = 24 * 4
169
+ else:
170
+ self.seq_len = size[0]
171
+ self.label_len = size[1]
172
+ self.pred_len = size[2]
173
+ # init
174
+ assert flag in ["train", "test", "val"]
175
+ type_map = {"train": 0, "val": 1, "test": 2}
176
+ self.set_type = type_map[flag]
177
+
178
+ self.features = features
179
+ self.target = target
180
+ self.scale = scale
181
+ self.inverse = inverse
182
+ self.timeenc = timeenc
183
+ self.freq = freq
184
+
185
+ self.root_path = root_path
186
+ self.data_path = data_path
187
+ self.__read_data__()
188
+
189
+ def __read_data__(self):
190
+ self.scaler = StandardScaler()
191
+ df_raw = pd.read_csv(os.path.join(self.root_path, self.data_path))
192
+
193
+ border1s = [
194
+ 0,
195
+ 12 * 30 * 24 * 4 - self.seq_len,
196
+ 12 * 30 * 24 * 4 + 4 * 30 * 24 * 4 - self.seq_len,
197
+ ]
198
+ border2s = [
199
+ 12 * 30 * 24 * 4,
200
+ 12 * 30 * 24 * 4 + 4 * 30 * 24 * 4,
201
+ 12 * 30 * 24 * 4 + 8 * 30 * 24 * 4,
202
+ ]
203
+ border1 = border1s[self.set_type]
204
+ border2 = border2s[self.set_type]
205
+
206
+ if self.features == "M" or self.features == "MS":
207
+ cols_data = df_raw.columns[1:]
208
+ df_data = df_raw[cols_data]
209
+ elif self.features == "S":
210
+ df_data = df_raw[[self.target]]
211
+
212
+ if self.scale:
213
+ train_data = df_data[border1s[0] : border2s[0]]
214
+ self.scaler.fit(train_data.values, scale_mean=not self.config.no_scale_mean)
215
+ data = self.scaler.transform(df_data.values)
216
+ else:
217
+ data = df_data.values
218
+
219
+ df_stamp = df_raw[["date"]][border1:border2]
220
+ df_stamp["date"] = pd.to_datetime(df_stamp.date)
221
+ self.raw_dates = df_stamp.date.to_numpy(dtype=np.datetime64)
222
+ data_stamp = time_features(df_stamp, timeenc=self.timeenc, freq=self.freq)
223
+
224
+ self.data_x = data[border1:border2]
225
+ if self.inverse:
226
+ self.data_y = df_data.values[border1:border2]
227
+ else:
228
+ self.data_y = data[border1:border2]
229
+ self.data_stamp = data_stamp
230
+
231
+ def __getitem__(self, index):
232
+ s_begin = index
233
+ s_end = s_begin + self.seq_len
234
+ r_begin = s_end - self.label_len
235
+ r_end = r_begin + self.label_len + self.pred_len
236
+
237
+ seq_x = self.data_x[s_begin:s_end]
238
+ if self.inverse:
239
+ seq_y = np.concatenate(
240
+ [
241
+ self.data_x[r_begin : r_begin + self.label_len],
242
+ self.data_y[r_begin + self.label_len : r_end],
243
+ ],
244
+ 0,
245
+ )
246
+ else:
247
+ seq_y = self.data_y[r_begin:r_end]
248
+ seq_x_mark = self.data_stamp[s_begin:s_end]
249
+ seq_y_mark = self.data_stamp[r_begin:r_end]
250
+
251
+ return seq_x, seq_y, seq_x_mark, seq_y_mark, index
252
+
253
+ def index_to_dates(self, index):
254
+ # index is of length batch_size
255
+ s_begin = index
256
+ s_end = s_begin + self.config.seq_len
257
+ r_begin = s_end - self.config.label_len
258
+ r_end = r_begin + self.config.label_len + self.config.pred_len
259
+
260
+ seq_x_raw_dates = self.raw_dates[
261
+ np.add.outer(s_begin, np.arange(self.config.seq_len))
262
+ ]
263
+ seq_y_raw_dates = self.raw_dates[
264
+ np.add.outer(
265
+ r_begin, np.arange(self.config.label_len + self.config.pred_len)
266
+ )
267
+ ]
268
+
269
+ return seq_x_raw_dates, seq_y_raw_dates
270
+
271
+ def __len__(self):
272
+ return len(self.data_x) - self.seq_len - self.pred_len + 1
273
+
274
+ def inverse_transform(self, data):
275
+ return self.scaler.inverse_transform(data)
276
+
277
+
278
+ class Dataset_Custom(Dataset):
279
+ def __init__(self, config, flag="train"):
280
+ # Default values
281
+ defaults = {
282
+ "size": None,
283
+ "features": "S",
284
+ "target": "OT",
285
+ "scale": True,
286
+ "inverse_pred": False,
287
+ "inverse_output": False,
288
+ "cols": None,
289
+ "date_start": None,
290
+ "date_end": None,
291
+ "date_test": None,
292
+ "date_val": None,
293
+ "t_embed": None,
294
+ }
295
+ config = dotdict({**defaults, **config})
296
+
297
+ assert config.seq_len is not None
298
+ assert config.label_len is not None
299
+ assert config.pred_len is not None
300
+ assert flag in ["train", "test", "val"]
301
+ assert config.freq is not None
302
+ assert config.root_path is not None
303
+ assert config.data_path is not None
304
+ assert (
305
+ (config.date_start is None)
306
+ or (config.date_end is None)
307
+ or (config.date_start < config.date_end)
308
+ ), "date_start isn't before date_end"
309
+
310
+ assert (
311
+ (config.date_test is None)
312
+ or (config.date_end is None)
313
+ or (config.date_test < config.date_end)
314
+ ), "date_test isn't before date_end"
315
+ assert (
316
+ (config.date_test is None)
317
+ or (config.date_start is None)
318
+ or (config.date_test > config.date_start)
319
+ ), "date_test isn't after date_start"
320
+
321
+ assert (config.date_val is None) or (
322
+ config.date_test is not None
323
+ ), "date_val is used without date_test"
324
+ assert (
325
+ (config.date_val is None)
326
+ or (config.date_test is None)
327
+ or (config.date_val < config.date_test)
328
+ ), "date_val isn't before date_test"
329
+
330
+ assert (
331
+ (config.date_val is None)
332
+ or (config.date_end is None)
333
+ or (config.date_val < config.date_end)
334
+ ), "date_val isn't before date_end"
335
+ assert (
336
+ (config.date_val is None)
337
+ or (config.date_start is None)
338
+ or (config.date_val > config.date_start)
339
+ ), "date_val isn't after date_start"
340
+
341
+ assert (config.label_len == 0) or (
342
+ config.inverse_output == config.inverse_pred
343
+ ), "If label length is non-zero then inverse_pred and inverse_output should be the same"
344
+
345
+ self.config = config
346
+ self.flag = flag
347
+
348
+ # self.timeenc = 0 if config.t_embed != "timeF" else 1
349
+ if config.t_embed == "timeF":
350
+ self.timeenc = 1
351
+ elif config.t_embed == "time2vec_add" or config.t_embed == "time2vec_app":
352
+ self.timeenc = 2
353
+ else:
354
+ self.timeenc = 0
355
+
356
+ type_map = {"train": 0, "val": 1, "test": 2}
357
+ self.set_type = type_map[flag]
358
+
359
+ self.__read_data__()
360
+
361
+ def __read_data__(self):
362
+ self.scaler = StandardScaler()
363
+ df_raw = pd.read_csv(os.path.join(self.config.root_path, self.config.data_path))
364
+ df_raw = df_raw.astype(
365
+ {c: np.float32 for c in df_raw.select_dtypes(include="float64").columns}
366
+ )
367
+ df_raw["date"] = pd.to_datetime(df_raw["date"])
368
+
369
+ if np.isinf(df_raw[df_raw.columns[1:]].to_numpy()).any():
370
+ raise Exception("There are inf's in the dataset")
371
+ if np.isnan(df_raw[df_raw.columns[1:]].to_numpy()).any():
372
+ raise Exception("There are nan's in the dataset")
373
+ """
374
+ df_raw.columns: ['date', ...(other features), target feature]
375
+ """
376
+ # Filter to datapoints in [date_start, date_end]
377
+ if self.config.date_start is not None:
378
+ df_raw = df_raw.loc[(df_raw["date"] >= self.config.date_start)]
379
+ if self.config.date_end is not None:
380
+ df_raw = df_raw.loc[(df_raw["date"] <= self.config.date_end)]
381
+
382
+ if self.config.cols:
383
+ cols = self.config.cols.copy()
384
+ assert self.config.target in cols, "Target not in cols"
385
+ cols.remove(self.config.target)
386
+ else:
387
+ cols = list(df_raw.columns)
388
+ assert self.config.target in cols, "Target not in data"
389
+ cols.remove(self.config.target)
390
+ assert "date" in cols, "`date` not in data"
391
+ cols.remove("date")
392
+ df_raw = df_raw[["date"] + cols + [self.config.target]]
393
+
394
+ # Define lengths of train, val, and test
395
+ if self.config.date_test is not None and self.config.date_val is not None:
396
+ # num_test and num_val are specified
397
+ num_test = len(df_raw.loc[df_raw["date"] >= self.config.date_test])
398
+ num_vali = len(
399
+ df_raw.loc[
400
+ (df_raw["date"] >= self.config.date_val)
401
+ & (df_raw["date"] < self.config.date_test)
402
+ ]
403
+ )
404
+ num_train = len(df_raw) - num_vali - num_test
405
+ elif self.config.date_test is not None:
406
+ # num_val is half of num_test which is specified
407
+ num_test = len(df_raw.loc[(df_raw["date"] >= self.config.date_test)])
408
+ num_vali = num_test // 2
409
+ num_train = len(df_raw) - num_vali - num_test
410
+ else:
411
+ # Default split
412
+ print("Warning: using default dataset split")
413
+ num_train = int(len(df_raw) * 0.9)
414
+ num_test = int(len(df_raw) * 0.05)
415
+ num_vali = len(df_raw) - num_train - num_test
416
+
417
+ if num_test == 0:
418
+ raise Exception("Dataset loading issue: num_test==0, check date settings")
419
+ elif num_vali == 0:
420
+ raise Exception("Dataset loading issue: num_vali==0, check date settings")
421
+ elif num_train == 0:
422
+ raise Exception("Dataset loading issue: num_train==0, check date settings")
423
+
424
+ border1s = [
425
+ 0,
426
+ num_train - self.config.seq_len,
427
+ len(df_raw) - num_test - self.config.seq_len,
428
+ ]
429
+ border2s = [num_train, num_train + num_vali, len(df_raw)]
430
+ border1 = border1s[self.set_type]
431
+ border2 = border2s[self.set_type]
432
+
433
+ if self.config.features == "M" or self.config.features == "MS":
434
+ cols_data = df_raw.columns[1:]
435
+ df_data = df_raw[cols_data]
436
+ elif self.config.features == "S":
437
+ df_data = df_raw[[self.config.target]]
438
+
439
+ if self.config.scale:
440
+ train_data = df_data[border1s[0] : border2s[0]]
441
+ self.scaler.fit(train_data.values, scale_mean=not self.config.no_scale_mean)
442
+ data = torch.from_numpy(self.scaler.transform(df_data.values))
443
+ else:
444
+ data = torch.from_numpy(df_data.values)
445
+
446
+ df_stamp = df_raw[["date"]][border1:border2]
447
+ df_stamp["date"] = pd.to_datetime(df_stamp.date)
448
+ self.raw_dates = df_stamp.date.to_numpy(dtype=np.datetime64)
449
+ self.data_stamp = np.float32(
450
+ time_features(df_stamp, timeenc=self.timeenc, freq=self.config.freq)
451
+ )
452
+
453
+ self.data_x = data[border1:border2]
454
+ if self.config.inverse_pred:
455
+ self.data_y = torch.from_numpy(df_data.values[border1:border2])
456
+ else:
457
+ self.data_y = data[border1:border2]
458
+
459
+ def __getitem__(self, index):
460
+ s_begin = index
461
+ s_end = s_begin + self.config.seq_len
462
+ r_begin = s_end - self.config.label_len
463
+ r_end = r_begin + self.config.label_len + self.config.pred_len
464
+
465
+ seq_x = self.data_x[s_begin:s_end]
466
+ if self.config.inverse_pred:
467
+ # this is where inverse_pred != inverse output gets wonky if label_len != 0
468
+ # its because the label doesn't get inversed
469
+ seq_y = np.concatenate(
470
+ [
471
+ self.data_x[
472
+ r_begin : r_begin + self.config.label_len
473
+ ], # Use non-scaled data_x
474
+ self.data_y[r_begin + self.config.label_len : r_end],
475
+ ],
476
+ axis=0,
477
+ )
478
+ else:
479
+ seq_y = self.data_y[r_begin:r_end]
480
+ seq_x_mark = self.data_stamp[s_begin:s_end]
481
+ seq_y_mark = self.data_stamp[r_begin:r_end]
482
+
483
+ return seq_x, seq_y, seq_x_mark, seq_y_mark, index
484
+
485
+ def index_to_dates(self, index):
486
+ # index is of length batch_size
487
+ s_begin = index
488
+ s_end = s_begin + self.config.seq_len
489
+ r_begin = s_end - self.config.label_len
490
+ r_end = r_begin + self.config.label_len + self.config.pred_len
491
+
492
+ seq_x_raw_dates = self.raw_dates[
493
+ np.add.outer(s_begin, np.arange(self.config.seq_len))
494
+ ]
495
+ seq_y_raw_dates = self.raw_dates[
496
+ np.add.outer(
497
+ r_begin, np.arange(self.config.label_len + self.config.pred_len)
498
+ )
499
+ ]
500
+ # seq_x_raw_dates = self.raw_dates[np.r_[s_begin,s_end-1].reshape(-1, index.shape[0]).T]# self.raw_dates.iloc[np.r_[s_begin,s_end]]
501
+ # seq_y_raw_dates = self.raw_dates[np.r_[r_begin,r_end-1].reshape(-1, index.shape[0]).T]# self.raw_dates.iloc[np.r_[r_begin,r_end]]
502
+
503
+ return seq_x_raw_dates, seq_y_raw_dates
504
+
505
+ def __len__(self):
506
+ return len(self.data_x) - self.config.seq_len - self.config.pred_len + 1
507
+
508
+ def inverse_transform(self, data):
509
+ return self.scaler.inverse_transform(data)
510
+
511
+
512
+ class Dataset_Pred(Dataset):
513
+ def __init__(self, config, flag="pred"):
514
+ # Default values
515
+ defaults = {
516
+ "size": None,
517
+ "features": "S",
518
+ "target": "OT",
519
+ "scale": True,
520
+ "inverse": False,
521
+ "cols": None,
522
+ "date_start": None,
523
+ "date_end": None,
524
+ "t_embed": None,
525
+ }
526
+ config = dotdict({**defaults, **config})
527
+
528
+ assert config.seq_len is not None
529
+ assert config.label_len is not None
530
+ assert config.pred_len is not None
531
+ assert flag in ["pred"]
532
+ assert config.freq is not None
533
+ assert config.root_path is not None
534
+ assert config.data_path is not None
535
+ assert (
536
+ (config.date_start is None)
537
+ or (config.date_end is None)
538
+ or (config.date_start < config.date_end)
539
+ ), "date_start isn't before date_end"
540
+
541
+ self.config = config
542
+ self.flag = flag
543
+ # self.timeenc = 0 if config.t_embed != "timeF" else 1
544
+ if config.t_embed == "timeF":
545
+ self.timeenc = 1
546
+ elif config.t_embed == "time2vec_add" or config.t_embed == "time2vec_app":
547
+ self.timeenc = 2
548
+ else:
549
+ self.timeenc = 0
550
+
551
+ self.__read_data__()
552
+
553
+ def __read_data__(self):
554
+ self.scaler = StandardScaler()
555
+ df_raw = pd.read_csv(os.path.join(self.config.root_path, self.config.data_path))
556
+ """
557
+ df_raw.columns: ['date', ...(other features), target feature]
558
+ """
559
+
560
+ # Filter to datapoints in [date_start, date_end]
561
+ if self.config.date_start is not None:
562
+ df_raw = df_raw.loc[(df_raw["date"] >= self.config.date_start)]
563
+ if self.config.date_end is not None:
564
+ df_raw = df_raw.loc[(df_raw["date"] <= self.config.date_end)]
565
+
566
+ if self.config.cols:
567
+ cols = self.config.cols.copy()
568
+ cols.remove(self.config.target)
569
+ else:
570
+ cols = list(df_raw.columns)
571
+ cols.remove(self.config.target)
572
+ cols.remove("date")
573
+ df_raw = df_raw[["date"] + cols + [self.config.target]]
574
+
575
+ border1 = len(df_raw) - self.config.seq_len
576
+ border2 = len(df_raw)
577
+
578
+ if self.config.features == "M" or self.config.features == "MS":
579
+ cols_data = df_raw.columns[1:]
580
+ df_data = df_raw[cols_data]
581
+ elif self.config.features == "S":
582
+ df_data = df_raw[[self.config.target]]
583
+
584
+ if self.config.scale:
585
+ self.scaler.fit(df_data.values, scale_mean=not self.config.no_scale_mean)
586
+ data = self.scaler.transform(df_data.values)
587
+ else:
588
+ data = df_data.values
589
+
590
+ tmp_stamp = df_raw[["date"]][border1:border2]
591
+ tmp_stamp["date"] = pd.to_datetime(tmp_stamp.date)
592
+ pred_dates = pd.date_range(
593
+ tmp_stamp.date.values[-1],
594
+ periods=self.config.pred_len + 1,
595
+ freq=self.config.freq,
596
+ )
597
+
598
+ df_stamp = pd.DataFrame(columns=["date"])
599
+ df_stamp.date = pd.to_datetime(
600
+ list(tmp_stamp.date.values) + list(pred_dates[1:]), utc=True
601
+ )
602
+ self.raw_dates = df_stamp.date.to_numpy(dtype=np.datetime64)
603
+ # TODO: What is the deal with .freq[-1:]
604
+ self.data_stamp = np.float32(
605
+ time_features(df_stamp, timeenc=self.timeenc, freq=self.config.freq[-1:])
606
+ )
607
+
608
+ self.data_x = data[border1:border2]
609
+ if self.config.inverse:
610
+ self.data_y = df_data.values[border1:border2]
611
+ else:
612
+ self.data_y = data[border1:border2]
613
+
614
+ def __getitem__(self, index):
615
+ s_begin = index
616
+ s_end = s_begin + self.config.seq_len
617
+ r_begin = s_end - self.config.label_len
618
+ r_end = r_begin + self.config.label_len + self.config.pred_len
619
+
620
+ seq_x = self.data_x[s_begin:s_end]
621
+ if self.config.inverse:
622
+ seq_y = self.data_x[r_begin : r_begin + self.config.label_len]
623
+ else:
624
+ seq_y = self.data_y[r_begin : r_begin + self.config.label_len]
625
+ seq_x_mark = self.data_stamp[s_begin:s_end]
626
+ seq_y_mark = self.data_stamp[r_begin:r_end]
627
+
628
+ return seq_x, seq_y, seq_x_mark, seq_y_mark, index
629
+
630
+ def index_to_dates(self, index):
631
+ # index is of length batch_size
632
+ s_begin = index
633
+ s_end = s_begin + self.config.seq_len
634
+ r_begin = s_end - self.config.label_len
635
+ r_end = r_begin + self.config.label_len + self.config.pred_len
636
+
637
+ seq_x_raw_dates = self.raw_dates[
638
+ np.add.outer(s_begin, np.arange(self.config.seq_len))
639
+ ]
640
+ seq_y_raw_dates = self.raw_dates[
641
+ np.add.outer(
642
+ r_begin, np.arange(self.config.label_len + self.config.pred_len)
643
+ )
644
+ ]
645
+
646
+ return seq_x_raw_dates, seq_y_raw_dates
647
+
648
+ def __len__(self):
649
+ return len(self.data_x) - self.config.seq_len + 1
650
+
651
+ def inverse_transform(self, data):
652
+ return self.scaler.inverse_transform(data)
data_prepare.ipynb ADDED
@@ -0,0 +1,311 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": null,
6
+ "metadata": {},
7
+ "outputs": [],
8
+ "source": [
9
+ "import pandas as pd\n",
10
+ "import os\n",
11
+ "import datetime\n",
12
+ "import pytz\n",
13
+ "import numpy as np\n",
14
+ "from utils.ipynb_helpers import read_data, write_df, convert_tz\n",
15
+ "\n",
16
+ "\n",
17
+ "# Location to open raw data from data providers\n",
18
+ "DATA_RAW = \"data/raw\""
19
+ ]
20
+ },
21
+ {
22
+ "cell_type": "markdown",
23
+ "metadata": {},
24
+ "source": [
25
+ "##### Read Data From All-Data CSV (Multi Index Columns)"
26
+ ]
27
+ },
28
+ {
29
+ "cell_type": "code",
30
+ "execution_count": null,
31
+ "metadata": {},
32
+ "outputs": [],
33
+ "source": [
34
+ "stock=True\n",
35
+ "df_all = read_data(os.path.join(DATA_RAW, \"realdata_pol_1h.csv\"), stock=stock)\n",
36
+ "# df_all = read_data(os.path.join(DATA_RAW, \"other/PEMSBAY.csv\"), stock=stock)\n",
37
+ "\n",
38
+ "df_all = df_all[df_all.columns[:-12]]"
39
+ ]
40
+ },
41
+ {
42
+ "cell_type": "markdown",
43
+ "metadata": {},
44
+ "source": [
45
+ "# Filtering & Processing the Master Dataset"
46
+ ]
47
+ },
48
+ {
49
+ "cell_type": "code",
50
+ "execution_count": null,
51
+ "metadata": {},
52
+ "outputs": [],
53
+ "source": [
54
+ "def percentage_nans(data, sort=True):\n",
55
+ " percent_missing = data.isnull().sum() * 100 / len(data)\n",
56
+ " missing_value_df = pd.DataFrame(\n",
57
+ " {\"percent_missing\": percent_missing} #'column_name': data.columns,\n",
58
+ " )\n",
59
+ " if sort:\n",
60
+ " missing_value_df.sort_values(\"percent_missing\", inplace=True)\n",
61
+ " return missing_value_df\n",
62
+ "\n",
63
+ "\n",
64
+ "def filter_percentage_nans(data, thresh=0.1):\n",
65
+ " thresh *= 100\n",
66
+ " per_nans = percentage_nans(data, sort=False)\n",
67
+ " return data.loc[:, per_nans[per_nans[\"percent_missing\"] < thresh].index]\n",
68
+ "\n",
69
+ "\n",
70
+ "def filter_intra_ticker(data, cols=[\"close\"]):\n",
71
+ " if cols is None:\n",
72
+ " return data\n",
73
+ " return data.iloc[\n",
74
+ " :, data.columns.get_level_values(1).isin(cols)\n",
75
+ " ] # data.xs(\"close\",level=1, axis=1)\n",
76
+ "\n",
77
+ "\n",
78
+ "def no_premarket_after_hours(data):\n",
79
+ " mkt_start = datetime.time(hour=9, minute=30, tzinfo=pytz.timezone(\"US/Eastern\"))\n",
80
+ " mkt_end = datetime.time(hour=15, minute=59, tzinfo=pytz.timezone(\"US/Eastern\"))\n",
81
+ " data = convert_tz(data, time_zone=\"US/Eastern\")\n",
82
+ " data = data.between_time(mkt_start, mkt_end)\n",
83
+ " data = convert_tz(data, time_zone=\"UTC\")\n",
84
+ " return data\n",
85
+ "\n",
86
+ "\n",
87
+ "def add_technical(data):\n",
88
+ " for ticker in data.columns.get_level_values(0).unique():\n",
89
+ " # Assumption: close/open values are positive and a zero value means that datapoint is missing so we say no change\n",
90
+ " data[ticker, \"pctchange\"] = (\n",
91
+ " data[ticker, \"close\"] / data[ticker, \"open\"] - 1\n",
92
+ " ).fillna(0.0).replace([np.inf, -np.inf, -1], 0.0)\n",
93
+ " data[ticker, \"logpctchange\"] = np.log(\n",
94
+ " data[ticker, \"close\"] / data[ticker, \"open\"]\n",
95
+ " ).fillna(0.0).replace([np.inf, -np.inf], 0.0)\n",
96
+ "\n",
97
+ "\n",
98
+ " # data[ticker, \"pctchange-1\"] = data[ticker, \"pctchange\"].shift(1,fill_value=0.0)\n",
99
+ " # data[ticker, \"pctchange-2\"] = data[ticker, \"pctchange\"].shift(2,fill_value=0.0)\n",
100
+ "\n",
101
+ " data[ticker, \"shortsma\"] = (\n",
102
+ " data[ticker, \"close\"].rolling(5).mean().fillna(data[ticker, \"close\"])\n",
103
+ " )\n",
104
+ " # data[ticker,'shortma-1'] = data[ticker,'shortsma'].shift(1)\n",
105
+ " # data[ticker,'shortma-2'] = data[ticker,'shortsma'].shift(2)\n",
106
+ " # print(data.columns.sort_values())\n",
107
+ " data = data.reindex(sorted(data.columns), axis=1)\n",
108
+ " # data.reindex(columns=data.columns.sort_values().get_level_values(0).unique(), level=0)\n",
109
+ " return data\n",
110
+ "\n",
111
+ "if stock:\n",
112
+ " # Filter df_all to normal hours\n",
113
+ " df_all = no_premarket_after_hours(df_all)\n",
114
+ "\n",
115
+ "percentage_nans(df_all).tail(40)"
116
+ ]
117
+ },
118
+ {
119
+ "cell_type": "code",
120
+ "execution_count": null,
121
+ "metadata": {},
122
+ "outputs": [],
123
+ "source": [
124
+ "df = filter_percentage_nans(df_all, 0.08) #0.40\n",
125
+ "print(df.columns.get_level_values(0).unique())\n",
126
+ "df.columns"
127
+ ]
128
+ },
129
+ {
130
+ "cell_type": "code",
131
+ "execution_count": null,
132
+ "metadata": {},
133
+ "outputs": [],
134
+ "source": [
135
+ "# Add & filter columns\n",
136
+ "df = add_technical(df)\n",
137
+ "\n",
138
+ "# None\n",
139
+ "# [\"close\"]\n",
140
+ "# [\"pctchange\"]\n",
141
+ "# [\"open\", \"high\", \"low\", \"close\", \"volume\", 'pctchange', \"shortsma\"]\n",
142
+ "df = filter_intra_ticker(\n",
143
+ " df, cols=[\"open\", \"close\", \"pctchange\", \"logpctchange\", \"shortsma\"]\n",
144
+ ")\n",
145
+ "\n",
146
+ "df.head(20)"
147
+ ]
148
+ },
149
+ {
150
+ "cell_type": "code",
151
+ "execution_count": null,
152
+ "metadata": {},
153
+ "outputs": [],
154
+ "source": [
155
+ "import matplotlib.pyplot as plt\n",
156
+ "df_t = df[\"WTI\", \"pctchange\"]\n",
157
+ "start_date = \"2022-10-01\"\n",
158
+ "end_date = \"2022-11-01\"\n",
159
+ "f1 = df_t[df.index > start_date]\n",
160
+ "f2 = f1[f1.index < end_date]\n",
161
+ "print(f2)\n",
162
+ "# f = plt.figure()\n",
163
+ "# f.set_figwidth(60)\n",
164
+ "# f.set_figheight(20)\n",
165
+ "plt.figure(figsize=(24,4))\n",
166
+ "plt.plot(np.arange(f2.index.to_numpy().shape[0]), 3.3* np.cumprod(f2.to_numpy()+1))"
167
+ ]
168
+ },
169
+ {
170
+ "cell_type": "markdown",
171
+ "metadata": {},
172
+ "source": [
173
+ "##### Fill NaNs"
174
+ ]
175
+ },
176
+ {
177
+ "cell_type": "code",
178
+ "execution_count": null,
179
+ "metadata": {},
180
+ "outputs": [],
181
+ "source": [
182
+ "def ffill_nans(data):\n",
183
+ " data = data.fillna(method=\"ffill\")\n",
184
+ " data = data.dropna()\n",
185
+ " return data\n",
186
+ "\n",
187
+ "\n",
188
+ "def del_nans_ffill(data, thresh):\n",
189
+ " data = data.dropna(thresh=thresh)\n",
190
+ " data = ffill_nans(data)\n",
191
+ " return data"
192
+ ]
193
+ },
194
+ {
195
+ "cell_type": "code",
196
+ "execution_count": null,
197
+ "metadata": {},
198
+ "outputs": [],
199
+ "source": [
200
+ "df = ffill_nans(df)\n",
201
+ "df.head()"
202
+ ]
203
+ },
204
+ {
205
+ "cell_type": "markdown",
206
+ "metadata": {},
207
+ "source": [
208
+ "#### Clip Outliers"
209
+ ]
210
+ },
211
+ {
212
+ "cell_type": "code",
213
+ "execution_count": null,
214
+ "metadata": {},
215
+ "outputs": [],
216
+ "source": [
217
+ "def clip_outliers(data, p=0.005):\n",
218
+ " lower = data.quantile(p)\n",
219
+ " upper = data.quantile(1 - p)\n",
220
+ "\n",
221
+ " return data.clip(lower=lower, upper=upper, axis=1)"
222
+ ]
223
+ },
224
+ {
225
+ "cell_type": "code",
226
+ "execution_count": null,
227
+ "metadata": {},
228
+ "outputs": [],
229
+ "source": [
230
+ "if stock:\n",
231
+ " df = clip_outliers(df)\n",
232
+ "\n",
233
+ "df.head()"
234
+ ]
235
+ },
236
+ {
237
+ "cell_type": "markdown",
238
+ "metadata": {},
239
+ "source": [
240
+ "##### Save Data"
241
+ ]
242
+ },
243
+ {
244
+ "cell_type": "code",
245
+ "execution_count": null,
246
+ "metadata": {},
247
+ "outputs": [],
248
+ "source": [
249
+ "# Sometimes it errors bc the path doesn't exist but just run it again\n",
250
+ "write_df(df, \"data/stock/material_1h.csv\")\n",
251
+ "# write_df(df, \"data/other/PEMSBAY.csv\")"
252
+ ]
253
+ },
254
+ {
255
+ "cell_type": "markdown",
256
+ "metadata": {},
257
+ "source": [
258
+ "## Extras"
259
+ ]
260
+ },
261
+ {
262
+ "cell_type": "markdown",
263
+ "metadata": {},
264
+ "source": [
265
+ "##### Read data and convert to percent delta"
266
+ ]
267
+ },
268
+ {
269
+ "cell_type": "code",
270
+ "execution_count": null,
271
+ "metadata": {},
272
+ "outputs": [],
273
+ "source": [
274
+ "# df_new = read_data(\"data/stock/close_1h.csv\")\n",
275
+ "\n",
276
+ "# print(\"Before:\\n\", df_new.head())\n",
277
+ "# df_new = df_new.pct_change()\n",
278
+ "# df_new.iloc[0] = 0\n",
279
+ "\n",
280
+ "# print(\"After:\\n\",df_new.head())\n",
281
+ "# write_df(df_new, \"data/stock/close_1h_pct_change.csv\")"
282
+ ]
283
+ }
284
+ ],
285
+ "metadata": {
286
+ "kernelspec": {
287
+ "display_name": ".venv",
288
+ "language": "python",
289
+ "name": "python3"
290
+ },
291
+ "language_info": {
292
+ "codemirror_mode": {
293
+ "name": "ipython",
294
+ "version": 3
295
+ },
296
+ "file_extension": ".py",
297
+ "mimetype": "text/x-python",
298
+ "name": "python",
299
+ "nbconvert_exporter": "python",
300
+ "pygments_lexer": "ipython3",
301
+ "version": "3.10.6"
302
+ },
303
+ "vscode": {
304
+ "interpreter": {
305
+ "hash": "51980e48e269f7c05efac26b22569386591d7f1d45336266d53ed7fc3ab7efc6"
306
+ }
307
+ }
308
+ },
309
+ "nbformat": 4,
310
+ "nbformat_minor": 2
311
+ }
data_prepare.py ADDED
@@ -0,0 +1,214 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+ # coding: utf-8
3
+
4
+ # In[ ]:
5
+
6
+
7
+ import pandas as pd
8
+ import os
9
+ import datetime
10
+ import pytz
11
+ import numpy as np
12
+ from utils.ipynb_helpers import read_data, write_df, convert_tz
13
+
14
+
15
+ # Location to open raw data from data providers
16
+ DATA_RAW = "data/raw"
17
+
18
+
19
+ # ##### Read Data From All-Data CSV (Multi Index Columns)
20
+
21
+ # In[ ]:
22
+
23
+
24
+ stock=True
25
+ df_all = read_data(os.path.join(DATA_RAW, "realdata_pol_1h.csv"), stock=stock)
26
+ # df_all = read_data(os.path.join(DATA_RAW, "other/PEMSBAY.csv"), stock=stock)
27
+
28
+ df_all = df_all[df_all.columns[:-12]]
29
+
30
+
31
+ # # Filtering & Processing the Master Dataset
32
+
33
+ # In[ ]:
34
+
35
+
36
+ def percentage_nans(data, sort=True):
37
+ percent_missing = data.isnull().sum() * 100 / len(data)
38
+ missing_value_df = pd.DataFrame(
39
+ {"percent_missing": percent_missing} #'column_name': data.columns,
40
+ )
41
+ if sort:
42
+ missing_value_df.sort_values("percent_missing", inplace=True)
43
+ return missing_value_df
44
+
45
+
46
+ def filter_percentage_nans(data, thresh=0.1):
47
+ thresh *= 100
48
+ per_nans = percentage_nans(data, sort=False)
49
+ return data.loc[:, per_nans[per_nans["percent_missing"] < thresh].index]
50
+
51
+
52
+ def filter_intra_ticker(data, cols=["close"]):
53
+ if cols is None:
54
+ return data
55
+ return data.iloc[
56
+ :, data.columns.get_level_values(1).isin(cols)
57
+ ] # data.xs("close",level=1, axis=1)
58
+
59
+
60
+ def no_premarket_after_hours(data):
61
+ mkt_start = datetime.time(hour=9, minute=30, tzinfo=pytz.timezone("US/Eastern"))
62
+ mkt_end = datetime.time(hour=15, minute=59, tzinfo=pytz.timezone("US/Eastern"))
63
+ data = convert_tz(data, time_zone="US/Eastern")
64
+ data = data.between_time(mkt_start, mkt_end)
65
+ data = convert_tz(data, time_zone="UTC")
66
+ return data
67
+
68
+
69
+ def add_technical(data):
70
+ for ticker in data.columns.get_level_values(0).unique():
71
+ # Assumption: close/open values are positive and a zero value means that datapoint is missing so we say no change
72
+ data[ticker, "pctchange"] = (
73
+ data[ticker, "close"] / data[ticker, "open"] - 1
74
+ ).fillna(0.0).replace([np.inf, -np.inf, -1], 0.0)
75
+ data[ticker, "logpctchange"] = np.log(
76
+ data[ticker, "close"] / data[ticker, "open"]
77
+ ).fillna(0.0).replace([np.inf, -np.inf], 0.0)
78
+
79
+
80
+ # data[ticker, "pctchange-1"] = data[ticker, "pctchange"].shift(1,fill_value=0.0)
81
+ # data[ticker, "pctchange-2"] = data[ticker, "pctchange"].shift(2,fill_value=0.0)
82
+
83
+ data[ticker, "shortsma"] = (
84
+ data[ticker, "close"].rolling(5).mean().fillna(data[ticker, "close"])
85
+ )
86
+ # data[ticker,'shortma-1'] = data[ticker,'shortsma'].shift(1)
87
+ # data[ticker,'shortma-2'] = data[ticker,'shortsma'].shift(2)
88
+ # print(data.columns.sort_values())
89
+ data = data.reindex(sorted(data.columns), axis=1)
90
+ # data.reindex(columns=data.columns.sort_values().get_level_values(0).unique(), level=0)
91
+ return data
92
+
93
+ if stock:
94
+ # Filter df_all to normal hours
95
+ df_all = no_premarket_after_hours(df_all)
96
+
97
+ percentage_nans(df_all).tail(40)
98
+
99
+
100
+ # In[ ]:
101
+
102
+
103
+ df = filter_percentage_nans(df_all, 0.08) #0.40
104
+ print(df.columns.get_level_values(0).unique())
105
+ df.columns
106
+
107
+
108
+ # In[ ]:
109
+
110
+
111
+ # Add & filter columns
112
+ df = add_technical(df)
113
+
114
+ # None
115
+ # ["close"]
116
+ # ["pctchange"]
117
+ # ["open", "high", "low", "close", "volume", 'pctchange', "shortsma"]
118
+ df = filter_intra_ticker(
119
+ df, cols=["open", "close", "pctchange", "logpctchange", "shortsma"]
120
+ )
121
+
122
+ df.head(20)
123
+
124
+
125
+ # In[ ]:
126
+
127
+
128
+ import matplotlib.pyplot as plt
129
+ df_t = df["WTI", "pctchange"]
130
+ start_date = "2022-10-01"
131
+ end_date = "2022-11-01"
132
+ f1 = df_t[df.index > start_date]
133
+ f2 = f1[f1.index < end_date]
134
+ print(f2)
135
+ # f = plt.figure()
136
+ # f.set_figwidth(60)
137
+ # f.set_figheight(20)
138
+ plt.figure(figsize=(24,4))
139
+ plt.plot(np.arange(f2.index.to_numpy().shape[0]), 3.3* np.cumprod(f2.to_numpy()+1))
140
+
141
+
142
+ # ##### Fill NaNs
143
+
144
+ # In[ ]:
145
+
146
+
147
+ def ffill_nans(data):
148
+ data = data.ffill()
149
+ # data = data.fillna(method="ffill")
150
+ data = data.dropna()
151
+ return data
152
+
153
+
154
+ def del_nans_ffill(data, thresh):
155
+ data = data.dropna(thresh=thresh)
156
+ data = ffill_nans(data)
157
+ return data
158
+
159
+
160
+ # In[ ]:
161
+
162
+
163
+ df = ffill_nans(df)
164
+ df.head()
165
+
166
+
167
+ # #### Clip Outliers
168
+
169
+ # In[ ]:
170
+
171
+
172
+ def clip_outliers(data, p=0.005):
173
+ lower = data.quantile(p)
174
+ upper = data.quantile(1 - p)
175
+
176
+ return data.clip(lower=lower, upper=upper, axis=1)
177
+
178
+
179
+ # In[ ]:
180
+
181
+
182
+ if stock:
183
+ df = clip_outliers(df)
184
+
185
+ df.head()
186
+
187
+
188
+ # ##### Save Data
189
+
190
+ # In[ ]:
191
+
192
+
193
+ # Sometimes it errors bc the path doesn't exist but just run it again
194
+ write_df(df, "data/stock/material_1h.csv")
195
+ # write_df(df, "data/other/PEMSBAY.csv")
196
+
197
+
198
+ # ## Extras
199
+
200
+ # ##### Read data and convert to percent delta
201
+
202
+ # In[ ]:
203
+
204
+
205
+ # df_new = read_data("data/stock/close_1h.csv")
206
+
207
+ # print("Before:\n", df_new.head())
208
+ # df_new = df_new.pct_change()
209
+ # df_new.iloc[0] = 0
210
+
211
+ # print("After:\n",df_new.head())
212
+ # write_df(df_new, "data/stock/close_1h_pct_change.csv")
213
+ plt.show()
214
+
data_provider/__init__.py ADDED
File without changes
data_provider/data_factory.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from data_provider.data_loader import (
2
+ Dataset_ETT_hour,
3
+ Dataset_ETT_minute,
4
+ Dataset_Custom,
5
+ Dataset_Pred,
6
+ )
7
+ from torch.utils.data import DataLoader
8
+
9
+ data_dict = {
10
+ "ETTh1": Dataset_ETT_hour,
11
+ "ETTh2": Dataset_ETT_hour,
12
+ "ETTm1": Dataset_ETT_minute,
13
+ "ETTm2": Dataset_ETT_minute,
14
+ "WTH": Dataset_Custom,
15
+ "ECL": Dataset_Custom,
16
+ "Solar": Dataset_Custom,
17
+ "custom": Dataset_Custom,
18
+ }
19
+
20
+
21
+ def data_provider(args, flag):
22
+ Data = data_dict[args.data]
23
+
24
+ assert (
25
+ not args.inverse
26
+ ) or args.scale, "Can't enable inverse without enabling scale"
27
+
28
+ if flag == "test":
29
+ shuffle_flag = False
30
+ drop_last = True
31
+ batch_size = args.batch_size
32
+ # freq = args.freq
33
+ elif flag == "pred":
34
+ shuffle_flag = False
35
+ drop_last = False
36
+ batch_size = 1
37
+ # freq = args.detail_freq
38
+ Data = Dataset_Pred
39
+ else:
40
+ shuffle_flag = True
41
+ drop_last = True
42
+ batch_size = args.batch_size
43
+ # freq = args.freq
44
+
45
+ data_set = Data(args, flag=flag)
46
+
47
+ print(flag, len(data_set))
48
+ data_loader = DataLoader(
49
+ data_set,
50
+ batch_size=batch_size,
51
+ shuffle=shuffle_flag,
52
+ num_workers=args.num_workers,
53
+ drop_last=drop_last,
54
+ )
55
+ return data_set, data_loader
data_provider/data_loader.py ADDED
@@ -0,0 +1,652 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import numpy as np
3
+ import pandas as pd
4
+
5
+ import torch
6
+ from torch.utils.data import Dataset
7
+
8
+ # from sklearn.preprocessing import StandardScaler
9
+
10
+ from utils.tools import StandardScaler, dotdict
11
+ from utils.timefeatures import time_features
12
+
13
+ import warnings
14
+
15
+ warnings.filterwarnings("ignore")
16
+
17
+
18
+ class Dataset_ETT_hour(Dataset):
19
+ def __init__(
20
+ self,
21
+ root_path,
22
+ flag="train",
23
+ size=None,
24
+ features="S",
25
+ data_path="ETTh1.csv",
26
+ target="OT",
27
+ scale=True,
28
+ inverse=False,
29
+ timeenc=0,
30
+ freq="h",
31
+ cols=None,
32
+ ):
33
+ # size [seq_len, label_len, pred_len]
34
+ # info
35
+ if size == None:
36
+ self.seq_len = 24 * 4 * 4
37
+ self.label_len = 24 * 4
38
+ self.pred_len = 24 * 4
39
+ else:
40
+ self.seq_len = size[0]
41
+ self.label_len = size[1]
42
+ self.pred_len = size[2]
43
+ # init
44
+ assert flag in ["train", "test", "val"]
45
+ type_map = {"train": 0, "val": 1, "test": 2}
46
+ self.set_type = type_map[flag]
47
+
48
+ self.features = features
49
+ self.target = target
50
+ self.scale = scale
51
+ self.inverse = inverse
52
+ self.timeenc = timeenc
53
+ self.freq = freq
54
+
55
+ self.root_path = root_path
56
+ self.data_path = data_path
57
+ self.__read_data__()
58
+
59
+ def __read_data__(self):
60
+ self.scaler = StandardScaler()
61
+ df_raw = pd.read_csv(os.path.join(self.root_path, self.data_path))
62
+
63
+ border1s = [
64
+ 0,
65
+ 12 * 30 * 24 - self.seq_len,
66
+ 12 * 30 * 24 + 4 * 30 * 24 - self.seq_len,
67
+ ]
68
+ border2s = [
69
+ 12 * 30 * 24,
70
+ 12 * 30 * 24 + 4 * 30 * 24,
71
+ 12 * 30 * 24 + 8 * 30 * 24,
72
+ ]
73
+ border1 = border1s[self.set_type]
74
+ border2 = border2s[self.set_type]
75
+
76
+ if self.features == "M" or self.features == "MS":
77
+ cols_data = df_raw.columns[1:]
78
+ df_data = df_raw[cols_data]
79
+ elif self.features == "S":
80
+ df_data = df_raw[[self.target]]
81
+
82
+ if self.scale:
83
+ train_data = df_data[border1s[0] : border2s[0]]
84
+ self.scaler.fit(train_data.values, scale_mean=not self.config.no_scale_mean)
85
+ data = self.scaler.transform(df_data.values)
86
+ else:
87
+ data = df_data.values
88
+
89
+ df_stamp = df_raw[["date"]][border1:border2]
90
+ df_stamp["date"] = pd.to_datetime(df_stamp.date)
91
+ self.raw_dates = df_stamp.date.to_numpy(dtype=np.datetime64)
92
+ data_stamp = time_features(df_stamp, timeenc=self.timeenc, freq=self.freq)
93
+
94
+ self.data_x = data[border1:border2]
95
+ if self.inverse:
96
+ self.data_y = df_data.values[border1:border2]
97
+ else:
98
+ self.data_y = data[border1:border2]
99
+ self.data_stamp = data_stamp
100
+
101
+ def __getitem__(self, index):
102
+ s_begin = index
103
+ s_end = s_begin + self.seq_len
104
+ r_begin = s_end - self.label_len
105
+ r_end = r_begin + self.label_len + self.pred_len
106
+
107
+ seq_x = self.data_x[s_begin:s_end]
108
+ if self.inverse:
109
+ seq_y = np.concatenate(
110
+ [
111
+ self.data_x[r_begin : r_begin + self.label_len],
112
+ self.data_y[r_begin + self.label_len : r_end],
113
+ ],
114
+ 0,
115
+ )
116
+ else:
117
+ seq_y = self.data_y[r_begin:r_end]
118
+ seq_x_mark = self.data_stamp[s_begin:s_end]
119
+ seq_y_mark = self.data_stamp[r_begin:r_end]
120
+
121
+ return seq_x, seq_y, seq_x_mark, seq_y_mark, index
122
+
123
+ def index_to_dates(self, index):
124
+ # index is of length batch_size
125
+ s_begin = index
126
+ s_end = s_begin + self.config.seq_len
127
+ r_begin = s_end - self.config.label_len
128
+ r_end = r_begin + self.config.label_len + self.config.pred_len
129
+
130
+ seq_x_raw_dates = self.raw_dates[
131
+ np.add.outer(s_begin, np.arange(self.config.seq_len))
132
+ ]
133
+ seq_y_raw_dates = self.raw_dates[
134
+ np.add.outer(
135
+ r_begin, np.arange(self.config.label_len + self.config.pred_len)
136
+ )
137
+ ]
138
+
139
+ return seq_x_raw_dates, seq_y_raw_dates
140
+
141
+ def __len__(self):
142
+ return len(self.data_x) - self.seq_len - self.pred_len + 1
143
+
144
+ def inverse_transform(self, data):
145
+ return self.scaler.inverse_transform(data)
146
+
147
+
148
+ class Dataset_ETT_minute(Dataset):
149
+ def __init__(
150
+ self,
151
+ root_path,
152
+ flag="train",
153
+ size=None,
154
+ features="S",
155
+ data_path="ETTm1.csv",
156
+ target="OT",
157
+ scale=True,
158
+ inverse=False,
159
+ timeenc=0,
160
+ freq="t",
161
+ cols=None,
162
+ ):
163
+ # size [seq_len, label_len, pred_len]
164
+ # info
165
+ if size == None:
166
+ self.seq_len = 24 * 4 * 4
167
+ self.label_len = 24 * 4
168
+ self.pred_len = 24 * 4
169
+ else:
170
+ self.seq_len = size[0]
171
+ self.label_len = size[1]
172
+ self.pred_len = size[2]
173
+ # init
174
+ assert flag in ["train", "test", "val"]
175
+ type_map = {"train": 0, "val": 1, "test": 2}
176
+ self.set_type = type_map[flag]
177
+
178
+ self.features = features
179
+ self.target = target
180
+ self.scale = scale
181
+ self.inverse = inverse
182
+ self.timeenc = timeenc
183
+ self.freq = freq
184
+
185
+ self.root_path = root_path
186
+ self.data_path = data_path
187
+ self.__read_data__()
188
+
189
+ def __read_data__(self):
190
+ self.scaler = StandardScaler()
191
+ df_raw = pd.read_csv(os.path.join(self.root_path, self.data_path))
192
+
193
+ border1s = [
194
+ 0,
195
+ 12 * 30 * 24 * 4 - self.seq_len,
196
+ 12 * 30 * 24 * 4 + 4 * 30 * 24 * 4 - self.seq_len,
197
+ ]
198
+ border2s = [
199
+ 12 * 30 * 24 * 4,
200
+ 12 * 30 * 24 * 4 + 4 * 30 * 24 * 4,
201
+ 12 * 30 * 24 * 4 + 8 * 30 * 24 * 4,
202
+ ]
203
+ border1 = border1s[self.set_type]
204
+ border2 = border2s[self.set_type]
205
+
206
+ if self.features == "M" or self.features == "MS":
207
+ cols_data = df_raw.columns[1:]
208
+ df_data = df_raw[cols_data]
209
+ elif self.features == "S":
210
+ df_data = df_raw[[self.target]]
211
+
212
+ if self.scale:
213
+ train_data = df_data[border1s[0] : border2s[0]]
214
+ self.scaler.fit(train_data.values, scale_mean=not self.config.no_scale_mean)
215
+ data = self.scaler.transform(df_data.values)
216
+ else:
217
+ data = df_data.values
218
+
219
+ df_stamp = df_raw[["date"]][border1:border2]
220
+ df_stamp["date"] = pd.to_datetime(df_stamp.date)
221
+ self.raw_dates = df_stamp.date.to_numpy(dtype=np.datetime64)
222
+ data_stamp = time_features(df_stamp, timeenc=self.timeenc, freq=self.freq)
223
+
224
+ self.data_x = data[border1:border2]
225
+ if self.inverse:
226
+ self.data_y = df_data.values[border1:border2]
227
+ else:
228
+ self.data_y = data[border1:border2]
229
+ self.data_stamp = data_stamp
230
+
231
+ def __getitem__(self, index):
232
+ s_begin = index
233
+ s_end = s_begin + self.seq_len
234
+ r_begin = s_end - self.label_len
235
+ r_end = r_begin + self.label_len + self.pred_len
236
+
237
+ seq_x = self.data_x[s_begin:s_end]
238
+ if self.inverse:
239
+ seq_y = np.concatenate(
240
+ [
241
+ self.data_x[r_begin : r_begin + self.label_len],
242
+ self.data_y[r_begin + self.label_len : r_end],
243
+ ],
244
+ 0,
245
+ )
246
+ else:
247
+ seq_y = self.data_y[r_begin:r_end]
248
+ seq_x_mark = self.data_stamp[s_begin:s_end]
249
+ seq_y_mark = self.data_stamp[r_begin:r_end]
250
+
251
+ return seq_x, seq_y, seq_x_mark, seq_y_mark, index
252
+
253
+ def index_to_dates(self, index):
254
+ # index is of length batch_size
255
+ s_begin = index
256
+ s_end = s_begin + self.config.seq_len
257
+ r_begin = s_end - self.config.label_len
258
+ r_end = r_begin + self.config.label_len + self.config.pred_len
259
+
260
+ seq_x_raw_dates = self.raw_dates[
261
+ np.add.outer(s_begin, np.arange(self.config.seq_len))
262
+ ]
263
+ seq_y_raw_dates = self.raw_dates[
264
+ np.add.outer(
265
+ r_begin, np.arange(self.config.label_len + self.config.pred_len)
266
+ )
267
+ ]
268
+
269
+ return seq_x_raw_dates, seq_y_raw_dates
270
+
271
+ def __len__(self):
272
+ return len(self.data_x) - self.seq_len - self.pred_len + 1
273
+
274
+ def inverse_transform(self, data):
275
+ return self.scaler.inverse_transform(data)
276
+
277
+
278
+ class Dataset_Custom(Dataset):
279
+ def __init__(self, config, flag="train"):
280
+ # Default values
281
+ defaults = {
282
+ "size": None,
283
+ "features": "S",
284
+ "target": "OT",
285
+ "scale": True,
286
+ "inverse_pred": False,
287
+ "inverse_output": False,
288
+ "cols": None,
289
+ "date_start": None,
290
+ "date_end": None,
291
+ "date_test": None,
292
+ "date_val": None,
293
+ "t_embed": None,
294
+ }
295
+ config = dotdict({**defaults, **config})
296
+
297
+ assert config.seq_len is not None
298
+ assert config.label_len is not None
299
+ assert config.pred_len is not None
300
+ assert flag in ["train", "test", "val"]
301
+ assert config.freq is not None
302
+ assert config.root_path is not None
303
+ assert config.data_path is not None
304
+ assert (
305
+ (config.date_start is None)
306
+ or (config.date_end is None)
307
+ or (config.date_start < config.date_end)
308
+ ), "date_start isn't before date_end"
309
+
310
+ assert (
311
+ (config.date_test is None)
312
+ or (config.date_end is None)
313
+ or (config.date_test < config.date_end)
314
+ ), "date_test isn't before date_end"
315
+ assert (
316
+ (config.date_test is None)
317
+ or (config.date_start is None)
318
+ or (config.date_test > config.date_start)
319
+ ), "date_test isn't after date_start"
320
+
321
+ assert (config.date_val is None) or (
322
+ config.date_test is not None
323
+ ), "date_val is used without date_test"
324
+ assert (
325
+ (config.date_val is None)
326
+ or (config.date_test is None)
327
+ or (config.date_val < config.date_test)
328
+ ), "date_val isn't before date_test"
329
+
330
+ assert (
331
+ (config.date_val is None)
332
+ or (config.date_end is None)
333
+ or (config.date_val < config.date_end)
334
+ ), "date_val isn't before date_end"
335
+ assert (
336
+ (config.date_val is None)
337
+ or (config.date_start is None)
338
+ or (config.date_val > config.date_start)
339
+ ), "date_val isn't after date_start"
340
+
341
+ assert (config.label_len == 0) or (
342
+ config.inverse_output == config.inverse_pred
343
+ ), "If label length is non-zero then inverse_pred and inverse_output should be the same"
344
+
345
+ self.config = config
346
+ self.flag = flag
347
+
348
+ # self.timeenc = 0 if config.t_embed != "timeF" else 1
349
+ if config.t_embed == "timeF":
350
+ self.timeenc = 1
351
+ elif config.t_embed == "time2vec_add" or config.t_embed == "time2vec_app":
352
+ self.timeenc = 2
353
+ else:
354
+ self.timeenc = 0
355
+
356
+ type_map = {"train": 0, "val": 1, "test": 2}
357
+ self.set_type = type_map[flag]
358
+
359
+ self.__read_data__()
360
+
361
+ def __read_data__(self):
362
+ self.scaler = StandardScaler()
363
+ df_raw = pd.read_csv(os.path.join(self.config.root_path, self.config.data_path))
364
+ df_raw = df_raw.astype(
365
+ {c: np.float32 for c in df_raw.select_dtypes(include="float64").columns}
366
+ )
367
+ df_raw["date"] = pd.to_datetime(df_raw["date"])
368
+
369
+ if np.isinf(df_raw[df_raw.columns[1:]].to_numpy()).any():
370
+ raise Exception("There are inf's in the dataset")
371
+ if np.isnan(df_raw[df_raw.columns[1:]].to_numpy()).any():
372
+ raise Exception("There are nan's in the dataset")
373
+ """
374
+ df_raw.columns: ['date', ...(other features), target feature]
375
+ """
376
+ # Filter to datapoints in [date_start, date_end]
377
+ if self.config.date_start is not None:
378
+ df_raw = df_raw.loc[(df_raw["date"] >= self.config.date_start)]
379
+ if self.config.date_end is not None:
380
+ df_raw = df_raw.loc[(df_raw["date"] <= self.config.date_end)]
381
+
382
+ if self.config.cols:
383
+ cols = self.config.cols.copy()
384
+ assert self.config.target in cols, "Target not in cols"
385
+ cols.remove(self.config.target)
386
+ else:
387
+ cols = list(df_raw.columns)
388
+ assert self.config.target in cols, "Target not in data"
389
+ cols.remove(self.config.target)
390
+ assert "date" in cols, "`date` not in data"
391
+ cols.remove("date")
392
+ df_raw = df_raw[["date"] + cols + [self.config.target]]
393
+
394
+ # Define lengths of train, val, and test
395
+ if self.config.date_test is not None and self.config.date_val is not None:
396
+ # num_test and num_val are specified
397
+ num_test = len(df_raw.loc[df_raw["date"] >= self.config.date_test])
398
+ num_vali = len(
399
+ df_raw.loc[
400
+ (df_raw["date"] >= self.config.date_val)
401
+ & (df_raw["date"] < self.config.date_test)
402
+ ]
403
+ )
404
+ num_train = len(df_raw) - num_vali - num_test
405
+ elif self.config.date_test is not None:
406
+ # num_val is half of num_test which is specified
407
+ num_test = len(df_raw.loc[(df_raw["date"] >= self.config.date_test)])
408
+ num_vali = num_test // 2
409
+ num_train = len(df_raw) - num_vali - num_test
410
+ else:
411
+ # Default split
412
+ print("Warning: using default dataset split")
413
+ num_train = int(len(df_raw) * 0.7)
414
+ num_test = int(len(df_raw) * 0.2)
415
+ num_vali = len(df_raw) - num_train - num_test
416
+
417
+ if num_test == 0:
418
+ raise Exception("Dataset loading issue: num_test==0, check date settings")
419
+ elif num_vali == 0:
420
+ raise Exception("Dataset loading issue: num_vali==0, check date settings")
421
+ elif num_train == 0:
422
+ raise Exception("Dataset loading issue: num_train==0, check date settings")
423
+
424
+ border1s = [
425
+ 0,
426
+ num_train - self.config.seq_len,
427
+ len(df_raw) - num_test - self.config.seq_len,
428
+ ]
429
+ border2s = [num_train, num_train + num_vali, len(df_raw)]
430
+ border1 = border1s[self.set_type]
431
+ border2 = border2s[self.set_type]
432
+
433
+ if self.config.features == "M" or self.config.features == "MS":
434
+ cols_data = df_raw.columns[1:]
435
+ df_data = df_raw[cols_data]
436
+ elif self.config.features == "S":
437
+ df_data = df_raw[[self.config.target]]
438
+
439
+ if self.config.scale:
440
+ train_data = df_data[border1s[0] : border2s[0]]
441
+ self.scaler.fit(train_data.values, scale_mean=not self.config.no_scale_mean)
442
+ data = torch.from_numpy(self.scaler.transform(df_data.values))
443
+ else:
444
+ data = torch.from_numpy(df_data.values)
445
+
446
+ df_stamp = df_raw[["date"]][border1:border2]
447
+ df_stamp["date"] = pd.to_datetime(df_stamp.date)
448
+ self.raw_dates = df_stamp.date.to_numpy(dtype=np.datetime64)
449
+ self.data_stamp = np.float32(
450
+ time_features(df_stamp, timeenc=self.timeenc, freq=self.config.freq)
451
+ )
452
+
453
+ self.data_x = data[border1:border2]
454
+ if self.config.inverse_pred:
455
+ self.data_y = torch.from_numpy(df_data.values[border1:border2])
456
+ else:
457
+ self.data_y = data[border1:border2]
458
+
459
+ def __getitem__(self, index):
460
+ s_begin = index
461
+ s_end = s_begin + self.config.seq_len
462
+ r_begin = s_end - self.config.label_len
463
+ r_end = r_begin + self.config.label_len + self.config.pred_len
464
+
465
+ seq_x = self.data_x[s_begin:s_end]
466
+ if self.config.inverse_pred:
467
+ # this is where inverse_pred != inverse output gets wonky if label_len != 0
468
+ # its because the label doesn't get inversed
469
+ seq_y = np.concatenate(
470
+ [
471
+ self.data_x[
472
+ r_begin : r_begin + self.config.label_len
473
+ ], # Use non-scaled data_x
474
+ self.data_y[r_begin + self.config.label_len : r_end],
475
+ ],
476
+ axis=0,
477
+ )
478
+ else:
479
+ seq_y = self.data_y[r_begin:r_end]
480
+ seq_x_mark = self.data_stamp[s_begin:s_end]
481
+ seq_y_mark = self.data_stamp[r_begin:r_end]
482
+
483
+ return seq_x, seq_y, seq_x_mark, seq_y_mark, index
484
+
485
+ def index_to_dates(self, index):
486
+ # index is of length batch_size
487
+ s_begin = index
488
+ s_end = s_begin + self.config.seq_len
489
+ r_begin = s_end - self.config.label_len
490
+ r_end = r_begin + self.config.label_len + self.config.pred_len
491
+
492
+ seq_x_raw_dates = self.raw_dates[
493
+ np.add.outer(s_begin, np.arange(self.config.seq_len))
494
+ ]
495
+ seq_y_raw_dates = self.raw_dates[
496
+ np.add.outer(
497
+ r_begin, np.arange(self.config.label_len + self.config.pred_len)
498
+ )
499
+ ]
500
+ # seq_x_raw_dates = self.raw_dates[np.r_[s_begin,s_end-1].reshape(-1, index.shape[0]).T]# self.raw_dates.iloc[np.r_[s_begin,s_end]]
501
+ # seq_y_raw_dates = self.raw_dates[np.r_[r_begin,r_end-1].reshape(-1, index.shape[0]).T]# self.raw_dates.iloc[np.r_[r_begin,r_end]]
502
+
503
+ return seq_x_raw_dates, seq_y_raw_dates
504
+
505
+ def __len__(self):
506
+ return len(self.data_x) - self.config.seq_len - self.config.pred_len + 1
507
+
508
+ def inverse_transform(self, data):
509
+ return self.scaler.inverse_transform(data)
510
+
511
+
512
+ class Dataset_Pred(Dataset):
513
+ def __init__(self, config, flag="pred"):
514
+ # Default values
515
+ defaults = {
516
+ "size": None,
517
+ "features": "S",
518
+ "target": "OT",
519
+ "scale": True,
520
+ "inverse": False,
521
+ "cols": None,
522
+ "date_start": None,
523
+ "date_end": None,
524
+ "t_embed": None,
525
+ }
526
+ config = dotdict({**defaults, **config})
527
+
528
+ assert config.seq_len is not None
529
+ assert config.label_len is not None
530
+ assert config.pred_len is not None
531
+ assert flag in ["pred"]
532
+ assert config.freq is not None
533
+ assert config.root_path is not None
534
+ assert config.data_path is not None
535
+ assert (
536
+ (config.date_start is None)
537
+ or (config.date_end is None)
538
+ or (config.date_start < config.date_end)
539
+ ), "date_start isn't before date_end"
540
+
541
+ self.config = config
542
+ self.flag = flag
543
+ # self.timeenc = 0 if config.t_embed != "timeF" else 1
544
+ if config.t_embed == "timeF":
545
+ self.timeenc = 1
546
+ elif config.t_embed == "time2vec_add" or config.t_embed == "time2vec_app":
547
+ self.timeenc = 2
548
+ else:
549
+ self.timeenc = 0
550
+
551
+ self.__read_data__()
552
+
553
+ def __read_data__(self):
554
+ self.scaler = StandardScaler()
555
+ df_raw = pd.read_csv(os.path.join(self.config.root_path, self.config.data_path))
556
+ """
557
+ df_raw.columns: ['date', ...(other features), target feature]
558
+ """
559
+
560
+ # Filter to datapoints in [date_start, date_end]
561
+ if self.config.date_start is not None:
562
+ df_raw = df_raw.loc[(df_raw["date"] >= self.config.date_start)]
563
+ if self.config.date_end is not None:
564
+ df_raw = df_raw.loc[(df_raw["date"] <= self.config.date_end)]
565
+
566
+ if self.config.cols:
567
+ cols = self.config.cols.copy()
568
+ cols.remove(self.config.target)
569
+ else:
570
+ cols = list(df_raw.columns)
571
+ cols.remove(self.config.target)
572
+ cols.remove("date")
573
+ df_raw = df_raw[["date"] + cols + [self.config.target]]
574
+
575
+ border1 = len(df_raw) - self.config.seq_len
576
+ border2 = len(df_raw)
577
+
578
+ if self.config.features == "M" or self.config.features == "MS":
579
+ cols_data = df_raw.columns[1:]
580
+ df_data = df_raw[cols_data]
581
+ elif self.config.features == "S":
582
+ df_data = df_raw[[self.config.target]]
583
+
584
+ if self.config.scale:
585
+ self.scaler.fit(df_data.values, scale_mean=not self.config.no_scale_mean)
586
+ data = self.scaler.transform(df_data.values)
587
+ else:
588
+ data = df_data.values
589
+
590
+ tmp_stamp = df_raw[["date"]][border1:border2]
591
+ tmp_stamp["date"] = pd.to_datetime(tmp_stamp.date)
592
+ pred_dates = pd.date_range(
593
+ tmp_stamp.date.values[-1],
594
+ periods=self.config.pred_len + 1,
595
+ freq=self.config.freq,
596
+ )
597
+
598
+ df_stamp = pd.DataFrame(columns=["date"])
599
+ df_stamp.date = pd.to_datetime(
600
+ list(tmp_stamp.date.values) + list(pred_dates[1:]), utc=True
601
+ )
602
+ self.raw_dates = df_stamp.date.to_numpy(dtype=np.datetime64)
603
+ # TODO: What is the deal with .freq[-1:]
604
+ self.data_stamp = np.float32(
605
+ time_features(df_stamp, timeenc=self.timeenc, freq=self.config.freq[-1:])
606
+ )
607
+
608
+ self.data_x = data[border1:border2]
609
+ if self.config.inverse:
610
+ self.data_y = df_data.values[border1:border2]
611
+ else:
612
+ self.data_y = data[border1:border2]
613
+
614
+ def __getitem__(self, index):
615
+ s_begin = index
616
+ s_end = s_begin + self.config.seq_len
617
+ r_begin = s_end - self.config.label_len
618
+ r_end = r_begin + self.config.label_len + self.config.pred_len
619
+
620
+ seq_x = self.data_x[s_begin:s_end]
621
+ if self.config.inverse:
622
+ seq_y = self.data_x[r_begin : r_begin + self.config.label_len]
623
+ else:
624
+ seq_y = self.data_y[r_begin : r_begin + self.config.label_len]
625
+ seq_x_mark = self.data_stamp[s_begin:s_end]
626
+ seq_y_mark = self.data_stamp[r_begin:r_end]
627
+
628
+ return seq_x, seq_y, seq_x_mark, seq_y_mark, index
629
+
630
+ def index_to_dates(self, index):
631
+ # index is of length batch_size
632
+ s_begin = index
633
+ s_end = s_begin + self.config.seq_len
634
+ r_begin = s_end - self.config.label_len
635
+ r_end = r_begin + self.config.label_len + self.config.pred_len
636
+
637
+ seq_x_raw_dates = self.raw_dates[
638
+ np.add.outer(s_begin, np.arange(self.config.seq_len))
639
+ ]
640
+ seq_y_raw_dates = self.raw_dates[
641
+ np.add.outer(
642
+ r_begin, np.arange(self.config.label_len + self.config.pred_len)
643
+ )
644
+ ]
645
+
646
+ return seq_x_raw_dates, seq_y_raw_dates
647
+
648
+ def __len__(self):
649
+ return len(self.data_x) - self.config.seq_len + 1
650
+
651
+ def inverse_transform(self, data):
652
+ return self.scaler.inverse_transform(data)
data_provider/data_module.py ADDED
@@ -0,0 +1,135 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import pandas as pd
3
+
4
+ from torch.utils.data import Dataset, DataLoader
5
+ from data_provider.data_loader import (
6
+ Dataset_Custom,
7
+ Dataset_Pred,
8
+ # Dataset_ETT_hour,
9
+ # Dataset_ETT_minute,
10
+ )
11
+ from utils.tools import dotdict
12
+ import pytorch_lightning as pl
13
+
14
+
15
+ class CustomDataModule(pl.LightningDataModule):
16
+ def __init__(self, config: dotdict, num_workers: int = 0):
17
+ super().__init__()
18
+ self.data_train: Dataset | None = None
19
+ self.data_val: Dataset | None = None
20
+ self.data_test: Dataset | None = None
21
+ self.config = config
22
+
23
+ # pl makes self.batch_size special
24
+ self.batch_size = config.batch_size
25
+ self.num_workers = num_workers
26
+
27
+ assert (
28
+ not config.inverse
29
+ ) or config.scale, "Can't enable inverse without enabling scale"
30
+
31
+ def prepare_data(self):
32
+ """Download data if needed. This method is called only from a single GPU.
33
+ Do not use it to assign state (self.x = y)."""
34
+ pass
35
+
36
+ def setup(self, stage: str | None = None):
37
+ """Load data. Set variables: `self.data_train`, `self.data_val`, `self.data_test`.
38
+ This method is called by lightning twice for `trainer.fit()` and `trainer.test()`, so be careful if you do a random split!
39
+ The `stage` can be used to differentiate whether it's called before trainer.fit()` or `trainer.test()`.
40
+ """
41
+
42
+ self.data_train = Dataset_Custom(self.config, flag="train")
43
+ self.data_val = Dataset_Custom(self.config, flag="val")
44
+ self.data_test = Dataset_Custom(self.config, flag="test")
45
+ # self.data_pred = Dataset_Pred(self.config, flag="pred")
46
+ print(
47
+ f"LOADED DATASETS for {stage}: train: {len(self.data_train)}\tval: {len(self.data_val)}\ttest: {len(self.data_test)}"
48
+ )
49
+
50
+ def train_dataloader(self):
51
+ return DataLoader(
52
+ self.data_train,
53
+ batch_size=self.batch_size,
54
+ shuffle=not self.config.dont_shuffle_train,
55
+ num_workers=self.num_workers,
56
+ drop_last=True,
57
+ )
58
+
59
+ def val_dataloader(self):
60
+ # assert self.batch_size <= len(
61
+ # self.data_val
62
+ # ), f"Batch size larger than val data set, batch size: {self.batch_size}, val size: {len(self.data_val)}"
63
+ return [
64
+ DataLoader(
65
+ self.data_val,
66
+ batch_size=self.batch_size,
67
+ shuffle=False,
68
+ drop_last=False,
69
+ num_workers=self.num_workers,
70
+ ),
71
+ DataLoader(
72
+ self.data_test,
73
+ batch_size=self.batch_size,
74
+ shuffle=False,
75
+ drop_last=False,
76
+ num_workers=self.num_workers,
77
+ ),
78
+ ]
79
+
80
+ def test_dataloader(self):
81
+ return [
82
+ DataLoader(
83
+ self.data_train,
84
+ batch_size=self.config.batch_size,
85
+ shuffle=False,
86
+ drop_last=False,
87
+ num_workers=self.num_workers,
88
+ ),
89
+ DataLoader(
90
+ self.data_val,
91
+ batch_size=self.config.batch_size,
92
+ shuffle=False,
93
+ drop_last=False,
94
+ num_workers=self.num_workers,
95
+ ),
96
+ DataLoader(
97
+ self.data_test,
98
+ batch_size=self.config.batch_size,
99
+ shuffle=False,
100
+ drop_last=False,
101
+ num_workers=self.num_workers,
102
+ ),
103
+ ]
104
+
105
+ def predict_dataloader(self):
106
+ return (
107
+ DataLoader(
108
+ self.data_train,
109
+ batch_size=self.config.batch_size,
110
+ shuffle=False,
111
+ drop_last=False,
112
+ num_workers=self.num_workers,
113
+ ),
114
+ DataLoader(
115
+ self.data_val,
116
+ batch_size=self.config.batch_size,
117
+ shuffle=False,
118
+ drop_last=False,
119
+ num_workers=self.num_workers,
120
+ ),
121
+ DataLoader(
122
+ self.data_test,
123
+ batch_size=self.config.batch_size,
124
+ shuffle=False,
125
+ drop_last=False,
126
+ num_workers=self.num_workers,
127
+ ),
128
+ # DataLoader(
129
+ # self.data_pred,
130
+ # batch_size=self.config.batch_size,
131
+ # shuffle=False,
132
+ # drop_last=False,
133
+ # num_workers=self.num_workers,
134
+ # ),
135
+ )
embed.py ADDED
@@ -0,0 +1,228 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import torch.nn as nn
3
+ import torch.nn.functional as F
4
+
5
+ import math
6
+
7
+
8
+ class PositionalEmbedding(nn.Module):
9
+ def __init__(self, d_model, max_len=5000):
10
+ super(PositionalEmbedding, self).__init__()
11
+ # Compute the positional encodings once in log space.
12
+ pe = torch.zeros(max_len, d_model).float()
13
+ pe.require_grad = False
14
+
15
+ position = torch.arange(0, max_len).float().unsqueeze(1)
16
+ div_term = (
17
+ torch.arange(0, d_model, 2).float() * -(math.log(10000.0) / d_model)
18
+ ).exp()
19
+
20
+ pe[:, 0::2] = torch.sin(position * div_term)
21
+ pe[:, 1::2] = torch.cos(position * div_term)
22
+
23
+ pe = pe.unsqueeze(0)
24
+ self.register_buffer("pe", pe)
25
+
26
+ def forward(self, x):
27
+ return self.pe[:, : x.size(1)]
28
+
29
+
30
+ class TokenEmbedding(nn.Module):
31
+ def __init__(self, c_in, d_model):
32
+ super(TokenEmbedding, self).__init__()
33
+ padding = 1 if torch.__version__ >= "1.5.0" else 2
34
+ self.tokenConv = nn.Conv1d(
35
+ in_channels=c_in,
36
+ out_channels=d_model,
37
+ kernel_size=3,
38
+ padding=padding,
39
+ padding_mode="circular",
40
+ )
41
+ for m in self.modules():
42
+ if isinstance(m, nn.Conv1d):
43
+ nn.init.kaiming_normal_(
44
+ m.weight, mode="fan_in", nonlinearity="leaky_relu"
45
+ )
46
+
47
+ def forward(self, x):
48
+ x = self.tokenConv(x.permute(0, 2, 1)).transpose(1, 2)
49
+ return x
50
+
51
+
52
+ class TokenEmbeddingBasic(nn.Module):
53
+ def __init__(self, c_in, d_model):
54
+ super(TokenEmbeddingBasic, self).__init__()
55
+ self.linear = nn.Linear(c_in, d_model)
56
+
57
+ def forward(self, x):
58
+ x = self.linear(x)
59
+ return x
60
+
61
+
62
+ class FixedEmbedding(nn.Module):
63
+ def __init__(self, c_in, d_model):
64
+ super(FixedEmbedding, self).__init__()
65
+
66
+ w = torch.zeros(c_in, d_model).float()
67
+ w.require_grad = False
68
+
69
+ position = torch.arange(0, c_in).float().unsqueeze(1)
70
+ div_term = (
71
+ torch.arange(0, d_model, 2).float() * -(math.log(10000.0) / d_model)
72
+ ).exp()
73
+
74
+ w[:, 0::2] = torch.sin(position * div_term)
75
+ w[:, 1::2] = torch.cos(position * div_term)
76
+
77
+ self.emb = nn.Embedding(c_in, d_model)
78
+ self.emb.weight = nn.Parameter(w, requires_grad=False)
79
+
80
+ def forward(self, x):
81
+ return self.emb(x).detach()
82
+
83
+
84
+ class TemporalEmbedding(nn.Module):
85
+ def __init__(self, d_model, t_embed="fixed", freq="h"):
86
+ super(TemporalEmbedding, self).__init__()
87
+
88
+ minute_size = 4
89
+ hour_size = 24
90
+ weekday_size = 7
91
+ day_size = 32
92
+ month_size = 13
93
+
94
+ Embed = FixedEmbedding if t_embed == "fixed" else nn.Embedding
95
+ if freq == "t":
96
+ self.minute_embed = Embed(minute_size, d_model)
97
+ self.hour_embed = Embed(hour_size, d_model)
98
+ self.weekday_embed = Embed(weekday_size, d_model)
99
+ self.day_embed = Embed(day_size, d_model)
100
+ self.month_embed = Embed(month_size, d_model)
101
+
102
+ def forward(self, x):
103
+ x = x.long()
104
+
105
+ minute_x = (
106
+ self.minute_embed(x[:, :, 4]) if hasattr(self, "minute_embed") else 0.0
107
+ )
108
+ hour_x = self.hour_embed(x[:, :, 3])
109
+ weekday_x = self.weekday_embed(x[:, :, 2])
110
+ day_x = self.day_embed(x[:, :, 1])
111
+ month_x = self.month_embed(x[:, :, 0])
112
+
113
+ return hour_x + weekday_x + day_x + month_x + minute_x
114
+
115
+
116
+ class TimeFeatureEmbedding(nn.Module):
117
+ def __init__(self, d_model, t_embed="timeF", freq="h"):
118
+ super(TimeFeatureEmbedding, self).__init__()
119
+
120
+ freq_map = {"h": 4, "t": 5, "s": 6, "m": 1, "a": 1, "w": 2, "d": 3, "b": 3}
121
+ d_inp = freq_map[freq]
122
+ self.embed = nn.Linear(d_inp, d_model)
123
+
124
+ def forward(self, x):
125
+ return self.embed(x)
126
+
127
+
128
+ class Time2Vec(nn.Module):
129
+ def __init__(self, time_emb_dim, freq="h"):
130
+ super(Time2Vec, self).__init__()
131
+ freq_map = {"h": 4, "t": 5, "s": 6, "m": 1, "a": 1, "w": 2, "d": 3, "b": 3}
132
+ time_feat_dim = freq_map[freq]
133
+
134
+ self.output_dim = time_emb_dim
135
+
136
+ self.out_features = time_emb_dim
137
+
138
+ # TODO: Initialize uniform
139
+ self.linear_periodic = nn.Linear(time_feat_dim, time_emb_dim - 1)
140
+ self.linear_non_periodic = nn.Linear(time_feat_dim, 1)
141
+
142
+ def forward(self, x):
143
+ non_periodic = self.linear_non_periodic(x.float())
144
+ periodic = torch.sin(self.linear_periodic(x.float()))
145
+ out = torch.cat([non_periodic, periodic], -1)
146
+ return out
147
+
148
+
149
+ class DataEmbedding(nn.Module):
150
+ def __init__(
151
+ self,
152
+ c_in,
153
+ d_model,
154
+ t_embed="fixed",
155
+ freq="h",
156
+ dropout_emb=0.01,
157
+ position_embedding=True,
158
+ emb_t2v_app_dim=32,
159
+ tok_emb="default",
160
+ ):
161
+ super(DataEmbedding, self).__init__()
162
+
163
+ self.append_time_emb = t_embed == "time2vec_app"
164
+
165
+ # For the temporal embedding
166
+ if t_embed is not None:
167
+ assert t_embed in [
168
+ "fixed",
169
+ "learned",
170
+ "timeF",
171
+ "time2vec_add",
172
+ "time2vec_app",
173
+ ], "Invalid t_embed"
174
+ if t_embed == "fixed" or t_embed == "learned":
175
+ self.temporal_embedding = TemporalEmbedding(
176
+ d_model=d_model, t_embed=t_embed, freq=freq
177
+ )
178
+ elif t_embed == "timeF":
179
+ self.temporal_embedding = TimeFeatureEmbedding(
180
+ d_model=d_model, t_embed=t_embed, freq=freq
181
+ )
182
+ elif t_embed == "time2vec_add":
183
+ # Time2Vec time embedding add elementwise
184
+ self.temporal_embedding = Time2Vec(time_emb_dim=d_model, freq=freq)
185
+ elif t_embed == "time2vec_app":
186
+ # Time2Vec time embedding appended
187
+ assert (
188
+ emb_t2v_app_dim is not None
189
+ ), "Need to provide the emb_t2v_app_dim argument"
190
+ assert emb_t2v_app_dim > 0 and emb_t2v_app_dim < d_model
191
+ self.temporal_embedding = Time2Vec(
192
+ time_emb_dim=emb_t2v_app_dim, freq=freq
193
+ )
194
+ d_model -= emb_t2v_app_dim
195
+ else:
196
+ self.temporal_embedding = lambda _: 0
197
+
198
+ # For the value embedding
199
+ if tok_emb == "basic":
200
+ self.value_embedding = TokenEmbeddingBasic(c_in=c_in, d_model=d_model)
201
+ elif tok_emb == "raw":
202
+ self.value_embedding = lambda x: x
203
+ assert c_in == d_model, "c_in and d_model must be equal for raw embedding"
204
+ assert (
205
+ t_embed != "time2vec_app"
206
+ ), "time2vec_app not supported for raw embedding"
207
+ else:
208
+ self.value_embedding = TokenEmbedding(c_in=c_in, d_model=d_model)
209
+
210
+ self.position_embedding = (
211
+ PositionalEmbedding(d_model=d_model) if position_embedding else lambda x: 0
212
+ )
213
+
214
+ self.dropout = nn.Dropout(p=dropout_emb)
215
+
216
+ def forward(self, x, x_mark):
217
+ if self.append_time_emb:
218
+ x = self.value_embedding(x) + self.position_embedding(x)
219
+ x_drop = self.dropout(x)
220
+ time_emb = self.temporal_embedding(x_mark)
221
+ return torch.concat([x_drop, time_emb], -1)
222
+ else:
223
+ x = (
224
+ self.value_embedding(x)
225
+ + self.position_embedding(x)
226
+ + self.temporal_embedding(x_mark)
227
+ )
228
+ return self.dropout(x)
exp/__init__.py ADDED
File without changes
exp/exp_basic.py ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import torch
3
+ import numpy as np
4
+
5
+
6
+ class Exp_Basic(object):
7
+ def __init__(self, args):
8
+ self.args = args
9
+ self.device = self._acquire_device()
10
+ self.model = self._build_model().to(self.device)
11
+
12
+ def _build_model(self):
13
+ raise NotImplementedError
14
+ return None
15
+
16
+ def _acquire_device(self):
17
+ if self.args.use_gpu:
18
+ os.environ["CUDA_VISIBLE_DEVICES"] = (
19
+ str(self.args.gpu) if not self.args.use_multi_gpu else self.args.devices
20
+ )
21
+ device = torch.device(f"cuda:{self.args.gpu}")
22
+ print(f"Use GPU: cuda:{self.args.gpu}")
23
+ else:
24
+ device = torch.device("cpu")
25
+ print("Use CPU")
26
+ return device
27
+
28
+ def _get_data(self, *args, **kwargs):
29
+ pass
30
+
31
+ def vali(self, *args, **kwargs):
32
+ pass
33
+
34
+ def train(self, *args, **kwargs):
35
+ pass
36
+
37
+ def test(self, *args, **kwargs):
38
+ pass
exp/exp_informer.py ADDED
@@ -0,0 +1,370 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from data_provider.data_factory import data_provider
2
+ from exp.exp_basic import Exp_Basic
3
+ from models.Informer import Informer, InformerStack
4
+ from models.Basic import NLinear, MLP
5
+ from models.Stockformer import Stockformer
6
+
7
+ from utils.tools import EarlyStopping, adjust_learning_rate
8
+ from utils.metrics import metric
9
+ from utils.stock_metrics import stock_loss
10
+
11
+ import numpy as np
12
+
13
+ import torch
14
+ import torch.nn as nn
15
+ from torch import optim
16
+
17
+ import os
18
+ import time
19
+ import json
20
+
21
+ import warnings
22
+
23
+ warnings.filterwarnings("ignore")
24
+
25
+
26
+ class Exp_Informer(Exp_Basic):
27
+ def __init__(self, args):
28
+ super(Exp_Informer, self).__init__(args)
29
+
30
+ def _build_model(self):
31
+ model_dict = {
32
+ "informer": Informer,
33
+ "informerstack": InformerStack,
34
+ "mlp": MLP,
35
+ "stockformer": Stockformer,
36
+ "nlinear": NLinear,
37
+ }
38
+
39
+ # Use stack layers for encoder layers if using informerstack
40
+ self.args.e_layers = (
41
+ self.args.s_layers
42
+ if self.args.model == "informerstack"
43
+ else self.args.e_layers
44
+ )
45
+
46
+ assert (
47
+ self.args.model in model_dict
48
+ ), f"Invalid args.model: {self.args.model}, options: {list(model_dict.keys())}"
49
+ model = model_dict[self.args.model](self.args).float()
50
+
51
+ if self.args.use_multi_gpu and self.args.use_gpu:
52
+ model = nn.DataParallel(model, device_ids=self.args.device_ids)
53
+ return model
54
+
55
+ def _get_data(self, flag):
56
+ data_set, data_loader = data_provider(self.args, flag)
57
+ return data_set, data_loader
58
+
59
+ def _select_optimizer(self):
60
+ model_optim = optim.Adam(self.model.parameters(), lr=self.args.learning_rate)
61
+ return model_optim
62
+
63
+ def _select_criterion(self):
64
+ if "stock" in self.args.loss:
65
+ _, stock_loss_mode = self.args.loss.split("_")
66
+ assert (
67
+ self.args.target.split("_")[1] == "pctchange"
68
+ ), "Can't use stock loss unless target is pctchange"
69
+ assert not (
70
+ self.args.scale and not self.args.inverse
71
+ ), "Can't use stock loss when args.scale==True and args.inverse==False."
72
+ criterion = stock_loss(self.args, stock_loss_mode=stock_loss_mode)
73
+ else:
74
+ assert self.args.loss == "mse"
75
+ criterion = nn.MSELoss()
76
+ return criterion
77
+
78
+ def _select_scheduler(self, optimizer):
79
+ if self.args.lradj == "type1":
80
+ lmbda = lambda epoch: 0.5
81
+ scheduler = torch.optim.lr_scheduler.MultiplicativeLR(
82
+ optimizer, lr_lambda=lmbda, verbose=True
83
+ )
84
+ elif self.args.lradj == "type2":
85
+ scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(
86
+ optimizer,
87
+ factor=0.5,
88
+ patience=2,
89
+ threshold=1e-2,
90
+ cooldown=0,
91
+ verbose=True,
92
+ )
93
+ else:
94
+ scheduler = None
95
+ return scheduler
96
+
97
+ def vali(self, vali_data, vali_loader, criterion):
98
+ self.model.eval()
99
+ total_loss = []
100
+ for i, (batch_x, batch_y, batch_x_mark, batch_y_mark, _) in enumerate(
101
+ vali_loader
102
+ ):
103
+ pred, true, _ = self._process_one_batch(
104
+ vali_data, batch_x, batch_y, batch_x_mark, batch_y_mark, ds_index=None
105
+ )
106
+ loss = criterion(pred.detach().cpu(), true.detach().cpu())
107
+ total_loss.append(loss)
108
+ total_loss = np.average(total_loss)
109
+ self.model.train()
110
+ return total_loss
111
+
112
+ def train(self, setting):
113
+ train_data, train_loader = self._get_data(flag="train")
114
+ vali_data, vali_loader = self._get_data(flag="val")
115
+ test_data, test_loader = self._get_data(flag="test")
116
+
117
+ path = os.path.join(self.args.checkpoints, setting)
118
+ if not os.path.exists(path):
119
+ os.makedirs(path)
120
+
121
+ # Save args
122
+ with open(os.path.join(path, "args.json"), "w") as convert_file:
123
+ convert_file.write(json.dumps(self.args))
124
+
125
+ time_now = time.time()
126
+
127
+ train_steps = len(train_loader)
128
+
129
+ early_stopping = None
130
+ if not self.args.no_early_stop:
131
+ early_stopping = EarlyStopping(patience=self.args.patience, verbose=True)
132
+
133
+ model_optim = self._select_optimizer()
134
+ criterion = self._select_criterion()
135
+ scheduler = self._select_scheduler(model_optim)
136
+
137
+ if self.args.use_amp:
138
+ scaler = torch.cuda.amp.GradScaler()
139
+
140
+ for epoch in range(self.args.max_epochs):
141
+ if epoch == 0:
142
+ for param_group in model_optim.param_groups:
143
+ param_group["lr"] = 1e-8
144
+ elif epoch == 1:
145
+ for param_group in model_optim.param_groups:
146
+ param_group["lr"] = self.args.learning_rate
147
+ iter_count = 0
148
+ train_loss = []
149
+
150
+ self.model.train()
151
+ epoch_time = time.time()
152
+ for i, (batch_x, batch_y, batch_x_mark, batch_y_mark, _) in enumerate(
153
+ train_loader
154
+ ):
155
+ iter_count += 1
156
+
157
+ model_optim.zero_grad()
158
+ pred, true, _ = self._process_one_batch(
159
+ train_data,
160
+ batch_x,
161
+ batch_y,
162
+ batch_x_mark,
163
+ batch_y_mark,
164
+ ds_index=None,
165
+ )
166
+ loss = criterion(pred, true)
167
+ train_loss.append(loss.item())
168
+
169
+ if (i + 1) % 100 == 0:
170
+ print(
171
+ "\titers: {0}, epoch: {1} | loss: {2:.7f}".format(
172
+ i + 1, epoch + 1, loss.item()
173
+ )
174
+ )
175
+ speed = (time.time() - time_now) / iter_count
176
+ left_time = speed * (
177
+ (self.args.max_epochs - epoch) * train_steps - i
178
+ )
179
+ print(
180
+ "\tspeed: {:.4f}s/iter; left time: {:.4f}s".format(
181
+ speed, left_time
182
+ )
183
+ )
184
+ iter_count = 0
185
+ time_now = time.time()
186
+
187
+ if self.args.use_amp:
188
+ scaler.scale(loss).backward()
189
+ scaler.step(model_optim)
190
+ scaler.update()
191
+ else:
192
+ loss.backward()
193
+ model_optim.step()
194
+
195
+ print(f"Epoch: {epoch+1} cost time: {time.time()-epoch_time}")
196
+ train_loss = np.average(train_loss)
197
+ vali_loss = self.vali(vali_data, vali_loader, criterion)
198
+ test_loss = self.vali(test_data, test_loader, criterion)
199
+
200
+ print(
201
+ "Epoch: {0}, Steps: {1} | Train Loss: {2:.7f} Vali Loss: {3:.7f} Test"
202
+ " Loss: {4:.7f}".format(
203
+ epoch + 1, train_steps, train_loss, vali_loss, test_loss
204
+ )
205
+ )
206
+
207
+ if not self.args.no_early_stop:
208
+ early_stopping(vali_loss, self.model, path)
209
+ if early_stopping.early_stop:
210
+ print("Early stopping")
211
+ break
212
+
213
+ # adjust_learning_rate(model_optim, epoch+1, self.args)
214
+ if scheduler is not None:
215
+ scheduler.step(metrics=vali_loss)
216
+
217
+ if self.args.no_early_stop:
218
+ # This is only for debugging
219
+ print("Saving overfitted model")
220
+ # os.rename(os.path.join(path, 'checkpoint.pth'), os.path.join(path, 'checkpoint-real.pth'))
221
+ torch.save(self.model.state_dict(), os.path.join(path, "checkpoint.pth"))
222
+ else:
223
+ best_model_path = os.path.join(path, "checkpoint.pth")
224
+ self.model.load_state_dict(torch.load(best_model_path))
225
+
226
+ return self.model
227
+
228
+ def test(self, setting, flag="test", inverse=True):
229
+ # Enable inverse if scale
230
+ inverse_og = self.args.inverse
231
+ self.args.inverse = self.args.scale and inverse
232
+
233
+ data, loader = self._get_data(flag=flag)
234
+
235
+ self.model.eval()
236
+
237
+ preds = []
238
+ trues = []
239
+ raw_dates = []
240
+
241
+ for i, (batch_x, batch_y, batch_x_mark, batch_y_mark, ds_index) in enumerate(
242
+ loader
243
+ ):
244
+ pred, true, rdates = self._process_one_batch(
245
+ data, batch_x, batch_y, batch_x_mark, batch_y_mark, ds_index=ds_index
246
+ )
247
+ preds.append(pred.detach().cpu().numpy())
248
+ trues.append(true.detach().cpu().numpy())
249
+ raw_dates.append(rdates)
250
+
251
+ assert len(preds) == len(trues)
252
+ preds = np.array(preds)
253
+ trues = np.array(trues)
254
+ raw_dates = np.array(raw_dates)
255
+ print(flag, "shape:", preds.shape, trues.shape)
256
+ preds = preds.reshape(-1, preds.shape[-2], preds.shape[-1])
257
+ trues = trues.reshape(-1, trues.shape[-2], trues.shape[-1])
258
+ raw_dates = raw_dates.reshape(-1, raw_dates.shape[-1])
259
+ print(flag, "shape:", preds.shape, trues.shape)
260
+
261
+ # Result save
262
+ folder_path = os.path.join("./results/", setting)
263
+ if not os.path.exists(folder_path):
264
+ os.makedirs(folder_path)
265
+
266
+ # Save args
267
+ with open(os.path.join(folder_path, "args.json"), "w") as convert_file:
268
+ convert_file.write(json.dumps(self.args))
269
+
270
+ mae, mse, rmse, mape, mspe = metric(preds, trues)
271
+ print(f"{flag} mse:{mse}, mae:{mae}")
272
+
273
+ # Save metrics
274
+ with open(os.path.join(folder_path, "results.txt"), "a") as f:
275
+ f.write(f"{setting}\t{flag}\nmse:{mse}, mae:{mae}\n\n")
276
+ np.save(
277
+ os.path.join(folder_path, f"metrics_{flag}.npy"),
278
+ np.array([mae, mse, rmse, mape, mspe]),
279
+ )
280
+
281
+ # Save pred & true & raw dates
282
+ np.save(os.path.join(folder_path, f"pred_{flag}.npy"), preds)
283
+ np.save(os.path.join(folder_path, f"true_{flag}.npy"), trues)
284
+ np.save(os.path.join(folder_path, f"date_{flag}.npy"), raw_dates)
285
+ self.args.inverse = inverse_og
286
+ return
287
+
288
+ def predict(self, setting, load=False):
289
+ pred_data, pred_loader = self._get_data(flag="pred")
290
+
291
+ if load:
292
+ path = os.path.join(self.args.checkpoints, setting)
293
+ best_model_path = os.path.join(path, "checkpoint.pth")
294
+ self.model.load_state_dict(torch.load(best_model_path))
295
+
296
+ self.model.eval()
297
+
298
+ preds = []
299
+ # pred_trues = []
300
+ for i, (batch_x, batch_y, batch_x_mark, batch_y_mark, _) in enumerate(
301
+ pred_loader
302
+ ):
303
+ pred, true, _ = self._process_one_batch(
304
+ pred_data, batch_x, batch_y, batch_x_mark, batch_y_mark, ds_index=None
305
+ )
306
+ preds.append(pred.detach().cpu().numpy())
307
+ # pred_trues.append(true.detach().cpu().numpy())
308
+
309
+ preds = np.array(preds)
310
+ preds = preds.reshape(-1, preds.shape[-2], preds.shape[-1])
311
+
312
+ # result save
313
+ folder_path = os.path.join("./results/", setting)
314
+ if not os.path.exists(folder_path):
315
+ os.makedirs(folder_path)
316
+
317
+ np.save(os.path.join(folder_path, "real_prediction.npy"), preds)
318
+
319
+ return
320
+
321
+ def _process_one_batch(
322
+ self,
323
+ dataset_object,
324
+ batch_x,
325
+ batch_y,
326
+ batch_x_mark,
327
+ batch_y_mark,
328
+ ds_index=None,
329
+ ):
330
+ batch_x = batch_x.float().to(self.device)
331
+ batch_y = batch_y.float()
332
+
333
+ batch_x_mark = batch_x_mark.float().to(self.device)
334
+ batch_y_mark = batch_y_mark.float().to(self.device)
335
+
336
+ # Decoder input if self.args.dec_in
337
+ dec_inp = None
338
+ if self.args.dec_in and (self.args.padding == 0 or self.args.padding == 1):
339
+ # FF: dec_inp = torch.zeros_like(batch_y[:, -self.args.pred_len:, :]).float()
340
+ dec_inp = torch.full(
341
+ [batch_y.shape[0], self.args.pred_len, batch_y.shape[-1]],
342
+ self.args.padding,
343
+ ).float()
344
+ dec_inp = (
345
+ torch.cat([batch_y[:, : self.args.label_len, :], dec_inp], dim=1)
346
+ .float()
347
+ .to(self.device)
348
+ )
349
+
350
+ # Encoder - Decoder
351
+ with torch.cuda.amp.autocast(enabled=self.args.use_amp):
352
+ if self.args.output_attention:
353
+ outputs = self.model(batch_x, batch_x_mark, dec_inp, batch_y_mark)[0]
354
+ else:
355
+ outputs = self.model(batch_x, batch_x_mark, dec_inp, batch_y_mark)
356
+ if self.args.inverse:
357
+ outputs = dataset_object.inverse_transform(outputs)
358
+ f_dim = -1 if self.args.features == "MS" else 0
359
+
360
+ if ds_index is None:
361
+ batch_y = batch_y[:, -self.args.pred_len :, f_dim:].to(self.device)
362
+ return outputs, batch_y, None
363
+ else:
364
+ batch_x_raw_dates, batch_y_raw_dates = dataset_object.index_to_dates(
365
+ ds_index
366
+ )
367
+ assert batch_y_raw_dates.shape == batch_y.shape[0:2]
368
+ batch_y = batch_y[:, -self.args.pred_len :, f_dim:].to(self.device)
369
+ batch_y_raw_dates = batch_y_raw_dates[:, -self.args.pred_len :]
370
+ return outputs, batch_y, batch_y_raw_dates
exp/exp_timeseries.py ADDED
@@ -0,0 +1,368 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import pytorch_lightning as pl
3
+
4
+ from models.Basic import MLP
5
+ from models.Lstm import LSTM
6
+ from models.Informer import Informer, InformerStack
7
+ from models.Stockformer import Stockformer
8
+ from utils.stock_metrics import get_stock_algo, pct_direction_torch
9
+ from torchmetrics import MeanSquaredError, MeanAbsoluteError
10
+ from torch_optimizer import Ranger
11
+
12
+
13
+ class ExpTimeseries(pl.LightningModule):
14
+ def __init__(self, config):
15
+ super().__init__()
16
+ self.config = config
17
+
18
+ # pl makes self.learning_rate special
19
+ self.learning_rate = config.learning_rate
20
+
21
+ # Torch metrics has a state that resets but val and train can be called in unison so we split
22
+ # If pre_loss isn't supplied (ie: pre_loss is None) it will default to config.loss
23
+ self.train_criterion = self._select_criterion(
24
+ loss_override=self.config.pre_loss
25
+ )
26
+ self.other_criterion = self._select_criterion(
27
+ loss_override=self.config.pre_loss
28
+ )
29
+ self.loss_switched = False
30
+
31
+ self._build_model()
32
+ # self.save_hyperparameters()
33
+
34
+ def _build_model(self):
35
+ model_dict = {
36
+ "informer": Informer,
37
+ "informerstack": InformerStack,
38
+ "mlp": MLP,
39
+ "stockformer": Stockformer,
40
+ "lstm": LSTM,
41
+ }
42
+ assert (
43
+ self.config.model in model_dict
44
+ ), f"Invalid config.model: {self.config.model}, options: {list(model_dict.keys())}"
45
+ self.model = model_dict[self.config.model](self.config).float()
46
+
47
+ # Load model
48
+ if self.config.load_model_path is not None:
49
+ self.load_from_checkpoint(self.config.load_model_path)
50
+
51
+ def _select_criterion(self, loss_override=None):
52
+ loss = self.config.loss
53
+ if loss_override is not None:
54
+ loss = loss_override
55
+
56
+ def combine_loss(loss, weights=None):
57
+ if weights is None:
58
+ weights = [1.0] * len(loss)
59
+ def combined(pred, target, inv_pred):
60
+ # print(pred.shape, target.shape)
61
+ # while(1):pass
62
+ return sum(w*l(inv_pred, target) if "Mean" in l.__class__.__name__ else w*l(pred, target) for w,l in zip(weights, loss))
63
+ return combined
64
+
65
+ def loss_lib(loss: str):
66
+ if "stock" in loss:
67
+ # Using Stock Loss
68
+ _, stock_loss_mode = loss.split("_")
69
+ target_type = self.config.target.split("_")[1]
70
+ assert (
71
+ target_type == "pctchange" or target_type == "logpctchange"
72
+ ), "Can't use stock loss unless target is pctchange or logpctchange"
73
+ assert (
74
+ self.config.scale
75
+ and self.config.inverse_pred
76
+ # and not self.config.inverse_output
77
+ ), "Can't use stock loss without scale, inverse pred, and not inverse output"
78
+
79
+ criterion = get_stock_algo(target_type, stock_loss_mode)
80
+ print("criterion:", criterion)
81
+ return lambda x, y: -1 * criterion.loss(x, y).mean()
82
+ # return lambda x, y: -LogPctProfitTanhV1.loss(x, y).mean()
83
+ # return get_stock_loss(target_type, stock_loss_mode, threshold=0.0)
84
+ elif loss == "mae":
85
+ assert (
86
+ self.config.scale
87
+ and self.config.inverse_pred
88
+ # and self.config.inverse_output
89
+ ), "Can't use mae loss without scale, inverse pred, and inverse output"
90
+ return MeanAbsoluteError().cuda()
91
+ elif loss == "mse":
92
+ assert (
93
+ self.config.scale
94
+ and self.config.inverse_pred
95
+ # and self.config.inverse_output
96
+ ), "Can't use mse loss without scale, inverse pred, and inverse output"
97
+ return MeanSquaredError().cuda()
98
+ loss_list = [ loss_lib(loss_type) for loss_type in loss.split('+') ]
99
+ weights = [1.0] if '+' not in loss else [10.0, 1.0]
100
+ return combine_loss(loss_list, weights)
101
+
102
+ raise Exception(f"Invalid loss: {loss}")
103
+
104
+ def forward(self, x):
105
+ # in lightning, forward defines the prediction/inference actions
106
+ return self.model(x)
107
+
108
+ def training_step(self, batch, batch_idx):
109
+ # training_step defines the train loop. It is independent of forward
110
+ batch_x, batch_y, batch_x_mark, batch_y_mark, _ = batch
111
+
112
+ pred, true, inv_pred = self._process_one_batch(
113
+ self.trainer.datamodule.data_train,
114
+ batch_x,
115
+ batch_y,
116
+ batch_x_mark,
117
+ batch_y_mark,
118
+ ds_index=None,
119
+ )
120
+ loss = self.train_criterion(pred, true, inv_pred)
121
+
122
+ self.log("train_loss", loss, prog_bar=True, on_step=True, on_epoch=True)
123
+
124
+ self.log(
125
+ "train_pct_dir",
126
+ pct_direction_torch(pred, true),
127
+ prog_bar=True,
128
+ on_step=False,
129
+ on_epoch=True,
130
+ )
131
+ self.log(
132
+ "train_mag",
133
+ torch.linalg.norm(pred), # torch.mean(torch.abs(pred))
134
+ prog_bar=False,
135
+ on_step=False,
136
+ on_epoch=True,
137
+ )
138
+
139
+ if (
140
+ self.config.pre_epochs is not None
141
+ and self.config.pre_loss is not None
142
+ and self.current_epoch == self.config.pre_epochs
143
+ and not self.loss_switched
144
+ ):
145
+ # Revert to default loss
146
+ self.train_criterion = self._select_criterion(
147
+ loss_override=self.config.loss
148
+ )
149
+ self.other_criterion = self._select_criterion(
150
+ loss_override=self.config.loss
151
+ )
152
+ self.loss_switched = True
153
+
154
+ return loss
155
+
156
+ def validation_step(self, batch, batch_idx, dataloader_idx=0):
157
+ # validation_step defines the validation loop. It is independent of forward
158
+ batch_x, batch_y, batch_x_mark, batch_y_mark, _ = batch
159
+
160
+ pred, true, inv_pred = self._process_one_batch(
161
+ self.trainer.datamodule.data_val,
162
+ batch_x,
163
+ batch_y,
164
+ batch_x_mark,
165
+ batch_y_mark,
166
+ ds_index=None,
167
+ )
168
+
169
+ if dataloader_idx == 0:
170
+ # Actual val dataset
171
+ assert self.trainer.val_dataloaders[0].dataset.flag == "val"
172
+ loss = self.other_criterion(pred, true, inv_pred)
173
+ self.log(
174
+ "val_loss",
175
+ loss,
176
+ prog_bar=True,
177
+ on_step=False,
178
+ on_epoch=True,
179
+ sync_dist=False,
180
+ add_dataloader_idx=False,
181
+ )
182
+
183
+ self.log(
184
+ "val_pct_dir",
185
+ pct_direction_torch(pred, true),
186
+ prog_bar=False,
187
+ on_step=False,
188
+ on_epoch=True,
189
+ add_dataloader_idx=False,
190
+ )
191
+ return loss
192
+ elif dataloader_idx == 1:
193
+ # TODO: If we are using torch metrics we should create an additional loss function
194
+ # Test dataset
195
+ assert self.trainer.val_dataloaders[1].dataset.flag == "test"
196
+ loss = self.other_criterion(pred, true, inv_pred)
197
+ self.log(
198
+ "test_loss",
199
+ loss,
200
+ prog_bar=True,
201
+ on_step=False,
202
+ on_epoch=True,
203
+ sync_dist=False,
204
+ add_dataloader_idx=False,
205
+ )
206
+ self.log(
207
+ "test_pct_dir",
208
+ pct_direction_torch(pred, true),
209
+ prog_bar=False,
210
+ on_step=False,
211
+ on_epoch=True,
212
+ add_dataloader_idx=False,
213
+ )
214
+ return loss
215
+
216
+ def test_step(self, batch, batch_idx, dataloader_idx=0):
217
+ # test_step defines the test loop. It is independent of forward
218
+ batch_x, batch_y, batch_x_mark, batch_y_mark, _ = batch
219
+
220
+ data_sets = [
221
+ self.trainer.datamodule.data_train,
222
+ self.trainer.datamodule.data_val,
223
+ self.trainer.datamodule.data_test,
224
+ ]
225
+
226
+ pred, true, inv_pred = self._process_one_batch(
227
+ data_sets[dataloader_idx],
228
+ batch_x,
229
+ batch_y,
230
+ batch_x_mark,
231
+ batch_y_mark,
232
+ ds_index=None,
233
+ )
234
+ loss = self.other_criterion(pred, true, inv_pred)
235
+
236
+ # if dataloader_idx == 0:
237
+ self.log(
238
+ "test_loss",
239
+ loss,
240
+ sync_dist=False,
241
+ )
242
+
243
+ def predict_step(self, batch, batch_idx, dataloader_idx=0):
244
+ batch_x, batch_y, batch_x_mark, batch_y_mark, _ = batch
245
+
246
+ data_sets = [
247
+ self.trainer.datamodule.data_train,
248
+ self.trainer.datamodule.data_val,
249
+ self.trainer.datamodule.data_test,
250
+ ]
251
+
252
+ pred, true, inv_pred = self._process_one_batch(
253
+ data_sets[dataloader_idx],
254
+ batch_x,
255
+ batch_y,
256
+ batch_x_mark,
257
+ batch_y_mark,
258
+ ds_index=None,
259
+ )
260
+
261
+ # dataset = self.trainer.predict_dataloaders[dataloader_idx].dataset
262
+ # batch_x_raw_date, batch_y_raw_date = dataset.index_to_dates(batch_idx)
263
+
264
+ if "mse" in self.config.loss or "mae" in self.config.loss:
265
+ pred = inv_pred
266
+ return {
267
+ "pred": pred,
268
+ "true": true,
269
+ }
270
+
271
+ # def on_predict_epoch_end(self, results):
272
+ # pass
273
+
274
+ # def on_predict_end(self):
275
+ # pass
276
+
277
+ def _process_one_batch(
278
+ self,
279
+ dataset_object,
280
+ batch_x,
281
+ batch_y,
282
+ batch_x_mark,
283
+ batch_y_mark,
284
+ ds_index=None,
285
+ ):
286
+ # Decoder input if self.config.dec_in
287
+ dec_inp = None
288
+ # if self.config.dec_in and (
289
+ # self.config.padding == 0 or self.config.padding == 1
290
+ # ):
291
+ # # FF: dec_inp = torch.zeros_like(batch_y[:, -self.config.pred_len:, :]).float()
292
+ # dec_inp = torch.full(
293
+ # [batch_y.shape[0], self.config.pred_len, batch_y.shape[-1]],
294
+ # self.config.padding,
295
+ # ).float()
296
+ # dec_inp = (
297
+ # torch.cat([batch_y[:, : self.config.label_len, :], dec_inp], dim=1)
298
+ # .float()
299
+ # .to(self.device)
300
+ # )
301
+
302
+ # Encoder - Decoder
303
+ if self.config.output_attention:
304
+ outputs = self.model(batch_x, batch_x_mark, dec_inp, batch_y_mark)[0]
305
+ else:
306
+ outputs = self.model(batch_x, batch_x_mark, dec_inp, batch_y_mark)
307
+ # if self.config.inverse_output:
308
+ inv_outputs = dataset_object.inverse_transform(outputs)
309
+ f_dim = -1 if self.config.features == "MS" else 0
310
+
311
+ # if ds_index is None:
312
+ batch_y = batch_y[:, -self.config.pred_len :, f_dim:]
313
+ return outputs, batch_y, inv_outputs
314
+ # else:
315
+ # batch_x_raw_dates, batch_y_raw_dates = dataset_object.index_to_dates(
316
+ # ds_index
317
+ # )
318
+ # assert batch_y_raw_dates.shape == batch_y.shape[0:2]
319
+ # batch_y = batch_y[:, -self.config.pred_len :, f_dim:].to(self.device)
320
+ # batch_y_raw_dates = batch_y_raw_dates[:, -self.config.pred_len :]
321
+ # return outputs, batch_y, batch_y_raw_dates
322
+
323
+ def configure_optimizers(self):
324
+ if self.config.optim == "AdamW":
325
+ optimizer = torch.optim.AdamW(self.parameters(), lr=self.learning_rate)
326
+ elif self.config.optim == "Ranger":
327
+ optimizer = Ranger(self.parameters(), lr=self.learning_rate)
328
+ else:
329
+ optimizer = torch.optim.Adam(self.parameters(), lr=self.learning_rate)
330
+ # optimizer = torch.optim.SGD(self.parameters(), lr=self.learning_rate)
331
+
332
+ # Learning rate scheduler
333
+ if self.config.lradj == "type1":
334
+ lmbda = lambda epoch: 0.5
335
+ scheduler = torch.optim.lr_scheduler.MultiplicativeLR(
336
+ optimizer, lr_lambda=lmbda, verbose=True
337
+ )
338
+ elif self.config.lradj == "type2":
339
+ scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(
340
+ optimizer,
341
+ factor=0.5,
342
+ patience=10,
343
+ threshold=0,
344
+ cooldown=0,
345
+ verbose=True,
346
+ min_lr=1e-8,
347
+ )
348
+ scheduler = {
349
+ "scheduler": scheduler,
350
+ "interval": "epoch", # called after each training epoch
351
+ "monitor": "val_loss",
352
+ }
353
+ elif self.config.lradj == "type3":
354
+ scheduler = torch.optim.lr_scheduler.OneCycleLR(
355
+ optimizer,
356
+ max_lr=self.config.learning_rate,
357
+ steps_per_epoch=len(self.trainer.datamodule.data_train)
358
+ // self.config.batch_size, # Would be nicer to use self.trainer.train_dataloader.dataset but there is a pl bug
359
+ epochs=self.config.max_epochs,
360
+ )
361
+ scheduler = {
362
+ "scheduler": scheduler,
363
+ "interval": "step", # called after each training step
364
+ }
365
+ else:
366
+ return optimizer
367
+
368
+ return [optimizer], [scheduler]
exp_timeseries.py ADDED
@@ -0,0 +1,466 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import pytorch_lightning as pl
3
+
4
+ from collections import defaultdict
5
+ from models.Basic import MLP
6
+ from models.Lstm import LSTM
7
+ from models.Informer import Informer, InformerStack
8
+ from models.Stockformer import Stockformer
9
+ from utils.stock_metrics import get_stock_algo, pct_direction_torch
10
+ from torchmetrics import MeanSquaredError, MeanAbsoluteError
11
+ from torch_optimizer import Ranger
12
+
13
+
14
+ class ExpTimeseries(pl.LightningModule):
15
+ def __init__(self, config):
16
+ super().__init__()
17
+ self.config = config
18
+
19
+ # pl makes self.learning_rate special
20
+ self.learning_rate = config.learning_rate
21
+
22
+ # Torch metrics has a state that resets but val and train can be called in unison so we split
23
+ # If pre_loss isn't supplied (ie: pre_loss is None) it will default to config.loss
24
+ self.train_criterion = self._select_criterion(
25
+ loss_override=self.config.pre_loss
26
+ )
27
+ self.other_criterion = self._select_criterion(
28
+ loss_override=self.config.pre_loss
29
+ )
30
+ self.metric = self._select_criterion(metric=True)
31
+ self.loss_switched = False
32
+
33
+ self._build_model()
34
+ # self.save_hyperparameters()
35
+ self.loss_reg = None
36
+ self.scale = None
37
+ self.val_log_growth_sum = None
38
+ self.val_log_growth_count = None
39
+ self.test_log_growth_sum = None
40
+ self.test_log_growth_count = None
41
+
42
+ def _build_model(self):
43
+ model_dict = {
44
+ "informer": Informer,
45
+ "informerstack": InformerStack,
46
+ "mlp": MLP,
47
+ "stockformer": Stockformer,
48
+ "lstm": LSTM,
49
+ }
50
+ assert (
51
+ self.config.model in model_dict
52
+ ), f"Invalid config.model: {self.config.model}, options: {list(model_dict.keys())}"
53
+ self.model = model_dict[self.config.model](self.config).float()
54
+
55
+ # Load model
56
+ if self.config.load_model_path is not None:
57
+ self.load_from_checkpoint(self.config.load_model_path)
58
+
59
+ def _select_criterion(self, loss_override=None, metric=False):
60
+ loss = self.config.loss
61
+ if loss_override is not None:
62
+ loss = loss_override
63
+
64
+ def combine_loss(loss, weights=None):
65
+ if weights is None:
66
+ weights = [1.0] * len(loss)
67
+ def combined(pred, target, inv_pred, input_scale=None):
68
+ return loss[0](pred, target, input_scale=input_scale)
69
+ # return sum(w*l(inv_pred, target) if "Mean" in l.__class__.__name__ else w*l(pred, target) for w,l in zip(weights, loss))
70
+ return combined
71
+
72
+ def loss_lib(loss: str):
73
+ if "stock" in loss:
74
+ # Using Stock Loss
75
+ _, stock_loss_mode = loss.split("_")
76
+ target_type = self.config.target.split("_")[1]
77
+ assert (
78
+ target_type == "pctchange" or target_type == "logpctchange"
79
+ ), "Can't use stock loss unless target is pctchange or logpctchange"
80
+ assert (
81
+ self.config.scale and
82
+ self.config.inverse_pred
83
+ # and not self.config.inverse_output
84
+ ), "Can't use stock loss without scale, inverse pred, and not inverse output"
85
+
86
+ criterion = get_stock_algo(target_type, stock_loss_mode)
87
+ print("criterion:", criterion)
88
+ if metric:
89
+ def mt(x, y, input_scale):
90
+ return criterion.metric(x, y, input_scale=input_scale)
91
+ return mt
92
+ else:
93
+ return lambda x, y, input_scale: [-1 * criterion.loss(x, y).mean(), criterion.sharpe(x, y).mean()]
94
+ # return lambda x, y: -LogPctProfitTanhV1.loss(x, y).mean()
95
+ # return get_stock_loss(target_type, stock_loss_mode, threshold=0.0)
96
+ elif loss == "mae":
97
+ assert (
98
+ self.config.scale
99
+ and self.config.inverse_pred
100
+ # and self.config.inverse_output
101
+ ), "Can't use mae loss without scale, inverse pred, and inverse output"
102
+ return MeanAbsoluteError().cuda()
103
+ elif loss == "mse":
104
+ assert (
105
+ self.config.scale
106
+ and self.config.inverse_pred
107
+ # and self.config.inverse_output
108
+ ), "Can't use mse loss without scale, inverse pred, and inverse output"
109
+ return MeanSquaredError().cuda()
110
+ loss_list = [ loss_lib(loss_type) for loss_type in loss.split('+') ]
111
+ weights = [1.0] if '+' not in loss else [1.0, 0.1]
112
+ return combine_loss(loss_list, weights)
113
+
114
+ raise Exception(f"Invalid loss: {loss}")
115
+
116
+ def forward(self, x):
117
+ # in lightning, forward defines the prediction/inference actions
118
+ return self.model(x)
119
+
120
+ def training_step(self, batch, batch_idx):
121
+ # training_step defines the train loop. It is independent of forward
122
+ batch_x, batch_y, batch_x_mark, batch_y_mark, _ = batch
123
+
124
+ sigma_x = 0.001
125
+ batch_x = batch_x + (torch.randn_like(batch_x)*2-1) * sigma_x
126
+ # print(sigma_x.mean(), batch_x.mean(), batch_x.shape)
127
+ # sigma_y = 0.01 * batch_y.std(dim=(1, 2), keepdim=True)
128
+ # batch_y = batch_y + (torch.randn_like(batch_y)*2-1) * sigma_y
129
+
130
+ pred, true, inv_pred = self._process_one_batch(
131
+ self.trainer.datamodule.data_train,
132
+ batch_x,
133
+ batch_y,
134
+ batch_x_mark,
135
+ batch_y_mark,
136
+ ds_index=None,
137
+ )
138
+ # print(self.loss_reg)
139
+ loss, sharpe = self.train_criterion(pred, true, inv_pred)
140
+ self.log("train_loss", loss, prog_bar=True, on_step=False, on_epoch=True)
141
+ self.log("train_sharpe", sharpe, prog_bar=True, on_step=False, on_epoch=True)
142
+ self.log("wavelet_loss", self.loss_reg, prog_bar=True, on_step=False, on_epoch=True)
143
+
144
+ # self.log(
145
+ # "tr_pct_dir",
146
+ # pct_direction_torch(pred, true),
147
+ # prog_bar=True,
148
+ # on_step=False,
149
+ # on_epoch=True,
150
+ # )
151
+ # self.log(
152
+ # "tr_mag",
153
+ # torch.linalg.norm(pred), # torch.mean(torch.abs(pred))
154
+ # prog_bar=False,
155
+ # on_step=False,
156
+ # on_epoch=True,
157
+ # )
158
+
159
+ if (
160
+ self.config.pre_epochs is not None
161
+ and self.config.pre_loss is not None
162
+ and self.current_epoch == self.config.pre_epochs
163
+ and not self.loss_switched
164
+ ):
165
+ # Revert to default loss
166
+ self.train_criterion = self._select_criterion(
167
+ loss_override=self.config.loss
168
+ )
169
+ self.other_criterion = self._select_criterion(
170
+ loss_override=self.config.loss
171
+ )
172
+ self.loss_switched = True
173
+
174
+ return loss + torch.exp(-2.5*sharpe) + 1e0*self.loss_reg
175
+
176
+ def validation_step(self, batch, batch_idx, dataloader_idx=0):
177
+ # validation_step defines the validation loop. It is independent of forward
178
+ batch_x, batch_y, batch_x_mark, batch_y_mark, _ = batch
179
+
180
+ pred, true, inv_pred = self._process_one_batch(
181
+ self.trainer.datamodule.data_val,
182
+ batch_x,
183
+ batch_y,
184
+ batch_x_mark,
185
+ batch_y_mark,
186
+ ds_index=None,
187
+ )
188
+
189
+ if dataloader_idx == 0:
190
+ # Actual val dataset
191
+ # assert self.trainer.val_dataloaders[0].dataset.flag == "val"
192
+ loss, sharpe = self.other_criterion(pred, true, inv_pred)
193
+ self.log(
194
+ "val_loss",
195
+ loss,
196
+ prog_bar=True,
197
+ on_step=False,
198
+ on_epoch=True,
199
+ sync_dist=False,
200
+ add_dataloader_idx=False,
201
+ )
202
+ self.log(
203
+ "val_sharpe",
204
+ sharpe,
205
+ prog_bar=True,
206
+ on_step=False,
207
+ on_epoch=True,
208
+ sync_dist=False,
209
+ add_dataloader_idx=False,
210
+ )
211
+ raw, self.scale = self.metric(pred, true, inv_pred)
212
+ self.val_log_growth_sum[0] += raw.detach().sum()
213
+ self.val_log_growth_count[0] += raw.numel()
214
+ # self.log(
215
+ # "val_pct_dir",
216
+ # pct_direction_torch(pred, true),
217
+ # prog_bar=False,
218
+ # on_step=False,
219
+ # on_epoch=True,
220
+ # add_dataloader_idx=False,
221
+ # )
222
+ return
223
+ elif dataloader_idx == 1:
224
+ # TODO: If we are using torch metrics we should create an additional loss function
225
+ # Test dataset
226
+ assert self.trainer.val_dataloaders[1].dataset.flag == "test"
227
+ loss, sharpe = self.other_criterion(pred, true, inv_pred)
228
+ self.log(
229
+ "test_loss",
230
+ loss,
231
+ prog_bar=True,
232
+ on_step=False,
233
+ on_epoch=True,
234
+ sync_dist=False,
235
+ add_dataloader_idx=False,
236
+ )
237
+ self.log(
238
+ "test_sharpe",
239
+ sharpe,
240
+ prog_bar=True,
241
+ on_step=False,
242
+ on_epoch=True,
243
+ sync_dist=False,
244
+ add_dataloader_idx=False,
245
+ )
246
+ raw, _ = self.metric(pred, true, inv_pred, self.scale)
247
+ self.val_log_growth_sum[1] += raw.detach().sum()
248
+ self.val_log_growth_count[1] += raw.numel()
249
+ # self.log(
250
+ # "test_pct_dir",
251
+ # pct_direction_torch(pred, true),
252
+ # prog_bar=False,
253
+ # on_step=False,
254
+ # on_epoch=True,
255
+ # add_dataloader_idx=False,
256
+ # )
257
+ return
258
+
259
+ def on_validation_epoch_start(self):
260
+ self.val_log_growth_sum = defaultdict(lambda: 0.0)
261
+ self.val_log_growth_count = defaultdict(int)
262
+
263
+ def on_validation_epoch_end(self):
264
+ for dl_idx, sum_log in self.val_log_growth_sum.items():
265
+ # count = self.val_log_growth_count[dl_idx]
266
+ factor = torch.exp(sum_log)
267
+ roi = factor - 1
268
+ if dl_idx == 0:
269
+ name = "val_roi"
270
+ elif dl_idx == 1:
271
+ name = "test_roi"
272
+ else:
273
+ raise Exception
274
+ self.log(
275
+ name,
276
+ roi,
277
+ prog_bar=True,
278
+ on_step=False,
279
+ on_epoch=True,
280
+ sync_dist=False,
281
+ add_dataloader_idx=False,
282
+ )
283
+ # # 或者用平均 log-growth 当 metric(和 T 无关,更稳)
284
+ # mean_log_growth = self.val_log_growth_sum / self.val_log_growth_count
285
+ # self.log("val_mean_log_growth", mean_log_growth, prog_bar=False)
286
+
287
+ def test_step(self, batch, batch_idx, dataloader_idx=0):
288
+ # test_step defines the test loop. It is independent of forward
289
+ batch_x, batch_y, batch_x_mark, batch_y_mark, _ = batch
290
+
291
+ data_sets = [
292
+ self.trainer.datamodule.data_train,
293
+ self.trainer.datamodule.data_val,
294
+ self.trainer.datamodule.data_test,
295
+ ]
296
+
297
+ pred, true, inv_pred = self._process_one_batch(
298
+ data_sets[dataloader_idx],
299
+ batch_x,
300
+ batch_y,
301
+ batch_x_mark,
302
+ batch_y_mark,
303
+ ds_index=None,
304
+ )
305
+ # loss = self.other_criterion(pred, true, inv_pred)
306
+ # # if dataloader_idx == 0:
307
+ # self.log(
308
+ # "test_loss",
309
+ # loss,
310
+ # sync_dist=False,
311
+ # )
312
+
313
+ if dataloader_idx == 0:
314
+ raw, _ = self.metric(pred, true, inv_pred)
315
+ if dataloader_idx == 1:
316
+ raw, self.scale = self.metric(pred, true, inv_pred)
317
+ if dataloader_idx == 2:
318
+ raw, _ = self.metric(pred, true, inv_pred, self.scale)
319
+ self.test_log_growth_sum[dataloader_idx] += raw.detach().sum()
320
+ self.test_log_growth_count[dataloader_idx] += raw.numel()
321
+
322
+ def on_test_epoch_start(self):
323
+ self.test_log_growth_sum = defaultdict(lambda: 0.0)
324
+ self.test_log_growth_count = defaultdict(int)
325
+
326
+ def on_test_epoch_end(self):
327
+ for dl_idx, sum_log in self.test_log_growth_sum.items():
328
+ factor = torch.exp(sum_log)
329
+ roi = factor - 1
330
+ self.log(
331
+ "test_roi",
332
+ roi,
333
+ sync_dist=False,
334
+ )
335
+
336
+ def predict_step(self, batch, batch_idx, dataloader_idx=0):
337
+ batch_x, batch_y, batch_x_mark, batch_y_mark, _ = batch
338
+
339
+ data_sets = [
340
+ self.trainer.datamodule.data_train,
341
+ self.trainer.datamodule.data_val,
342
+ self.trainer.datamodule.data_test,
343
+ ]
344
+
345
+ pred, true, inv_pred = self._process_one_batch(
346
+ data_sets[dataloader_idx],
347
+ batch_x,
348
+ batch_y,
349
+ batch_x_mark,
350
+ batch_y_mark,
351
+ ds_index=None,
352
+ )
353
+
354
+ # dataset = self.trainer.predict_dataloaders[dataloader_idx].dataset
355
+ # batch_x_raw_date, batch_y_raw_date = dataset.index_to_dates(batch_idx)
356
+
357
+ if "mse" in self.config.loss or "mae" in self.config.loss:
358
+ pred = inv_pred
359
+ return {
360
+ "pred": pred.detach().to(torch.float32),
361
+ "true": true.detach().to(torch.float32),
362
+ }
363
+
364
+ # def on_predict_epoch_end(self, results):
365
+ # pass
366
+
367
+ # def on_predict_end(self):
368
+ # pass
369
+
370
+ def _process_one_batch(
371
+ self,
372
+ dataset_object,
373
+ batch_x,
374
+ batch_y,
375
+ batch_x_mark,
376
+ batch_y_mark,
377
+ ds_index=None,
378
+ ):
379
+ # Decoder input if self.config.dec_in
380
+ dec_inp = None
381
+ # if self.config.dec_in and (
382
+ # self.config.padding == 0 or self.config.padding == 1
383
+ # ):
384
+ # # FF: dec_inp = torch.zeros_like(batch_y[:, -self.config.pred_len:, :]).float()
385
+ # dec_inp = torch.full(
386
+ # [batch_y.shape[0], self.config.pred_len, batch_y.shape[-1]],
387
+ # self.config.padding,
388
+ # ).float()
389
+ # dec_inp = (
390
+ # torch.cat([batch_y[:, : self.config.label_len, :], dec_inp], dim=1)
391
+ # .float()
392
+ # .to(self.device)
393
+ # )
394
+
395
+ # Encoder - Decoder
396
+ if self.config.output_attention:
397
+ outputs = self.model(batch_x, batch_x_mark, dec_inp, batch_y_mark)[0]
398
+ else:
399
+ outputs, loss_reg = self.model(batch_x, batch_x_mark, dec_inp, batch_y_mark)
400
+ self.loss_reg = loss_reg
401
+ # if self.config.inverse_output:
402
+ f_dim = -1 if self.config.features == "MS" else 0
403
+
404
+ # if ds_index is None:
405
+ batch_y = batch_y[:, -self.config.pred_len :, f_dim:]
406
+ # print(batch_y.std())
407
+ # batch_y = dataset_object.inverse_transform(batch_y)
408
+ # print(batch_y.std())
409
+ # while 1:pass
410
+ inv_outputs = dataset_object.inverse_transform(outputs)
411
+ return outputs, batch_y, inv_outputs
412
+ # else:
413
+ # batch_x_raw_dates, batch_y_raw_dates = dataset_object.index_to_dates(
414
+ # ds_index
415
+ # )
416
+ # assert batch_y_raw_dates.shape == batch_y.shape[0:2]
417
+ # batch_y = batch_y[:, -self.config.pred_len :, f_dim:].to(self.device)
418
+ # batch_y_raw_dates = batch_y_raw_dates[:, -self.config.pred_len :]
419
+ # return outputs, batch_y, batch_y_raw_dates
420
+
421
+ def configure_optimizers(self):
422
+ if self.config.optim == "AdamW":
423
+ optimizer = torch.optim.AdamW(self.parameters(), lr=self.learning_rate)
424
+ elif self.config.optim == "Ranger":
425
+ optimizer = Ranger(self.parameters(), lr=self.learning_rate)
426
+ else:
427
+ optimizer = torch.optim.Adam(self.parameters(), lr=self.learning_rate)
428
+ # optimizer = torch.optim.SGD(self.parameters(), lr=self.learning_rate)
429
+
430
+ # Learning rate scheduler
431
+ if self.config.lradj == "type1":
432
+ lmbda = lambda epoch: 0.5
433
+ scheduler = torch.optim.lr_scheduler.MultiplicativeLR(
434
+ optimizer, lr_lambda=lmbda, verbose=True
435
+ )
436
+ elif self.config.lradj == "type2":
437
+ scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(
438
+ optimizer,
439
+ factor=0.5,
440
+ patience=10,
441
+ threshold=0,
442
+ cooldown=0,
443
+ verbose=True,
444
+ min_lr=1e-8,
445
+ )
446
+ scheduler = {
447
+ "scheduler": scheduler,
448
+ "interval": "epoch", # called after each training epoch
449
+ "monitor": "val_loss",
450
+ }
451
+ elif self.config.lradj == "type3":
452
+ scheduler = torch.optim.lr_scheduler.OneCycleLR(
453
+ optimizer,
454
+ max_lr=self.config.learning_rate,
455
+ steps_per_epoch=len(self.trainer.datamodule.data_train)
456
+ // self.config.batch_size, # Would be nicer to use self.trainer.train_dataloader.dataset but there is a pl bug
457
+ epochs=self.config.max_epochs,
458
+ )
459
+ scheduler = {
460
+ "scheduler": scheduler,
461
+ "interval": "step", # called after each training step
462
+ }
463
+ else:
464
+ return optimizer
465
+
466
+ return [optimizer], [scheduler]
general_Banks_Diversified.yaml ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ activation: gelu
2
+ tok_emb: raw
3
+ attn: full
4
+ c_out: 1
5
+ cols:
6
+ - EWBC_logpctchange
7
+ - SNV_logpctchange
8
+ - FITB_logpctchange
9
+ - TFC_logpctchange
10
+ - FNB_logpctchange
11
+ - MTB_logpctchange
12
+ - FULT_logpctchange
13
+ - ZION_logpctchange
14
+ - KEY_logpctchange
15
+ - CFG_logpctchange
16
+ - HBAN_logpctchange
17
+ data_path: material_Banks_Diversified_1h.csv
18
+ date_end: '2025-10-29'
19
+ date_start: '2020-10-29'
20
+ # date_test: '2025-06-29'
21
+ des: full_1h
22
+ distil: false
23
+ dont_shuffle_train: false
24
+ dropout: 0.1
25
+ dropout_emb: 0.0
26
+ t_embed: time2vec_app
27
+ enc_in: 11
28
+ factor: 5
29
+ features: MS
30
+ freq: h
31
+ inverse_pred: true
32
+ loss: stock_tanhv1
33
+ final_mode: mode3
34
+ label_len: 0
35
+ learning_rate: 1.0e-04
36
+ batch_size: 256
37
+ d_ff: 1024
38
+ d_model: 512
39
+ n_heads: 512
40
+ seq_len: 100
41
+ e_layers: 6
42
+ emb_t2v_app_dim: 128
43
+ ln_mode: pre
44
+ lradj: null
45
+ mix: false
46
+ model: stockformer
47
+ no_early_stop: false
48
+ no_scale_mean: true
49
+ optim: AdamW
50
+ output_attention: false
51
+ patience: 100
52
+ pred_len: 1
53
+ root_path: ./data/stock/
54
+ scale: true
55
+ seed: 4
56
+ target: HBAN_logpctchange
57
+ max_epochs: 1000
general_Life_Insurance.yaml ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ activation: gelu
2
+ tok_emb: raw
3
+ attn: full
4
+ c_out: 1
5
+ cols:
6
+ - CNO_logpctchange
7
+ - PFG_logpctchange
8
+ - LNC_logpctchange
9
+ - MET_logpctchange
10
+ - PRU_logpctchange
11
+ - BHF_logpctchange
12
+ - EQH_logpctchange
13
+ data_path: material_Life_Insurance_1h.csv
14
+ date_end: '2025-10-29'
15
+ date_start: '2020-10-29'
16
+ # date_test: '2025-06-29'
17
+ des: full_1h
18
+ distil: false
19
+ dont_shuffle_train: false
20
+ dropout: 0.1
21
+ dropout_emb: 0.0
22
+ t_embed: time2vec_app
23
+ enc_in: 7
24
+ factor: 5
25
+ features: MS
26
+ freq: h
27
+ inverse_pred: true
28
+ loss: stock_tanhv1
29
+ final_mode: mode3
30
+ label_len: 0
31
+ learning_rate: 1.0e-04
32
+ batch_size: 256
33
+ d_ff: 1024
34
+ d_model: 512
35
+ n_heads: 512
36
+ seq_len: 100
37
+ e_layers: 6
38
+ emb_t2v_app_dim: 128
39
+ ln_mode: pre
40
+ lradj: null
41
+ mix: false
42
+ model: stockformer
43
+ no_early_stop: false
44
+ no_scale_mean: true
45
+ optim: AdamW
46
+ output_attention: false
47
+ patience: 100
48
+ pred_len: 1
49
+ root_path: ./data/stock/
50
+ scale: true
51
+ seed: 4
52
+ target: EQH_logpctchange
53
+ max_epochs: 1000
general_Semiconductors_Equipment.yaml ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ activation: gelu
2
+ attn: full
3
+ c_out: 1
4
+ cols:
5
+ - AMAT_logpctchange
6
+ - LRCX_logpctchange
7
+ - KLAC_logpctchange
8
+ data_path: material_Semiconductors_Equipment_1h.csv
9
+ date_end: '2025-10-29'
10
+ date_start: '2020-10-29'
11
+ # date_test: '2025-06-29'
12
+ des: full_1h
13
+ distil: false
14
+ dont_shuffle_train: false
15
+ dropout: 0.0
16
+ dropout_emb: 0.0
17
+ t_embed: time2vec_app
18
+ enc_in: 3
19
+ factor: 5
20
+ features: MS
21
+ freq: h
22
+ inverse_pred: true
23
+ loss: stock_tanhv1
24
+ final_mode: mode3
25
+ label_len: 0
26
+ learning_rate: 1.0e-04
27
+ batch_size: 256
28
+ d_ff: 1024
29
+ d_model: 512
30
+ n_heads: 512
31
+ seq_len: 100
32
+ e_layers: 12
33
+ emb_t2v_app_dim: 256
34
+ ln_mode: pre
35
+ lradj: null
36
+ mix: false
37
+ model: stockformer
38
+ no_early_stop: false
39
+ no_scale_mean: true
40
+ optim: AdamW
41
+ output_attention: false
42
+ patience: 100
43
+ pred_len: 1
44
+ root_path: ./data/stock/
45
+ scale: true
46
+ seed: 4
47
+ target: KLAC_logpctchange
48
+ max_epochs: 333
layers/__init__.py ADDED
File without changes
layers/attn.py ADDED
@@ -0,0 +1,184 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import torch.nn as nn
3
+ import torch.nn.functional as F
4
+
5
+ import numpy as np
6
+
7
+ from math import sqrt
8
+ from utils.masking import TriangularCausalMask, ProbMask
9
+
10
+
11
+ class FullAttention(nn.Module):
12
+ def __init__(
13
+ self,
14
+ mask_flag=True,
15
+ factor=5,
16
+ scale=None,
17
+ attention_dropout=0.1,
18
+ output_attention=False,
19
+ ):
20
+ super(FullAttention, self).__init__()
21
+ self.scale = scale
22
+ self.mask_flag = mask_flag
23
+ self.output_attention = output_attention
24
+ self.dropout = nn.Dropout(attention_dropout)
25
+
26
+ def forward(self, queries, keys, values, attn_mask):
27
+ B, L, H, E = queries.shape
28
+ _, S, _, D = values.shape
29
+ scale = self.scale or 1.0 / sqrt(E)
30
+
31
+ scores = torch.einsum("blhe,bshe->bhls", queries, keys)
32
+ if self.mask_flag:
33
+ if attn_mask is None:
34
+ attn_mask = TriangularCausalMask(B, L, device=queries.device)
35
+
36
+ scores.masked_fill_(attn_mask.mask, -np.inf)
37
+
38
+ A = self.dropout(torch.softmax(scale * scores, dim=-1))
39
+ V = torch.einsum("bhls,bshd->blhd", A, values)
40
+
41
+ if self.output_attention:
42
+ return (V.contiguous(), A)
43
+ else:
44
+ return (V.contiguous(), None)
45
+
46
+
47
+ class ProbAttention(nn.Module):
48
+ def __init__(
49
+ self,
50
+ mask_flag=True,
51
+ factor=5,
52
+ scale=None,
53
+ attention_dropout=0.1,
54
+ output_attention=False,
55
+ ):
56
+ super(ProbAttention, self).__init__()
57
+ self.factor = factor
58
+ self.scale = scale
59
+ self.mask_flag = mask_flag
60
+ self.output_attention = output_attention
61
+ self.dropout = nn.Dropout(attention_dropout)
62
+
63
+ def _prob_QK(self, Q, K, sample_k, n_top): # n_top: c*ln(L_q)
64
+ # Q [B, H, L, D]
65
+ B, H, L_K, E = K.shape
66
+ _, _, L_Q, _ = Q.shape
67
+
68
+ # calculate the sampled Q_K
69
+ K_expand = K.unsqueeze(-3).expand(B, H, L_Q, L_K, E)
70
+ index_sample = torch.randint(
71
+ L_K, (L_Q, sample_k)
72
+ ) # real U = U_part(factor*ln(L_k))*L_q
73
+ K_sample = K_expand[:, :, torch.arange(L_Q).unsqueeze(1), index_sample, :]
74
+ Q_K_sample = torch.matmul(Q.unsqueeze(-2), K_sample.transpose(-2, -1)).squeeze(
75
+ -2
76
+ )
77
+
78
+ # find the Top_k query with sparisty measurement
79
+ M = Q_K_sample.max(-1)[0] - torch.div(Q_K_sample.sum(-1), L_K)
80
+ M_top = M.topk(n_top, sorted=False)[1]
81
+
82
+ # use the reduced Q to calculate Q_K
83
+ Q_reduce = Q[
84
+ torch.arange(B)[:, None, None], torch.arange(H)[None, :, None], M_top, :
85
+ ] # factor*ln(L_q)
86
+ Q_K = torch.matmul(Q_reduce, K.transpose(-2, -1)) # factor*ln(L_q)*L_k
87
+
88
+ return Q_K, M_top
89
+
90
+ def _get_initial_context(self, V, L_Q):
91
+ B, H, L_V, D = V.shape
92
+ if not self.mask_flag:
93
+ # V_sum = V.sum(dim=-2)
94
+ V_sum = V.mean(dim=-2)
95
+ contex = V_sum.unsqueeze(-2).expand(B, H, L_Q, V_sum.shape[-1]).clone()
96
+ else: # use mask
97
+ assert L_Q == L_V # requires that L_Q == L_V, i.e. for self-attention only
98
+ contex = V.cumsum(dim=-2)
99
+ return contex
100
+
101
+ def _update_context(self, context_in, V, scores, index, L_Q, attn_mask):
102
+ B, H, L_V, D = V.shape
103
+
104
+ if self.mask_flag:
105
+ attn_mask = ProbMask(B, H, L_Q, index, scores, device=V.device)
106
+ scores.masked_fill_(attn_mask.mask, -np.inf)
107
+
108
+ attn = torch.softmax(scores, dim=-1) # nn.Softmax(dim=-1)(scores)
109
+
110
+ context_in[
111
+ torch.arange(B)[:, None, None], torch.arange(H)[None, :, None], index, :
112
+ ] = torch.matmul(attn, V).type_as(context_in)
113
+ if self.output_attention:
114
+ attns = (torch.ones([B, H, L_V, L_V]) / L_V).type_as(attn).to(attn.device)
115
+ attns[
116
+ torch.arange(B)[:, None, None], torch.arange(H)[None, :, None], index, :
117
+ ] = attn
118
+ return (context_in, attns)
119
+ else:
120
+ return (context_in, None)
121
+
122
+ def forward(self, queries, keys, values, attn_mask):
123
+ B, L_Q, H, D = queries.shape
124
+ _, L_K, _, _ = keys.shape
125
+
126
+ queries = queries.transpose(2, 1)
127
+ keys = keys.transpose(2, 1)
128
+ values = values.transpose(2, 1)
129
+
130
+ U_part = self.factor * np.ceil(np.log(L_K)).astype("int").item() # c*ln(L_k)
131
+ u = self.factor * np.ceil(np.log(L_Q)).astype("int").item() # c*ln(L_q)
132
+
133
+ U_part = U_part if U_part < L_K else L_K
134
+ u = u if u < L_Q else L_Q
135
+
136
+ scores_top, index = self._prob_QK(queries, keys, sample_k=U_part, n_top=u)
137
+
138
+ # add scale factor
139
+ scale = self.scale or 1.0 / sqrt(D)
140
+ if scale is not None:
141
+ scores_top = scores_top * scale
142
+ # get the context
143
+ context = self._get_initial_context(values, L_Q)
144
+ # update the context with selected top_k queries
145
+ context, attn = self._update_context(
146
+ context, values, scores_top, index, L_Q, attn_mask
147
+ )
148
+
149
+ return context.transpose(2, 1).contiguous(), attn
150
+
151
+
152
+ class AttentionLayer(nn.Module):
153
+ def __init__(
154
+ self, attention, d_model, n_heads, d_keys=None, d_values=None, mix=False
155
+ ):
156
+ super(AttentionLayer, self).__init__()
157
+
158
+ d_keys = d_keys or (d_model // n_heads)
159
+ d_values = d_values or (d_model // n_heads)
160
+
161
+ self.inner_attention = attention
162
+ self.query_projection = nn.Linear(d_model, d_keys * n_heads)
163
+ self.key_projection = nn.Linear(d_model, d_keys * n_heads)
164
+ self.value_projection = nn.Linear(d_model, d_values * n_heads)
165
+ self.out_projection = nn.Linear(d_values * n_heads, d_model)
166
+ self.n_heads = n_heads
167
+ self.mix = mix
168
+
169
+ def forward(self, queries, keys, values, attn_mask):
170
+ B, L, _ = queries.shape
171
+ _, S, _ = keys.shape
172
+ H = self.n_heads
173
+
174
+ queries = self.query_projection(queries).view(B, L, H, -1)
175
+ keys = self.key_projection(keys).view(B, S, H, -1)
176
+ values = self.value_projection(values).view(B, S, H, -1)
177
+
178
+ out, attn = self.inner_attention(queries, keys, values, attn_mask)
179
+ if self.mix:
180
+ # https://arxiv.org/pdf/2109.02789.pdf
181
+ out = out.transpose(2, 1).contiguous()
182
+ out = out.view(B, L, -1)
183
+
184
+ return self.out_projection(out), attn
layers/decoder.py ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import torch.nn as nn
3
+ import torch.nn.functional as F
4
+
5
+
6
+ class DecoderLayer(nn.Module):
7
+ def __init__(
8
+ self,
9
+ self_attention,
10
+ cross_attention,
11
+ d_model,
12
+ d_ff=None,
13
+ dropout=0.1,
14
+ activation="relu",
15
+ ):
16
+ super(DecoderLayer, self).__init__()
17
+ d_ff = d_ff or 4 * d_model
18
+ self.self_attention = self_attention
19
+ self.cross_attention = cross_attention
20
+ self.conv1 = nn.Conv1d(in_channels=d_model, out_channels=d_ff, kernel_size=1)
21
+ self.conv2 = nn.Conv1d(in_channels=d_ff, out_channels=d_model, kernel_size=1)
22
+ self.norm1 = nn.LayerNorm(d_model)
23
+ self.norm2 = nn.LayerNorm(d_model)
24
+ self.norm3 = nn.LayerNorm(d_model)
25
+ self.dropout = nn.Dropout(dropout)
26
+ self.activation = F.relu if activation == "relu" else F.gelu
27
+
28
+ def forward(self, x, cross, x_mask=None, cross_mask=None):
29
+ x = x + self.dropout(self.self_attention(x, x, x, attn_mask=x_mask)[0])
30
+ x = self.norm1(x)
31
+
32
+ x = x + self.dropout(
33
+ self.cross_attention(x, cross, cross, attn_mask=cross_mask)[0]
34
+ )
35
+
36
+ y = x = self.norm2(x)
37
+ y = self.dropout(self.activation(self.conv1(y.transpose(-1, 1))))
38
+ y = self.dropout(self.conv2(y).transpose(-1, 1))
39
+
40
+ return self.norm3(x + y)
41
+
42
+
43
+ class Decoder(nn.Module):
44
+ def __init__(self, layers, norm_layer=None):
45
+ super(Decoder, self).__init__()
46
+ self.layers = nn.ModuleList(layers)
47
+ self.norm = norm_layer
48
+
49
+ def forward(self, x, cross, x_mask=None, cross_mask=None):
50
+ for layer in self.layers:
51
+ x = layer(x, cross, x_mask=x_mask, cross_mask=cross_mask)
52
+
53
+ if self.norm is not None:
54
+ x = self.norm(x)
55
+
56
+ return x
layers/embed.py ADDED
@@ -0,0 +1,228 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import torch.nn as nn
3
+ import torch.nn.functional as F
4
+
5
+ import math
6
+
7
+
8
+ class PositionalEmbedding(nn.Module):
9
+ def __init__(self, d_model, max_len=5000):
10
+ super(PositionalEmbedding, self).__init__()
11
+ # Compute the positional encodings once in log space.
12
+ pe = torch.zeros(max_len, d_model).float()
13
+ pe.require_grad = False
14
+
15
+ position = torch.arange(0, max_len).float().unsqueeze(1)
16
+ div_term = (
17
+ torch.arange(0, d_model, 2).float() * -(math.log(10000.0) / d_model)
18
+ ).exp()
19
+
20
+ pe[:, 0::2] = torch.sin(position * div_term)
21
+ pe[:, 1::2] = torch.cos(position * div_term)
22
+
23
+ pe = pe.unsqueeze(0)
24
+ self.register_buffer("pe", pe)
25
+
26
+ def forward(self, x):
27
+ return self.pe[:, : x.size(1)]
28
+
29
+
30
+ class TokenEmbedding(nn.Module):
31
+ def __init__(self, c_in, d_model):
32
+ super(TokenEmbedding, self).__init__()
33
+ padding = 1 if torch.__version__ >= "1.5.0" else 2
34
+ self.tokenConv = nn.Conv1d(
35
+ in_channels=c_in,
36
+ out_channels=d_model,
37
+ kernel_size=3,
38
+ padding=padding,
39
+ padding_mode="circular",
40
+ )
41
+ for m in self.modules():
42
+ if isinstance(m, nn.Conv1d):
43
+ nn.init.kaiming_normal_(
44
+ m.weight, mode="fan_in", nonlinearity="leaky_relu"
45
+ )
46
+
47
+ def forward(self, x):
48
+ x = self.tokenConv(x.permute(0, 2, 1)).transpose(1, 2)
49
+ return x
50
+
51
+
52
+ class TokenEmbeddingBasic(nn.Module):
53
+ def __init__(self, c_in, d_model):
54
+ super(TokenEmbeddingBasic, self).__init__()
55
+ self.linear = nn.Linear(c_in, d_model)
56
+
57
+ def forward(self, x):
58
+ x = self.linear(x)
59
+ return x
60
+
61
+
62
+ class FixedEmbedding(nn.Module):
63
+ def __init__(self, c_in, d_model):
64
+ super(FixedEmbedding, self).__init__()
65
+
66
+ w = torch.zeros(c_in, d_model).float()
67
+ w.require_grad = False
68
+
69
+ position = torch.arange(0, c_in).float().unsqueeze(1)
70
+ div_term = (
71
+ torch.arange(0, d_model, 2).float() * -(math.log(10000.0) / d_model)
72
+ ).exp()
73
+
74
+ w[:, 0::2] = torch.sin(position * div_term)
75
+ w[:, 1::2] = torch.cos(position * div_term)
76
+
77
+ self.emb = nn.Embedding(c_in, d_model)
78
+ self.emb.weight = nn.Parameter(w, requires_grad=False)
79
+
80
+ def forward(self, x):
81
+ return self.emb(x).detach()
82
+
83
+
84
+ class TemporalEmbedding(nn.Module):
85
+ def __init__(self, d_model, t_embed="fixed", freq="h"):
86
+ super(TemporalEmbedding, self).__init__()
87
+
88
+ minute_size = 4
89
+ hour_size = 24
90
+ weekday_size = 7
91
+ day_size = 32
92
+ month_size = 13
93
+
94
+ Embed = FixedEmbedding if t_embed == "fixed" else nn.Embedding
95
+ if freq == "t":
96
+ self.minute_embed = Embed(minute_size, d_model)
97
+ self.hour_embed = Embed(hour_size, d_model)
98
+ self.weekday_embed = Embed(weekday_size, d_model)
99
+ self.day_embed = Embed(day_size, d_model)
100
+ self.month_embed = Embed(month_size, d_model)
101
+
102
+ def forward(self, x):
103
+ x = x.long()
104
+
105
+ minute_x = (
106
+ self.minute_embed(x[:, :, 4]) if hasattr(self, "minute_embed") else 0.0
107
+ )
108
+ hour_x = self.hour_embed(x[:, :, 3])
109
+ weekday_x = self.weekday_embed(x[:, :, 2])
110
+ day_x = self.day_embed(x[:, :, 1])
111
+ month_x = self.month_embed(x[:, :, 0])
112
+
113
+ return hour_x + weekday_x + day_x + month_x + minute_x
114
+
115
+
116
+ class TimeFeatureEmbedding(nn.Module):
117
+ def __init__(self, d_model, t_embed="timeF", freq="h"):
118
+ super(TimeFeatureEmbedding, self).__init__()
119
+
120
+ freq_map = {"h": 4, "t": 5, "s": 6, "m": 1, "a": 1, "w": 2, "d": 3, "b": 3}
121
+ d_inp = freq_map[freq]
122
+ self.embed = nn.Linear(d_inp, d_model)
123
+
124
+ def forward(self, x):
125
+ return self.embed(x)
126
+
127
+
128
+ class Time2Vec(nn.Module):
129
+ def __init__(self, time_emb_dim, freq="h"):
130
+ super(Time2Vec, self).__init__()
131
+ freq_map = {"h": 4, "t": 5, "s": 6, "m": 1, "a": 1, "w": 2, "d": 3, "b": 3}
132
+ time_feat_dim = freq_map[freq]
133
+
134
+ self.output_dim = time_emb_dim
135
+
136
+ self.out_features = time_emb_dim
137
+
138
+ # TODO: Initialize uniform
139
+ self.linear_periodic = nn.Linear(time_feat_dim, time_emb_dim - 1)
140
+ self.linear_non_periodic = nn.Linear(time_feat_dim, 1)
141
+
142
+ def forward(self, x):
143
+ non_periodic = self.linear_non_periodic(x.float())
144
+ periodic = torch.sin(self.linear_periodic(x.float()))
145
+ out = torch.cat([non_periodic, periodic], -1)
146
+ return out
147
+
148
+
149
+ class DataEmbedding(nn.Module):
150
+ def __init__(
151
+ self,
152
+ c_in,
153
+ d_model,
154
+ t_embed="fixed",
155
+ freq="h",
156
+ dropout_emb=0.01,
157
+ position_embedding=True,
158
+ emb_t2v_app_dim=32,
159
+ tok_emb="default",
160
+ ):
161
+ super(DataEmbedding, self).__init__()
162
+
163
+ self.append_time_emb = t_embed == "time2vec_app"
164
+
165
+ # For the temporal embedding
166
+ if t_embed is not None:
167
+ assert t_embed in [
168
+ "fixed",
169
+ "learned",
170
+ "timeF",
171
+ "time2vec_add",
172
+ "time2vec_app",
173
+ ], "Invalid t_embed"
174
+ if t_embed == "fixed" or t_embed == "learned":
175
+ self.temporal_embedding = TemporalEmbedding(
176
+ d_model=d_model, t_embed=t_embed, freq=freq
177
+ )
178
+ elif t_embed == "timeF":
179
+ self.temporal_embedding = TimeFeatureEmbedding(
180
+ d_model=d_model, t_embed=t_embed, freq=freq
181
+ )
182
+ elif t_embed == "time2vec_add":
183
+ # Time2Vec time embedding add elementwise
184
+ self.temporal_embedding = Time2Vec(time_emb_dim=d_model, freq=freq)
185
+ elif t_embed == "time2vec_app":
186
+ # Time2Vec time embedding appended
187
+ assert (
188
+ emb_t2v_app_dim is not None
189
+ ), "Need to provide the emb_t2v_app_dim argument"
190
+ assert emb_t2v_app_dim > 0 and emb_t2v_app_dim < d_model
191
+ self.temporal_embedding = Time2Vec(
192
+ time_emb_dim=emb_t2v_app_dim, freq=freq
193
+ )
194
+ d_model -= emb_t2v_app_dim
195
+ else:
196
+ self.temporal_embedding = lambda _: 0
197
+
198
+ # For the value embedding
199
+ if tok_emb == "basic":
200
+ self.value_embedding = TokenEmbeddingBasic(c_in=c_in, d_model=d_model)
201
+ elif tok_emb == "raw":
202
+ self.value_embedding = lambda x: x
203
+ assert c_in == d_model, "c_in and d_model must be equal for raw embedding"
204
+ assert (
205
+ t_embed != "time2vec_app"
206
+ ), "time2vec_app not supported for raw embedding"
207
+ else:
208
+ self.value_embedding = TokenEmbedding(c_in=c_in, d_model=d_model)
209
+
210
+ self.position_embedding = (
211
+ PositionalEmbedding(d_model=d_model) if position_embedding else lambda x: 0
212
+ )
213
+
214
+ self.dropout = nn.Dropout(p=dropout_emb)
215
+
216
+ def forward(self, x, x_mark):
217
+ if self.append_time_emb:
218
+ x = self.value_embedding(x) + self.position_embedding(x)
219
+ x_drop = self.dropout(x)
220
+ time_emb = self.temporal_embedding(x_mark)
221
+ return torch.concat([x_drop, time_emb], -1)
222
+ else:
223
+ x = (
224
+ self.value_embedding(x)
225
+ + self.position_embedding(x)
226
+ + self.temporal_embedding(x_mark)
227
+ )
228
+ return self.dropout(x)
layers/encoder.py ADDED
@@ -0,0 +1,216 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import math
2
+ import torch
3
+ import torch.nn as nn
4
+ import torch.nn.functional as F
5
+
6
+
7
+ # --------------------------
8
+ # Utilities / Norm / Activations
9
+ # --------------------------
10
+
11
+ class RMSNorm(nn.Module):
12
+ """RMSNorm with learnable weight. Drop-in for LayerNorm when using Pre-Norm."""
13
+ def __init__(self, d_model, eps=1e-8):
14
+ super().__init__()
15
+ self.eps = eps
16
+ self.weight = nn.Parameter(torch.ones(d_model))
17
+
18
+ def forward(self, x):
19
+ # x: (..., D)
20
+ norm = x.pow(2).mean(dim=-1, keepdim=True).add(self.eps).rsqrt()
21
+ return self.weight * x * norm
22
+
23
+
24
+ def get_activation(name: str):
25
+ name = (name or "relu").lower()
26
+ if name == "relu":
27
+ return nn.ReLU()
28
+ if name in ("gelu", "geglu"):
29
+ return nn.GELU()
30
+ if name in ("silu", "swish"):
31
+ return nn.SiLU()
32
+ return nn.ReLU()
33
+
34
+
35
+ class SwiGLU(nn.Module):
36
+ """SwiGLU FFN: proj( SiLU(a) * b ), a,b from linear split."""
37
+ def __init__(self, d_model, d_ff):
38
+ super().__init__()
39
+ self.w12 = nn.Linear(d_model, 2 * d_ff, bias=True)
40
+ self.proj = nn.Linear(d_ff, d_model, bias=True)
41
+
42
+ def forward(self, x):
43
+ a, b = self.w12(x).chunk(2, dim=-1)
44
+ return self.proj(F.silu(a) * b)
45
+
46
+
47
+ # --------------------------
48
+ # Conv Layer (kept signature)
49
+ # --------------------------
50
+
51
+ class ConvLayer(nn.Module):
52
+ def __init__(self, c_in):
53
+ super(ConvLayer, self).__init__()
54
+ padding = 1 if torch.__version__ >= "1.5.0" else 2
55
+ self.downConv = nn.Conv1d(
56
+ in_channels=c_in,
57
+ out_channels=c_in,
58
+ kernel_size=3,
59
+ padding=padding,
60
+ padding_mode="circular",
61
+ )
62
+ self.norm = nn.BatchNorm1d(c_in)
63
+ self.activation = nn.ELU()
64
+ self.maxPool = nn.MaxPool1d(kernel_size=3, stride=2, padding=1)
65
+
66
+ def forward(self, x):
67
+ # x: [B, L, D]
68
+ x = x.permute(0, 2, 1) # B, D, L
69
+ y = self.downConv(x)
70
+ y = self.norm(y)
71
+ y = self.activation(y)
72
+ y = self.maxPool(y)
73
+ y = y.transpose(1, 2).contiguous() # B, L', D
74
+ return y
75
+
76
+
77
+ # --------------------------
78
+ # Encoder Layer (kept signature)
79
+ # --------------------------
80
+
81
+ class EncoderLayer(nn.Module):
82
+ """
83
+ Keep the same signature:
84
+ __init__(self, attention, d_model, d_ff=None, dropout=0.1, activation="relu", ln_mode="pre", conv_layer=False)
85
+ forward(self, x, attn_mask=None)
86
+ Internals:
87
+ - Pre-Norm by default (ln_mode="pre")
88
+ - RMSNorm (instead of LN) but callable doesn’t change
89
+ - Residual scaling 1/sqrt(2)
90
+ - FFN uses SwiGLU, dropout after branch
91
+ - Attention module is expected to have signature (q, k, v, attn_mask=None) -> (new_x, attn)
92
+ and internally do q *= 1/sqrt(d_head)
93
+ """
94
+ def __init__(
95
+ self,
96
+ attention,
97
+ d_model,
98
+ d_ff=None,
99
+ dropout=0.1,
100
+ activation="relu",
101
+ ln_mode="pre",
102
+ conv_layer=False,
103
+ ):
104
+ super(EncoderLayer, self).__init__()
105
+ self.attention = attention
106
+ self.conv_layer = ConvLayer(d_model) if conv_layer else None
107
+ self.dropout = nn.Dropout(dropout)
108
+ self.activation = get_activation(activation)
109
+ self.ln_mode = ln_mode # will honor "pre" / "post" without changing signature
110
+
111
+ # Core hyperparams
112
+ self.d_model = d_model
113
+ self.d_ff = d_ff or 4 * d_model
114
+ self.res_scale = 1.0 / math.sqrt(2.0)
115
+
116
+ # Use RMSNorm but keep object names norm1/norm2 to avoid API change elsewhere
117
+ self.norm1 = RMSNorm(d_model)
118
+ self.norm2 = RMSNorm(d_model)
119
+
120
+ # FFN: use SwiGLU for better stability/accuracy
121
+ self.ff = SwiGLU(d_model, self.d_ff)
122
+
123
+ # In case some pipeline expects LayerNorm instance, we also keep a post-norm if ln_mode="post"
124
+ # (But the actual normalization used is RMSNorm above; this is just to respect the mode)
125
+ if self.ln_mode == "post":
126
+ self.post_ln1 = nn.LayerNorm(d_model)
127
+ self.post_ln2 = nn.LayerNorm(d_model)
128
+
129
+ def forward(self, x, attn_mask=None):
130
+ # x: [B, L, D]
131
+
132
+ if self.conv_layer is not None:
133
+ x = x + self.dropout(self.conv_layer(x)) * self.res_scale
134
+
135
+ if self.ln_mode == "post":
136
+ # -------- Post-LN path (kept behavior but more explicit/clean) --------
137
+ new_x, attn = self.attention(x, x, x, attn_mask=attn_mask)
138
+ x = x + self.dropout(new_x) * self.res_scale
139
+ x = self.post_ln1(x)
140
+
141
+ y = self.ff(x)
142
+ x = x + self.dropout(y) * self.res_scale
143
+ x = self.post_ln2(x)
144
+ return x, attn
145
+
146
+ # -------- Default: Pre-LN (recommended) --------
147
+ # Attention branch (Pre-Norm)
148
+ h, attn = self.attention(self.norm1(x), self.norm1(x), self.norm1(x), attn_mask=attn_mask)
149
+ x = x + self.dropout(h) * self.res_scale
150
+
151
+ # FFN branch (Pre-Norm)
152
+ y = self.ff(self.norm2(x))
153
+ x = x + self.dropout(y) * self.res_scale
154
+
155
+ return x, attn
156
+
157
+
158
+ # --------------------------
159
+ # Encoder (kept signature)
160
+ # --------------------------
161
+
162
+ class Encoder(nn.Module):
163
+ """
164
+ Keep the same signature:
165
+ __init__(self, attn_layers, conv_layers=None, norm_layer=None)
166
+ forward(self, x, attn_mask=None)
167
+ """
168
+ def __init__(self, attn_layers, conv_layers=None, norm_layer=None):
169
+ super(Encoder, self).__init__()
170
+ self.attn_layers = nn.ModuleList(attn_layers)
171
+ self.conv_layers = nn.ModuleList(conv_layers) if conv_layers is not None else None
172
+ self.norm = norm_layer # can be None or nn.Module
173
+
174
+ def forward(self, x, attn_mask=None):
175
+ # x: [B, L, D]
176
+ attns = []
177
+ for i, attn_layer in enumerate(self.attn_layers):
178
+ x, attn = attn_layer(x, attn_mask=attn_mask)
179
+ attns.append(attn)
180
+ if self.conv_layers is not None and i < len(self.conv_layers):
181
+ x = self.conv_layers[i](x)
182
+
183
+ if self.norm is not None:
184
+ x = self.norm(x)
185
+ return x, attns
186
+
187
+
188
+ # --------------------------
189
+ # Encoder Stack (kept signature)
190
+ # --------------------------
191
+
192
+ class EncoderStack(nn.Module):
193
+ """
194
+ Keep the same signature:
195
+ __init__(self, encoders, inp_lens, d_model)
196
+ forward(self, x, attn_mask=None)
197
+ """
198
+ def __init__(self, encoders, inp_lens, d_model):
199
+ super(EncoderStack, self).__init__()
200
+ self.encoders = nn.ModuleList(encoders)
201
+ self.inp_lens = inp_lens
202
+ self.d_model = d_model
203
+
204
+ def forward(self, x, attn_mask=None):
205
+ # x: [B, L, D]
206
+ x_stack = []
207
+ attns = []
208
+ # For each pyramid level, take the tail part of the sequence
209
+ for i_len, encoder in zip(self.inp_lens, self.encoders):
210
+ inp_len = x.shape[1] // (2 ** i_len)
211
+ x_s, attn = encoder(x[:, -inp_len:, :], attn_mask=attn_mask)
212
+ x_stack.append(x_s)
213
+ attns.append(attn)
214
+ x_stack = torch.cat(x_stack, dim=-2) # concat on sequence length axis
215
+ return x_stack, attns
216
+
models/Basic.py ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import torch.nn as nn
3
+ import torch.nn.functional as F
4
+ import numpy as np
5
+
6
+ from layers.embed import Time2Vec
7
+
8
+
9
+ class MLP(nn.Module):
10
+ """
11
+ Just your everyday neural net
12
+ """
13
+
14
+ def __init__(self, config):
15
+ super(MLP, self).__init__()
16
+ self.seq_len = config.seq_len
17
+ self.pred_len = config.pred_len
18
+ assert config.pred_len == 1
19
+
20
+ self.e_layers = config.e_layers
21
+ assert config.e_layers >= 1
22
+
23
+ self.enc_in = config.enc_in
24
+ self.d_model = config.d_model
25
+ self.c_out = config.c_out
26
+
27
+ # Time Embedding
28
+ self.app_time_emb = config.t_embed is not None
29
+ if self.app_time_emb:
30
+ if config.t_embed != "time2vec_app":
31
+ raise Exception(
32
+ "The only options for t_embed with mlp are null and time2vec_app"
33
+ )
34
+ elif not (config.emb_t2v_app_dim > 0):
35
+ raise Exception("Need to specify a valid emb_t2v_app_dim")
36
+ self.enc_in += config.emb_t2v_app_dim
37
+ self.temporal_embedding = Time2Vec(
38
+ time_emb_dim=config.emb_t2v_app_dim, freq=config.freq
39
+ )
40
+
41
+ flattened_enc_in = self.seq_len * self.enc_in
42
+
43
+ if self.e_layers == 1:
44
+ layers = [nn.Linear(flattened_enc_in, self.c_out)]
45
+ else:
46
+ layers = [nn.Linear(flattened_enc_in, self.d_model), nn.GELU()]
47
+ for _ in range(self.e_layers - 2):
48
+ layers.append(nn.Dropout(config.dropout))
49
+ layers.append(nn.Linear(self.d_model, self.d_model))
50
+ layers.append(nn.GELU())
51
+
52
+ layers.append(nn.Linear(self.d_model, self.c_out))
53
+
54
+ self.model = nn.Sequential(*layers)
55
+
56
+ def forward(self, x, x_mark, *args):
57
+ # x: [Batch, Input length, Channel]
58
+ if self.app_time_emb:
59
+ time_emb = self.temporal_embedding(x_mark)
60
+ x = torch.concat([x, time_emb], dim=-1)
61
+
62
+ x_flat = x.reshape(x.shape[0], 1, -1)
63
+ return self.model(x_flat)
models/DLinear.py ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Code is from https://github.com/cure-lab/LTSF-Linear
2
+
3
+ import torch
4
+ import torch.nn as nn
5
+ import torch.nn.functional as F
6
+ import numpy as np
7
+
8
+
9
+ class moving_avg(nn.Module):
10
+ """
11
+ Moving average block to highlight the trend of time series
12
+ """
13
+
14
+ def __init__(self, kernel_size, stride):
15
+ super(moving_avg, self).__init__()
16
+ self.kernel_size = kernel_size
17
+ self.avg = nn.AvgPool1d(kernel_size=kernel_size, stride=stride, padding=0)
18
+
19
+ def forward(self, x):
20
+ # padding on the both ends of time series
21
+ front = x[:, 0:1, :].repeat(1, (self.kernel_size - 1) // 2, 1)
22
+ end = x[:, -1:, :].repeat(1, (self.kernel_size - 1) // 2, 1)
23
+ x = torch.cat([front, x, end], dim=1)
24
+ x = self.avg(x.permute(0, 2, 1))
25
+ x = x.permute(0, 2, 1)
26
+ return x
27
+
28
+
29
+ class series_decomp(nn.Module):
30
+ """
31
+ Series decomposition block
32
+ """
33
+
34
+ def __init__(self, kernel_size):
35
+ super(series_decomp, self).__init__()
36
+ self.moving_avg = moving_avg(kernel_size, stride=1)
37
+
38
+ def forward(self, x):
39
+ moving_mean = self.moving_avg(x)
40
+ res = x - moving_mean
41
+ return res, moving_mean
42
+
43
+
44
+ class Model(nn.Module):
45
+ """
46
+ Decomposition-Linear
47
+ """
48
+
49
+ def __init__(self, configs):
50
+ super(Model, self).__init__()
51
+ self.seq_len = configs.seq_len
52
+ self.pred_len = configs.pred_len
53
+
54
+ # Decompsition Kernel Size
55
+ kernel_size = 25
56
+ self.decompsition = series_decomp(kernel_size)
57
+ self.individual = configs.individual
58
+ self.channels = configs.enc_in
59
+
60
+ if self.individual:
61
+ self.Linear_Seasonal = nn.ModuleList()
62
+ self.Linear_Trend = nn.ModuleList()
63
+
64
+ for i in range(self.channels):
65
+ self.Linear_Seasonal.append(nn.Linear(self.seq_len, self.pred_len))
66
+ self.Linear_Trend.append(nn.Linear(self.seq_len, self.pred_len))
67
+
68
+ # Use this two lines if you want to visualize the weights
69
+ # self.Linear_Seasonal[i].weight = nn.Parameter((1/self.seq_len)*torch.ones([self.pred_len,self.seq_len]))
70
+ # self.Linear_Trend[i].weight = nn.Parameter((1/self.seq_len)*torch.ones([self.pred_len,self.seq_len]))
71
+ else:
72
+ self.Linear_Seasonal = nn.Linear(self.seq_len, self.pred_len)
73
+ self.Linear_Trend = nn.Linear(self.seq_len, self.pred_len)
74
+
75
+ # Use this two lines if you want to visualize the weights
76
+ # self.Linear_Seasonal.weight = nn.Parameter((1/self.seq_len)*torch.ones([self.pred_len,self.seq_len]))
77
+ # self.Linear_Trend.weight = nn.Parameter((1/self.seq_len)*torch.ones([self.pred_len,self.seq_len]))
78
+
79
+ def forward(self, x, *args):
80
+ # x: [Batch, Input length, Channel]
81
+ seasonal_init, trend_init = self.decompsition(x)
82
+ seasonal_init, trend_init = seasonal_init.permute(0, 2, 1), trend_init.permute(
83
+ 0, 2, 1
84
+ )
85
+ if self.individual:
86
+ seasonal_output = torch.zeros(
87
+ [seasonal_init.size(0), seasonal_init.size(1), self.pred_len],
88
+ dtype=seasonal_init.dtype,
89
+ ).to(seasonal_init.device)
90
+ trend_output = torch.zeros(
91
+ [trend_init.size(0), trend_init.size(1), self.pred_len],
92
+ dtype=trend_init.dtype,
93
+ ).to(trend_init.device)
94
+ for i in range(self.channels):
95
+ seasonal_output[:, i, :] = self.Linear_Seasonal[i](
96
+ seasonal_init[:, i, :]
97
+ )
98
+ trend_output[:, i, :] = self.Linear_Trend[i](trend_init[:, i, :])
99
+ else:
100
+ seasonal_output = self.Linear_Seasonal(seasonal_init)
101
+ trend_output = self.Linear_Trend(trend_init)
102
+
103
+ x = seasonal_output + trend_output
104
+ return x.permute(0, 2, 1) # to [Batch, Output length, Channel]
models/Informer.py ADDED
@@ -0,0 +1,242 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import torch.nn as nn
3
+ import torch.nn.functional as F
4
+
5
+ from utils.masking import TriangularCausalMask, ProbMask
6
+ from layers.encoder import Encoder, EncoderLayer, ConvLayer, EncoderStack
7
+ from layers.decoder import Decoder, DecoderLayer
8
+ from layers.attn import FullAttention, ProbAttention, AttentionLayer
9
+ from layers.embed import DataEmbedding
10
+
11
+
12
+ class Informer(nn.Module):
13
+ def __init__(self, config):
14
+ # enc_in, dec_in, c_out, seq_len, label_len, out_len,
15
+ # factor=5, d_model=512, n_heads=8, e_layers=3, d_layers=2, d_ff=512,
16
+ # dropout=0.0, attn='prob', t_embed='fixed', freq='h', activation='gelu',
17
+ # output_attention = False, distil=True, mix=True,
18
+ # device=torch.device('cuda:0')
19
+ super(Informer, self).__init__()
20
+ self.pred_len = config.pred_len
21
+ self.attn = config.attn
22
+ self.output_attention = config.output_attention
23
+
24
+ # Encoding
25
+ self.enc_embedding = DataEmbedding(
26
+ config.enc_in, config.d_model, config.t_embed, config.freq, config.dropout_emb
27
+ )
28
+ self.dec_embedding = DataEmbedding(
29
+ config.dec_in, config.d_model, config.t_embed, config.freq, config.dropout_emb
30
+ )
31
+ # Attention
32
+ Attn = ProbAttention if config.attn == "prob" else FullAttention
33
+ # Encoder
34
+ self.encoder = Encoder(
35
+ [
36
+ EncoderLayer(
37
+ AttentionLayer(
38
+ Attn(
39
+ False,
40
+ config.factor,
41
+ attention_dropout=config.dropout,
42
+ output_attention=config.output_attention,
43
+ ),
44
+ config.d_model,
45
+ config.n_heads,
46
+ mix=False,
47
+ ),
48
+ config.d_model,
49
+ config.d_ff,
50
+ dropout=config.dropout,
51
+ activation=config.activation,
52
+ )
53
+ for l in range(config.e_layers)
54
+ ],
55
+ [ConvLayer(config.d_model) for l in range(config.e_layers - 1)]
56
+ if config.distil
57
+ else None,
58
+ norm_layer=torch.nn.LayerNorm(config.d_model),
59
+ )
60
+ # Decoder
61
+ self.decoder = Decoder(
62
+ [
63
+ DecoderLayer(
64
+ AttentionLayer(
65
+ Attn(
66
+ True,
67
+ config.factor,
68
+ attention_dropout=config.dropout,
69
+ output_attention=False,
70
+ ),
71
+ config.d_model,
72
+ config.n_heads,
73
+ mix=config.mix,
74
+ ),
75
+ AttentionLayer(
76
+ FullAttention(
77
+ False,
78
+ config.factor,
79
+ attention_dropout=config.dropout,
80
+ output_attention=False,
81
+ ),
82
+ config.d_model,
83
+ config.n_heads,
84
+ mix=False,
85
+ ),
86
+ config.d_model,
87
+ config.d_ff,
88
+ dropout=config.dropout,
89
+ activation=config.activation,
90
+ )
91
+ for l in range(config.d_layers)
92
+ ],
93
+ norm_layer=torch.nn.LayerNorm(config.d_model),
94
+ )
95
+ self.projection = nn.Linear(config.d_model, config.c_out, bias=True)
96
+
97
+ def forward(
98
+ self,
99
+ x_enc,
100
+ x_mark_enc,
101
+ x_dec,
102
+ x_mark_dec,
103
+ enc_self_mask=None,
104
+ dec_self_mask=None,
105
+ dec_enc_mask=None,
106
+ ):
107
+ enc_out = self.enc_embedding(x_enc, x_mark_enc)
108
+ enc_out, attns = self.encoder(enc_out, attn_mask=enc_self_mask)
109
+
110
+ dec_out = self.dec_embedding(x_dec, x_mark_dec)
111
+ dec_out = self.decoder(
112
+ dec_out, enc_out, x_mask=dec_self_mask, cross_mask=dec_enc_mask
113
+ )
114
+ dec_out = self.projection(dec_out)
115
+
116
+ if self.output_attention:
117
+ return dec_out[:, -self.pred_len :, :], attns
118
+ else:
119
+ return dec_out[:, -self.pred_len :, :] # [B, L, D]
120
+
121
+
122
+ class InformerStack(nn.Module):
123
+ def __init__(self, config):
124
+ # enc_in, dec_in, c_out, seq_len, label_len, out_len,
125
+ # factor=5, d_model=512, n_heads=8, e_layers=[3,2,1], d_layers=2, d_ff=512,
126
+ # dropout=0.0, attn='prob', t_embed='fixed', freq='h', activation='gelu',
127
+ # output_attention = False, distil=True, mix=True,
128
+ # device=torch.device('cuda:0'))
129
+ super(InformerStack, self).__init__()
130
+ self.pred_len = config.pred_len
131
+ self.attn = config.attn
132
+ self.output_attention = config.output_attention
133
+
134
+ assert (
135
+ type(config.e_layers) is list
136
+ ), "For Informer Stack e_layers must be a list"
137
+
138
+ # Encoding
139
+ self.enc_embedding = DataEmbedding(
140
+ config.enc_in, config.d_model, config.t_embed, config.freq, config.dropout_emb
141
+ )
142
+ self.dec_embedding = DataEmbedding(
143
+ config.dec_in, config.d_model, config.t_embed, config.freq, config.dropout_emb
144
+ )
145
+ # Attention
146
+ Attn = ProbAttention if config.attn == "prob" else FullAttention
147
+ # Encoder
148
+
149
+ inp_lens = list(
150
+ range(len(config.e_layers))
151
+ ) # [0,1,2,...] you can customize here
152
+ encoders = [
153
+ Encoder(
154
+ [
155
+ EncoderLayer(
156
+ AttentionLayer(
157
+ Attn(
158
+ False,
159
+ config.factor,
160
+ attention_dropout=config.dropout,
161
+ output_attention=config.output_attention,
162
+ ),
163
+ config.d_model,
164
+ config.n_heads,
165
+ mix=False,
166
+ ),
167
+ config.d_model,
168
+ config.d_ff,
169
+ dropout=config.dropout,
170
+ activation=config.activation,
171
+ )
172
+ for l in range(el)
173
+ ],
174
+ [ConvLayer(config.d_model) for l in range(el - 1)]
175
+ if config.distil
176
+ else None,
177
+ norm_layer=torch.nn.LayerNorm(config.d_model),
178
+ )
179
+ for el in config.e_layers
180
+ ]
181
+ self.encoder = EncoderStack(encoders, inp_lens)
182
+ # Decoder
183
+ self.decoder = Decoder(
184
+ [
185
+ DecoderLayer(
186
+ AttentionLayer(
187
+ Attn(
188
+ True,
189
+ config.factor,
190
+ attention_dropout=config.dropout,
191
+ output_attention=False,
192
+ ),
193
+ config.d_model,
194
+ config.n_heads,
195
+ mix=config.mix,
196
+ ),
197
+ AttentionLayer(
198
+ FullAttention(
199
+ False,
200
+ config.factor,
201
+ attention_dropout=config.dropout,
202
+ output_attention=False,
203
+ ),
204
+ config.d_model,
205
+ config.n_heads,
206
+ mix=False,
207
+ ),
208
+ config.d_model,
209
+ config.d_ff,
210
+ dropout=config.dropout,
211
+ activation=config.activation,
212
+ )
213
+ for l in range(config.d_layers)
214
+ ],
215
+ norm_layer=torch.nn.LayerNorm(config.d_model),
216
+ )
217
+
218
+ self.projection = nn.Linear(config.d_model, config.c_out, bias=True)
219
+
220
+ def forward(
221
+ self,
222
+ x_enc,
223
+ x_mark_enc,
224
+ x_dec,
225
+ x_mark_dec,
226
+ enc_self_mask=None,
227
+ dec_self_mask=None,
228
+ dec_enc_mask=None,
229
+ ):
230
+ enc_out = self.enc_embedding(x_enc, x_mark_enc)
231
+ enc_out, attns = self.encoder(enc_out, attn_mask=enc_self_mask)
232
+
233
+ dec_out = self.dec_embedding(x_dec, x_mark_dec)
234
+ dec_out = self.decoder(
235
+ dec_out, enc_out, x_mask=dec_self_mask, cross_mask=dec_enc_mask
236
+ )
237
+ dec_out = self.projection(dec_out)
238
+
239
+ if self.output_attention:
240
+ return dec_out[:, -self.pred_len :, :], attns
241
+ else:
242
+ return dec_out[:, -self.pred_len :, :] # [B, L, D]
models/Lstm.py ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from torch import nn
3
+
4
+ from layers.embed import Time2Vec
5
+
6
+
7
+ class LSTM(nn.Module):
8
+ def __init__(self, config):
9
+ super(LSTM, self).__init__()
10
+ assert config.pred_len == 1
11
+ assert config.label_len == 0
12
+ # Hidden dimensions
13
+ self.d_model = config.d_model
14
+
15
+ # Number of hidden layers
16
+ self.e_layers = config.e_layers
17
+
18
+ self.enc_in = config.enc_in
19
+
20
+ # Time Embedding
21
+
22
+ self.t_embed = config.t_embed
23
+ if self.t_embed is not None:
24
+ if config.t_embed == "time2vec_app":
25
+ if not (config.emb_t2v_app_dim > 0):
26
+ raise Exception("Need to specify a valid emb_t2v_app_dim")
27
+ self.enc_in += config.emb_t2v_app_dim
28
+ self.temporal_embedding = Time2Vec(
29
+ time_emb_dim=config.emb_t2v_app_dim, freq=config.freq
30
+ )
31
+ elif config.t_embed == "time2vec_add":
32
+ self.temporal_embedding = Time2Vec(
33
+ time_emb_dim=self.enc_in, freq=config.freq
34
+ )
35
+ else:
36
+ raise Exception(
37
+ "The only options for t_embed with mlp are null and time2vec_app"
38
+ )
39
+
40
+ # batch_first=True causes input/output tensors to be of shape
41
+ # (batch_dim, seq_dim, feature_dim)
42
+ self.lstm = nn.LSTM(
43
+ input_size=self.enc_in,
44
+ hidden_size=config.d_model,
45
+ num_layers=config.e_layers,
46
+ batch_first=True,
47
+ dropout=config.dropout,
48
+ bidirectional=False,
49
+ )
50
+
51
+ self.fc_1 = nn.Linear(config.d_model, config.d_ff)
52
+ self.relu = nn.ReLU()
53
+ # Readout layer
54
+ self.fc = nn.Linear(config.d_ff, config.c_out)
55
+
56
+ def forward(self, x, x_mark, *args, **kwargs):
57
+ if self.t_embed is not None:
58
+ if self.t_embed == "time2vec_app":
59
+ time_emb = self.temporal_embedding(x_mark)
60
+ x = torch.concat([x, time_emb], dim=-1)
61
+ elif self.t_embed == "time2vec_add":
62
+ time_emb = self.temporal_embedding(x_mark)
63
+ x = x + time_emb
64
+
65
+ # Initialize hidden state with zeros
66
+ h0 = torch.zeros(self.e_layers, x.size(0), self.d_model).to(x)
67
+
68
+ # Initialize cell state
69
+ c0 = torch.zeros(self.e_layers, x.size(0), self.d_model).to(x)
70
+
71
+ # We need to detach as we are doing truncated backpropagation through time (BPTT)
72
+ # If we don't, we'll backprop all the way to the start even after going through another batch
73
+ out, (hn, cn) = self.lstm(x, (h0, c0))
74
+
75
+ # Index hidden state of last time step
76
+ # out.size() --> 100, 32, 100
77
+ # out[:, -1, :] --> 100, 100 --> just want last time step hidden states!
78
+
79
+ # out = self.relu(self.fc_1(out[:, -1, :]))
80
+ out = self.relu(self.fc_1(self.relu(hn[-1])))
81
+
82
+ out = self.fc(out)
83
+ # out.size() --> 100, 10
84
+ return out[:, None]
models/Stockformer.py ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import torch
3
+ import torch.nn as nn
4
+
5
+ from layers.encoder import Encoder, EncoderLayer, ConvLayer
6
+ from layers.attn import FullAttention, AttentionLayer, ProbAttention
7
+ from layers.embed import DataEmbedding
8
+ from utils.masking import QuestionMask
9
+
10
+
11
+ class Stockformer(nn.Module):
12
+ def __init__(self, config):
13
+ super(Stockformer, self).__init__()
14
+ self.pred_len = config.pred_len
15
+ assert self.pred_len == 1, "Stockformer needs pred_len to be 1"
16
+ self.attn = config.attn
17
+ self.output_attention = config.output_attention
18
+
19
+ self.seq_len = config.seq_len
20
+
21
+ self.final_mode = config.final_mode
22
+
23
+ # Embedding
24
+ self.enc_embedding = DataEmbedding(
25
+ config.enc_in,
26
+ config.d_model,
27
+ config.t_embed,
28
+ config.freq,
29
+ config.dropout_emb,
30
+ emb_t2v_app_dim=config.emb_t2v_app_dim,
31
+ tok_emb=config.tok_emb,
32
+ )
33
+ # Attention
34
+ Attn = ProbAttention if config.attn == "prob" else FullAttention
35
+ # Encoder
36
+ self.encoder = Encoder(
37
+ [
38
+ EncoderLayer(
39
+ AttentionLayer(
40
+ Attn(
41
+ True if config.final_mode == "mode3" else False,
42
+ config.factor,
43
+ attention_dropout=config.dropout,
44
+ output_attention=config.output_attention,
45
+ ),
46
+ config.d_model,
47
+ config.n_heads,
48
+ mix=False,
49
+ ),
50
+ config.d_model,
51
+ config.d_ff,
52
+ dropout=config.dropout,
53
+ activation=config.activation,
54
+ ln_mode=config.ln_mode,
55
+ )
56
+ for l in range(config.e_layers)
57
+ ],
58
+ [ConvLayer(config.d_model) for l in range(config.e_layers - 1)]
59
+ if config.distil
60
+ else None,
61
+ # norm_layer=torch.nn.LayerNorm(config.d_model),
62
+ norm_layer=torch.nn.RMSNorm(config.d_model),
63
+ )
64
+
65
+ if config.final_mode == "mode1":
66
+ self.final = nn.Linear(
67
+ config.d_model * config.seq_len, config.c_out, bias=True
68
+ )
69
+ elif config.final_mode == "mode2" or config.final_mode == "mode3":
70
+ self.final = nn.Linear(config.d_model, config.c_out, bias=True)
71
+ else:
72
+ raise Exception(f"Invalid final_mode: {config.final_mode}")
73
+ # nn.init.xavier_normal_(self.final.weight, gain=nn.init.calculate_gain("tanh"))
74
+
75
+ # self.final = nn.Sequential(*[
76
+ # nn.Linear(config.d_model * config.seq_len, config.d_model * 4, bias=True),
77
+ # nn.GELU(),
78
+ # nn.Linear(config.d_model * 4, config.c_out, bias=True)
79
+ # ])
80
+
81
+ # Load pre-trained model
82
+ if config.load_model_path is not None:
83
+ path = os.path.join(config.checkpoints, config.load_model_path)
84
+ print(f"Loading Model from {path}")
85
+ self.load_state_dict(torch.load(path))
86
+
87
+ def forward(
88
+ self,
89
+ x_enc,
90
+ x_mark_enc,
91
+ x_dec,
92
+ x_mark_dec,
93
+ enc_self_mask=None,
94
+ dec_self_mask=None,
95
+ dec_enc_mask=None,
96
+ pre_train=False,
97
+ ):
98
+ # x_enc is (batch_size / num gpus, seq_len, enc_in)
99
+ # x_mark_enc is (batch_size / num gpus, seq_len, date-representation (7forhours)
100
+ assert len(x_enc.shape) == 3
101
+ assert x_enc.shape[1] == self.seq_len
102
+
103
+ if self.final_mode == "mode3":
104
+ # This gives the encoder a question input as the last token
105
+ # TODO: Maybe this should be initialized differently, like to the mean of x_enc, random, mean of dataset?
106
+ zeros = torch.zeros([x_enc.shape[0], 1, x_enc.shape[2]]).to(x_enc)
107
+ x_enc = torch.cat([x_enc, zeros], 1)
108
+ x_mark_enc = torch.cat([x_mark_enc, x_mark_dec], 1)
109
+ assert enc_self_mask is None
110
+ enc_self_mask = QuestionMask(
111
+ x_enc.shape[0], x_enc.shape[1], device=x_enc.device
112
+ )
113
+
114
+ # emb_out is (batch_size / num gpus, seq_len, d_model)
115
+ emb_out = self.enc_embedding(x_enc, x_mark_enc)
116
+
117
+ # enc_out is (batch_size / num gpus, seq_len, d_model) but seq_len will change if distil
118
+ enc_out, attns = self.encoder(emb_out, attn_mask=enc_self_mask)
119
+
120
+ if self.final_mode == "mode1":
121
+ out = self.final(enc_out.flatten(start_dim=1))
122
+ elif self.final_mode == "mode2" or self.final_mode == "mode3":
123
+ out = self.final(enc_out[:, -1, :])
124
+ else:
125
+ assert False, f"Forward missing valid final mode {self.final_mode}"
126
+
127
+ # The None below is just adding a dummy dimension
128
+ if self.output_attention:
129
+ return out[:, None, :], attns
130
+ else:
131
+ return out[:, None, :] # (batch_size, 1, c_out)
models/__init__.py ADDED
File without changes
old_stuff/Dockerfile ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ FROM continuumio/miniconda3:4.7.12
2
+
3
+ ADD ./environment.yml ./environment.yml
4
+
5
+ RUN conda install -n base -c conda-forge mamba && \
6
+ mamba env update -n base -f ./environment.yml && \
7
+ conda clean -afy
8
+
old_stuff/Informer.ipynb ADDED
@@ -0,0 +1,698 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {
6
+ "id": "5IM6CZzW_CH0"
7
+ },
8
+ "source": [
9
+ "# Informer Demo"
10
+ ]
11
+ },
12
+ {
13
+ "cell_type": "code",
14
+ "execution_count": null,
15
+ "metadata": {
16
+ "id": "b5GFng7v7Eq0"
17
+ },
18
+ "outputs": [],
19
+ "source": [
20
+ "import sys\n",
21
+ "\n",
22
+ "# if not 'Informer2020' in sys.path:\n",
23
+ "# sys.path += ['Informer2020']"
24
+ ]
25
+ },
26
+ {
27
+ "cell_type": "markdown",
28
+ "metadata": {
29
+ "id": "rIjZdN5e_SWe"
30
+ },
31
+ "source": [
32
+ "## Experiments: Train and Test"
33
+ ]
34
+ },
35
+ {
36
+ "cell_type": "code",
37
+ "execution_count": null,
38
+ "metadata": {
39
+ "id": "RPdt-Kwc_RRZ"
40
+ },
41
+ "outputs": [],
42
+ "source": [
43
+ "from utils.tools import dotdict\n",
44
+ "from exp.exp_informer import Exp_Informer\n",
45
+ "import torch\n",
46
+ "import numpy as np\n",
47
+ "import pandas as pd\n",
48
+ "import os\n",
49
+ "from utils.ipynb_helpers import args_from_setting, setting_from_args, handle_gpu"
50
+ ]
51
+ },
52
+ {
53
+ "cell_type": "code",
54
+ "execution_count": null,
55
+ "metadata": {
56
+ "id": "6mx2dnwY9dWi"
57
+ },
58
+ "outputs": [],
59
+ "source": [
60
+ "args = dotdict()\n",
61
+ "args.des = \"full_1h\"\n",
62
+ "\n",
63
+ "args.model = \"informer\" # model of experiment, options: [informer, informerstack, informerlight(TBD)]\n",
64
+ "\n",
65
+ "args.data = \"custom\" # data\n",
66
+ "args.root_path = \"./data/stock/\" # root path of data file\n",
67
+ "\n",
68
+ "\n",
69
+ "args.data_path = \"full_1h.csv\" # data file\n",
70
+ "args.features = \"MS\" # forecasting task, options:[M, S, MS]; M:multivariate predict multivariate, S:univariate predict univariate, MS:multivariate predict univariate\n",
71
+ "args.target = \"XOM_pctchange\" # target feature in S or MS task\n",
72
+ "args.freq = \"h\" # freq for time features encoding, options:[s:secondly, t:minutely, h:hourly, d:daily, b:business days, w:weekly, m:monthly], you can also use more detailed freq like 15min or 3h\n",
73
+ "args.checkpoints = \"./checkpoints\" # location of model checkpoints\n",
74
+ "\n",
75
+ "args.seq_len = 16 # input sequence length of Informer encoder\n",
76
+ "args.label_len = 4 # start token length of Informer decoder\n",
77
+ "args.pred_len = 1 # prediction sequence length\n",
78
+ "# Informer decoder input: concat[start token series(label_len), zero padding series(pred_len)]\n",
79
+ "\n",
80
+ "args.cols = [\n",
81
+ " \"XOM_open\",\n",
82
+ " \"XOM_high\",\n",
83
+ " \"XOM_low\",\n",
84
+ " \"XOM_close\",\n",
85
+ " \"XOM_volume\",\n",
86
+ " \"XOM_pctchange\",\n",
87
+ " \"XOM_shortsma\",\n",
88
+ "] # [\"XOM_close\", \"BP_close\", \"CVX_close\", \"WTI_close\"]\n",
89
+ "args.enc_in = 7 # 13 # encoder input size\n",
90
+ "args.dec_in = 7 # 13 # decoder input size\n",
91
+ "args.c_out = 1 # output size\n",
92
+ "args.factor = 5 # probsparse attn factor\n",
93
+ "args.d_model = 64 # 512 # dimension of model\n",
94
+ "args.n_heads = 8 # num of heads\n",
95
+ "args.e_layers = 4 # 2 # num of encoder layers\n",
96
+ "args.d_layers = 2 # 1 # num of decoder layers\n",
97
+ "args.d_ff = 2048 # dimension of fcn in model\n",
98
+ "args.dropout = 0.05 # dropout\n",
99
+ "args.attn = \"prob\" # attention used in encoder, options:[prob, full]\n",
100
+ "args.t_embed = \"timeF\" # time features encoding, options:[timeF, fixed, learned]\n",
101
+ "args.activation = \"gelu\" # activation\n",
102
+ "args.distil = True # whether to use distilling in encoder\n",
103
+ "args.output_attention = False # whether to output attention in encoder\n",
104
+ "args.mix = True\n",
105
+ "args.padding = 0\n",
106
+ "\n",
107
+ "args.batch_size = 64\n",
108
+ "args.learning_rate = 0.00001\n",
109
+ "args.loss = \"mse\"\n",
110
+ "args.lradj = \"type1\"\n",
111
+ "args.use_amp = False # whether to use automatic mixed precision training\n",
112
+ "\n",
113
+ "args.num_workers = 0\n",
114
+ "args.itr = 1 # number of runs\n",
115
+ "args.max_epochs = 15\n",
116
+ "args.patience = 3\n",
117
+ "\n",
118
+ "\n",
119
+ "args.scale = True # True # True\n",
120
+ "args.inverse = True # True # Defaultly False but @Zac thinks it should be True\n",
121
+ "\n",
122
+ "\n",
123
+ "args.date_start = None # \"2021-01-01\"\n",
124
+ "args.date_end = None\n",
125
+ "args.date_test = \"2022-04-01\" # None\n",
126
+ "\n",
127
+ "handle_gpu(args, None)\n",
128
+ "\n",
129
+ "# idk what this is for\n",
130
+ "args.detail_freq = args.freq\n",
131
+ "args.freq = args.freq[-1:]\n",
132
+ "\n",
133
+ "print(\"Args in experiment:\")\n",
134
+ "print(args)\n",
135
+ "Exp = Exp_Informer"
136
+ ]
137
+ },
138
+ {
139
+ "cell_type": "markdown",
140
+ "metadata": {},
141
+ "source": [
142
+ "### Train & Test *args.itr* models"
143
+ ]
144
+ },
145
+ {
146
+ "cell_type": "code",
147
+ "execution_count": null,
148
+ "metadata": {
149
+ "colab": {
150
+ "base_uri": "https://localhost:8080/"
151
+ },
152
+ "id": "928tzaA2AA2g",
153
+ "outputId": "c19f673a-02d1-4f4d-91c3-d0f25e600443"
154
+ },
155
+ "outputs": [],
156
+ "source": [
157
+ "exp = None\n",
158
+ "setting = None\n",
159
+ "for ii in range(args.itr):\n",
160
+ " # setting record of experiments\n",
161
+ " setting = setting_from_args(args, ii)\n",
162
+ "\n",
163
+ " # set experiments\n",
164
+ " exp = Exp(args)\n",
165
+ "\n",
166
+ " # train\n",
167
+ " print(f\">>>>>>>start training : {setting}>>>>>>>>>>>>>>>>>>>>>>>>>>\")\n",
168
+ " exp.train(setting)\n",
169
+ "\n",
170
+ " # test\n",
171
+ " print(f\">>>>>>>testing : {setting}<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\")\n",
172
+ " exp.test(setting)\n",
173
+ "\n",
174
+ " torch.cuda.empty_cache()"
175
+ ]
176
+ },
177
+ {
178
+ "cell_type": "markdown",
179
+ "metadata": {
180
+ "id": "CDHF-HerAE3u"
181
+ },
182
+ "source": [
183
+ "## Prediction"
184
+ ]
185
+ },
186
+ {
187
+ "cell_type": "code",
188
+ "execution_count": null,
189
+ "metadata": {
190
+ "colab": {
191
+ "base_uri": "https://localhost:8080/"
192
+ },
193
+ "id": "nTkluNNcyMJt",
194
+ "outputId": "780767fe-6321-4081-e827-6701daeb375b"
195
+ },
196
+ "outputs": [],
197
+ "source": [
198
+ "# If you already have a trained model, you can set the arguments and model path, then initialize a Experiment and use it to predict\n",
199
+ "# Prediction is a sequence which is adjacent to the last date of the data, and does not exist in the data\n",
200
+ "# If you want to get more information about prediction, you can refer to code `exp/exp_informer.py function predict()` and `data/data_loader.py class Dataset_Pred`\n",
201
+ "\n",
202
+ "# args = dotdict(model='informer', data='WTH', root_path='./data/ETT/', data_path='WTH.csv', features='M', target='WetBulbCelsius', freq='h', checkpoints='./checkpoints/', seq_len=96, label_len=48, pred_len=24, enc_in=12, dec_in=12, c_out=12, d_model=512, n_heads=8, e_layers=2, d_layers=1, s_layers=[3, 2, 1], d_ff=2048, factor=5, padding=0, distil=True, dropout=0.05, attn='prob', t_embed='timeF', activation='gelu', output_attention=False, do_predict=False, mix=True, cols=None, num_workers=0, itr=2, max_epochs=6, batch_size=32, patience=3, learning_rate=0.0001, des='test', loss='mse', lradj='type1', use_amp=False, inverse=False, use_gpu=True, gpu=0, use_multi_gpu=False, devices='0,1,2,3', detail_freq='h')\n",
203
+ "\n",
204
+ "manual = False\n",
205
+ "\n",
206
+ "if manual:\n",
207
+ " setting = \"informer_custom_ftMS_sl256_ll64_pl16_ei1_di1_co1_iFalse_dm512_nh8_el2_dl1_df2048_atprob_fc5_ebtimeF_dtTrue_mxTrue_exp_0\"\n",
208
+ " args = args_from_setting(setting, args)\n",
209
+ "\n",
210
+ " exp = Exp(args)\n",
211
+ "\n",
212
+ "path = os.path.join(args.checkpoints, setting, \"checkpoint.pth\")\n",
213
+ "\n",
214
+ "exp.predict(setting, True)"
215
+ ]
216
+ },
217
+ {
218
+ "cell_type": "code",
219
+ "execution_count": null,
220
+ "metadata": {
221
+ "colab": {
222
+ "base_uri": "https://localhost:8080/"
223
+ },
224
+ "id": "KBCPbjGuzAZb",
225
+ "outputId": "945dc447-88e8-4b08-b7e5-f0a0b486d138"
226
+ },
227
+ "outputs": [],
228
+ "source": [
229
+ "# the prediction will be saved in ./results/{setting}/real_prediction.npy\n",
230
+ "\n",
231
+ "prediction = np.load(f\"./results/{setting}/real_prediction.npy\")\n",
232
+ "\n",
233
+ "prediction.shape"
234
+ ]
235
+ },
236
+ {
237
+ "cell_type": "markdown",
238
+ "metadata": {
239
+ "id": "5yFuVkTV30_j"
240
+ },
241
+ "source": [
242
+ "### More details about Prediction - prediction function"
243
+ ]
244
+ },
245
+ {
246
+ "cell_type": "code",
247
+ "execution_count": null,
248
+ "metadata": {
249
+ "id": "Sv9AR_Aw030r"
250
+ },
251
+ "outputs": [],
252
+ "source": [
253
+ "# here is the detailed code of function predict\n",
254
+ "\n",
255
+ "\n",
256
+ "def predict(exp, setting, load=False):\n",
257
+ " pred_data, pred_loader = exp._get_data(flag=\"pred\")\n",
258
+ "\n",
259
+ " if load:\n",
260
+ " path = os.path.join(exp.args.checkpoints, setting)\n",
261
+ " best_model_path = path + \"/\" + \"checkpoint.pth\"\n",
262
+ " exp.model.load_state_dict(torch.load(best_model_path))\n",
263
+ "\n",
264
+ " exp.model.eval()\n",
265
+ "\n",
266
+ " preds = []\n",
267
+ "\n",
268
+ " for i, (batch_x, batch_y, batch_x_mark, batch_y_mark) in enumerate(pred_loader):\n",
269
+ " batch_x = batch_x.float().to(exp.device)\n",
270
+ " batch_y = batch_y.float()\n",
271
+ " batch_x_mark = batch_x_mark.float().to(exp.device)\n",
272
+ " batch_y_mark = batch_y_mark.float().to(exp.device)\n",
273
+ "\n",
274
+ " # decoder input\n",
275
+ " if exp.args.padding == 0:\n",
276
+ " dec_inp = torch.zeros(\n",
277
+ " [batch_y.shape[0], exp.args.pred_len, batch_y.shape[-1]]\n",
278
+ " ).float()\n",
279
+ " elif exp.args.padding == 1:\n",
280
+ " dec_inp = torch.ones(\n",
281
+ " [batch_y.shape[0], exp.args.pred_len, batch_y.shape[-1]]\n",
282
+ " ).float()\n",
283
+ " else:\n",
284
+ " dec_inp = torch.zeros(\n",
285
+ " [batch_y.shape[0], exp.args.pred_len, batch_y.shape[-1]]\n",
286
+ " ).float()\n",
287
+ " dec_inp = (\n",
288
+ " torch.cat([batch_y[:, : exp.args.label_len, :], dec_inp], dim=1)\n",
289
+ " .float()\n",
290
+ " .to(exp.device)\n",
291
+ " )\n",
292
+ " # encoder - decoder\n",
293
+ " if exp.args.use_amp:\n",
294
+ " with torch.cuda.amp.autocast():\n",
295
+ " if exp.args.output_attention:\n",
296
+ " outputs = exp.model(batch_x, batch_x_mark, dec_inp, batch_y_mark)[0]\n",
297
+ " else:\n",
298
+ " outputs = exp.model(batch_x, batch_x_mark, dec_inp, batch_y_mark)\n",
299
+ " else:\n",
300
+ " if exp.args.output_attention:\n",
301
+ " outputs = exp.model(batch_x, batch_x_mark, dec_inp, batch_y_mark)[0]\n",
302
+ " else:\n",
303
+ " outputs = exp.model(batch_x, batch_x_mark, dec_inp, batch_y_mark)\n",
304
+ " f_dim = -1 if exp.args.features == \"MS\" else 0\n",
305
+ " batch_y = batch_y[:, -exp.args.pred_len :, f_dim:].to(exp.device)\n",
306
+ "\n",
307
+ " pred = outputs.detach().cpu().numpy() # .squeeze()\n",
308
+ "\n",
309
+ " preds.append(pred)\n",
310
+ "\n",
311
+ " preds = np.array(preds)\n",
312
+ " preds = preds.reshape(-1, preds.shape[-2], preds.shape[-1])\n",
313
+ "\n",
314
+ " # result save\n",
315
+ " folder_path = \"./results/\" + setting + \"/\"\n",
316
+ " if not os.path.exists(folder_path):\n",
317
+ " os.makedirs(folder_path)\n",
318
+ "\n",
319
+ " np.save(folder_path + \"real_prediction.npy\", preds)\n",
320
+ "\n",
321
+ " return preds"
322
+ ]
323
+ },
324
+ {
325
+ "cell_type": "code",
326
+ "execution_count": null,
327
+ "metadata": {
328
+ "colab": {
329
+ "base_uri": "https://localhost:8080/"
330
+ },
331
+ "id": "tVLWZL2a1pwB",
332
+ "outputId": "421e9ae1-f024-42b6-c8cb-ed1d38c864cd"
333
+ },
334
+ "outputs": [],
335
+ "source": [
336
+ "# you can also use this prediction function to get result\n",
337
+ "prediction = predict(exp, setting, True)"
338
+ ]
339
+ },
340
+ {
341
+ "cell_type": "code",
342
+ "execution_count": null,
343
+ "metadata": {
344
+ "colab": {
345
+ "base_uri": "https://localhost:8080/",
346
+ "height": 269
347
+ },
348
+ "id": "NwtZmQC71uc8",
349
+ "outputId": "eec9d116-f122-42d9-8e02-c893ff764db0"
350
+ },
351
+ "outputs": [],
352
+ "source": [
353
+ "import matplotlib.pyplot as plt\n",
354
+ "\n",
355
+ "plt.figure()\n",
356
+ "plt.plot(prediction[0, :, -1])\n",
357
+ "plt.show()"
358
+ ]
359
+ },
360
+ {
361
+ "cell_type": "markdown",
362
+ "metadata": {
363
+ "id": "EnePVyrW4I14"
364
+ },
365
+ "source": [
366
+ "### More details about Prediction - prediction dataset\n",
367
+ "\n",
368
+ "You can give a `root_path` and `data_path` of the data you want to forecast, and set `seq_len`, `label_len`, `pred_len` and other arguments as other Dataset. The difference is that you can set a more detailed freq such as `15min` or `3h` to generate the timestamp of prediction series.\n",
369
+ "\n",
370
+ "`Dataset_Pred` only has one sample (including `encoder_input: [1, seq_len, dim]`, `decoder_token: [1, label_len, dim]`, `encoder_input_timestamp: [1, seq_len, date_dim]`, `decoder_input_timstamp: [1, label_len+pred_len, date_dim]`). It will intercept the last sequence of the given data (seq_len data) to forecast the unseen future sequence (pred_len data)."
371
+ ]
372
+ },
373
+ {
374
+ "cell_type": "code",
375
+ "execution_count": 1,
376
+ "metadata": {
377
+ "id": "ZpXhNGp34Hf4"
378
+ },
379
+ "outputs": [],
380
+ "source": [
381
+ "from data_provider.data_loader import Dataset_Pred\n",
382
+ "from torch.utils.data import DataLoader"
383
+ ]
384
+ },
385
+ {
386
+ "cell_type": "code",
387
+ "execution_count": null,
388
+ "metadata": {
389
+ "id": "j4Rpd1q74T8N"
390
+ },
391
+ "outputs": [],
392
+ "source": [
393
+ "Data = Dataset_Pred\n",
394
+ "timeenc = 0 if args.t_embed != \"timeF\" else 1\n",
395
+ "flag = \"pred\"\n",
396
+ "shuffle_flag = False\n",
397
+ "drop_last = False\n",
398
+ "batch_size = 1\n",
399
+ "\n",
400
+ "freq = args.detail_freq\n",
401
+ "\n",
402
+ "data_set = Data(args, flag=flag, freq=freq, timeenc=timeenc)\n",
403
+ "\n",
404
+ "data_loader = DataLoader(\n",
405
+ " data_set,\n",
406
+ " batch_size=batch_size,\n",
407
+ " shuffle=shuffle_flag,\n",
408
+ " num_workers=args.num_workers,\n",
409
+ " drop_last=drop_last,\n",
410
+ ")"
411
+ ]
412
+ },
413
+ {
414
+ "cell_type": "code",
415
+ "execution_count": null,
416
+ "metadata": {
417
+ "colab": {
418
+ "base_uri": "https://localhost:8080/"
419
+ },
420
+ "id": "42C84BfY6UPV",
421
+ "outputId": "f5ccc428-db92-4708-e104-f5d29aa5adf9"
422
+ },
423
+ "outputs": [],
424
+ "source": [
425
+ "len(data_set), len(data_loader)"
426
+ ]
427
+ },
428
+ {
429
+ "cell_type": "markdown",
430
+ "metadata": {
431
+ "id": "cNhEP_7sAgqC"
432
+ },
433
+ "source": [
434
+ "## Visualization"
435
+ ]
436
+ },
437
+ {
438
+ "cell_type": "code",
439
+ "execution_count": null,
440
+ "metadata": {
441
+ "colab": {
442
+ "base_uri": "https://localhost:8080/"
443
+ },
444
+ "id": "vMRk8VkQ2Iko",
445
+ "outputId": "bbf3cd10-7294-472d-e330-21e00f20963a"
446
+ },
447
+ "outputs": [],
448
+ "source": [
449
+ "# When we finished exp.train(setting) and exp.test(setting), we will get a trained model and the results of test experiment\n",
450
+ "# The results of test experiment will be saved in ./results/{setting}/pred.npy (prediction of test dataset) and ./results/{setting}/true.npy (groundtruth of test dataset)\n",
451
+ "\n",
452
+ "preds = np.load(f\"./results/{setting}/pred.npy\")\n",
453
+ "trues = np.load(f\"./results/{setting}/true.npy\")\n",
454
+ "\n",
455
+ "# [samples, pred_len, dimensions]\n",
456
+ "preds.shape, trues.shape"
457
+ ]
458
+ },
459
+ {
460
+ "cell_type": "code",
461
+ "execution_count": null,
462
+ "metadata": {
463
+ "id": "ZEGhDOmxAeAb"
464
+ },
465
+ "outputs": [],
466
+ "source": [
467
+ "import matplotlib.pyplot as plt\n",
468
+ "import seaborn as sns"
469
+ ]
470
+ },
471
+ {
472
+ "cell_type": "code",
473
+ "execution_count": null,
474
+ "metadata": {
475
+ "colab": {
476
+ "base_uri": "https://localhost:8080/",
477
+ "height": 265
478
+ },
479
+ "id": "kyPuOPGAAjl3",
480
+ "outputId": "8554f6f8-c13a-43e1-b04b-5f27823445d0"
481
+ },
482
+ "outputs": [],
483
+ "source": [
484
+ "# draw OT prediction\n",
485
+ "plt.figure()\n",
486
+ "plt.plot(trues[0, :, -1], label=\"GroundTruth\")\n",
487
+ "plt.plot(preds[0, :, -1], label=\"Prediction\")\n",
488
+ "plt.legend()\n",
489
+ "plt.show()"
490
+ ]
491
+ },
492
+ {
493
+ "cell_type": "code",
494
+ "execution_count": null,
495
+ "metadata": {},
496
+ "outputs": [],
497
+ "source": [
498
+ "print(trues.shape)\n",
499
+ "print(preds.shape)\n",
500
+ "MSE = np.square(np.subtract(trues, preds)).mean()\n",
501
+ "RMSE = np.sqrt(MSE)\n",
502
+ "\n",
503
+ "print(\"against preds\", MSE, RMSE)\n",
504
+ "\n",
505
+ "\n",
506
+ "MSE = np.square(np.subtract(preds, np.zeros(preds.shape))).mean()\n",
507
+ "RMSE = np.sqrt(MSE)\n",
508
+ "print(\"against 0s\", MSE, RMSE)"
509
+ ]
510
+ },
511
+ {
512
+ "cell_type": "code",
513
+ "execution_count": null,
514
+ "metadata": {
515
+ "colab": {
516
+ "base_uri": "https://localhost:8080/",
517
+ "height": 265
518
+ },
519
+ "id": "43MIgWfpMYIB",
520
+ "outputId": "327f64b7-363c-44f9-c7c8-1f654911068c"
521
+ },
522
+ "outputs": [],
523
+ "source": [
524
+ "# draw HUFL prediction\n",
525
+ "plt.figure()\n",
526
+ "plt.plot(trues[0, :, 0], label=\"GroundTruth\")\n",
527
+ "plt.plot(preds[0, :, 0], label=\"Prediction\")\n",
528
+ "plt.legend()\n",
529
+ "plt.show()"
530
+ ]
531
+ },
532
+ {
533
+ "cell_type": "code",
534
+ "execution_count": null,
535
+ "metadata": {
536
+ "id": "hKmqhCfmt0xd"
537
+ },
538
+ "outputs": [],
539
+ "source": [
540
+ "from data_provider.data_loader import Dataset_Custom\n",
541
+ "from torch.utils.data import DataLoader\n",
542
+ "\n",
543
+ "Data = Dataset_Custom\n",
544
+ "timeenc = 0 if args.t_embed != \"timeF\" else 1\n",
545
+ "flag = \"test\"\n",
546
+ "shuffle_flag = False\n",
547
+ "drop_last = True\n",
548
+ "batch_size = 1\n",
549
+ "data_set = Data(args, flag=flag, freq=freq, timeenc=timeenc)\n",
550
+ "\n",
551
+ "data_loader = DataLoader(\n",
552
+ " data_set,\n",
553
+ " batch_size=batch_size,\n",
554
+ " shuffle=shuffle_flag,\n",
555
+ " num_workers=args.num_workers,\n",
556
+ " drop_last=drop_last,\n",
557
+ ")"
558
+ ]
559
+ },
560
+ {
561
+ "cell_type": "code",
562
+ "execution_count": null,
563
+ "metadata": {
564
+ "colab": {
565
+ "base_uri": "https://localhost:8080/"
566
+ },
567
+ "id": "iflTTl0quCoK",
568
+ "outputId": "3708fc91-517e-4c83-e133-059381bde271"
569
+ },
570
+ "outputs": [],
571
+ "source": [
572
+ "import os\n",
573
+ "\n",
574
+ "args.output_attention = True\n",
575
+ "\n",
576
+ "exp = Exp(args)\n",
577
+ "\n",
578
+ "model = exp.model\n",
579
+ "\n",
580
+ "path = os.path.join(args.checkpoints, setting, \"checkpoint.pth\")\n",
581
+ "\n",
582
+ "print(model.load_state_dict(torch.load(path)))\n",
583
+ "\n",
584
+ "df = pd.read_csv(os.path.join(args.root_path, args.data_path))\n",
585
+ "df[args.cols].head()"
586
+ ]
587
+ },
588
+ {
589
+ "cell_type": "markdown",
590
+ "metadata": {},
591
+ "source": [
592
+ "### Attention Visualization"
593
+ ]
594
+ },
595
+ {
596
+ "cell_type": "code",
597
+ "execution_count": null,
598
+ "metadata": {
599
+ "id": "lDdzqm9HAk2C"
600
+ },
601
+ "outputs": [],
602
+ "source": [
603
+ "idx = 0\n",
604
+ "for i, (batch_x, batch_y, batch_x_mark, batch_y_mark) in enumerate(data_loader):\n",
605
+ " if i != idx:\n",
606
+ " continue\n",
607
+ " batch_x = batch_x.float().to(exp.device)\n",
608
+ " batch_y = batch_y.float()\n",
609
+ "\n",
610
+ " batch_x_mark = batch_x_mark.float().to(exp.device)\n",
611
+ " batch_y_mark = batch_y_mark.float().to(exp.device)\n",
612
+ "\n",
613
+ " dec_inp = torch.zeros_like(batch_y[:, -args.pred_len :, :]).float()\n",
614
+ " dec_inp = (\n",
615
+ " torch.cat([batch_y[:, : args.label_len, :], dec_inp], dim=1)\n",
616
+ " .float()\n",
617
+ " .to(exp.device)\n",
618
+ " )\n",
619
+ "\n",
620
+ " outputs, attn = model(batch_x, batch_x_mark, dec_inp, batch_y_mark)"
621
+ ]
622
+ },
623
+ {
624
+ "cell_type": "code",
625
+ "execution_count": null,
626
+ "metadata": {
627
+ "colab": {
628
+ "base_uri": "https://localhost:8080/"
629
+ },
630
+ "id": "hWef23vWAmUz",
631
+ "outputId": "021eca83-e12f-402c-c87e-4fffa643d2f1"
632
+ },
633
+ "outputs": [],
634
+ "source": [
635
+ "attn[0].shape, attn[1].shape # , attn[2].shape"
636
+ ]
637
+ },
638
+ {
639
+ "cell_type": "code",
640
+ "execution_count": null,
641
+ "metadata": {
642
+ "colab": {
643
+ "base_uri": "https://localhost:8080/",
644
+ "height": 1000
645
+ },
646
+ "id": "iZDH1fZgAnrl",
647
+ "outputId": "991cae95-04a2-402d-f179-777e962f46fe"
648
+ },
649
+ "outputs": [],
650
+ "source": [
651
+ "layers = [0, 1]\n",
652
+ "distil = \"Distil\" if args.distil else \"NoDistil\"\n",
653
+ "for layer in layers:\n",
654
+ " print(\"\\n\\n==========================\")\n",
655
+ " print(\"Showing attention layer\", layer)\n",
656
+ " print(\"==========================\\n\\n\")\n",
657
+ " for h in range(0, args.n_heads):\n",
658
+ " plt.figure(figsize=[10, 8])\n",
659
+ " plt.title(f\"Informer, {distil}, attn:{args.attn} layer:{layer} head:{h}\")\n",
660
+ " A = attn[layer][0, h].detach().cpu().numpy()\n",
661
+ " ax = sns.heatmap(A, vmin=0, vmax=A.max() + 0.01)\n",
662
+ " plt.show()"
663
+ ]
664
+ }
665
+ ],
666
+ "metadata": {
667
+ "accelerator": "GPU",
668
+ "colab": {
669
+ "collapsed_sections": [],
670
+ "provenance": [],
671
+ "toc_visible": true
672
+ },
673
+ "kernelspec": {
674
+ "display_name": "former",
675
+ "language": "python",
676
+ "name": "python3"
677
+ },
678
+ "language_info": {
679
+ "codemirror_mode": {
680
+ "name": "ipython",
681
+ "version": 3
682
+ },
683
+ "file_extension": ".py",
684
+ "mimetype": "text/x-python",
685
+ "name": "python",
686
+ "nbconvert_exporter": "python",
687
+ "pygments_lexer": "ipython3",
688
+ "version": "3.10.6 (main, Oct 24 2022, 16:07:47) [GCC 11.2.0]"
689
+ },
690
+ "vscode": {
691
+ "interpreter": {
692
+ "hash": "44e5710a47a66ec240c2a0834fd7c20e15c61536e70be6891d892a39679ad994"
693
+ }
694
+ }
695
+ },
696
+ "nbformat": 4,
697
+ "nbformat_minor": 0
698
+ }
old_stuff/Makefile ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ IMAGE := informer
2
+ ROOT := $(shell dirname $(realpath $(firstword ${MAKEFILE_LIST})))
3
+ PARENT_ROOT := $(shell dirname ${ROOT})
4
+ PORT := 8888
5
+
6
+ DOCKER_PARAMETERS := \
7
+ --user $(shell id -u) \
8
+ -v ${ROOT}:/app \
9
+ -w /app \
10
+ -e HOME=/tmp
11
+
12
+ init:
13
+ docker build -t ${IMAGE} .
14
+
15
+ dataset:
16
+ mkdir -p data/ETT && \
17
+ wget -O data/ETT/ETTh1.csv https://raw.githubusercontent.com/zhouhaoyi/ETDataset/main/ETT-small/ETTh1.csv && \
18
+ wget -O data/ETT/ETTh2.csv https://raw.githubusercontent.com/zhouhaoyi/ETDataset/main/ETT-small/ETTh2.csv && \
19
+ wget -O data/ETT/ETTm1.csv https://raw.githubusercontent.com/zhouhaoyi/ETDataset/main/ETT-small/ETTm1.csv && \
20
+ wget -O data/ETT/ETTm2.csv https://raw.githubusercontent.com/zhouhaoyi/ETDataset/main/ETT-small/ETTm2.csv && \
21
+ wget -O data/ETT/ECL.csv "https://drive.google.com/uc?export=download&id=1rUPdR7R2iWFW-LMoDdHoO2g4KgnkpFzP" && \
22
+ wget -O data/ETT/WTH.csv "https://drive.google.com/uc?export=download&id=1UBRz-aM_57i_KCC-iaSWoKDPTGGv6EaG"
23
+
24
+ jupyter:
25
+ docker run -d --rm ${DOCKER_PARAMETERS} -e HOME=/tmp -p ${PORT}:8888 ${IMAGE} \
26
+ bash -c "jupyter lab --ip=0.0.0.0 --no-browser --NotebookApp.token=''"
27
+
28
+ run_module: .require-module
29
+ docker run -i --rm ${DOCKER_PARAMETERS} \
30
+ ${IMAGE} ${module}
31
+
32
+ bash_docker:
33
+ docker run -it --rm ${DOCKER_PARAMETERS} ${IMAGE}
34
+
35
+ .require-module:
36
+ ifndef module
37
+ $(error module is required)
38
+ endif