From bb5f3cb33d32f1c186d6aadc157a39b29b91cafe Mon Sep 17 00:00:00 2001 From: Jactus Date: Tue, 1 Dec 2020 09:59:46 +0800 Subject: [PATCH 01/17] Fix and move to version 0.6.0 --- examples/run_all_model.py | 4 ++-- qlib/__init__.py | 2 +- setup.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/run_all_model.py b/examples/run_all_model.py index 8843573ab..3d8628c4a 100644 --- a/examples/run_all_model.py +++ b/examples/run_all_model.py @@ -243,11 +243,11 @@ def run(times=1, models=None, exclude=False): execute(f"{python_path} -m pip install --upgrade cython") # TODO: FIX ME! if fn == "TFT": execute( - f"cd {env_path} && {python_path} -m pip install --upgrade --force-reinstall --ignore-installed PyYAML -e git+https://github.com/you-n-g/qlib#egg=pyqlib" + f"cd {env_path} && {python_path} -m pip install --upgrade --force-reinstall --ignore-installed PyYAML -e git+https://github.com/microsoft/qlib#egg=pyqlib" ) # TODO: FIX ME! else: execute( - f"cd {env_path} && {python_path} -m pip install --upgrade --force-reinstall -e git+https://github.com/you-n-g/qlib#egg=pyqlib" + f"cd {env_path} && {python_path} -m pip install --upgrade --force-reinstall -e git+https://github.com/microsoft/qlib#egg=pyqlib" ) # TODO: FIX ME! sys.stderr.write("\n") # run workflow_by_config for multiple times diff --git a/qlib/__init__.py b/qlib/__init__.py index 2b8989303..73d985d04 100644 --- a/qlib/__init__.py +++ b/qlib/__init__.py @@ -2,7 +2,7 @@ # Licensed under the MIT License. -__version__ = "0.6.0.alpha" +__version__ = "0.6.0" import os import re diff --git a/setup.py b/setup.py index 0696a766f..b7a37e028 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ from setuptools import find_packages, setup, Extension NAME = "pyqlib" DESCRIPTION = "A Quantitative-research Platform" REQUIRES_PYTHON = ">=3.5.0" -VERSION = "0.6.0.alpha" +VERSION = "0.6.0" # Detect Cython try: From 77884db3a562a795d29e16e844c0c21fa17c26e2 Mon Sep 17 00:00:00 2001 From: Jactus Date: Tue, 1 Dec 2020 11:54:26 +0800 Subject: [PATCH 02/17] Fix and update run_all_model --- .../ALSTM/workflow_config_alstm.yaml | 1 - .../benchmarks/GATs/workflow_config_gats.yaml | 1 - .../benchmarks/GRU/workflow_config_gru.yaml | 1 - .../benchmarks/LSTM/workflow_config_lstm.yaml | 1 - .../benchmarks/SFM/workflow_config_sfm.yaml | 1 - examples/run_all_model.py | 19 ++++++++++++++++--- qlib/contrib/model/pytorch_alstm.py | 7 ++++--- qlib/contrib/model/pytorch_gats.py | 9 ++++++--- qlib/contrib/model/pytorch_gru.py | 7 ++++--- qlib/contrib/model/pytorch_lstm.py | 7 ++++--- qlib/contrib/model/pytorch_nn.py | 7 ++++--- qlib/contrib/model/pytorch_sfm.py | 7 ++++--- 12 files changed, 42 insertions(+), 26 deletions(-) diff --git a/examples/benchmarks/ALSTM/workflow_config_alstm.yaml b/examples/benchmarks/ALSTM/workflow_config_alstm.yaml index 66367034d..37dceaacb 100644 --- a/examples/benchmarks/ALSTM/workflow_config_alstm.yaml +++ b/examples/benchmarks/ALSTM/workflow_config_alstm.yaml @@ -54,7 +54,6 @@ task: batch_size: 800 metric: loss loss: mse - seed: 0 GPU: 0 rnn_type: GRU dataset: diff --git a/examples/benchmarks/GATs/workflow_config_gats.yaml b/examples/benchmarks/GATs/workflow_config_gats.yaml index a608a7e49..d4f2c3106 100644 --- a/examples/benchmarks/GATs/workflow_config_gats.yaml +++ b/examples/benchmarks/GATs/workflow_config_gats.yaml @@ -56,7 +56,6 @@ task: base_model: LSTM with_pretrain: True model_path: "benchmarks/LSTM/model_lstm_csi300.pkl" - seed: 0 GPU: 0 dataset: class: DatasetH diff --git a/examples/benchmarks/GRU/workflow_config_gru.yaml b/examples/benchmarks/GRU/workflow_config_gru.yaml index 381581a77..64ae3437c 100644 --- a/examples/benchmarks/GRU/workflow_config_gru.yaml +++ b/examples/benchmarks/GRU/workflow_config_gru.yaml @@ -54,7 +54,6 @@ task: batch_size: 800 metric: loss loss: mse - seed: 0 GPU: 0 dataset: class: DatasetH diff --git a/examples/benchmarks/LSTM/workflow_config_lstm.yaml b/examples/benchmarks/LSTM/workflow_config_lstm.yaml index cb3b2a789..b857d97d4 100644 --- a/examples/benchmarks/LSTM/workflow_config_lstm.yaml +++ b/examples/benchmarks/LSTM/workflow_config_lstm.yaml @@ -54,7 +54,6 @@ task: batch_size: 800 metric: loss loss: mse - seed: 0 GPU: 0 dataset: class: DatasetH diff --git a/examples/benchmarks/SFM/workflow_config_sfm.yaml b/examples/benchmarks/SFM/workflow_config_sfm.yaml index edf176e62..d0a95bfa5 100644 --- a/examples/benchmarks/SFM/workflow_config_sfm.yaml +++ b/examples/benchmarks/SFM/workflow_config_sfm.yaml @@ -58,7 +58,6 @@ task: loss: mse optimizer: adam GPU: 1 - seed: 710 dataset: class: DatasetH module_path: qlib.data.dataset diff --git a/examples/run_all_model.py b/examples/run_all_model.py index 3d8628c4a..6df0ff4bb 100644 --- a/examples/run_all_model.py +++ b/examples/run_all_model.py @@ -152,6 +152,10 @@ def get_all_results(folders) -> dict: result["annualized_return_with_cost"] = list() result["information_ratio_with_cost"] = list() result["max_drawdown_with_cost"] = list() + result["ic"] = list() + result["icir"] = list() + result["rank_ic"] = list() + result["rank_icir"] = list() for recorder_id in recorders: if recorders[recorder_id].status == "FINISHED": recorder = R.get_recorder(recorder_id=recorder_id, experiment_name=fn) @@ -159,19 +163,27 @@ def get_all_results(folders) -> dict: result["annualized_return_with_cost"].append(metrics["excess_return_with_cost.annualized_return"]) result["information_ratio_with_cost"].append(metrics["excess_return_with_cost.information_ratio"]) result["max_drawdown_with_cost"].append(metrics["excess_return_with_cost.max_drawdown"]) + result["ic"].append(metrics["IC"]) + result["icir"].append(metrics["ICIR"]) + result["rank_ic"].append(metrics["Rank IC"]) + result["rank_icir"].append(metrics["Rank ICIR"]) results[fn] = result return results # function to generate and save markdown table def gen_and_save_md_table(metrics): - table = "| Model Name | Annualized Return | Information Ratio | Max Drawdown |\n" - table += "|---|---|---|---|\n" + table = "| Model Name | Annualized Return | Information Ratio | Max Drawdown | IC | ICIR | Rank IC | Rank ICIR |\n" + table += "|---|---|---|---|---|---|---|---|\n" for fn in metrics: ar = metrics[fn]["annualized_return_with_cost"] ir = metrics[fn]["information_ratio_with_cost"] md = metrics[fn]["max_drawdown_with_cost"] - table += f"| {fn} | {ar[0]:9.4f}±{ar[1]:9.2f} | {ir[0]:9.4f}±{ir[1]:9.2f}| {md[0]:9.4f}±{md[1]:9.2f} |\n" + ic = metrics[fn]["ic"] + icir = metrics[fn]["icir"] + ric = metrics[fn]["rank_ic"] + ricir = metrics[fn]["rank_icir"] + table += f"| {fn} | {ar[0]:5.4f}±{ar[1]:2.2f} | {ir[0]:5.4f}±{ir[1]:2.2f}| {md[0]:5.4f}±{md[1]:2.2f} | {ic[0]:5.4f}±{ic[1]:2.2f} | {icir[0]:5.4f}±{icir[1]:2.2f}| {ric[0]:5.4f}±{ric[1]:2.2f} | {ricir[0]:5.4f}±{ricir[1]:2.2f} |\n" pprint(table) with open("table.md", "w") as f: f.write(table) @@ -240,6 +252,7 @@ def run(times=1, models=None, exclude=False): sys.stderr.write("\n") # install qlib sys.stderr.write("Installing qlib...\n") + execute(f"{python_path} -m pip install --upgrade pip") # TODO: FIX ME! execute(f"{python_path} -m pip install --upgrade cython") # TODO: FIX ME! if fn == "TFT": execute( diff --git a/qlib/contrib/model/pytorch_alstm.py b/qlib/contrib/model/pytorch_alstm.py index ba75c70ca..d992ec52f 100644 --- a/qlib/contrib/model/pytorch_alstm.py +++ b/qlib/contrib/model/pytorch_alstm.py @@ -57,7 +57,7 @@ class ALSTM(Model): loss="mse", optimizer="adam", GPU="0", - seed=0, + seed=None, **kwargs ): # Set logger. @@ -113,8 +113,9 @@ class ALSTM(Model): ) ) - np.random.seed(self.seed) - torch.manual_seed(self.seed) + if self.seed is not None: + np.random.seed(self.seed) + torch.manual_seed(self.seed) self.ALSTM_model = ALSTMModel( d_feat=self.d_feat, diff --git a/qlib/contrib/model/pytorch_gats.py b/qlib/contrib/model/pytorch_gats.py index 2e19c0542..83f2633c5 100644 --- a/qlib/contrib/model/pytorch_gats.py +++ b/qlib/contrib/model/pytorch_gats.py @@ -62,7 +62,7 @@ class GATs(Model): model_path=None, optimizer="adam", GPU="0", - seed=0, + seed=None, **kwargs ): # Set logger. @@ -123,8 +123,11 @@ class GATs(Model): seed, ) ) - np.random.seed(self.seed) - torch.manual_seed(self.seed) + + if self.seed is not None: + np.random.seed(self.seed) + torch.manual_seed(self.seed) + self.GAT_model = GATModel( d_feat=self.d_feat, hidden_size=self.hidden_size, diff --git a/qlib/contrib/model/pytorch_gru.py b/qlib/contrib/model/pytorch_gru.py index 4ef4e2553..1c24017fc 100755 --- a/qlib/contrib/model/pytorch_gru.py +++ b/qlib/contrib/model/pytorch_gru.py @@ -57,7 +57,7 @@ class GRU(Model): loss="mse", optimizer="adam", GPU="0", - seed=0, + seed=None, **kwargs ): # Set logger. @@ -113,8 +113,9 @@ class GRU(Model): ) ) - np.random.seed(self.seed) - torch.manual_seed(self.seed) + if self.seed is not None: + np.random.seed(self.seed) + torch.manual_seed(self.seed) self.gru_model = GRUModel( d_feat=self.d_feat, diff --git a/qlib/contrib/model/pytorch_lstm.py b/qlib/contrib/model/pytorch_lstm.py index 59df51e42..81e803e96 100755 --- a/qlib/contrib/model/pytorch_lstm.py +++ b/qlib/contrib/model/pytorch_lstm.py @@ -57,7 +57,7 @@ class LSTM(Model): loss="mse", optimizer="adam", GPU="0", - seed=0, + seed=None, **kwargs ): # Set logger. @@ -113,8 +113,9 @@ class LSTM(Model): ) ) - np.random.seed(self.seed) - torch.manual_seed(self.seed) + if self.seed is not None: + np.random.seed(self.seed) + torch.manual_seed(self.seed) self.lstm_model = LSTMModel( d_feat=self.d_feat, diff --git a/qlib/contrib/model/pytorch_nn.py b/qlib/contrib/model/pytorch_nn.py index a60227ff0..fac9d4607 100644 --- a/qlib/contrib/model/pytorch_nn.py +++ b/qlib/contrib/model/pytorch_nn.py @@ -61,7 +61,7 @@ class DNNModelPytorch(Model): optimizer="gd", loss="mse", GPU="0", - seed=0, + seed=None, **kwargs ): # Set logger. @@ -116,8 +116,9 @@ class DNNModelPytorch(Model): ) ) - np.random.seed(self.seed) - torch.manual_seed(self.seed) + if self.seed is not None: + np.random.seed(self.seed) + torch.manual_seed(self.seed) if loss not in {"mse", "binary"}: raise NotImplementedError("loss {} is not supported!".format(loss)) diff --git a/qlib/contrib/model/pytorch_sfm.py b/qlib/contrib/model/pytorch_sfm.py index d845f6245..da75b1bca 100644 --- a/qlib/contrib/model/pytorch_sfm.py +++ b/qlib/contrib/model/pytorch_sfm.py @@ -217,7 +217,7 @@ class SFM(Model): loss="mse", optimizer="gd", GPU="0", - seed=0, + seed=None, **kwargs ): # Set logger. @@ -282,8 +282,9 @@ class SFM(Model): ) ) - np.random.seed(self.seed) - torch.manual_seed(self.seed) + if self.seed is not None: + np.random.seed(self.seed) + torch.manual_seed(self.seed) self.sfm_model = SFM_Model( d_feat=self.d_feat, From a2603fe27ad06acb5863987b4876f25951253412 Mon Sep 17 00:00:00 2001 From: Jactus Date: Wed, 2 Dec 2020 09:41:24 +0800 Subject: [PATCH 03/17] Update config --- examples/benchmarks/GATs/workflow_config_gats.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/examples/benchmarks/GATs/workflow_config_gats.yaml b/examples/benchmarks/GATs/workflow_config_gats.yaml index d4f2c3106..0ab0cae8d 100644 --- a/examples/benchmarks/GATs/workflow_config_gats.yaml +++ b/examples/benchmarks/GATs/workflow_config_gats.yaml @@ -73,6 +73,11 @@ task: - class: SignalRecord module_path: qlib.workflow.record_temp kwargs: {} + - class: SigAnaRecord + module_path: qlib.workflow.record_temp + kwargs: + ana_long_short: False + ann_scaler: 252 - class: PortAnaRecord module_path: qlib.workflow.record_temp kwargs: From d109d3d44e88b4675b1289406c7d837aa88bb410 Mon Sep 17 00:00:00 2001 From: Jactus Date: Wed, 2 Dec 2020 12:23:42 +0800 Subject: [PATCH 04/17] Fix GPU --- examples/benchmarks/SFM/workflow_config_sfm.yaml | 2 +- qlib/contrib/model/pytorch_alstm.py | 2 +- qlib/contrib/model/pytorch_gats.py | 2 +- qlib/contrib/model/pytorch_gru.py | 2 +- qlib/contrib/model/pytorch_lstm.py | 2 +- qlib/contrib/model/pytorch_nn.py | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/benchmarks/SFM/workflow_config_sfm.yaml b/examples/benchmarks/SFM/workflow_config_sfm.yaml index d0a95bfa5..5a0448cfe 100644 --- a/examples/benchmarks/SFM/workflow_config_sfm.yaml +++ b/examples/benchmarks/SFM/workflow_config_sfm.yaml @@ -57,7 +57,7 @@ task: eval_steps: 5 loss: mse optimizer: adam - GPU: 1 + GPU: 0 dataset: class: DatasetH module_path: qlib.data.dataset diff --git a/qlib/contrib/model/pytorch_alstm.py b/qlib/contrib/model/pytorch_alstm.py index d992ec52f..9b5db8042 100644 --- a/qlib/contrib/model/pytorch_alstm.py +++ b/qlib/contrib/model/pytorch_alstm.py @@ -135,7 +135,7 @@ class ALSTM(Model): self.ALSTM_model.cuda() # set the visible GPU if self.visible_GPU: - os.environ["CUDA_VISIBLE_DEVICES"] = self.visible_GPU + os.environ["CUDA_VISIBLE_DEVICES"] = str(self.visible_GPU) def mse(self, pred, label): loss = (pred - label) ** 2 diff --git a/qlib/contrib/model/pytorch_gats.py b/qlib/contrib/model/pytorch_gats.py index 83f2633c5..5bc91eb3b 100644 --- a/qlib/contrib/model/pytorch_gats.py +++ b/qlib/contrib/model/pytorch_gats.py @@ -147,7 +147,7 @@ class GATs(Model): self.GAT_model.cuda() # set the visible GPU if self.visible_GPU: - os.environ["CUDA_VISIBLE_DEVICES"] = self.visible_GPU + os.environ["CUDA_VISIBLE_DEVICES"] = str(self.visible_GPU) def mse(self, pred, label): loss = (pred - label) ** 2 diff --git a/qlib/contrib/model/pytorch_gru.py b/qlib/contrib/model/pytorch_gru.py index 1c24017fc..7974e7c33 100755 --- a/qlib/contrib/model/pytorch_gru.py +++ b/qlib/contrib/model/pytorch_gru.py @@ -135,7 +135,7 @@ class GRU(Model): self.gru_model.cuda() # set the visible GPU if self.visible_GPU: - os.environ["CUDA_VISIBLE_DEVICES"] = self.visible_GPU + os.environ["CUDA_VISIBLE_DEVICES"] = str(self.visible_GPU) def mse(self, pred, label): loss = (pred - label) ** 2 diff --git a/qlib/contrib/model/pytorch_lstm.py b/qlib/contrib/model/pytorch_lstm.py index 81e803e96..2eb6ae69f 100755 --- a/qlib/contrib/model/pytorch_lstm.py +++ b/qlib/contrib/model/pytorch_lstm.py @@ -135,7 +135,7 @@ class LSTM(Model): self.lstm_model.cuda() # set the visible GPU if self.visible_GPU: - os.environ["CUDA_VISIBLE_DEVICES"] = self.visible_GPU + os.environ["CUDA_VISIBLE_DEVICES"] = str(self.visible_GPU) def mse(self, pred, label): loss = (pred - label) ** 2 diff --git a/qlib/contrib/model/pytorch_nn.py b/qlib/contrib/model/pytorch_nn.py index fac9d4607..a9d8a38d0 100644 --- a/qlib/contrib/model/pytorch_nn.py +++ b/qlib/contrib/model/pytorch_nn.py @@ -151,7 +151,7 @@ class DNNModelPytorch(Model): self.dnn_model.cuda() # set the visible GPU if self.visible_GPU: - os.environ["CUDA_VISIBLE_DEVICES"] = self.visible_GPU + os.environ["CUDA_VISIBLE_DEVICES"] = str(self.visible_GPU) def fit( self, From 7f385345bb41d4af7dc6c27265ddc52d3cc8b633 Mon Sep 17 00:00:00 2001 From: Jactus Date: Wed, 2 Dec 2020 13:25:29 +0800 Subject: [PATCH 05/17] Fix GPU --- qlib/contrib/model/pytorch_alstm.py | 29 ++++++------------------- qlib/contrib/model/pytorch_gats.py | 29 ++++++------------------- qlib/contrib/model/pytorch_gru.py | 29 ++++++------------------- qlib/contrib/model/pytorch_lstm.py | 29 ++++++------------------- qlib/contrib/model/pytorch_nn.py | 33 ++++++++--------------------- 5 files changed, 37 insertions(+), 112 deletions(-) diff --git a/qlib/contrib/model/pytorch_alstm.py b/qlib/contrib/model/pytorch_alstm.py index 9b5db8042..cfe629fa8 100644 --- a/qlib/contrib/model/pytorch_alstm.py +++ b/qlib/contrib/model/pytorch_alstm.py @@ -76,7 +76,7 @@ class ALSTM(Model): self.early_stop = early_stop self.optimizer = optimizer.lower() self.loss = loss - self.visible_GPU = GPU + self.device = "cuda:%d" % (GPU) if torch.cuda.is_available() else "cpu" self.use_gpu = torch.cuda.is_available() self.seed = seed @@ -131,11 +131,7 @@ class ALSTM(Model): raise NotImplementedError("optimizer {} is not supported!".format(optimizer)) self._fitted = False - if self.use_gpu: - self.ALSTM_model.cuda() - # set the visible GPU - if self.visible_GPU: - os.environ["CUDA_VISIBLE_DEVICES"] = str(self.visible_GPU) + self.ALSTM_model.to(self.device) def mse(self, pred, label): loss = (pred - label) ** 2 @@ -173,12 +169,8 @@ class ALSTM(Model): if len(indices) - i < self.batch_size: break - feature = torch.from_numpy(x_train_values[indices[i : i + self.batch_size]]).float() - label = torch.from_numpy(y_train_values[indices[i : i + self.batch_size]]).float() - - if self.use_gpu: - feature = feature.cuda() - label = label.cuda() + feature = torch.from_numpy(x_train_values[indices[i : i + self.batch_size]]).float().to(self.device) + label = torch.from_numpy(y_train_values[indices[i : i + self.batch_size]]).float().to(self.device) pred = self.ALSTM_model(feature) loss = self.loss_fn(pred, label) @@ -206,12 +198,8 @@ class ALSTM(Model): if len(indices) - i < self.batch_size: break - feature = torch.from_numpy(x_values[indices[i : i + self.batch_size]]).float() - label = torch.from_numpy(y_values[indices[i : i + self.batch_size]]).float() - - if self.use_gpu: - feature = feature.cuda() - label = label.cuda() + feature = torch.from_numpy(x_values[indices[i : i + self.batch_size]]).float().to(self.device) + label = torch.from_numpy(y_values[indices[i : i + self.batch_size]]).float().to(self.device) pred = self.ALSTM_model(feature) loss = self.loss_fn(pred, label) @@ -299,10 +287,7 @@ class ALSTM(Model): else: end = begin + self.batch_size - x_batch = torch.from_numpy(x_values[begin:end]).float() - - if self.use_gpu: - x_batch = x_batch.cuda() + x_batch = torch.from_numpy(x_values[begin:end]).float().to(self.device) with torch.no_grad(): if self.use_gpu: diff --git a/qlib/contrib/model/pytorch_gats.py b/qlib/contrib/model/pytorch_gats.py index 5bc91eb3b..1759ae5ba 100644 --- a/qlib/contrib/model/pytorch_gats.py +++ b/qlib/contrib/model/pytorch_gats.py @@ -83,7 +83,7 @@ class GATs(Model): self.base_model = base_model self.with_pretrain = with_pretrain self.model_path = model_path - self.visible_GPU = GPU + self.device = "cuda:%d" % (GPU) if torch.cuda.is_available() else "cpu" self.use_gpu = torch.cuda.is_available() self.seed = seed @@ -143,11 +143,7 @@ class GATs(Model): raise NotImplementedError("optimizer {} is not supported!".format(optimizer)) self._fitted = False - if self.use_gpu: - self.GAT_model.cuda() - # set the visible GPU - if self.visible_GPU: - os.environ["CUDA_VISIBLE_DEVICES"] = str(self.visible_GPU) + self.GAT_model.to(self.device) def mse(self, pred, label): loss = (pred - label) ** 2 @@ -193,12 +189,8 @@ class GATs(Model): for idx, count in zip(daily_index, daily_count): batch = slice(idx, idx + count) - feature = torch.from_numpy(x_train_values[batch]).float() - label = torch.from_numpy(y_train_values[batch]).float() - - if self.use_gpu: - feature = feature.cuda() - label = label.cuda() + feature = torch.from_numpy(x_train_values[batch]).float().to(self.device) + label = torch.from_numpy(y_train_values[batch]).float().to(self.device) pred = self.GAT_model(feature) loss = self.loss_fn(pred, label) @@ -224,12 +216,8 @@ class GATs(Model): for idx, count in zip(daily_index, daily_count): batch = slice(idx, idx + count) - feature = torch.from_numpy(x_values[batch]).float() - label = torch.from_numpy(y_values[batch]).float() - - if self.use_gpu: - feature = feature.cuda() - label = label.cuda() + feature = torch.from_numpy(x_values[batch]).float().to(self.device) + label = torch.from_numpy(y_values[batch]).float().to(self.device) pred = self.GAT_model(feature) loss = self.loss_fn(pred, label) @@ -333,10 +321,7 @@ class GATs(Model): for idx, count in zip(daily_index, daily_count): batch = slice(idx, idx + count) - x_batch = torch.from_numpy(x_values[batch]).float() - - if self.use_gpu: - x_batch = x_batch.cuda() + x_batch = torch.from_numpy(x_values[batch]).float().to(self.device) with torch.no_grad(): if self.use_gpu: diff --git a/qlib/contrib/model/pytorch_gru.py b/qlib/contrib/model/pytorch_gru.py index 7974e7c33..8d5a9e461 100755 --- a/qlib/contrib/model/pytorch_gru.py +++ b/qlib/contrib/model/pytorch_gru.py @@ -76,7 +76,7 @@ class GRU(Model): self.early_stop = early_stop self.optimizer = optimizer.lower() self.loss = loss - self.visible_GPU = GPU + self.device = "cuda:%d" % (GPU) if torch.cuda.is_available() else "cpu" self.use_gpu = torch.cuda.is_available() self.seed = seed @@ -131,11 +131,7 @@ class GRU(Model): raise NotImplementedError("optimizer {} is not supported!".format(optimizer)) self._fitted = False - if self.use_gpu: - self.gru_model.cuda() - # set the visible GPU - if self.visible_GPU: - os.environ["CUDA_VISIBLE_DEVICES"] = str(self.visible_GPU) + self.gru_model.to(self.device) def mse(self, pred, label): loss = (pred - label) ** 2 @@ -173,12 +169,8 @@ class GRU(Model): if len(indices) - i < self.batch_size: break - feature = torch.from_numpy(x_train_values[indices[i : i + self.batch_size]]).float() - label = torch.from_numpy(y_train_values[indices[i : i + self.batch_size]]).float() - - if self.use_gpu: - feature = feature.cuda() - label = label.cuda() + feature = torch.from_numpy(x_train_values[indices[i : i + self.batch_size]]).float().to(self.device) + label = torch.from_numpy(y_train_values[indices[i : i + self.batch_size]]).float().to(self.device) pred = self.gru_model(feature) loss = self.loss_fn(pred, label) @@ -206,12 +198,8 @@ class GRU(Model): if len(indices) - i < self.batch_size: break - feature = torch.from_numpy(x_values[indices[i : i + self.batch_size]]).float() - label = torch.from_numpy(y_values[indices[i : i + self.batch_size]]).float() - - if self.use_gpu: - feature = feature.cuda() - label = label.cuda() + feature = torch.from_numpy(x_values[indices[i : i + self.batch_size]]).float().to(self.device) + label = torch.from_numpy(y_values[indices[i : i + self.batch_size]]).float().to(self.device) pred = self.gru_model(feature) loss = self.loss_fn(pred, label) @@ -299,10 +287,7 @@ class GRU(Model): else: end = begin + self.batch_size - x_batch = torch.from_numpy(x_values[begin:end]).float() - - if self.use_gpu: - x_batch = x_batch.cuda() + x_batch = torch.from_numpy(x_values[begin:end]).float().to(self.device) with torch.no_grad(): if self.use_gpu: diff --git a/qlib/contrib/model/pytorch_lstm.py b/qlib/contrib/model/pytorch_lstm.py index 2eb6ae69f..8032c54eb 100755 --- a/qlib/contrib/model/pytorch_lstm.py +++ b/qlib/contrib/model/pytorch_lstm.py @@ -76,7 +76,7 @@ class LSTM(Model): self.early_stop = early_stop self.optimizer = optimizer.lower() self.loss = loss - self.visible_GPU = GPU + self.device = "cuda:%d" % (GPU) if torch.cuda.is_available() else "cpu" self.use_gpu = torch.cuda.is_available() self.seed = seed @@ -131,11 +131,7 @@ class LSTM(Model): raise NotImplementedError("optimizer {} is not supported!".format(optimizer)) self._fitted = False - if self.use_gpu: - self.lstm_model.cuda() - # set the visible GPU - if self.visible_GPU: - os.environ["CUDA_VISIBLE_DEVICES"] = str(self.visible_GPU) + self.lstm_model.to(self.device) def mse(self, pred, label): loss = (pred - label) ** 2 @@ -173,12 +169,8 @@ class LSTM(Model): if len(indices) - i < self.batch_size: break - feature = torch.from_numpy(x_train_values[indices[i : i + self.batch_size]]).float() - label = torch.from_numpy(y_train_values[indices[i : i + self.batch_size]]).float() - - if self.use_gpu: - feature = feature.cuda() - label = label.cuda() + feature = torch.from_numpy(x_train_values[indices[i : i + self.batch_size]]).float().to(self.device) + label = torch.from_numpy(y_train_values[indices[i : i + self.batch_size]]).float().to(self.device) pred = self.lstm_model(feature) loss = self.loss_fn(pred, label) @@ -206,12 +198,8 @@ class LSTM(Model): if len(indices) - i < self.batch_size: break - feature = torch.from_numpy(x_values[indices[i : i + self.batch_size]]).float() - label = torch.from_numpy(y_values[indices[i : i + self.batch_size]]).float() - - if self.use_gpu: - feature = feature.cuda() - label = label.cuda() + feature = torch.from_numpy(x_values[indices[i : i + self.batch_size]]).float().to(self.device) + label = torch.from_numpy(y_values[indices[i : i + self.batch_size]]).float().to(self.device) pred = self.lstm_model(feature) loss = self.loss_fn(pred, label) @@ -299,10 +287,7 @@ class LSTM(Model): else: end = begin + self.batch_size - x_batch = torch.from_numpy(x_values[begin:end]).float() - - if self.use_gpu: - x_batch = x_batch.cuda() + x_batch = torch.from_numpy(x_values[begin:end]).float().to(self.device) with torch.no_grad(): if self.use_gpu: diff --git a/qlib/contrib/model/pytorch_nn.py b/qlib/contrib/model/pytorch_nn.py index a9d8a38d0..ed4ba8692 100644 --- a/qlib/contrib/model/pytorch_nn.py +++ b/qlib/contrib/model/pytorch_nn.py @@ -79,7 +79,7 @@ class DNNModelPytorch(Model): self.lr_decay_steps = lr_decay_steps self.optimizer = optimizer.lower() self.loss_type = loss - self.visible_GPU = GPU + self.device = "cuda:%d" % (GPU) if torch.cuda.is_available() else "cpu" self.use_GPU = torch.cuda.is_available() self.seed = seed @@ -147,11 +147,7 @@ class DNNModelPytorch(Model): ) self._fitted = False - if self.use_GPU: - self.dnn_model.cuda() - # set the visible GPU - if self.visible_GPU: - os.environ["CUDA_VISIBLE_DEVICES"] = str(self.visible_GPU) + self.dnn_model.to(self.device) def fit( self, @@ -188,13 +184,9 @@ class DNNModelPytorch(Model): w_train_values = torch.from_numpy(w_train.values).float() train_num = y_train_values.shape[0] # prepare validation data - x_val_auto = torch.from_numpy(x_valid.values).float() - y_val_auto = torch.from_numpy(y_valid.values).float() - w_val_auto = torch.from_numpy(w_valid.values).float() - if self.use_GPU: - x_val_auto = x_val_auto.cuda() - y_val_auto = y_val_auto.cuda() - w_val_auto = w_val_auto.cuda() + x_val_auto = torch.from_numpy(x_valid.values).float().to(self.device) + y_val_auto = torch.from_numpy(y_valid.values).float().to(self.device) + w_val_auto = torch.from_numpy(w_valid.values).float().to(self.device) for step in range(self.max_steps): if stop_steps >= self.early_stop_rounds: @@ -205,14 +197,9 @@ class DNNModelPytorch(Model): self.dnn_model.train() self.train_optimizer.zero_grad() choice = np.random.choice(train_num, self.batch_size) - x_batch_auto = x_train_values[choice] - y_batch_auto = y_train_values[choice] - w_batch_auto = w_train_values[choice] - - if self.use_GPU: - x_batch_auto = x_batch_auto.cuda() - y_batch_auto = y_batch_auto.cuda() - w_batch_auto = w_batch_auto.cuda() + x_batch_auto = x_train_values[choice].to(self.device) + y_batch_auto = y_train_values[choice].to(self.device) + w_batch_auto = w_train_values[choice].to(self.device) # forward preds = self.dnn_model(x_batch_auto) @@ -277,9 +264,7 @@ class DNNModelPytorch(Model): if not self._fitted: raise ValueError("model is not fitted yet!") x_test_pd = dataset.prepare("test", col_set="feature") - x_test = torch.from_numpy(x_test_pd.values).float() - if self.use_GPU: - x_test = x_test.cuda() + x_test = torch.from_numpy(x_test_pd.values).float().to(self.device) self.dnn_model.eval() with torch.no_grad(): From 745b93138d300e1e4ff90b6b79f193b2c18fe5b4 Mon Sep 17 00:00:00 2001 From: Jactus Date: Wed, 2 Dec 2020 13:28:32 +0800 Subject: [PATCH 06/17] Update devices --- qlib/contrib/model/pytorch_alstm.py | 2 +- qlib/contrib/model/pytorch_gats.py | 2 +- qlib/contrib/model/pytorch_gru.py | 2 +- qlib/contrib/model/pytorch_lstm.py | 2 +- qlib/contrib/model/pytorch_nn.py | 2 +- qlib/contrib/model/pytorch_sfm.py | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/qlib/contrib/model/pytorch_alstm.py b/qlib/contrib/model/pytorch_alstm.py index cfe629fa8..d85fef628 100644 --- a/qlib/contrib/model/pytorch_alstm.py +++ b/qlib/contrib/model/pytorch_alstm.py @@ -76,7 +76,7 @@ class ALSTM(Model): self.early_stop = early_stop self.optimizer = optimizer.lower() self.loss = loss - self.device = "cuda:%d" % (GPU) if torch.cuda.is_available() else "cpu" + self.device = torch.device("cuda:%d" % (GPU) if torch.cuda.is_available() else "cpu") self.use_gpu = torch.cuda.is_available() self.seed = seed diff --git a/qlib/contrib/model/pytorch_gats.py b/qlib/contrib/model/pytorch_gats.py index 1759ae5ba..c22e48204 100644 --- a/qlib/contrib/model/pytorch_gats.py +++ b/qlib/contrib/model/pytorch_gats.py @@ -83,7 +83,7 @@ class GATs(Model): self.base_model = base_model self.with_pretrain = with_pretrain self.model_path = model_path - self.device = "cuda:%d" % (GPU) if torch.cuda.is_available() else "cpu" + self.device = torch.device("cuda:%d" % (GPU) if torch.cuda.is_available() else "cpu") self.use_gpu = torch.cuda.is_available() self.seed = seed diff --git a/qlib/contrib/model/pytorch_gru.py b/qlib/contrib/model/pytorch_gru.py index 8d5a9e461..22c63c539 100755 --- a/qlib/contrib/model/pytorch_gru.py +++ b/qlib/contrib/model/pytorch_gru.py @@ -76,7 +76,7 @@ class GRU(Model): self.early_stop = early_stop self.optimizer = optimizer.lower() self.loss = loss - self.device = "cuda:%d" % (GPU) if torch.cuda.is_available() else "cpu" + self.device = torch.device("cuda:%d" % (GPU) if torch.cuda.is_available() else "cpu") self.use_gpu = torch.cuda.is_available() self.seed = seed diff --git a/qlib/contrib/model/pytorch_lstm.py b/qlib/contrib/model/pytorch_lstm.py index 8032c54eb..1c24246f8 100755 --- a/qlib/contrib/model/pytorch_lstm.py +++ b/qlib/contrib/model/pytorch_lstm.py @@ -76,7 +76,7 @@ class LSTM(Model): self.early_stop = early_stop self.optimizer = optimizer.lower() self.loss = loss - self.device = "cuda:%d" % (GPU) if torch.cuda.is_available() else "cpu" + self.device = torch.device("cuda:%d" % (GPU) if torch.cuda.is_available() else "cpu") self.use_gpu = torch.cuda.is_available() self.seed = seed diff --git a/qlib/contrib/model/pytorch_nn.py b/qlib/contrib/model/pytorch_nn.py index ed4ba8692..2e2a3e885 100644 --- a/qlib/contrib/model/pytorch_nn.py +++ b/qlib/contrib/model/pytorch_nn.py @@ -79,7 +79,7 @@ class DNNModelPytorch(Model): self.lr_decay_steps = lr_decay_steps self.optimizer = optimizer.lower() self.loss_type = loss - self.device = "cuda:%d" % (GPU) if torch.cuda.is_available() else "cpu" + self.device = torch.device("cuda:%d" % (GPU) if torch.cuda.is_available() else "cpu") self.use_GPU = torch.cuda.is_available() self.seed = seed diff --git a/qlib/contrib/model/pytorch_sfm.py b/qlib/contrib/model/pytorch_sfm.py index da75b1bca..15d945c89 100644 --- a/qlib/contrib/model/pytorch_sfm.py +++ b/qlib/contrib/model/pytorch_sfm.py @@ -239,7 +239,7 @@ class SFM(Model): self.eval_steps = eval_steps self.optimizer = optimizer.lower() self.loss = loss - self.device = "cuda:%d" % (GPU) if torch.cuda.is_available() else "cpu" + self.device = torch.device("cuda:%d" % (GPU) if torch.cuda.is_available() else "cpu") self.use_gpu = torch.cuda.is_available() self.seed = seed From 91c3dfddf51bd169cf57ebd40b2162a1c9156b59 Mon Sep 17 00:00:00 2001 From: Jactus Date: Wed, 2 Dec 2020 17:55:11 +0800 Subject: [PATCH 07/17] Update run_all_model --- examples/run_all_model.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/run_all_model.py b/examples/run_all_model.py index 6df0ff4bb..78e01f623 100644 --- a/examples/run_all_model.py +++ b/examples/run_all_model.py @@ -15,6 +15,7 @@ import traceback import functools import statistics import subprocess +from datetime import datetime from pathlib import Path from operator import xor from pprint import pprint @@ -45,8 +46,6 @@ if not exists_qlib_data(provider_uri): GetData().qlib_data(target_dir=provider_uri, region=REG_CN) qlib.init(provider_uri=provider_uri, region=REG_CN, exp_manager=exp_manager) -if os.path.isdir(exp_path): - shutil.rmtree(exp_path) # decorator to check the arguments def only_allow_defined_args(function_to_decorate): @@ -291,7 +290,8 @@ def run(times=1, models=None, exclude=False): sys.stderr.write(f"Here are some of the errors of the models...\n") pprint(errors) sys.stderr.write("\n") - + # move results folder + shutil.move(exp_path, exp_path + f"_{datetime.now().strftime("%Y-%m-%d_%H:%M:%S")}") if __name__ == "__main__": fire.Fire(run) # run all the model From 703ae5d4aab1d52b074cc05c691a439253445525 Mon Sep 17 00:00:00 2001 From: Jactus Date: Wed, 2 Dec 2020 18:00:26 +0800 Subject: [PATCH 08/17] Update tft and readme --- README.md | 6 +++--- examples/benchmarks/TFT/data_formatters/qlib_Alpha158.py | 2 +- examples/run_all_model.py | 3 ++- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index b1a5f7092..1999160a1 100644 --- a/README.md +++ b/README.md @@ -27,10 +27,10 @@ For more details, please refer to our paper ["Qlib: An AI-oriented Quantitative - [Data Preparation](#data-preparation) - [Auto Quant Research Workflow](#auto-quant-research-workflow) - [Building Customized Quant Research Workflow by Code](#building-customized-quant-research-workflow-by-code) -- [**Quant Model Zoo**](#quant-model-zoo) +- [Quant Model Zoo](#quant-model-zoo) - [Run a single model](#run-a-single-model) - [Run multiple models](#run-multiple-models) -- [**Quant Dataset Zoo**](#quant-dataset-zoo) +- [Quant Dataset Zoo](#quant-dataset-zoo) - [More About Qlib](#more-about-qlib) - [Offline Mode and Online Mode](#offline-mode-and-online-mode) - [Performance of Qlib Data Server](#performance-of-qlib-data-server) @@ -218,7 +218,7 @@ All the models listed above are runnable with ``Qlib``. Users can find the confi ## Run multiple models `Qlib` also provides a script [`run_all_model.py`](examples/run_all_model.py) which can run multiple models for several iterations. (**Note**: the script only supprots *Linux* now. Other OS will be supported in the future.) -The script will create a unique virtual environment for each model, and delete the environments after training. Thus, only experiment results such as `IC` and `backtest` results will be generated and stored. (**Note**: the script will erase your previous experiment records created by running itself.) +The script will create a unique virtual environment for each model, and delete the environments after training. Thus, only experiment results such as `IC` and `backtest` results will be generated and stored. Here is an example of running all the models for 10 iterations: ```python diff --git a/examples/benchmarks/TFT/data_formatters/qlib_Alpha158.py b/examples/benchmarks/TFT/data_formatters/qlib_Alpha158.py index 44a9284f7..03c169b9b 100644 --- a/examples/benchmarks/TFT/data_formatters/qlib_Alpha158.py +++ b/examples/benchmarks/TFT/data_formatters/qlib_Alpha158.py @@ -208,7 +208,7 @@ class Alpha158Formatter(GenericDataFormatter): model_params = { "dropout_rate": 0.4, - "hidden_layer_size": 16, + "hidden_layer_size": 160, "learning_rate": 0.0001, "minibatch_size": 128, "max_gradient_norm": 0.0135, diff --git a/examples/run_all_model.py b/examples/run_all_model.py index 78e01f623..416f1b47f 100644 --- a/examples/run_all_model.py +++ b/examples/run_all_model.py @@ -291,7 +291,8 @@ def run(times=1, models=None, exclude=False): pprint(errors) sys.stderr.write("\n") # move results folder - shutil.move(exp_path, exp_path + f"_{datetime.now().strftime("%Y-%m-%d_%H:%M:%S")}") + shutil.move(exp_path, exp_path + f"_{datetime.now().strftime('%Y-%m-%d_%H:%M:%S')}") + if __name__ == "__main__": fire.Fire(run) # run all the model From ab762b3cd79ba9c08cc97b7279f32f88e6557dcb Mon Sep 17 00:00:00 2001 From: Jactus Date: Wed, 2 Dec 2020 20:04:00 +0800 Subject: [PATCH 09/17] Update lightgbm lr --- examples/benchmarks/LightGBM/workflow_config_lightgbm.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/benchmarks/LightGBM/workflow_config_lightgbm.yaml b/examples/benchmarks/LightGBM/workflow_config_lightgbm.yaml index 76a6347db..88202be1b 100644 --- a/examples/benchmarks/LightGBM/workflow_config_lightgbm.yaml +++ b/examples/benchmarks/LightGBM/workflow_config_lightgbm.yaml @@ -32,7 +32,7 @@ task: kwargs: loss: mse colsample_bytree: 0.8879 - learning_rate: 0.0421 + learning_rate: 0.2 subsample: 0.8789 lambda_l1: 205.6999 lambda_l2: 580.9768 From f237a344c34e7e7a27735c4754c9a0589947dbd9 Mon Sep 17 00:00:00 2001 From: Jactus Date: Fri, 4 Dec 2020 10:31:50 +0800 Subject: [PATCH 10/17] Update --- examples/run_all_model.py | 26 ++++++++++++++++---------- qlib/__init__.py | 2 +- requirements.txt | 25 ------------------------- setup.py | 2 +- 4 files changed, 18 insertions(+), 37 deletions(-) delete mode 100644 requirements.txt diff --git a/examples/run_all_model.py b/examples/run_all_model.py index 416f1b47f..9cc1bd2d6 100644 --- a/examples/run_all_model.py +++ b/examples/run_all_model.py @@ -135,9 +135,9 @@ def get_all_folders(models, exclude) -> dict: # function to get all the files under the model folder -def get_all_files(folder_path) -> (str, str): - yaml_path = str(Path(f"{folder_path}") / "*.yaml") - req_path = str(Path(f"{folder_path}") / "*.txt") +def get_all_files(folder_path, dataset) -> (str, str): + yaml_path = str(Path(f"{folder_path}") / f"*{dataset}*.yaml") + req_path = str(Path(f"{folder_path}") / f"*{dataset}*.txt") return glob.glob(yaml_path)[0], glob.glob(req_path)[0] @@ -191,7 +191,7 @@ def gen_and_save_md_table(metrics): # function to run the all the models @only_allow_defined_args -def run(times=1, models=None, exclude=False): +def run(times=1, models=None, dataset='Alpha360', exclude=False): """ Please be aware that this function can only work under Linux. MacOS and Windows will be supported in the future. Any PR to enhance this method is highly welcomed. @@ -204,6 +204,8 @@ def run(times=1, models=None, exclude=False): determines the specific model or list of models to run or exclude. exclude : boolean determines whether the model being used is excluded or included. + dataset : str + determines the dataset to be used for each model. Usage: ------- @@ -217,13 +219,16 @@ def run(times=1, models=None, exclude=False): # Case 2 - run specific models multiple times python run_all_model.py 3 mlp - # Case 3 - run other models except those are given as arguments for multiple times - python run_all_model.py 3 [mlp,tft,lstm] True + # Case 3 - run specific models multiple times with specific dataset + python run_all_model.py 3 mlp Alpha158 - # Case 4 - run specific models for one time + # Case 4 - run other models except those are given as arguments for multiple times + python run_all_model.py 3 [mlp,tft,lstm] --exclude=True + + # Case 5 - run specific models for one time python run_all_model.py --models=[mlp,lightgbm] - # Case 5 - run other models except those are given as aruments for one time + # Case 6 - run other models except those are given as aruments for one time python run_all_model.py --models=[mlp,tft,sfm] --exclude=True """ @@ -237,7 +242,7 @@ def run(times=1, models=None, exclude=False): env_path, python_path, conda_activate = create_env() # get all files sys.stderr.write("Retrieving files...\n") - yaml_path, req_path = get_all_files(folders[fn]) + yaml_path, req_path = get_all_files(folders[fn], dataset) sys.stderr.write("\n") # install requirements.txt sys.stderr.write("Installing requirements.txt...\n") @@ -291,7 +296,8 @@ def run(times=1, models=None, exclude=False): pprint(errors) sys.stderr.write("\n") # move results folder - shutil.move(exp_path, exp_path + f"_{datetime.now().strftime('%Y-%m-%d_%H:%M:%S')}") + shutil.move(exp_path, exp_path + f"_{dataset}_{datetime.now().strftime('%Y-%m-%d_%H:%M:%S')}") + shutil.move("table.md", f"table_{dataset}_{datetime.now().strftime('%Y-%m-%d_%H:%M:%S')}.md") if __name__ == "__main__": diff --git a/qlib/__init__.py b/qlib/__init__.py index e84e48ce8..f79b8c4f5 100644 --- a/qlib/__init__.py +++ b/qlib/__init__.py @@ -2,7 +2,7 @@ # Licensed under the MIT License. -__version__ = "0.6.0" +__version__ = "0.6.0.dev" import os diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 638ce22f4..000000000 --- a/requirements.txt +++ /dev/null @@ -1,25 +0,0 @@ -requests==2.22.0 -six==1.14.0 -lxml==4.5.0 -statsmodels==0.12.0 -pandas==1.1.2 -matplotlib==3.3.2 -scipy==1.3.3 -numpy==1.17.4 -Cython==0.29.21 -fire==0.3.1 -gevent_socketio==0.3.6 -hyperopt==0.2.4 -lightgbm==3.0.0 -loguru==0.5.3 -plotly==4.10.0 -pymongo==3.11.0 -PyYAML==5.3.1 -redis==3.5.3 -redis_lock==0.2.0 -sacred==0.8.1 -scikit_learn==0.23.2 -torch==1.6.0 -tqdm==4.49.0 -yahooquery==2.2.7 -mlflow==1.12.1 \ No newline at end of file diff --git a/setup.py b/setup.py index 0cb23f771..cc495824e 100644 --- a/setup.py +++ b/setup.py @@ -11,7 +11,7 @@ NAME = "pyqlib" DESCRIPTION = "A Quantitative-research Platform" REQUIRES_PYTHON = ">=3.5.0" -VERSION = "0.6.0" +VERSION = "0.6.0.dev" # Detect Cython try: From 07fb9031c6c7a07235322fbe2ff70a0083038609 Mon Sep 17 00:00:00 2001 From: Jactus Date: Fri, 4 Dec 2020 10:47:20 +0800 Subject: [PATCH 11/17] Update setup --- examples/run_all_model.py | 2 +- setup.py | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/examples/run_all_model.py b/examples/run_all_model.py index 9cc1bd2d6..5223634b2 100644 --- a/examples/run_all_model.py +++ b/examples/run_all_model.py @@ -191,7 +191,7 @@ def gen_and_save_md_table(metrics): # function to run the all the models @only_allow_defined_args -def run(times=1, models=None, dataset='Alpha360', exclude=False): +def run(times=1, models=None, dataset="Alpha360", exclude=False): """ Please be aware that this function can only work under Linux. MacOS and Windows will be supported in the future. Any PR to enhance this method is highly welcomed. diff --git a/setup.py b/setup.py index cc495824e..66d836444 100644 --- a/setup.py +++ b/setup.py @@ -94,7 +94,12 @@ setup( long_description=long_description, long_description_content_type="text/markdown", python_requires=REQUIRES_PYTHON, - packages=find_packages(exclude=("tests",)), + packages=find_packages( + exclude=( + "tests", + "examples", + ) + ), # if your package is a single module, use this instead of 'packages': # py_modules=['qlib'], entry_points={ From 99adc514a545b9fde8ea145334af6f32dc4e2427 Mon Sep 17 00:00:00 2001 From: Jactus Date: Fri, 4 Dec 2020 11:51:45 +0800 Subject: [PATCH 12/17] Update CI --- .github/workflows/test.yml | 1 + examples/run_all_model.py | 10 +++++----- setup.py | 7 +------ 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 033d31536..9cc4d8cd4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -27,6 +27,7 @@ jobs: run: | pip install --upgrade cython pip install numpy jupyter jupyter_contrib_nbextensions + pip install -U scipy scikit-learn # installing without this line will cause errors on GitHub Actions, while instsalling locally won't python setup.py install - name: Install Lightgbm for MacOS diff --git a/examples/run_all_model.py b/examples/run_all_model.py index 5223634b2..34651227c 100644 --- a/examples/run_all_model.py +++ b/examples/run_all_model.py @@ -171,9 +171,9 @@ def get_all_results(folders) -> dict: # function to generate and save markdown table -def gen_and_save_md_table(metrics): - table = "| Model Name | Annualized Return | Information Ratio | Max Drawdown | IC | ICIR | Rank IC | Rank ICIR |\n" - table += "|---|---|---|---|---|---|---|---|\n" +def gen_and_save_md_table(metrics, dataset): + table = "| Model Name | Dataset | Annualized Return | Information Ratio | Max Drawdown | IC | ICIR | Rank IC | Rank ICIR |\n" + table += "|---|---|---|---|---|---|---|---|---|\n" for fn in metrics: ar = metrics[fn]["annualized_return_with_cost"] ir = metrics[fn]["information_ratio_with_cost"] @@ -182,7 +182,7 @@ def gen_and_save_md_table(metrics): icir = metrics[fn]["icir"] ric = metrics[fn]["rank_ic"] ricir = metrics[fn]["rank_icir"] - table += f"| {fn} | {ar[0]:5.4f}±{ar[1]:2.2f} | {ir[0]:5.4f}±{ir[1]:2.2f}| {md[0]:5.4f}±{md[1]:2.2f} | {ic[0]:5.4f}±{ic[1]:2.2f} | {icir[0]:5.4f}±{icir[1]:2.2f}| {ric[0]:5.4f}±{ric[1]:2.2f} | {ricir[0]:5.4f}±{ricir[1]:2.2f} |\n" + table += f"| {fn} | {dataset} | {ar[0]:5.4f}±{ar[1]:2.2f} | {ir[0]:5.4f}±{ir[1]:2.2f}| {md[0]:5.4f}±{md[1]:2.2f} | {ic[0]:5.4f}±{ic[1]:2.2f} | {icir[0]:5.4f}±{icir[1]:2.2f}| {ric[0]:5.4f}±{ric[1]:2.2f} | {ricir[0]:5.4f}±{ricir[1]:2.2f} |\n" pprint(table) with open("table.md", "w") as f: f.write(table) @@ -289,7 +289,7 @@ def run(times=1, models=None, dataset="Alpha360", exclude=False): results = cal_mean_std(results) # generating md table sys.stderr.write(f"Generating markdown table...\n") - gen_and_save_md_table(results) + gen_and_save_md_table(results, dataset) sys.stderr.write("\n") # print erros sys.stderr.write(f"Here are some of the errors of the models...\n") diff --git a/setup.py b/setup.py index 66d836444..cc495824e 100644 --- a/setup.py +++ b/setup.py @@ -94,12 +94,7 @@ setup( long_description=long_description, long_description_content_type="text/markdown", python_requires=REQUIRES_PYTHON, - packages=find_packages( - exclude=( - "tests", - "examples", - ) - ), + packages=find_packages(exclude=("tests",)), # if your package is a single module, use this instead of 'packages': # py_modules=['qlib'], entry_points={ From 86b0b63771ccfefae9658b84ef63cd7ee45932df Mon Sep 17 00:00:00 2001 From: Jactus Date: Fri, 4 Dec 2020 12:55:22 +0800 Subject: [PATCH 13/17] Update table generator --- examples/run_all_model.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/run_all_model.py b/examples/run_all_model.py index 34651227c..c8fdebd84 100644 --- a/examples/run_all_model.py +++ b/examples/run_all_model.py @@ -137,7 +137,7 @@ def get_all_folders(models, exclude) -> dict: # function to get all the files under the model folder def get_all_files(folder_path, dataset) -> (str, str): yaml_path = str(Path(f"{folder_path}") / f"*{dataset}*.yaml") - req_path = str(Path(f"{folder_path}") / f"*{dataset}*.txt") + req_path = str(Path(f"{folder_path}") / f"*.txt") return glob.glob(yaml_path)[0], glob.glob(req_path)[0] @@ -172,17 +172,17 @@ def get_all_results(folders) -> dict: # function to generate and save markdown table def gen_and_save_md_table(metrics, dataset): - table = "| Model Name | Dataset | Annualized Return | Information Ratio | Max Drawdown | IC | ICIR | Rank IC | Rank ICIR |\n" + table = "| Model Name | Dataset | IC | ICIR | Rank IC | Rank ICIR | Annualized Return | Information Ratio | Max Drawdown |\n" table += "|---|---|---|---|---|---|---|---|---|\n" for fn in metrics: - ar = metrics[fn]["annualized_return_with_cost"] - ir = metrics[fn]["information_ratio_with_cost"] - md = metrics[fn]["max_drawdown_with_cost"] ic = metrics[fn]["ic"] icir = metrics[fn]["icir"] ric = metrics[fn]["rank_ic"] ricir = metrics[fn]["rank_icir"] - table += f"| {fn} | {dataset} | {ar[0]:5.4f}±{ar[1]:2.2f} | {ir[0]:5.4f}±{ir[1]:2.2f}| {md[0]:5.4f}±{md[1]:2.2f} | {ic[0]:5.4f}±{ic[1]:2.2f} | {icir[0]:5.4f}±{icir[1]:2.2f}| {ric[0]:5.4f}±{ric[1]:2.2f} | {ricir[0]:5.4f}±{ricir[1]:2.2f} |\n" + ar = metrics[fn]["annualized_return_with_cost"] + ir = metrics[fn]["information_ratio_with_cost"] + md = metrics[fn]["max_drawdown_with_cost"] + table += f"| {fn} | {dataset} | {ic[0]:5.4f}±{ic[1]:2.2f} | {icir[0]:5.4f}±{icir[1]:2.2f}| {ric[0]:5.4f}±{ric[1]:2.2f} | {ricir[0]:5.4f}±{ricir[1]:2.2f} | {ar[0]:5.4f}±{ar[1]:2.2f} | {ir[0]:5.4f}±{ir[1]:2.2f}| {md[0]:5.4f}±{md[1]:2.2f} |\n" pprint(table) with open("table.md", "w") as f: f.write(table) From 2fb7774927ba91032f8ea28f422a4aa0ff2b3899 Mon Sep 17 00:00:00 2001 From: Jactus Date: Fri, 4 Dec 2020 13:02:09 +0800 Subject: [PATCH 14/17] Update config names --- CHANGES.rst | 2 +- ..._config_alstm.yaml => workflow_config_alstm_Alpha360.yaml} | 2 +- ...g_catboost.yaml => workflow_config_catboost_Alpha158.yaml} | 0 ...ow_config_gats.yaml => workflow_config_gats_Alpha360.yaml} | 2 +- ...flow_config_gru.yaml => workflow_config_gru_Alpha360.yaml} | 2 +- ...ow_config_lstm.yaml => workflow_config_lstm_Alpha360.yaml} | 2 +- ...g_lightgbm.yaml => workflow_config_lightgbm_Alpha158.yaml} | 0 ...onfig_linear.yaml => workflow_config_linear_Alpha158.yaml} | 0 ...flow_config_mlp.yaml => workflow_config_mlp_Alpha158.yaml} | 0 ...flow_config_sfm.yaml => workflow_config_sfm_Alpha360.yaml} | 2 +- ...flow_config_tft.yaml => workflow_config_tft_Alpha158.yaml} | 0 ...fig_xgboost.yaml => workflow_config_xgboost_Alpha158.yaml} | 0 qlib/contrib/data/handler.py | 4 ++-- 13 files changed, 8 insertions(+), 8 deletions(-) rename examples/benchmarks/ALSTM/{workflow_config_alstm.yaml => workflow_config_alstm_Alpha360.yaml} (98%) rename examples/benchmarks/CatBoost/{workflow_config_catboost.yaml => workflow_config_catboost_Alpha158.yaml} (100%) rename examples/benchmarks/GATs/{workflow_config_gats.yaml => workflow_config_gats_Alpha360.yaml} (98%) rename examples/benchmarks/GRU/{workflow_config_gru.yaml => workflow_config_gru_Alpha360.yaml} (98%) rename examples/benchmarks/LSTM/{workflow_config_lstm.yaml => workflow_config_lstm_Alpha360.yaml} (98%) rename examples/benchmarks/LightGBM/{workflow_config_lightgbm.yaml => workflow_config_lightgbm_Alpha158.yaml} (100%) rename examples/benchmarks/Linear/{workflow_config_linear.yaml => workflow_config_linear_Alpha158.yaml} (100%) rename examples/benchmarks/MLP/{workflow_config_mlp.yaml => workflow_config_mlp_Alpha158.yaml} (100%) rename examples/benchmarks/SFM/{workflow_config_sfm.yaml => workflow_config_sfm_Alpha360.yaml} (98%) rename examples/benchmarks/TFT/{workflow_config_tft.yaml => workflow_config_tft_Alpha158.yaml} (100%) rename examples/benchmarks/XGBoost/{workflow_config_xgboost.yaml => workflow_config_xgboost_Alpha158.yaml} (100%) diff --git a/CHANGES.rst b/CHANGES.rst index 1b0982242..114d577f3 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -114,7 +114,7 @@ Version 0.4.1 Version 0.4.2 -------------------- - Refactor DataHandler -- Add ``ALPHA360`` DataHandler +- Add ``Alpha360`` DataHandler Version 0.4.3 diff --git a/examples/benchmarks/ALSTM/workflow_config_alstm.yaml b/examples/benchmarks/ALSTM/workflow_config_alstm_Alpha360.yaml similarity index 98% rename from examples/benchmarks/ALSTM/workflow_config_alstm.yaml rename to examples/benchmarks/ALSTM/workflow_config_alstm_Alpha360.yaml index 37dceaacb..6226cdaf2 100644 --- a/examples/benchmarks/ALSTM/workflow_config_alstm.yaml +++ b/examples/benchmarks/ALSTM/workflow_config_alstm_Alpha360.yaml @@ -61,7 +61,7 @@ task: module_path: qlib.data.dataset kwargs: handler: - class: ALPHA360 + class: Alpha360 module_path: qlib.contrib.data.handler kwargs: *data_handler_config segments: diff --git a/examples/benchmarks/CatBoost/workflow_config_catboost.yaml b/examples/benchmarks/CatBoost/workflow_config_catboost_Alpha158.yaml similarity index 100% rename from examples/benchmarks/CatBoost/workflow_config_catboost.yaml rename to examples/benchmarks/CatBoost/workflow_config_catboost_Alpha158.yaml diff --git a/examples/benchmarks/GATs/workflow_config_gats.yaml b/examples/benchmarks/GATs/workflow_config_gats_Alpha360.yaml similarity index 98% rename from examples/benchmarks/GATs/workflow_config_gats.yaml rename to examples/benchmarks/GATs/workflow_config_gats_Alpha360.yaml index 0ab0cae8d..d778c9b1b 100644 --- a/examples/benchmarks/GATs/workflow_config_gats.yaml +++ b/examples/benchmarks/GATs/workflow_config_gats_Alpha360.yaml @@ -62,7 +62,7 @@ task: module_path: qlib.data.dataset kwargs: handler: - class: ALPHA360 + class: Alpha360 module_path: qlib.contrib.data.handler kwargs: *data_handler_config segments: diff --git a/examples/benchmarks/GRU/workflow_config_gru.yaml b/examples/benchmarks/GRU/workflow_config_gru_Alpha360.yaml similarity index 98% rename from examples/benchmarks/GRU/workflow_config_gru.yaml rename to examples/benchmarks/GRU/workflow_config_gru_Alpha360.yaml index 64ae3437c..2494d40f0 100644 --- a/examples/benchmarks/GRU/workflow_config_gru.yaml +++ b/examples/benchmarks/GRU/workflow_config_gru_Alpha360.yaml @@ -60,7 +60,7 @@ task: module_path: qlib.data.dataset kwargs: handler: - class: ALPHA360 + class: Alpha360 module_path: qlib.contrib.data.handler kwargs: *data_handler_config segments: diff --git a/examples/benchmarks/LSTM/workflow_config_lstm.yaml b/examples/benchmarks/LSTM/workflow_config_lstm_Alpha360.yaml similarity index 98% rename from examples/benchmarks/LSTM/workflow_config_lstm.yaml rename to examples/benchmarks/LSTM/workflow_config_lstm_Alpha360.yaml index b857d97d4..2aa5fd061 100644 --- a/examples/benchmarks/LSTM/workflow_config_lstm.yaml +++ b/examples/benchmarks/LSTM/workflow_config_lstm_Alpha360.yaml @@ -60,7 +60,7 @@ task: module_path: qlib.data.dataset kwargs: handler: - class: ALPHA360 + class: Alpha360 module_path: qlib.contrib.data.handler kwargs: *data_handler_config segments: diff --git a/examples/benchmarks/LightGBM/workflow_config_lightgbm.yaml b/examples/benchmarks/LightGBM/workflow_config_lightgbm_Alpha158.yaml similarity index 100% rename from examples/benchmarks/LightGBM/workflow_config_lightgbm.yaml rename to examples/benchmarks/LightGBM/workflow_config_lightgbm_Alpha158.yaml diff --git a/examples/benchmarks/Linear/workflow_config_linear.yaml b/examples/benchmarks/Linear/workflow_config_linear_Alpha158.yaml similarity index 100% rename from examples/benchmarks/Linear/workflow_config_linear.yaml rename to examples/benchmarks/Linear/workflow_config_linear_Alpha158.yaml diff --git a/examples/benchmarks/MLP/workflow_config_mlp.yaml b/examples/benchmarks/MLP/workflow_config_mlp_Alpha158.yaml similarity index 100% rename from examples/benchmarks/MLP/workflow_config_mlp.yaml rename to examples/benchmarks/MLP/workflow_config_mlp_Alpha158.yaml diff --git a/examples/benchmarks/SFM/workflow_config_sfm.yaml b/examples/benchmarks/SFM/workflow_config_sfm_Alpha360.yaml similarity index 98% rename from examples/benchmarks/SFM/workflow_config_sfm.yaml rename to examples/benchmarks/SFM/workflow_config_sfm_Alpha360.yaml index 5a0448cfe..a23fe3854 100644 --- a/examples/benchmarks/SFM/workflow_config_sfm.yaml +++ b/examples/benchmarks/SFM/workflow_config_sfm_Alpha360.yaml @@ -63,7 +63,7 @@ task: module_path: qlib.data.dataset kwargs: handler: - class: ALPHA360 + class: Alpha360 module_path: qlib.contrib.data.handler kwargs: *data_handler_config segments: diff --git a/examples/benchmarks/TFT/workflow_config_tft.yaml b/examples/benchmarks/TFT/workflow_config_tft_Alpha158.yaml similarity index 100% rename from examples/benchmarks/TFT/workflow_config_tft.yaml rename to examples/benchmarks/TFT/workflow_config_tft_Alpha158.yaml diff --git a/examples/benchmarks/XGBoost/workflow_config_xgboost.yaml b/examples/benchmarks/XGBoost/workflow_config_xgboost_Alpha158.yaml similarity index 100% rename from examples/benchmarks/XGBoost/workflow_config_xgboost.yaml rename to examples/benchmarks/XGBoost/workflow_config_xgboost_Alpha158.yaml diff --git a/qlib/contrib/data/handler.py b/qlib/contrib/data/handler.py index 6b3de336d..88a1f0680 100644 --- a/qlib/contrib/data/handler.py +++ b/qlib/contrib/data/handler.py @@ -43,7 +43,7 @@ _DEFAULT_INFER_PROCESSORS = [ ] -class ALPHA360(DataHandlerLP): +class Alpha360(DataHandlerLP): def __init__( self, instruments="csi500", @@ -119,7 +119,7 @@ class ALPHA360(DataHandlerLP): return fields, names -class ALPHA360vwap(ALPHA360): +class Alpha360vwap(Alpha360): def get_label_config(self): return (["Ref($vwap, -2)/Ref($vwap, -1) - 1"], ["LABEL0"]) From 895b1e794428e54618a1316fead63dbfd2324521 Mon Sep 17 00:00:00 2001 From: Jactus Date: Fri, 4 Dec 2020 13:10:45 +0800 Subject: [PATCH 15/17] Update CI --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9cc4d8cd4..261599401 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -57,4 +57,4 @@ jobs: - name: Test workflow by config run: | - qrun examples/benchmarks/LightGBM/workflow_config_lightgbm.yaml + qrun examples/benchmarks/LightGBM/workflow_config_lightgbm_Alpha158.yaml From eef90c7901a792392471fdc0faae090033f1fbcb Mon Sep 17 00:00:00 2001 From: Jactus Date: Fri, 4 Dec 2020 14:25:26 +0800 Subject: [PATCH 16/17] Update readme --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1999160a1..b58456291 100644 --- a/README.md +++ b/README.md @@ -27,10 +27,10 @@ For more details, please refer to our paper ["Qlib: An AI-oriented Quantitative - [Data Preparation](#data-preparation) - [Auto Quant Research Workflow](#auto-quant-research-workflow) - [Building Customized Quant Research Workflow by Code](#building-customized-quant-research-workflow-by-code) -- [Quant Model Zoo](#quant-model-zoo) +- [**Quant Model Zoo**](#quant-model-zoo) - [Run a single model](#run-a-single-model) - [Run multiple models](#run-multiple-models) -- [Quant Dataset Zoo](#quant-dataset-zoo) +- [**Quant Dataset Zoo**](#quant-dataset-zoo) - [More About Qlib](#more-about-qlib) - [Offline Mode and Online Mode](#offline-mode-and-online-mode) - [Performance of Qlib Data Server](#performance-of-qlib-data-server) @@ -153,6 +153,7 @@ Qlib provides a tool named `qrun` to run the whole workflow automatically (inclu annualized_return 0.128982 information_ratio 1.444287 max_drawdown -0.091078 + ``` @@ -234,7 +235,7 @@ Dataset plays a very important role in Quant. Here is a list of the datasets bui | Dataset | US Market | China Market | | -- | -- | -- | | [Alpha360](./qlib/contrib/data/handler.py) | √ | √ | -| [Alpha158](./qlib/contrib/data/handler.py) | √ | √ | +| [Alpha158](./qlib/contrib/data/handler.py) | √ | √ | [Here](https://qlib.readthedocs.io/en/latest/advanced/alpha.html) is a tutorial to build dataset with `Qlib`. Your PR to build new Quant dataset is highly welcomed. From 46396c229a128e616ba1add4a1eacff24e7c217a Mon Sep 17 00:00:00 2001 From: Dingsu Wang Date: Fri, 4 Dec 2020 14:28:13 +0800 Subject: [PATCH 17/17] Update README.md --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index b58456291..de7dd1cf0 100644 --- a/README.md +++ b/README.md @@ -153,10 +153,6 @@ Qlib provides a tool named `qrun` to run the whole workflow automatically (inclu annualized_return 0.128982 information_ratio 1.444287 max_drawdown -0.091078 - ``` - - - ``` Here are detailed documents for `qrun` and [workflow](https://qlib.readthedocs.io/en/latest/component/workflow.html).