diff --git a/.github/stale.yml b/.github/stale.yml new file mode 100644 index 000000000..3d025c987 --- /dev/null +++ b/.github/stale.yml @@ -0,0 +1,62 @@ +# Configuration for probot-stale - https://github.com/probot/stale + +# Number of days of inactivity before an Issue or Pull Request becomes stale +daysUntilStale: 60 + +# Number of days of inactivity before an Issue or Pull Request with the stale label is closed. +# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale. +daysUntilClose: 7 + +# Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled) +onlyLabels: [] + +# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable +exemptLabels: + - bug + - pinned + - security + - "[Status] Maybe Later" + +# Set to true to ignore issues in a project (defaults to false) +exemptProjects: false + +# Set to true to ignore issues in a milestone (defaults to false) +exemptMilestones: false + +# Set to true to ignore issues with an assignee (defaults to false) +exemptAssignees: false + +# Label to use when marking as stale +staleLabel: wontfix + +# Comment to post when marking as stale. Set to `false` to disable +markComment: > + This issue has been automatically marked as stale because it has not had + recent activity. It will be closed if no further activity occurs. Thank you + for your contributions. + +# Comment to post when removing the stale label. +# unmarkComment: > +# Your comment here. + +# Comment to post when closing a stale Issue or Pull Request. +# closeComment: > +# Your comment here. + +# Limit the number of actions per hour, from 1-30. Default is 30 +limitPerRun: 30 + +# Limit to only `issues` or `pulls` +# only: issues + +# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls': +# pulls: +# daysUntilStale: 30 +# markComment: > +# This pull request has been automatically marked as stale because it has not had +# recent activity. It will be closed if no further activity occurs. Thank you +# for your contributions. + +# issues: +# exemptLabels: +# - confirmed \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 64ff99dfe..637b0c291 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -22,9 +22,58 @@ jobs: uses: actions/setup-python@v2 with: python-version: ${{ matrix.python-version }} + + - name: Lint with Black + run: | + cd .. + if [ "$RUNNER_OS" == "Windows" ]; then + $CONDA\\python.exe -m pip install black + $CONDA\\python.exe -m black qlib -l 120 --check --diff + else + sudo $CONDA/bin/python -m pip install black + $CONDA/bin/python -m black qlib -l 120 --check --diff + fi + shell: bash + + # Test Qlib installed with pip + - name: Install Qlib with pip + run: | + if [ "$RUNNER_OS" == "Windows" ]; then + $CONDA\\python.exe -m pip install pyqlib --ignore-installed ruamel.yaml --user + else + sudo $CONDA/bin/python -m pip install pyqlib --ignore-installed ruamel.yaml + fi + shell: bash - - name: Install dependencies - run: | + - name: Install Lightgbm for MacOS + if: runner.os == 'macOS' + run: | + /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Microsoft/qlib/main/.github/brew_install.sh)" + HOMEBREW_NO_AUTO_UPDATE=1 brew install lightgbm + + - name: Test data downloads + run: | + if [ "$RUNNER_OS" == "Windows" ]; then + $CONDA\\python.exe scripts/get_data.py qlib_data --target_dir ~/.qlib/qlib_data/cn_data --interval 1d --region cn + else + $CONDA/bin/python scripts/get_data.py qlib_data --target_dir ~/.qlib/qlib_data/cn_data --interval 1d --region cn + fi + shell: bash + + - name: Test workflow by config (install from pip) + run: | + if [ "$RUNNER_OS" == "Windows" ]; then + $CONDA\\python.exe qlib\\workflow\\cli.py examples\\benchmarks\\LightGBM\\workflow_config_lightgbm_Alpha158.yaml + $CONDA\\python.exe -m pip uninstall -y pyqlib + else + $CONDA/bin/python qlib/workflow/cli.py examples/benchmarks/LightGBM/workflow_config_lightgbm_Alpha158.yaml + sudo $CONDA/bin/python -m pip uninstall -y pyqlib + fi + shell: bash + + # Test Qlib installed from source + - name: Install Qlib from source + run: | if [ "$RUNNER_OS" == "Windows" ]; then $CONDA\\python.exe -m pip install --upgrade cython $CONDA\\python.exe -m pip install numpy jupyter jupyter_contrib_nbextensions @@ -36,13 +85,7 @@ jobs: sudo $CONDA/bin/python -m pip install -U scipy scikit-learn # installing without this line will cause errors on GitHub Actions, while instsalling locally won't sudo $CONDA/bin/python setup.py install fi - shell: bash - - - name: Install Lightgbm for MacOS - if: runner.os == 'macOS' - run: | - /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Microsoft/qlib/main/.github/brew_install.sh)" - HOMEBREW_NO_AUTO_UPDATE=1 brew install lightgbm + shell: bash - name: Install test dependencies run: | @@ -54,16 +97,6 @@ jobs: sudo $CONDA/bin/python -m pip install black pytest fi shell: bash - - - name: Lint with Black - run: | - cd .. - if [ "$RUNNER_OS" == "Windows" ]; then - $CONDA\\python.exe -m black qlib -l 120 --check --diff - else - $CONDA/bin/python -m black qlib -l 120 --check --diff - fi - shell: bash - name: Unit tests with Pytest run: | @@ -73,22 +106,13 @@ jobs: else $CONDA/bin/python -m pytest . --durations=0 fi - shell: bash + shell: bash - - name: Test data downloads - run: | - if [ "$RUNNER_OS" == "Windows" ]; then - $CONDA\\python.exe scripts/get_data.py qlib_data --target_dir ~/.qlib/qlib_data/cn_data --interval 1d --region cn - else - $CONDA/bin/python scripts/get_data.py qlib_data --target_dir ~/.qlib/qlib_data/cn_data --interval 1d --region cn - fi - shell: bash - - - name: Test workflow by config + - name: Test workflow by config (install from source) run: | if [ "$RUNNER_OS" == "Windows" ]; then $CONDA\\python.exe qlib\\workflow\\cli.py examples\\benchmarks\\LightGBM\\workflow_config_lightgbm_Alpha158.yaml else $CONDA/bin/python qlib/workflow/cli.py examples/benchmarks/LightGBM/workflow_config_lightgbm_Alpha158.yaml fi - shell: bash + shell: bash \ No newline at end of file diff --git a/README.md b/README.md index ca91925dc..2ae36827e 100644 --- a/README.md +++ b/README.md @@ -61,17 +61,22 @@ At the module level, Qlib is a platform that consists of the above components. T This quick start guide tries to demonstrate 1. It's very easy to build a complete Quant research workflow and try your ideas with _Qlib_. -1. Though with *public data* and *simple models*, machine learning technologies **work very well** in practical Quant investment. +2. Though with *public data* and *simple models*, machine learning technologies **work very well** in practical Quant investment. + +Here is a quick **[demo](https://terminalizer.com/view/3f24561a4470)** shows how to install ``Qlib``, and run LightGBM with ``qrun``. **But**, please make sure you have already prepared the data following the [instruction](#data-preparation). + ## Installation -Users can easily install ``Qlib`` by pip according to the following command +Users can easily install ``Qlib`` by pip according to the following command(Currently, Qlib only support Python 3.6, 3.7 and 3.8). ```bash pip install pyqlib ``` -Also, users can install ``Qlib`` by the source code according to the following steps: +**Note**: pip will install the latest stable qlib. However, the main branch of qlib is in active development. If you want to test the latest scripts or functions in the main branch. Please install qlib with the methods below. + +Also, users can install the latest dev version ``Qlib`` by the source code according to the following steps: * Before installing ``Qlib`` from source, users need to install some dependencies: @@ -79,15 +84,20 @@ Also, users can install ``Qlib`` by the source code according to the following s pip install numpy pip install --upgrade cython ``` - **Note**: please pay attention that installing cython in Python 3.6 will raise some error when installing ``Qlib`` from source. If users use Python 3.6 on their machines, it is recommended to *upgrade* Python to version 3.7 or use `conda`'s Python to install ``Qlib`` from source. - -* Clone the repository and install ``Qlib``: - - ```bash - git clone https://github.com/microsoft/qlib.git && cd qlib - python setup.py install - ``` + **Note**: Please pay attention that installing cython in Python 3.6 will raise some error when installing ``Qlib`` from source. If users use Python 3.6 on their machines, it is recommended to *upgrade* Python to version 3.7 or use `conda`'s Python to install ``Qlib`` from source. +* Clone the repository and install ``Qlib`` as follows. + * If you haven't installed qlib by the command ``pip install pyqlib`` before: + ```bash + git clone https://github.com/microsoft/qlib.git && cd qlib + python setup.py install + ``` + * If you have already installed the stable version by the command ``pip install pyqlib``: + ```bash + git clone https://github.com/microsoft/qlib.git && cd qlib + pip install . + ``` + **Note**: **Only** the command ``pip install .`` **can** overwrite the stable version installed by ``pip install pyqlib``, while the command ``python setup.py install`` **can't**. ## Data Preparation Load and prepare data by running the following code: @@ -131,10 +141,10 @@ Users could create the same dataset with it. ## Auto Quant Research Workflow Qlib provides a tool named `qrun` to run the whole workflow automatically (including building dataset, training models, backtest and evaluation). You can start an auto quant research workflow and have a graphical reports analysis according to the following steps: -1. Quant Research Workflow: Run `qrun` with lightgbm workflow config ([workflow_config_lightgbm.yaml](examples/benchmarks/LightGBM/workflow_config_lightgbm.yaml)) as following. +1. Quant Research Workflow: Run `qrun` with lightgbm workflow config ([workflow_config_lightgbm_Alpha158.yaml](examples/benchmarks/LightGBM/workflow_config_lightgbm_Alpha158.yaml) as following. ```bash cd examples # Avoid running program under the directory contains `qlib` - qrun benchmarks/LightGBM/workflow_config_lightgbm.yaml + qrun benchmarks/LightGBM/workflow_config_lightgbm_Alpha158.yaml ``` The result of `qrun` is as follows, please refer to please refer to [Intraday Trading](https://qlib.readthedocs.io/en/latest/component/backtest.html) for more details about the result. @@ -191,16 +201,16 @@ The automatic workflow may not suite the research workflow of all Quant research # [Quant Model Zoo](examples/benchmarks) Here is a list of models built on `Qlib`. -- [GBDT based on LightGBM](qlib/contrib/model/gbdt.py) -- [GBDT based on Catboost](qlib/contrib/model/catboost_model.py) -- [GBDT based on XGBoost](qlib/contrib/model/xgboost.py) +- [GBDT based on LightGBM (Guolin Ke, et al.)](qlib/contrib/model/gbdt.py) +- [GBDT based on Catboost (Liudmila Prokhorenkova, et al.)](qlib/contrib/model/catboost_model.py) +- [GBDT based on XGBoost (Tianqi Chen, et al.)](qlib/contrib/model/xgboost.py) - [MLP based on pytorch](qlib/contrib/model/pytorch_nn.py) -- [GRU based on pytorch](qlib/contrib/model/pytorch_gru.py) -- [LSTM based on pytorcn](qlib/contrib/model/pytorch_lstm.py) -- [ALSTM based on pytorcn](qlib/contrib/model/pytorch_alstm.py) -- [GATs based on pytorch](qlib/contrib/model/pytorch_gats.py) -- [SFM based on pytorch](qlib/contrib/model/pytorch_sfm.py) -- [TFT based on tensorflow](examples/benchmarks/TFT/tft.py) +- [GRU based on pytorch (Kyunghyun Cho, et al.)](qlib/contrib/model/pytorch_gru.py) +- [LSTM based on pytorcn (Sepp Hochreiter, et al.)](qlib/contrib/model/pytorch_lstm.py) +- [ALSTM based on pytorcn (Yao Qin, et al.)](qlib/contrib/model/pytorch_alstm.py) +- [GATs based on pytorch (Petar Velickovic, et al.)](qlib/contrib/model/pytorch_gats.py) +- [SFM based on pytorch (Liheng Zhang, et al.)](qlib/contrib/model/pytorch_sfm.py) +- [TFT based on tensorflow (Bryan Lim, et al.)](examples/benchmarks/TFT/tft.py) Your PR of new Quant models is highly welcomed. @@ -296,4 +306,4 @@ provided by the bot. You will only need to do this once across all repos using o This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or -contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. +contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. \ No newline at end of file diff --git a/docs/_static/demo.sh b/docs/_static/demo.sh new file mode 100644 index 000000000..bd2367a92 --- /dev/null +++ b/docs/_static/demo.sh @@ -0,0 +1,12 @@ +#!/bin/sh +git clone https://github.com/microsoft/qlib.git +cd qlib +ls +pip install pyqlib +# or +# pip install numpy +# pip install --upgrade cython +# python setup.py install +cd examples +ls +qrun benchmarks/LightGBM/workflow_config_lightgbm_Alpha158.yaml \ No newline at end of file diff --git a/docs/component/recorder.rst b/docs/component/recorder.rst index baf12448b..baf8f2bca 100644 --- a/docs/component/recorder.rst +++ b/docs/component/recorder.rst @@ -91,7 +91,7 @@ Record Template The ``RecordTemp`` class is a class that enables generate experiment results such as IC and backtest in a certain format. We have provided three different `Record Template` class: -- ``SignalRecord``: This class generates the `preidction` results of the model. +- ``SignalRecord``: This class generates the `prediction` results of the model. - ``SigAnaRecord``: This class generates the `IC`, `ICIR`, `Rank IC` and `Rank ICIR` of the model. - ``PortAnaRecord``: This class generates the results of `backtest`. The detailed information about `backtest` as well as the available `strategy`, users can refer to `Strategy <../component/strategy.html>`_ and `Backtest <../component/backtest.html>`_. diff --git a/examples/README.md b/examples/README.md index b3728a1ec..124c34363 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,6 +1,6 @@ # Requirements -Here is the minimal hardware requirements to run the example. +Here is the minimal hardware requirements to run the `workflow_by_code` example. - Memory: 16G - Free Disk: 5G diff --git a/examples/benchmarks/README.md b/examples/benchmarks/README.md index 3f9b1f55b..6ed872ef5 100644 --- a/examples/benchmarks/README.md +++ b/examples/benchmarks/README.md @@ -29,4 +29,4 @@ The numbers shown below demonstrate the performance of the entire `workflow` of | GRU (Kyunghyun Cho, et al.) | Alpha158 (with selected 20 features) | 0.0311±0.00 | 0.2418±0.04| 0.0425±0.00 | 0.3434±0.02 | 0.0330±0.02 | 0.4805±0.30| -0.1021±0.02 | | LSTM (Sepp Hochreiter, et al.) | Alpha158 (with selected 20 features) | 0.0312±0.00 | 0.2394±0.04| 0.0418±0.00 | 0.3324±0.03 | 0.0298±0.02 | 0.4198±0.33| -0.1348±0.03 | | ALSTM (Yao Qin, et al.) | Alpha158 (with selected 20 features) | 0.0385±0.01 | 0.3022±0.06| 0.0478±0.00 | 0.3874±0.04 | 0.0486±0.03 | 0.7141±0.45| -0.1088±0.03 | -| GATs (Petar Velickovic, et al.) | Alpha158 (with selected 20 features) | 0.0349±0.00 | 0.2511±0.01| 0.0457±0.00 | 0.3537±0.01 | 0.0578±0.02 | 0.8221±0.25| -0.0824±0.02 | \ No newline at end of file +| GATs (Petar Velickovic, et al.) | Alpha158 (with selected 20 features) | 0.0349±0.00 | 0.2511±0.01| 0.0457±0.00 | 0.3537±0.01 | 0.0578±0.02 | 0.8221±0.25| -0.0824±0.02 | diff --git a/examples/benchmarks/SFM/README.md b/examples/benchmarks/SFM/README.md index 5f74c15d2..ff54145af 100644 --- a/examples/benchmarks/SFM/README.md +++ b/examples/benchmarks/SFM/README.md @@ -1,3 +1,3 @@ # State-Frequency-Memory - State Frequency Memory (SFM) is a novel recurrent network that uses Discrete Fourier Transform to decompose the hidden states of memory cells and capture the multi-frequency trading patterns from past market data to make stock price predictions. -- Paper: Stock Price Prediction via Discovering Multi-Frequency Trading Patterns. [https://www.cs.ucf.edu/~gqi/publications/kdd2017_stock.pdf.](https://www.cs.ucf.edu/~gqi/publications/kdd2017_stock.pdf.) \ No newline at end of file +- Paper: Stock Price Prediction via Discovering Multi-Frequency Trading Patterns. [http://www.eecs.ucf.edu/~gqi/publications/kdd2017_stock.pdf.](http://www.eecs.ucf.edu/~gqi/publications/kdd2017_stock.pdf) \ No newline at end of file diff --git a/examples/benchmarks/TFT/expt_settings/configs.py b/examples/benchmarks/TFT/expt_settings/configs.py index 6aef0c395..62aa68c38 100644 --- a/examples/benchmarks/TFT/expt_settings/configs.py +++ b/examples/benchmarks/TFT/expt_settings/configs.py @@ -25,7 +25,7 @@ import os import data_formatters.qlib_Alpha158 -class ExperimentConfig(object): +class ExperimentConfig: """Defines experiment configs and paths to outputs. Attributes: diff --git a/examples/benchmarks/TFT/libs/tft_model.py b/examples/benchmarks/TFT/libs/tft_model.py index 658bae60f..b39f17825 100644 --- a/examples/benchmarks/TFT/libs/tft_model.py +++ b/examples/benchmarks/TFT/libs/tft_model.py @@ -320,7 +320,7 @@ class InterpretableMultiHeadAttention: return outputs, attn -class TFTDataCache(object): +class TFTDataCache: """Caches data for the TFT.""" _data_cache = {} @@ -348,7 +348,7 @@ class TFTDataCache(object): # TFT model definitions. -class TemporalFusionTransformer(object): +class TemporalFusionTransformer: """Defines Temporal Fusion Transformer. Attributes: @@ -972,7 +972,7 @@ class TemporalFusionTransformer(object): valid_quantiles = self.quantiles output_size = self.output_size - class QuantileLossCalculator(object): + class QuantileLossCalculator: """Computes the combined quantile loss for prespecified quantiles. Attributes: diff --git a/examples/run_all_model.py b/examples/run_all_model.py index 505a20bcb..d587eff15 100644 --- a/examples/run_all_model.py +++ b/examples/run_all_model.py @@ -69,9 +69,9 @@ def handler(signum, frame): os.system("kill -9 %d" % os.getpid()) -signal.signal(signal.SIGTSTP, handler) signal.signal(signal.SIGINT, handler) + # function to calculate the mean and std of a list in the results dictionary def cal_mean_std(results) -> dict: mean_std = dict() diff --git a/qlib/__init__.py b/qlib/__init__.py index f79b8c4f5..98920ed04 100644 --- a/qlib/__init__.py +++ b/qlib/__init__.py @@ -2,7 +2,7 @@ # Licensed under the MIT License. -__version__ = "0.6.0.dev" +__version__ = "0.6.1.dev" import os diff --git a/qlib/contrib/backtest/__init__.py b/qlib/contrib/backtest/__init__.py index 31746819c..6fcdf2142 100644 --- a/qlib/contrib/backtest/__init__.py +++ b/qlib/contrib/backtest/__init__.py @@ -1,7 +1,6 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. -# -*- coding: utf-8 -*- from .order import Order from .account import Account from .position import Position diff --git a/qlib/contrib/model/pytorch_nn.py b/qlib/contrib/model/pytorch_nn.py index 308494443..a41eeabbb 100644 --- a/qlib/contrib/model/pytorch_nn.py +++ b/qlib/contrib/model/pytorch_nn.py @@ -296,7 +296,7 @@ class DNNModelPytorch(Model): self._fitted = True -class AverageMeter(object): +class AverageMeter: """Computes and stores the average and current value""" def __init__(self): diff --git a/qlib/contrib/model/pytorch_sfm.py b/qlib/contrib/model/pytorch_sfm.py index 15d945c89..ae175a202 100644 --- a/qlib/contrib/model/pytorch_sfm.py +++ b/qlib/contrib/model/pytorch_sfm.py @@ -464,7 +464,7 @@ class SFM(Model): return pd.Series(np.concatenate(preds), index=index) -class AverageMeter(object): +class AverageMeter: """Computes and stores the average and current value""" def __init__(self): diff --git a/qlib/contrib/online/operator.py b/qlib/contrib/online/operator.py index a00e17d40..c8b44f578 100644 --- a/qlib/contrib/online/operator.py +++ b/qlib/contrib/online/operator.py @@ -21,7 +21,7 @@ from .executor import SimulatorExecutor from .executor import save_score_series, load_score_series -class Operator(object): +class Operator: def __init__(self, client: str): """ Parameters diff --git a/qlib/contrib/report/graph.py b/qlib/contrib/report/graph.py index 3fa688d36..70e382fb1 100644 --- a/qlib/contrib/report/graph.py +++ b/qlib/contrib/report/graph.py @@ -17,7 +17,7 @@ from plotly.figure_factory import create_distplot from ...utils import get_module_by_module_path -class BaseGraph(object): +class BaseGraph: """""" _name = None @@ -204,7 +204,7 @@ class HistogramGraph(BaseGraph): return _data -class SubplotsGraph(object): +class SubplotsGraph: """Create subplots same as df.plot(subplots=True) Simple package for `plotly.tools.subplots` diff --git a/qlib/contrib/tuner/config.py b/qlib/contrib/tuner/config.py index 4825ca092..f23d1b874 100644 --- a/qlib/contrib/tuner/config.py +++ b/qlib/contrib/tuner/config.py @@ -6,7 +6,7 @@ import copy import os -class TunerConfigManager(object): +class TunerConfigManager: def __init__(self, config_path): if not config_path: @@ -27,7 +27,7 @@ class TunerConfigManager(object): self.qlib_client_config = config.get("qlib_client", dict()) -class PipelineExperimentConfig(object): +class PipelineExperimentConfig: def __init__(self, config, TUNER_CONFIG_MANAGER): """ :param config: The config dict for tuner experiment @@ -53,7 +53,7 @@ class PipelineExperimentConfig(object): yaml.dump(TUNER_CONFIG_MANAGER.config, fp) -class OptimizationConfig(object): +class OptimizationConfig: def __init__(self, config, TUNER_CONFIG_MANAGER): self.report_type = config.get("report_type", "pred_long") diff --git a/qlib/contrib/tuner/pipeline.py b/qlib/contrib/tuner/pipeline.py index 3a76d071d..ee92db529 100644 --- a/qlib/contrib/tuner/pipeline.py +++ b/qlib/contrib/tuner/pipeline.py @@ -11,7 +11,7 @@ from ...log import get_module_logger, TimeInspector from ...utils import get_module_by_module_path -class Pipeline(object): +class Pipeline: GLOBAL_BEST_PARAMS_NAME = "global_best_params.json" diff --git a/qlib/contrib/tuner/tuner.py b/qlib/contrib/tuner/tuner.py index 8da40bc69..2ce957859 100644 --- a/qlib/contrib/tuner/tuner.py +++ b/qlib/contrib/tuner/tuner.py @@ -19,7 +19,7 @@ from hyperopt import fmin, tpe from hyperopt import STATUS_OK, STATUS_FAIL -class Tuner(object): +class Tuner: def __init__(self, tuner_config, optim_config): self.logger = get_module_logger("Tuner", sh_level=logging.INFO) diff --git a/qlib/data/_libs/expanding.pyx b/qlib/data/_libs/expanding.pyx index 47bc49610..6c27c07eb 100644 --- a/qlib/data/_libs/expanding.pyx +++ b/qlib/data/_libs/expanding.pyx @@ -8,7 +8,7 @@ from libc.math cimport sqrt, isnan, NAN from libcpp.vector cimport vector -cdef class Expanding(object): +cdef class Expanding: """1-D array expanding""" cdef vector[double] barv cdef int na_count diff --git a/qlib/data/_libs/rolling.pyx b/qlib/data/_libs/rolling.pyx index 37d27ffa4..a18679a99 100644 --- a/qlib/data/_libs/rolling.pyx +++ b/qlib/data/_libs/rolling.pyx @@ -8,7 +8,7 @@ from libc.math cimport sqrt, isnan, NAN from libcpp.deque cimport deque -cdef class Rolling(object): +cdef class Rolling: """1-D array rolling""" cdef int window cdef deque[double] barv diff --git a/qlib/data/cache.py b/qlib/data/cache.py index 3fab2b527..d53f578b1 100644 --- a/qlib/data/cache.py +++ b/qlib/data/cache.py @@ -68,7 +68,7 @@ class MemCacheUnit(OrderedDict): self.popitem(last=False) -class MemCache(object): +class MemCache: """Memory cache.""" def __init__(self, mem_cache_size_limit=None, limit_type="length"): @@ -140,7 +140,7 @@ class MemCacheExpire: return value, expire -class CacheUtils(object): +class CacheUtils: LOCK_ID = "QLIB" @staticmethod @@ -224,7 +224,7 @@ class CacheUtils(object): current_cache_wlock.release() -class BaseProviderCache(object): +class BaseProviderCache: """Provider cache base class""" def __init__(self, provider): diff --git a/qlib/data/client.py b/qlib/data/client.py index 65a830f20..5244a7e45 100644 --- a/qlib/data/client.py +++ b/qlib/data/client.py @@ -12,7 +12,7 @@ from ..log import get_module_logger import pickle -class Client(object): +class Client: """A client class Provide the connection tool functions for ClientProvider. diff --git a/qlib/data/ops.py b/qlib/data/ops.py index e17c0e4e6..7c13d345f 100644 --- a/qlib/data/ops.py +++ b/qlib/data/ops.py @@ -18,7 +18,9 @@ try: from ._libs.rolling import rolling_slope, rolling_rsquare, rolling_resi from ._libs.expanding import expanding_slope, expanding_rsquare, expanding_resi except ImportError as err: - print("Do not import qlib package in the repository directory!") + print( + "#### Do not import qlib package in the repository directory in case of importing qlib from . without compiling #####" + ) raise __all__ = ( @@ -143,6 +145,15 @@ class Sign(ElemOperator): def __init__(self, feature): super(Sign, self).__init__(feature, "sign") + def _load_internal(self, instrument, start_index, end_index, freq): + """ + To avoid error raised by bool type input, we transform the data into float32. + """ + series = self.feature.load(instrument, start_index, end_index, freq) + # TODO: More precision types should be configurable + series = series.astype(np.float32) + return getattr(np, self.func)(series) + class Log(ElemOperator): """Feature Log diff --git a/qlib/log.py b/qlib/log.py index 422a4c00b..6553dcb11 100644 --- a/qlib/log.py +++ b/qlib/log.py @@ -36,7 +36,7 @@ def get_module_logger(module_name, level=None): return module_logger -class TimeInspector(object): +class TimeInspector: timer_logger = get_module_logger("timer", level=logging.WARNING) diff --git a/qlib/portfolio/optimizer.py b/qlib/portfolio/optimizer.py index 534a66e2d..0e7d27254 100644 --- a/qlib/portfolio/optimizer.py +++ b/qlib/portfolio/optimizer.py @@ -9,7 +9,7 @@ import scipy.optimize as so from typing import Optional, Union, Callable, List -class PortfolioOptimizer(object): +class PortfolioOptimizer: """Portfolio Optimizer The following optimization algorithms are supported: diff --git a/qlib/utils/__init__.py b/qlib/utils/__init__.py index ab67b67e3..ddc17c478 100644 --- a/qlib/utils/__init__.py +++ b/qlib/utils/__init__.py @@ -686,7 +686,7 @@ def flatten_dict(d, parent_key="", sep="."): #################### Wrapper ##################### -class Wrapper(object): +class Wrapper: """Wrapper class for anything that needs to set up during qlib.init""" def __init__(self): diff --git a/scripts/collect_info.py b/scripts/collect_info.py index c9a9440b9..ba53deb30 100644 --- a/scripts/collect_info.py +++ b/scripts/collect_info.py @@ -1,28 +1,66 @@ -import sys, platform +import sys +import platform import qlib +import fire +import pkg_resources +from pathlib import Path + +QLIB_PATH = Path(__file__).absolute().resolve().parent.parent -def linux_distribution(): - try: - return platform.linux_distribution() - except: - return "N/A" +class InfoCollector: + def sys(self): + """collect system related info""" + for method in ["system", "machine", "platform", "version"]: + print(getattr(platform, method)()) + + def py(self): + """collect Python related info""" + print("Python version: {}".format(sys.version.replace("\n", " "))) + + def qlib(self): + """collect qlib related info""" + print("Qlib version: {}".format(qlib.__version__)) + REQUIRED = [ + "numpy", + "pandas", + "scipy", + "requests", + "sacred", + "pymongo", + "python-socketio", + "redis", + "python-redis-lock", + "schedule", + "cvxpy", + "hyperopt", + "fire", + "statsmodels", + "xlrd", + "plotly", + "matplotlib", + "tables", + "pyyaml", + "mlflow", + "tqdm", + "loguru", + "lightgbm", + "tornado", + "joblib", + "fire", + "ruamel.yaml", + ] + + for package in REQUIRED: + version = pkg_resources.get_distribution(package).version + print(f"{package}=={version}") + + def all(self): + """collect all info""" + for method in ["sys", "py", "qlib"]: + getattr(self, method)() + print() -print("Qlib version: {} \n".format(qlib.__version__)) -print( - """Python version: {} \n -linux_distribution: {} -system: {} -machine: {} -platform: {} -version: {} -""".format( - sys.version.split("\n"), - linux_distribution(), - platform.system(), - platform.machine(), - platform.platform(), - platform.version(), - ) -) +if __name__ == "__main__": + fire.Fire(InfoCollector) diff --git a/setup.py b/setup.py index 065e30605..109a6b032 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.dev" +VERSION = "0.6.1.dev" # Detect Cython try: