* fix: use baostock to fetch trading calendar instead of Eastmoney API
* fix: lint error
* fix: lint error
* ci: enable concurrency to cancel in-progress runs for same workflow and ref
---------
Co-authored-by: Linlang Lv (iSoftStone Information) <v-llv@microsoft.com>
* [fix] handler_mod func don't work when dealing None end date
* refactor: avoid deep access by extracting handler_kwargs and using get(end_time)
---------
Co-authored-by: Linlang <Lv.Linlang@hotmail.com>
* fix(client): fix missing dependencies and unsafe pickle usage
* ci: exclude client extra from default install to avoid macOS CI failures
* fix: CI error
* ci: install dependencies with --no-cache-dir to avoid disk space issues
* dont manually call setuptools_scm - its integrated
setuptools_scm automatically set the version attribute - manually setting it wrong
* fix(docs): set fallback version for setuptools-scm to fix autodoc import errors on Read the Docs
---------
Co-authored-by: SunsetWolf <Lv.Linlang@hotmail.com>
* fix: replace deprecated pandas fillna(method=) with ffill()/bfill()
Replace deprecated fillna(method="ffill"/"bfill") calls with modern
pandas ffill() and bfill() methods to fix FutureWarnings in pandas 2.x.
Also includes black formatting fixes for compliance.
This addresses the pandas deprecation warnings portion of issue #1981.
Other issues (date parsing, type conversion, timezone handling) will be
addressed in separate commits.
Fixes:
- Yahoo collector: 2 instances in calc_change() and adjusted_price()
- BaoStock collector: 1 instance in calc_change()
- Core utils: resam.py fillna operations
- Backtest: profit_attribution.py stock data processing
- High-freq ops: FFillNan and BFillNan operators
- Position analysis: parse_position.py weight processing
Partially addresses GitHub issue #1981
* lint with black
* lint with black
* limit minimum version of pandas
* limit minimum version of pandas
---------
Co-authored-by: Linlang <Lv.Linlang@hotmail.com>
* ci: auto release
* fix: bug getting version in qlib/__init__.py
* fix: bug getting version in setup.py
* fix: bug getting version in qlib/__init__.py
* fix: make the code in CI more complete
* fix: specify the root directory in the get_verison method
* fix: parameter error
* update: optimize code && add comments
* fix: upgrade the method of installing LightGBM on MacOS
* fix: upgrade the method of installing LightGBM on MacOS
* fix: upgrade the method of installing LightGBM on MacOS
* fix: upgrade the method of installing LightGBM on MacOS
* fix: upgrade the method of installing LightGBM on MacOS
* fix: upgrade the method of installing LightGBM on MacOS
* fix: upgrade the method of installing LightGBM on MacOS
* fix: upgrade the method of installing LightGBM on MacOS
* fix: upgrade the method of installing LightGBM on MacOS
* fix: upgrade the method of installing LightGBM on MacOS
* fix: upgrade the method of installing LightGBM on MacOS
* fix: upgrade the method of installing LightGBM on MacOS
* fix: upgrade the method of installing LightGBM on MacOS
* fix: upgrade the method of installing LightGBM on MacOS
* fix: upgrade the method of installing LightGBM on MacOS
* fix: upgrade the method of installing LightGBM on MacOS
* fix: upgrade the method of installing LightGBM on MacOS
* fix: upgrade the method of installing LightGBM on MacOS
* fix: upgrade the method of installing LightGBM on MacOS
* fix: upgrade the method of installing LightGBM on MacOS
* add: comments
* test: build package && check package
* test: build package && check package
* test: build package && check package
* optimize yml
* refactor: introduce BaseDataHandler and unify fetch interface
* refactor: include data_key in seg_kwargs and simplify segments loop
* refactor: default data_key to BaseDataHandler.DK_I in _get_df_by_key
* style: fix indentation and remove extra blank lines in data handlers
* refactor: use BaseDataHandler.DK_I as default data_key
* docs: fix BaseDataHandler docstring grammar and formatting
* refactor: remove unused **kwargs from storage fetch methods
* docs: refine BaseDataHandler and DataHandler docstrings
* refactor: rename BaseDataHandler to DataHandlerABC, update type hints
* feat: add flt_col to TSDatasetH and list-to-slice conversion in storage
* lint
* comment
* Fixing Security Vulnerabilities
* Fixing Pylint Error
* Fixing Security Vulnerabilities windows
* format with black
* using returncode to locate problems
* fix pylint error
* Update detailed_workflow.ipynb
the result figure is empty
* Update detailed_workflow.ipynb
fix issue: the plotly figure is empty
* The error message indicated that my code did not
comply with the code style guidelines.
Specifically, I had used double quotes "notebook"
for the string, whereas the required format was
single quotes 'notebook'.
This has now been corrected.
* comply with the code style guidelines.
Specifically, I had used double quotes "notebook"
for the string, whereas the required format was
single quotes 'notebook'.
This has now been corrected.
* I didn't use nbqa black to reformat my code. Now
is done!
* recover_code
---------
Co-authored-by: Linlang <Lv.Linlang@hotmail.com>
* fixed a problem with multi index caused by the default value of groupkey
* modify group_key default value
* limit pandas verion
* format with black
* fix docs error
* fix docs error
* fixed bugs caused by pandas upgrade
* remove needless code
* reformat with black
* limit version & add docs
* fix: resolve#1892 by retriving the data page by page
* fix: resolve#1892 by retriving the data page by page
* reformat with black
---------
Co-authored-by: shengyuhong <shengyuhong@bytedance.com>
Co-authored-by: fibers <yu8582@126.com>
* #854 implement first data health checker draft
* #854 added support for qlib's data format, implemented factor check, reformatted summary
* adaptation current dataset
* format with black
* add data health check to docs
* fix sphinx error
* fix pylint error
* update code
* format with black
* format with pylint
---------
Co-authored-by: Linlang <Lv.Linlang@hotmail.com>
* update readme
* Update README.md
add english and chinese link to rdagent
* add the logo of rdagent to readme
add the logo of rdagent to readme
* adjust the height of the logo
* improve some works in readme
* add a line
* Init model for both dataset
* Remove some deprecated code
* Add model template;
* We must align with previous results
* We choose another mode as the initial version
* Almost success to run GRU
* Successfully run training
* Passed general_nn test
* gru test
* Alignment test passed
* comment
* fix readme & minor errors
* general nn updates & benchmarks
* Update examples/benchmarks/GeneralPtNN/workflow_config_gru2mlp.yaml
---------
Co-authored-by: Young <afe.young@gmail.com>
Co-authored-by: you-n-g <you-n-g@users.noreply.github.com>
* Fix FutureWarning: Passing unit-less datetime64 dtype to .astype is deprecated and will raise in a future version. Pass 'datetime64[ns]' instead
* align index format while end date contains current day data
* fix black
* fix black
* optimize code
* optimize code
* optimize code
* fix ci error
* check ci error
* fix ci error
* check ci error
* check ci error
* check ci error
* check ci error
* check ci error
* check ci error
* fix ci error
* fix ci error
* fix ci error
* fix ci error
* fix ci error
---------
Co-authored-by: Cadenza-Li <362237642@qq.com>
Co-authored-by: Linlang <Lv.Linlang@hotmail.com>
* fix the bug that the HS_SYMBOLS_URL is 404
* fix bug
* format with black
* fix pylint error
* change error code
* fix ci error
* fix ci error
* optimize code
* optimize code
* add comments
---------
Co-authored-by: Linlang <Lv.Linlang@hotmail.com>
* Fix the bug of reading NA string as NaN in exists_qlib_data.
* Fix the .gitignore file.
* Update the fix and add some comments.
* format with black
---------
Co-authored-by: Chuan Xu <chuan.xu@sas.com>
Co-authored-by: Linlang Lv (iSoftStone Information) <v-lvlinlang@microsoft.com>
* download orderbook data
* fix CI error
* fix CI error
* test fix CI error
* test fix CI error
* test fix CI error
* test fix CI error
* test fix CI error
* test fix CI error
* test fix CI error
* test fix CI error
* test fix CI error
* test fix CI error
* test fix CI error
* test fix CI error
* test fix CI error
* test fix CI error
* test fix CI error
* test fix CI error
* test fix CI error
* test fix CI error
* test fix CI error
* optimize get_data code
* optimize get_data code
* optimize get_data code
* optimize README
---------
Co-authored-by: Linlang <v-linlanglv@microsoft.com>
* add_baostock_collector
* modify_comments
* fix_pylint_error
* solve_duplication_methods
* modified the logic of update_data_to_bin
* modified the logic of update_data_to_bin
* optimize code
* optimize pylint issue
* fix pylint error
* changes suggested by the review
* fix CI faild
* fix CI faild
* fix issue 1121
* format with black
* optimize code logic
* optimize code logic
* fix error code
* drop warning during code runs
* optimize code
* format with black
* fix bug
* format with black
* optimize code
* optimize code
* add comments
* df value is set as expected, suppress the warning;
* depress warning with pandas option_context
---------
Co-authored-by: Cadenza-Li <362237642@qq.com>
* Add multi pass port ana record
* Add list function
* Add documentation and support <MODEL> tag
* Add drop in replacement example
* reformat
* Change according to comments
* update format
* Update record_temp.py
Fix type hint
* Update record_temp.py
* Intermediate version
* Fix yaml template & Successfully run rolling
* Be compatible with benchmark
* Get same results with previous linear model
* Black formatting
* Update black
* Update the placeholder mechanism
* Update CI
* Update CI
* Upgrade Black
* Fix CI and simplify code
* Fix CI
* Move the data processing caching mechanism into utils.
* Adjusting DDG-DA
* Organize import
* move config file to benchmark_dynamic & switch default sim task model to GBDT
* Update benchmark_dynamic results
* Change the default value of alpha of DDG-DA
* transpose dimension 1 and 2 to match nn.Conv1d input
* 1.update TCN benchmarks;
2.Emphasize updating the benchmark table;
* replace specific version with main
---------
Co-authored-by: lijinhui <362237642@qq.com>
* 1.specify group_keys=False to avoid FutureWarning;
2.fix get train_start from dict unexpected problem;
* fix black
* Add comments
* Add make file
---------
Co-authored-by: Young <afe.young@gmail.com>
* Remove lr_decay and lr_decay_steps params
More flexible way to pass a scheduler (via callable function) is already
supported
* remove lr_decay and lr_decay_steps from mlp workflow configs
* wip
* wip
* wip
* Fix naming errors
* Backtest test passed
* Why training stuck?
* Minor
* Refine train configs
* Use dummy in training
* Remove pickle_dataframe
* CI
* CI
* Add more strict condition to filter orders
* Pass test
* Add TODO in example
---------
Co-authored-by: Young <afe.young@gmail.com>
* update ubuntu CI version;
(End of standard support for 18.04 LTS - 31 May 2023)
* update ubuntu CI version;
---------
Co-authored-by: lijinhui <362237642@qq.com>
* Waiting for bin data
* Complete readme
* CI
* Add inst filter by time
* Update qlib/data/dataset/processor.py
* typo
* Fix time filter bug
* Add Filter and set Universe
* Complete data pipeline
* Fix Provider Logger Info Args
* Add DQN; a minor bugfix in ppo reward.
* update readme. modify assertion logic in strategy check.
* Fix Doc issues and fix black
* Fix pylint Error
---------
Co-authored-by: Young <afe.young@gmail.com>
Co-authored-by: you-n-g <you-n-g@users.noreply.github.com>
* Update test_qlib_from_source.yml
* add ipynb format check to workflow
* test ipynb CI
* modify nbqa check path
* add pylint flake8 mypy check to ipynb
* check ipynb with black and pylint
* reformat .ipynb files
* format line length
nbqa black . -l 120
* update nbqa .ipynb format CI
* format old ipynb files
* add nbconvert check to CI
* adjust CI order to avoid repeating download data
* Workflow runnable
* CI
* Slight changes to make the workflow runnable. The changes of handler/provider should be reverted before merging.
* Train experiment successful
* Refine handler & provider
* test passed
* Ready to test on server
* Minor
* Test passed
* TWAP training
* Add PPOReward
* Add a FIXME
* Refine PPO reward according to PR comments
* Minor
* Resolve PR comments
* CI issues
* CI issues
* CI issues
* Workflow runnable
* CI
* Slight changes to make the workflow runnable. The changes of handler/provider should be reverted before merging.
* Train experiment successful
* Refine handler & provider
* CI issues
* Resolve PR comments
* Resolve PR comments
* CI issues
* Fix test issue
* Black
* 1) check limit_up/down should consider direction; 2) fix some typo, typehint etc
* fix error
* Update test_all_pipeline.py
Believe it's just some arbitrary number.
The excess return is expected to change when trading logic changes.
* add flag forbid_all_trade_at_limit to keep previous behivour for backward compatibility
* config.py: fix typo; static method
* fix typo in qlib/utils/paral
* 1) limit numpy version as numba support for 1.24+ has not been released; 2) no need to use custom numba version for pytest.
* remove useless argument
Co-authored-by: you-n-g <you-n-g@users.noreply.github.com>
* horizontally put the bar figures
* 1) use rangebreaks to handle gaps in datetime axis instead of make them string; 2) allow simultaneously plot rankic in ic_figure
* pylint improvement
* fix black lint
* better axis formatting
* default not show gaps
* resolve doc built error
* fix pylint
* Update qlib/contrib/report/analysis_model/analysis_model_performance.py
More detailed description
Co-authored-by: you-n-g <you-n-g@users.noreply.github.com>
* Update qlib/contrib/report/analysis_model/analysis_model_performance.py
for Python backward compatibility
Co-authored-by: you-n-g <you-n-g@users.noreply.github.com>
* add doc string
* fix black
* 1) limit numpy version as numba support for 1.24+ has not been released; 2) no need to use custom numba version for pytest.
Co-authored-by: you-n-g <you-n-g@users.noreply.github.com>
* Update YahooNormalizeUS1dExtend(#1196)
* Prevent pandas read_csv errors while running update_data_to_bin for US region
* Fix parse_index error while running update_data_to_bin for US region
* prevent pandas.read_csv error on specific symbol names
* Reordering parameters for better rendering
* removes prefix during feature_dir existence checking
* add explanation comments
* Fix the Errors/Warnings when building Qlib's documentation
* Fix
* Fix
* Empty
* Test CI
* Add doc compiling checking to CI
* Fix
* Tries to be consistent with Makefile
Co-authored-by: you-n-g <you-n-g@users.noreply.github.com>
* fix logging_level: make logging level specified in qlib.init apply to all loggers
* downgrade loglevel in expmanager __init__ to debug (it will be called in each process in multiprocessing operations such as read data)
* correct gramma error
* fix black lint
* use functor to cache loggers and set level
* correct black lint
* correct pylint
* correct pylint
* fix gramma error in doc strings
* fix typos in exchange.py
* fix typos and gramma errors
* fix typo and rename function param to avoid shading python keyword
* remove redundant parathesis; pass kwargs to parent class
* fix pyblack
* further correction
* assign -> be assigned to
* Optimize the implementation of uri
* remove redundant func
* Set the right order of _set_client_uri
* Update qlib/workflow/expm.py
* Simplify client & add test.Add docs; Fix async bug
* Fix comments & pylint
* Improve README
* bug fix: 1) 100 should be used to scale down percentileofscore return to 0-1, not length of array; 2) for (linear) weighted MA(n), weight should be n, n-1, ..., 1 instead of n-1, ..., 0
* use native pandas fucntion for rank
* remove useless import
* require pandas 1.4+
* rank for py37+pandas 1.3.5 compatibility
* lint improvement
* lint black fix
* use hasattr instead of version to check whether rolling.rank is implemented
* update TSDataSampler
* reformat code with black
* use pre-commit to reformat the code
* Add documents
* More docstring
* More Safety
Co-authored-by: Young <afe.young@gmail.com>
* Refine several todos
* CI issues
* Remove Dropna limitation of `quote_df` in Exchange (#1334)
* Remove Dropna limitation of `quote_df` of Exchange
* Impreove docstring
* Fix type error when expression is specified (#1335)
* Refine fill_missing_data()
* Remove several TODO comments
* Add back env for interpreters
* Change Literal import
* Resolve PR comments
* Move to SAOEState
* Add Trainer.get_policy_state_dict()
* Mypy issue
Co-authored-by: you-n-g <you-n-g@users.noreply.github.com>
* Don't disable existing logger when initializing qlib.
* Add comma in the end of the config line.
* Add comment to the added config.
Co-authored-by: Jinge Wang <jingewang@microsoft.com>
* add missing parameters to doc string in order_generate
* fix some typos in doc strings
* reformat base on code style standard
* Update qlib/backtest/__init__.py
* Update examples/run_all_model.py
* Update examples/run_all_model.py
Co-authored-by: you-n-g <you-n-g@users.noreply.github.com>
* Add REG_US and REG_TW into test case: test_utils.py.
* Fix black.
* Trigger checks.
* Add REG_US and REG_TW into test case: test_utils.py.
* Fix black.
* Trigger checks.
* RL backtest with simulator
* Minor modification in init_qlib
* Cherry pick PR 1302
* Resolve PR comments
* Fix missing data processing
* Minor bugfix
* Add TODOs and docs
* Add a comment
* feat(data): ✨ add a general highfreq data handler for open source
Add HighFreqOpenHandler and HighFreqOpenBacktestHandler for data pipeline without paused_num
information.
* fix: position of parameter init
* style(data): 💄 rename open to general
* style(data): 💄 lint
* style: 💄 delete useless comment & fix inheritance relation
* style: 💄 lint
* style: 💄 remove duplicated function
Co-authored-by: mingzhehan <v-zhaoxing@Microsoft.com>
* My own implementation of ChangeInstrument Op. There is a newer, simpler
implemenation from remote.
On branch main
Your branch is behind 'origin/main' by 127 commits, and can be fast-forwarded.
(use "git pull" to update your local branch)
Changes to be committed:
modified: qlib/data/ops.py
Changes not staged for commit:
modified: qlib/contrib/evaluate.py
modified: qlib/contrib/strategy/signal_strategy.py
modified: qlib/utils/__init__.py
modified: qlib/workflow/cli.py
modified: qlib/workflow/expm.py
Untracked files:
.idea/
------------------------ >8 ------------------------
Do not modify or remove the line above.
Everything below it will be ignored.
diff --git a/qlib/data/ops.py b/qlib/data/ops.py
index bdc032c0..23db25cc 100644
--- a/qlib/data/ops.py
+++ b/qlib/data/ops.py
@@ -32,6 +32,90 @@ except ValueError as e:
np.seterr(invalid="ignore")
+#################### Change instrument ########################
+# In some case, one may want to change to another instrument when calculating, for example
+# calculate beta of a stock with respect to a market index
+# this would require change the calculation of features from the stock (original instrument) to
+# the index (reference instrument)
+# #############################
+
+
+class ChangeInstrument(ExpressionOps):
+ """Change Instrument Operator
+ In some case, one may want to change to another instrument when calculating, for example, to
+ calculate beta of a stock with respect to a market index.
+ This would require changing the calculation of features from the stock (original instrument) to
+ the index (reference instrument)
+ Parameters
+ ----------
+ instrument: new instrument for which the downstream operations should be performed upon.
+ i.e., SH000300 (CSI300 index), or ^GPSC (SP500 index).
+
+ feature: the feature to be calculated for the new instrument.
+ Returns
+ ----------
+ Expression
+ feature operation output
+ """
+
+ def __init__(self, instrument, feature):
+ self.instrument = instrument
+ self.feature = feature
+
+ def __str__(self):
+ return "{}({},{})".format(type(self).__name__, self.instrument, self.feature)
+
+ def load(self, instrument, start_index, end_index, freq):
+ """load feature
+
+ Parameters
+ ----------
+ instrument : str
+ instrument code, however, the actual instrument loaded is self.instrument through initialization
+ start_index : str
+ feature start index [in calendar].
+ end_index : str
+ feature end index [in calendar].
+ freq : str
+ feature frequency.
+
+ Returns
+ ----------
+ pd.Series
+ feature series: The index of the series is the calendar index
+ """
+ from .cache import H # pylint: disable=C0415
+
+ # cache
+ args = str(self), self.instrument, start_index, end_index, freq
+ if args in H["f"]:
+ return H["f"][args]
+ if start_index is not None and end_index is not None and start_index > end_index:
+ raise ValueError("Invalid index range: {} {}".format(start_index, end_index))
+ try:
+ series = self._load_internal(self.instrument, start_index, end_index, freq)
+ except Exception as e:
+ get_module_logger("data").debug(
+ f"Loading data error: instrument={instrument}, expression={str(self)}, "
+ f"start_index={start_index}, end_index={end_index}, freq={freq}. "
+ f"error info: {str(e)}"
+ )
+ raise
+ series.name = str(self)
+ H["f"][args] = series
+ return series
+
+ def _load_internal(self, instrument, start_index, end_index, freq):
+ series = self.feature.load(self.instrument, start_index, end_index, freq)
+ return series
+
+ def get_longest_back_rolling(self):
+ return self.feature.get_longest_back_rolling()
+
+ def get_extended_window_size(self):
+ return self.feature.get_extended_window_size()
+
+
#################### Element-Wise Operator ####################
@@ -1541,6 +1625,7 @@ class TResample(ElemOperator):
TOpsList = [TResample]
OpsList = [
+ ChangeInstrument,
Rolling,
Ref,
Max,
* update expm.py
* removed duplicate implementation for ChangeInstrument
* Refine previous version RL codes
* Polish utils/__init__.py
* Draft
* Use | instead of Union
* Simulator & action interpreter
* Test passed
* Migrate to SAOEState & new qlib interpreter
* Black format
* . Revert file_storage change
* Refactor file structure & renaming functions
* Enrich test cases
* Add QlibIntradayBacktestData
* Test interpreter
* Black format
* .
.
.
* Rename receive_execute_result()
* Use indicator to simplify state update
* Format code
* Modify data path
* Adjust file structure
* Minor change
* Add copyright message
* Format code
* Rename util functions
* Add CI
* Pylint issue
* Remove useless code to pass pylint
* Pass mypy
* Mypy issue
* mypy issue
* mypy issue
* Revert "mypy issue"
This reverts commit 8eb1b0174e.
* mypy issue
* mypy issue
* Fix the numpy version incompatible bug
* Fix a minor typing issue
* Try to skip python 3.7 test for qlib simulator
* Resolve PR comments by Yuge; solve several CI issues.
* Black issue
* Fix a low-level type error
* Change data name
* Resolve PR comments. Leave TODOs in the code base.
Co-authored-by: Young <afe.young@gmail.com>
* Explain data crawler structure
* Add documentation for data and feature
* Update scripts/data_collector/yahoo/README.md
Co-authored-by: you-n-g <you-n-g@users.noreply.github.com>
* Remove some confusing wording
* Add third party data source
* Fix command typo
* Update commands
Co-authored-by: you-n-g <you-n-g@users.noreply.github.com>
This commit improves the documentation (rst files) only in the
following three ways:
* Aligned section headers with their underline/overline punctuation characters
* Deleted all trailling whitespaces in rst files
* Deleted a few trailling newlines at the end of the rst files
Co-authored-by: Bingyao Liu <Bingyao.Liu@sofund.com>
* add ChangeInstrument to ops
Adding Change instrument OP. This op allows one to use features of a different instrument.
* Update __init__.py
update parse_field to accommodate ChangeInstrument
* Propose test
* Add test case and fix bug
* Update ops.py
* Update ops.py
* simplify the operator further
* implement abstract method
* fix arg bug
* clean test
Co-authored-by: Young <afe.young@gmail.com>
Co-authored-by: you-n-g <you-n-g@users.noreply.github.com>
* Done
* Fix test errors
* Revert profit_attribution.py
* Minor
* A minor update on collect_data type hint
* Resolve PR comments
* Use black to format code
* Fix CI errors
* Fixed pandas FutureWarning
`FutureWarning: Passing a set as an indexer is deprecated and will raise in a future version. Use a list instead.`
* fixed another pandas FutureWarning
```
scripts/data_collector/index.py:228: FutureWarning: The frame.append method is deprecated and will be removed from pandas in a future version. Use pandas.concat instead.
new_df = new_df.append(_tmp_df, sort=False)
```
* fixed more pandas futurewarnings
* Update workflow.rst
Fixed a typo. `please refer to Qlib Model` should be `please refer to Qlib Data` in Dataset section.
* Fix typo. `preprossing` should be `preprocessing`
* Update data.rst
Remove extra `of`.
* Commit the code of HIST and IGMTF on Alpha360
* add stock index
* Update README.md
* delete useless code
* fix the bug of code format with black
* fix pylint bugs
* fix the bugs of pylint
* fix pylint bugs
* fix flake8
* update cli.py
update cli.py so that one can specify exp_manager uri in "qlib_init" and "experiment_name" in *.yaml file.
* black cli.py
* Resolving pre-commit-hook changes
* feat: download ibovespa index historic composition
ibovespa(ibov) is the largest index in Brazil's stocks exchange.
The br_index folder has support for downloading new companies for the current index composition.
And has support, as well, for downloading companies from historic composition of ibov index.
Partially resolves issue #956
* fix: typo error instead of end_date, it was written end_ate
* feat: adds support for downloading stocks historic prices from Brazil's stocks exchange (B3)
Together with commit c2f933 it resolves issue #956
* fix: code formatted with black.
* wip: Creating code logic for brazils stock market data normalization
* docs: brazils stock market data normalization code documentation
* fix: code formatted the with black
* docs: fixed typo
* docs: more info about python version used to generate requirements.txt file
* docs: added BeautifulSoup requirements
* feat: removed debug prints
* feat: added ibov_index_composition variable as a class attribute of IBOVIndex
* feat: added increment to generate the four month period used by the ibov index
* refactor: Added get_instruments() method inside utils.py for better code usability.
Message in the PR request to understand the context of the change
In the course of reviewing this PR we found two issues.
1. there are multiple places where the get_instruments() method is used,
and we feel that scripts.index.py is the best place for the
get_instruments() method to go.
2. data_collector.utils has some very generic stuff put inside it.
* refactor: improve brazils stocks download speed
The reason to use retry=2 is due to the fact that
Yahoo Finance unfortunately does not keep track of the majority
of Brazilian stocks.
Therefore, the decorator deco_retry with retry argument
set to 5 will keep trying to get the stock data 5 times,
which makes the code to download Brazilians stocks very slow.
In future, this may change, but for now
I suggest to leave retry argument to 1 or 2 in
order to improve download speed.
In order to achieve this code logic an argument called retry_config
was added into YahooCollectorBR1d and YahooCollectorBR1min
* fix: added __main__ at the bottom of the script
* refactor: changed interface inside each index
Using partial as `fire.Fire(partial(get_instruments, market_index="br_index" ))`
will make the interface easier for the user to execute the script.
Then all the collector.py CLI in each folder can remove a redundant arguments.
* refactor: implemented class interface retry into YahooCollectorBR
* docs: added BR as a possible region into the documentation
* refactor: make retry attribute part of the interface
This way we don't have to use hasattr to access the retry attribute as previously done
* Skip idx.is_lexsorted() when pandas version is larger than 1.3.0. The future warning is annoying.
* Skip idx.is_lexsorted() when pandas version is larger than 1.3.0. The future warning is annoying.
* Rewrite code.
* add period ops class
* black format
* add pit data read
* fix bug in period ops
* update ops runnable
* update PIT test example
* black format
* update PIT test
* update tets_PIT
* update code format
* add check_feature_exist
* black format
* optimize the PIT Algorithm
* fix bug
* update example
* update test_PIT name
* add pit collector
* black format
* fix bugs
* fix try
* fix bug & add dump_pit.py
* Successfully run and understand PIT
* Add some docs and remove a bug
* mv crypto collector
* black format
* Run succesfully after merging master
* Pass test and fix code
* remove useless PIT code
* fix PYlint
* Rename
Co-authored-by: Young <afe.young@gmail.com>
* change weight_decay & batchsize
* del weight_decay
* big weight_decay
* mid weight_decay
* small layer
* 2 layer
* full layer
* no weight decay
* divide into two data source
* change parse field
* delete some debug
* add Toperator
* new format of arctic
* fix cache bug to arctic read
* fix connection problem
* add some operator
* final version for arcitc
* clear HZ cache
* remove not used function
* add topswrappers
* successfully import data and run first test
* A simpler version to support arctic
* Successfully run all high-freq expressions
* Black format and fix add docs
* Add docs for download and test data
* update scripts and docs
* Add docs
* fix bug
* Refine docs
* fix test bug
* fix CI error
* clean code
Co-authored-by: bxdd <bxddream@gmail.com>
Co-authored-by: wangwenxi.handsome <wangwenxi.handsome@gmail.com>
Co-authored-by: Young <afe.young@gmail.com>
* Merge data selection to main
* Update trainer for reweighter
* Typos fixed.
* update data selection interface
* successfully run exp after refactor some interface
* data selection share handler & trainer
* fix meta model time series bug
* fix online workflow set_uri bug
* fix set_uri bug
* updawte ds docs and delay trainer bug
* docs
* resume reweighter
* add reweighting result
* fix qlib model import
* make recorder more friendly
* fix experiment workflow bug
* commit for merging master incase of conflictions
* Successful run DDG-DA with a single command
* remove unused code
* asdd more docs
* Update README.md
* Update & fix some bugs.
* Update configuration & remove debug functions
* Update README.md
* Modfify horizon from code rather than yaml
* Update performance in README.md
* fix part comments
* Remove unfinished TCTS.
* Fix some details.
* Update meta docs
* Update README.md of the benchmarks_dynamic
* Update README.md files
* Add README.md to the rolling_benchmark baseline.
* Refine the docs and link
* Rename README.md in benchmarks_dynamic.
* Remove comments.
* auto download data
Co-authored-by: wendili-cs <wendili.academic@qq.com>
Co-authored-by: demon143 <785696300@qq.com>
* Fix $volume normalization issue
Fix: https://github.com/microsoft/qlib/issues/765
* black formatting
black formatting
* black formatting
black formatting
* black formatting
black formatting
* Fix high-freq data name from `yahoo_cn_1min` to `cn_data_1min`
* re-format example data names using `qlib_{region}_{feq}`, e.g. qlib_cn_1d
* re-format example data names using `{region}_{feq}`, e.g. us_1d and cn_1min
* keep using for 1day data, and change 1min data to
* solve VERSION.txt bug
* back to main version
* change setup and init to follow pypi type
* add read function
* solve black format
Co-authored-by: DefangCui <170007807@pku.edu.cn>
* modify FileStorage to support multiple freqs
* modify backtest's sample documentation
* change the logging level of read data exception from error to debug
* fix the backtest exception when volume is 0 or np.nan
* fix test_storage.py
* add backtest_daily
* modify backtest_daily's docstring
* add __repr__/__str__ to Position
* fix the bug of nested_decision_execution example
Co-authored-by: Young <afe.young@gmail.com>
Co-authored-by: you-n-g <you-n-g@users.noreply.github.com>
* handler demo cache
* Update data_cache_demo.py
* example to reusing processed data in memory
* Skip dumping task of task_train
* FIX Black
Co-authored-by: Wangwuyi123 <51237097+Wangwuyi123@users.noreply.github.com>
* replace multi processing with joblib
* update class Parallel and data.py
* update class Parallel and data.py
* update class Parallel and data.py
* update class Parallel and data.py
* update class Parallel and data.py
* update class Parallel and data.py
* update class Parallel and data.py
* update class Parallel and data.py
* Fix Parallel support for maxtasksperchild
Co-authored-by: wangw <1666490690@qq.com>
Co-authored-by: zhupr <zhu.pengrong@foxmail.com>
* updated readme of yahoo collector where region parameter was incorrect
* changes
update readme of yahoo collector where region parameter was incorrect
* update readme of yahoo collector
update readme of yahoo collector where region parameter was incorrect
* updated changes
* updated readme of cn1d data
Co-authored-by: Gaurav Chauhan01/HO/Analytics/General <Gaurav.Chauhan01@bajajallianz.in>
remove 空格 before module_path, kwargs, etc, otherwise, yaml parser will report error: ruamel.yaml.scanner.ScannerError: mapping values are not allowed here
<!--- minor update (introduces new functionality): `feat` -->
<!--- Example: feature(parser): add ability to parse arrays -->
<!--- major update(destructive update): Include BREAKING CHANGE in the commit message footer, or add `! ` in the commit footer to indicate that there is a destructive update. -->
<!--- Example: feat(auth)! : remove support for old authentication method -->
echo"- ${tty_bold}Enter your password${tty_reset} to install to ${tty_underline}${HOMEBREW_PREFIX_DEFAULT}${tty_reset} (${tty_bold}recommended${tty_reset})"
echo"- ${tty_bold}Press Control-D${tty_reset} to install to ${tty_underline}$HOME/.linuxbrew${tty_reset}"
echo"- ${tty_bold}Press Control-C${tty_reset} to cancel installation"
# This workflows will upload a Python Package using Twine when a release is created
# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries
stale-issue-message:'This issue is stale because it has been open for three months with no activity. Remove the stale label or comment on the issue otherwise this will be closed in 5 days'
stale-pr-message:'This PR is stale because it has been open for a year with no activity. Remove the stale label or comment on the PR otherwise this will be closed in 5 days'
- Support ``backtest`` configuration parameters in the configuration file
@@ -65,24 +65,24 @@ Version 0.3.2
- Fix bug of ``filter`` module
Version 0.3.3
-------------------
-------------
- Fix bug of ``filter`` module
Version 0.3.4
--------------------
-------------
- Support for ``finetune model``
- Refactor ``fetcher`` code
Version 0.3.5
--------------------
-------------
- Support multi-label training, you can provide multiple label in ``handler``. (But LightGBM doesn't support due to the algorithm itself)
- Refactor ``handler`` code, dataset.py is no longer used, and you can deploy your own labels and features in ``feature_label_config``
- Handler only offer DataFrame. Also, ``trainer`` and model.py only receive DataFrame
- Change ``split_rolling_data``, we roll the data on market calender now, not on normal date
- Change ``split_rolling_data``, we roll the data on market calendar now, not on normal date
- Move some date config from ``handler`` to ``trainer``
Version 0.4.0
--------------------
-------------
- Add `data` package that holds all data-related codes
- Reform the data provider structure
- Create a server for data centralized management `qlib-server <https://amc-msra.visualstudio.com/trading-algo/_git/qlib-server>`_
@@ -100,7 +100,7 @@ Version 0.4.0
Version 0.4.1
--------------------
-------------
- Add support Windows
- Fix ``instruments`` type bug
- Fix ``features`` is empty bug(It will cause failure in updating)
@@ -112,19 +112,19 @@ Version 0.4.1
Version 0.4.2
--------------------
-------------
- Refactor DataHandler
- Add ``ALPHA360`` DataHandler
- Add ``Alpha360`` DataHandler
Version 0.4.3
--------------------
-------------
- Implementing Online Inference and Trading Framework
- Refactoring The interfaces of backtest and strategy module.
Version 0.4.4
--------------------
-------------
- Optimize cache generation performance
- Add report module
- Fix bug when using ``ServerDatasetCache`` offline.
@@ -138,7 +138,7 @@ Version 0.4.4
Version 0.4.5
--------------------
-------------
- Add multi-kernel implementation for both client and server.
- Support a new way to load data from client which skips dataset cache.
- Change the default dataset method from single kernel implementation to multi kernel implementation.
@@ -146,19 +146,34 @@ Version 0.4.5
- Support a new method to write config file by using dict.
Version 0.4.6
--------------------
-------------
- Some bugs are fixed
- The default config in `Version 0.4.5` is not friendly to daily frequency data.
- Backtest error in TopkWeightStrategy when `WithInteract=True`.
Version 0.5.0
--------------------
-------------
- First opensource version
- Refine the docs, code
- Add baselines
- public data crawler
Version greater than Version 0.5.0
----------------------------------
Version 0.8.0
-------------
- The backtest is greatly refactored.
- Nested decision execution framework is supported
- There are lots of changes for daily trading, it is hard to list all of them. But a few important changes could be noticed
- The trading limitation is more accurate;
- In `previous version <https://github.com/microsoft/qlib/blob/v0.7.2/qlib/contrib/backtest/exchange.py#L160>`__, longing and shorting actions share the same action.
- In `current version <https://github.com/microsoft/qlib/blob/7c31012b507a3823117bddcc693fc64899460b2a/qlib/backtest/exchange.py#L304>`__, the trading limitation is different between logging and shorting action.
- The constant is different when calculating annualized metrics.
- `Current version <https://github.com/microsoft/qlib/blob/7c31012b507a3823117bddcc693fc64899460b2a/qlib/contrib/evaluate.py#L42>`_ uses more accurate constant than `previous version <https://github.com/microsoft/qlib/blob/v0.7.2/qlib/contrib/evaluate.py#L22>`__
- `A new version <https://github.com/microsoft/qlib/blob/7c31012b507a3823117bddcc693fc64899460b2a/qlib/tests/data.py#L17>`__ of data is released. Due to the unstability of Yahoo data source, the data may be different after downloading data again.
- Users could check out the backtesting results between `Current version <https://github.com/microsoft/qlib/tree/7c31012b507a3823117bddcc693fc64899460b2a/examples/benchmarks>`__ and `previous version <https://github.com/microsoft/qlib/tree/v0.7.2/examples/benchmarks>`__
Other Versions
--------------
Please refer to `Github release Notes <https://github.com/microsoft/qlib/releases>`_
[](https://gitter.im/Microsoft/qlib?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
We are excited to announce the release of **RD-Agent**📢, a powerful tool that supports automated factor mining and model optimization in quant investment R&D.
RD-Agent is now available on [GitHub](https://github.com/microsoft/RD-Agent), and we welcome your star🌟!
To learn more, please visit the [RD-Agent repository](https://github.com/microsoft/RD-Agent). We have prepared several public demo videos for you:
| Scenario | Demo video (English) | Demo video (中文) |
| Ibovespa index data | :rice: [Released](https://github.com/microsoft/qlib/pull/990) on Apr 6, 2022 |
| Point-in-Time database | :hammer: [Released](https://github.com/microsoft/qlib/pull/343) on Mar 10, 2022 |
| Arctic Provider Backend & Orderbook data example | :hammer: [Released](https://github.com/microsoft/qlib/pull/744) on Jan 17, 2022 |
| Meta-Learning-based framework & DDG-DA | :chart_with_upwards_trend: :hammer: [Released](https://github.com/microsoft/qlib/pull/743) on Jan 10, 2022 |
| Planning-based portfolio optimization | :hammer: [Released](https://github.com/microsoft/qlib/pull/754) on Dec 28, 2021 |
| Release Qlib v0.8.0 | :octocat: [Released](https://github.com/microsoft/qlib/releases/tag/v0.8.0) on Dec 8, 2021 |
| ADD model | :chart_with_upwards_trend: [Released](https://github.com/microsoft/qlib/pull/704) on Nov 22, 2021 |
| ADARNN model | :chart_with_upwards_trend: [Released](https://github.com/microsoft/qlib/pull/689) on Nov 14, 2021 |
| TCN model | :chart_with_upwards_trend: [Released](https://github.com/microsoft/qlib/pull/668) on Nov 4, 2021 |
| Nested Decision Framework | :hammer: [Released](https://github.com/microsoft/qlib/pull/438) on Oct 1, 2021. [Example](https://github.com/microsoft/qlib/blob/main/examples/nested_decision_execution/workflow.py) and [Doc](https://qlib.readthedocs.io/en/latest/component/highfreq.html) |
| Temporal Routing Adaptor (TRA) | :chart_with_upwards_trend: [Released](https://github.com/microsoft/qlib/pull/531) on July 30, 2021 |
| Transformer & Localformer | :chart_with_upwards_trend: [Released](https://github.com/microsoft/qlib/pull/508) on July 22, 2021 |
| Release Qlib v0.7.0 | :octocat: [Released](https://github.com/microsoft/qlib/releases/tag/v0.7.0) on July 12, 2021 |
| TCTS Model | :chart_with_upwards_trend: [Released](https://github.com/microsoft/qlib/pull/491) on July 1, 2021 |
| Online serving and automatic model rolling | :hammer: [Released](https://github.com/microsoft/qlib/pull/290) on May 17, 2021 |
| DoubleEnsemble Model | :chart_with_upwards_trend: [Released](https://github.com/microsoft/qlib/pull/286) on Mar 2, 2021 |
| High-frequency data processing example | :hammer: [Released](https://github.com/microsoft/qlib/pull/257) on Feb 5, 2021 |
| High-frequency trading example | :chart_with_upwards_trend: [Part of code released](https://github.com/microsoft/qlib/pull/227) on Jan 28, 2021 |
| High-frequency data(1min) | :rice: [Released](https://github.com/microsoft/qlib/pull/221) on Jan 27, 2021 |
| Tabnet Model | :chart_with_upwards_trend: [Released](https://github.com/microsoft/qlib/pull/205) on Jan 22, 2021 |
Features released before 2021 are not listed here.
Qlib is an open-source, AI-oriented quantitative investment platform that aims to realize the potential, empower research, and create value using AI technologies in quantitative investment, from exploring ideas to implementing productions. Qlib supports diverse machine learning modeling paradigms, including supervised learning, market dynamics modeling, and reinforcement learning.
Qlib is an AI-oriented quantitative investment platform, which aims to realize the potential, empower the research, and create the value of AI technologies in quantitative investment.
With Qlib, you can easily try your ideas to create better Quant investment strategies.
An increasing number of SOTA Quant research works/papers in diverse paradigms are being released in Qlib to collaboratively solve key challenges in quantitative investment. For example, 1) using supervised learning to mine the market's complex non-linear patterns from rich and heterogeneous financial data, 2) modeling the dynamic nature of the financial market using adaptive concept drift technology, and 3) using reinforcement learning to model continuous investment decisions and assist investors in optimizing their trading strategies.
It contains the full ML pipeline of data processing, model training, back-testing; and covers the entire chain of quantitative investment: alpha seeking, risk modeling, portfolio optimization, and order execution.
For more details, please refer to our paper ["Qlib: An AI-oriented Quantitative Investment Platform"](https://arxiv.org/abs/2009.11189).
- [Framework of Qlib](#framework-of-qlib)
- [Quick Start](#quick-start)
- [Installation](#installation)
- [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 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)
- [Contributing](#contributing)
<table>
<tbody>
<tr>
<th>Frameworks, Tutorial, Data & DevOps</th>
<th>Main Challenges & Solutions in Quant Research</th>
The high-level framework of Qlib can be found above(users can find the [detailed framework](https://qlib.readthedocs.io/en/latest/introduction/introduction.html#framework) of Qlib's design when getting into nitty gritty).
The components are designed as loose-coupled modules, and each component could be used stand-alone.
At the module level, Qlib is a platform that consists of the above components. The components are designed as loose-coupled modules and each component could be used stand-alone.
| Name | Description |
| ------ | ----- |
| `Data layer` | `DataServer` focuses on providing high-performance infrastructure for users to manage and retrieve raw data. `DataEnhancement` will preprocess the data and provide the best dataset to be fed into the models. |
| `Interday Model` | `Interday model` focuses on producing prediction scores (aka. _alpha_). Models are trained by `Model Creator` and managed by `Model Manager`. Users could choose one or multiple models for prediction. Multiple models could be combined with `Ensemble` module. |
| `Interday Strategy` | `Portfolio Generator` will take prediction scores as input and output the orders based on the current position to achieve the target portfolio. |
| `Intraday Trading` | `Order Executor` is responsible for executing orders output by `Interday Strategy` and returning the executed results. |
| `Analysis` | Users could get a detailed analysis report of forecasting signals and portfolios in this part. |
* The modules with hand-drawn style are under development and will be released in the future.
* The modules with dashed borders are highly user-customizable and extendible.
Qlib provides a strong infrastructure to support Quant research. [Data](https://qlib.readthedocs.io/en/latest/component/data.html) is always an important part.
A strong learning framework is designed to support diverse learning paradigms (e.g. [reinforcement learning](https://qlib.readthedocs.io/en/latest/component/rl.html), [supervised learning](https://qlib.readthedocs.io/en/latest/component/workflow.html#model-section)) and patterns at different levels(e.g. [market dynamic modeling](https://qlib.readthedocs.io/en/latest/component/meta.html)).
By modeling the market, [trading strategies](https://qlib.readthedocs.io/en/latest/component/strategy.html) will generate trade decisions that will be executed. Multiple trading strategies and executors in different levels or granularities can be [nested to be optimized and run together](https://qlib.readthedocs.io/en/latest/component/highfreq.html).
At last, a comprehensive [analysis](https://qlib.readthedocs.io/en/latest/component/report.html) will be provided and the model can be [served online](https://qlib.readthedocs.io/en/latest/component/online.html) in a low cost.
# Quick Start
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
This table demonstrates the supported Python version of `Qlib`:
| | install with pip | install from source | plot |
1. **Conda** is suggested for managing your Python environment. In some cases, using Python outside of a `conda` environment may result in missing header files, causing the installation failure of certain packages.
2. 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.8 or higher, or use `conda`'s Python to install ``Qlib`` from source.
### Install with pip
Users can easily install ``Qlib`` by pip according to the following command.
```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.
### Install from source
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:
@@ -77,25 +198,96 @@ Also, Users can install ``Qlib`` by the source code according to the following s
pip install --upgrade cython
```
* Clone the repository and install ``Qlib``:
* Clone the repository and install ``Qlib`` as follows.
```bash
git clone https://github.com/microsoft/qlib.git && cd qlib
python setup.py install
pip install . # `pip install -e .[dev]` is recommended for development. check details in docs/developer/code_standard_and_dev_guide.rst
```
**Tips**: If you fail to install `Qlib` or run the examples in your environment, comparing your steps and the [CI workflow](.github/workflows/test_qlib_from_source.yml) may help you find the problem.
**Tips for Mac**: If you are using Mac with M1, you might encounter issues in building the wheel for LightGBM, which is due to missing dependencies from OpenMP. To solve the problem, install openmp first with ``brew install libomp`` and then run ``pip install .`` to build it successfully.
## Data Preparation
Load and prepare data by running the following code:
❗ Due to more restrict data security policy. The official dataset is disabled temporarily. You can try [this data source](https://github.com/chenditc/investment_data/releases) contributed by the community.
This dataset is created by public data collected by [crawler scripts](scripts/data_collector/), which have been released in
the same repository.
Users could create the same dataset with it.
Users could create the same dataset with it. [Description of dataset](https://github.com/microsoft/qlib/tree/main/scripts/data_collector#description-of-dataset)
*Please pay **ATTENTION** that the data is collected from [Yahoo Finance](https://finance.yahoo.com/lookup) and the data might not be perfect. We recommend users to prepare their own data if they have high-quality dataset. For more information, users can refer to the [related document](https://qlib.readthedocs.io/en/latest/component/data.html#converting-csv-format-into-qlib-format)*.
*Please pay **ATTENTION** that the data is collected from [Yahoo Finance](https://finance.yahoo.com/lookup), and the data might not be perfect.
We recommend users to prepare their own data if they have a high-quality dataset. For more information, users can refer to the [related document](https://qlib.readthedocs.io/en/latest/component/data.html#converting-csv-format-into-qlib-format)*.
### Automatic update of daily frequency data (from yahoo finance)
> This step is *Optional* if users only want to try their models and strategies on history data.
>
> It is recommended that users update the data manually once (--trading_date 2021-05-25) and then set it to update automatically.
>
> **NOTE**: Users can't incrementally update data based on the offline data provided by Qlib(some fields are removed to reduce the data size). Users should use [yahoo collector](https://github.com/microsoft/qlib/tree/main/scripts/data_collector/yahoo#automatic-update-of-daily-frequency-datafrom-yahoo-finance) to download Yahoo data from scratch and then incrementally update it.
>
> For more information, please refer to: [yahoo collector](https://github.com/microsoft/qlib/tree/main/scripts/data_collector/yahoo#automatic-update-of-daily-frequency-datafrom-yahoo-finance)
* Automatic update of data to the "qlib" directory each trading day(Linux)
* If you want more information about `check_data_health`, please refer to the [documentation](https://qlib.readthedocs.io/en/latest/component/data.html#checking-the-health-of-the-data).
<!--
- Run the initialization code and get stock data:
@@ -103,7 +295,7 @@ Users could create the same dataset with it.
@@ -124,51 +316,87 @@ Users could create the same dataset with it.
```
-->
## Auto Quant Research Workflow
Qlib provides a tool named `Estimator` 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:
## Docker images
1. Pulling a docker image from a docker hub repository
```bash
docker pull pyqlib/qlib_image_stable:stable
```
2. Start a new Docker container
```bash
docker run -it --name <container name> -v <Mounted local directory>:/app pyqlib/qlib_image_stable:stable
```
3. At this point you are in the docker environment and can run the qlib scripts. An example:
8. If you want to know more information, please refer to the [documentation](https://qlib.readthedocs.io/en/latest/developer/how_to_build_image.html).
1. Quant Research Workflow: Run `Estimator` with [estimator_config.yaml](examples/estimator/estimator_config.yaml) as following. (*Please note that this may **not work** under MacOS with Python 3.8 due to the incompatibility of the `sacred` package we use with Python 3.8. We will fix this bug in the future.*)
## 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_Alpha158.yaml](examples/benchmarks/LightGBM/workflow_config_lightgbm_Alpha158.yaml) as following.
```bash
cd examples # Avoid running program under the directory contains `qlib`
The result of `Estimator` 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.
If users want to use `qrun` under debug mode, please use the following command:
The result of `qrun` is as follows, please refer to [docs](https://qlib.readthedocs.io/en/latest/component/strategy.html#result) for more explanations about the result.
```bash
'The following are analysis results of the excess return without cost.'
risk
excess_return_without_cost mean 0.000675
std 0.005456
annualized_return 0.170077
information_ratio 1.963824
max_drawdown -0.063646
excess_return_with_cost mean 0.000479
std 0.005453
annualized_return 0.120776
information_ratio 1.395116
max_drawdown -0.071216
mean 0.000708
std 0.005626
annualized_return 0.178316
information_ratio 1.996555
max_drawdown -0.081806
'The following are analysis results of the excessreturnwithcost.'
risk
mean0.000512
std0.005626
annualized_return 0.128982
information_ratio 1.444287
max_drawdown -0.091078
```
Here are detailed documents for [Estimator](https://qlib.readthedocs.io/en/latest/component/estimator.html).
Here are detailed documents for `qrun` and [workflow](https://qlib.readthedocs.io/en/latest/component/workflow.html).
2. Graphical Reports Analysis: Run `examples/estimator/analyze_from_estimator.ipynb` with `jupyter notebook` to get graphical reports
2. Graphical Reports Analysis: First, run `python -m pip install .[analysis]` to install the required dependencies. Then run `examples/workflow_by_code.ipynb` with `jupyter notebook` to get graphical reports.
@@ -179,28 +407,128 @@ Qlib provides a tool named `Estimator` to run the whole workflow automatically (
- Rank Label

-->
- [Explanation](https://qlib.readthedocs.io/en/latest/component/report.html) of above results
## Building Customized Quant Research Workflow by Code
The automatic workflow may not suite the research workflow of all Quant researchers. To support a flexible Quant research workflow, Qlib also provides a modularized interface to allow researchers to build their own workflow by code. [Here](examples/train_backtest_analyze.ipynb) is a demo for customized Quant research workflow by code
The automatic workflow may not suit the research workflow of all Quant researchers. To support a flexible Quant research workflow, Qlib also provides a modularized interface to allow researchers to build their own workflow by code. [Here](examples/workflow_by_code.ipynb) is a demo for customized Quant research workflow by code.
# Main Challenges & Solutions in Quant Research
Quant investment is a very unique scenario with lots of key challenges to be solved.
Currently, Qlib provides some solutions for several of them.
## Forecasting: Finding Valuable Signals/Patterns
Accurate forecasting of the stock price trend is a very important part to construct profitable portfolios.
However, huge amount of data with various formats in the financial market which make it challenging to build forecasting models.
An increasing number of SOTA Quant research works/papers, which focus on building forecasting models to mine valuable signals/patterns in complex financial data, are released in `Qlib`
#Quant Model Zoo
### [Quant Model (Paper) Zoo](examples/benchmarks)
Here is a list of models build on `Qlib`.
- [GBDT based on lightgbm](qlib/contrib/model/gbdt.py)
- [MLP based on pytroch](qlib/contrib/model/pytorch_nn.py)
Here is a list of models built on `Qlib`.
- [GBDT based on XGBoost (Tianqi Chen, et al. KDD 2016)](examples/benchmarks/XGBoost/)
- [GBDT based on LightGBM (Guolin Ke, et al. NIPS 2017)](examples/benchmarks/LightGBM/)
- [GBDT based on Catboost (Liudmila Prokhorenkova, et al. NIPS 2018)](examples/benchmarks/CatBoost/)
- [MLP based on pytorch](examples/benchmarks/MLP/)
- [LSTM based on pytorch (Sepp Hochreiter, et al. Neural computation 1997)](examples/benchmarks/LSTM/)
- [GRU based on pytorch (Kyunghyun Cho, et al. 2014)](examples/benchmarks/GRU/)
- [ALSTM based on pytorch (Yao Qin, et al. IJCAI 2017)](examples/benchmarks/ALSTM)
- [GATs based on pytorch (Petar Velickovic, et al. 2017)](examples/benchmarks/GATs/)
- [SFM based on pytorch (Liheng Zhang, et al. KDD 2017)](examples/benchmarks/SFM/)
- [TFT based on tensorflow (Bryan Lim, et al. International Journal of Forecasting 2019)](examples/benchmarks/TFT/)
- [TabNet based on pytorch (Sercan O. Arik, et al. AAAI 2019)](examples/benchmarks/TabNet/)
- [DoubleEnsemble based on LightGBM (Chuheng Zhang, et al. ICDM 2020)](examples/benchmarks/DoubleEnsemble/)
- [TCTS based on pytorch (Xueqing Wu, et al. ICML 2021)](examples/benchmarks/TCTS/)
- [Transformer based on pytorch (Ashish Vaswani, et al. NeurIPS 2017)](examples/benchmarks/Transformer/)
- [Localformer based on pytorch (Juyong Jiang, et al.)](examples/benchmarks/Localformer/)
- [TRA based on pytorch (Hengxu, Dong, et al. KDD 2021)](examples/benchmarks/TRA/)
- [TCN based on pytorch (Shaojie Bai, et al. 2018)](examples/benchmarks/TCN/)
- [ADARNN based on pytorch (YunTao Du, et al. 2021)](examples/benchmarks/ADARNN/)
- [ADD based on pytorch (Hongshun Tang, et al.2020)](examples/benchmarks/ADD/)
- [IGMTF based on pytorch (Wentao Xu, et al.2021)](examples/benchmarks/IGMTF/)
- [HIST based on pytorch (Wentao Xu, et al.2021)](examples/benchmarks/HIST/)
- [KRNN based on pytorch](examples/benchmarks/KRNN/)
- [Sandwich based on pytorch](examples/benchmarks/Sandwich/)
Your PR of new Quant models is highly welcomed.
# Quant Dataset Zoo
Dataset plays a very important role in Quant. Here is a list of the datasets build on `Qlib`.
- [Alpha360](./qlib/contrib/estimator/handler.py)
- [Alpha158](./qlib/contrib/estimator/handler.py)
The performance of each model on the `Alpha158` and `Alpha360` datasets can be found [here](examples/benchmarks/README.md).
Here is a tutorial to build dataset with `Qlib`.
### Run a single model
All the models listed above are runnable with ``Qlib``. Users can find the config files we provide and some details about the model through the [benchmarks](examples/benchmarks) folder. More information can be retrieved at the model files listed above.
`Qlib` provides three different ways to run a single model, users can pick the one that fits their cases best:
- Users can use the tool `qrun` mentioned above to run a model's workflow based from a config file.
- Users can create a `workflow_by_code` python script based on the [one](examples/workflow_by_code.py) listed in the `examples` folder.
- Users can use the script [`run_all_model.py`](examples/run_all_model.py) listed in the `examples` folder to run a model. Here is an example of the specific shell command to be used: `python run_all_model.py run --models=lightgbm`, where the `--models` arguments can take any number of models listed above(the available models can be found in [benchmarks](examples/benchmarks/)). For more use cases, please refer to the file's [docstrings](examples/run_all_model.py).
- **NOTE**: Each baseline has different environment dependencies, please make sure that your python version aligns with the requirements(e.g. TFT only supports Python 3.6~3.7 due to the limitation of `tensorflow==1.15.0`)
### 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 support *Linux* for now. Other OS will be supported in the future. Besides, it doesn't support parallel running the same model for multiple times as well, and this will be fixed in the future development too.)
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
python run_all_model.py run 10
```
It also provides the API to run specific models at once. For more use cases, please refer to the file's [docstrings](examples/run_all_model.py).
### Break change
In `pandas`, `group_key` is one of the parameters of the `groupby` method. From version 1.5 to 2.0 of `pandas`, the default value of `group_key` has been changed from `no default` to `True`, which will cause qlib to report an error during operation. So we set `group_key=False`, but it doesn't guarantee that some programmes will run correctly, including:
## [Adapting to Market Dynamics](examples/benchmarks_dynamic)
Due to the non-stationary nature of the environment of the financial market, the data distribution may change in different periods, which makes the performance of models build on training data decays in the future test data.
So adapting the forecasting models/strategies to market dynamics is very important to the model/strategies' performance.
Qlib now supports reinforcement learning, a feature designed to model continuous investment decisions. This functionality assists investors in optimizing their trading strategies by learning from interactions with the environment to maximize some notion of cumulative reward.
Here is a list of solutions built on `Qlib` categorized by scenarios.
### [RL for order execution](examples/rl_order_execution)
[Here](https://qlib.readthedocs.io/en/latest/component/rl/overall.html#order-execution) is the introduction of this scenario. All the methods below are compared [here](examples/rl_order_execution).
- [PPO: "An End-to-End Optimal Trade Execution Framework based on Proximal Policy Optimization", IJCAL 2020](examples/rl_order_execution/exp_configs/backtest_ppo.yml)
- [OPDS: "Universal Trading for Order Execution with Oracle Policy Distillation", AAAI 2021](examples/rl_order_execution/exp_configs/backtest_opds.yml)
# Quant Dataset Zoo
Dataset plays a very important role in Quant. Here is a list of the datasets built on `Qlib`:
[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.
# Learning Framework
Qlib is high customizable and a lot of its components are learnable.
The learnable components are instances of `Forecast Model` and `Trading Agent`. They are learned based on the `Learning Framework` layer and then applied to multiple scenarios in `Workflow` layer.
The learning framework leverages the `Workflow` layer as well(e.g. sharing `Information Extractor`, creating environments based on `Execution Env`).
Based on learning paradigms, they can be categorized into reinforcement learning and supervised learning.
- For supervised learning, the detailed docs can be found [here](https://qlib.readthedocs.io/en/latest/component/model.html).
- For reinforcement learning, the detailed docs can be found [here](https://qlib.readthedocs.io/en/latest/component/rl.html). Qlib's RL learning framework leverages `Execution Env` in `Workflow` layer to create environments. It's worth noting that `NestedExecutor` is supported as well. This empowers users to optimize different level of strategies/models/agents together (e.g. optimizing an order execution strategy for a specific portfolio management strategy).
# More About Qlib
If you want to have a quick glance at the most frequently used components of qlib, you can try notebooks [here](examples/tutorial/).
The detailed documents are organized in [docs](docs/).
[Sphinx](http://www.sphinx-doc.org) and the readthedocs theme is required to build the documentation in html formats.
```bash
@@ -237,17 +565,62 @@ which creates a dataset (14 features/factors) from the basic OHLCV daily data of
* `+(-)E` indicates with (out) `ExpressionCache`
* `+(-)D` indicates with (out) `DatasetCache`
Most general-purpose databases take too much time on loading data. After looking into the underlying implementation, we find that data go through too many layers of interfaces and unnecessary format transformations in general-purpose database solutions.
Most general-purpose databases take too much time to load data. After looking into the underlying implementation, we find that data go through too many layers of interfaces and unnecessary format transformations in general-purpose database solutions.
Such overheads greatly slow down the data loading process.
Qlib data are stored in a compact format, which is efficient to be combined into arrays for scientific computation.
# Related Reports
- [Guide To Qlib: Microsoft’s AI Investment Platform](https://analyticsindiamag.com/qlib/)
- If you have any issues, please create issue [here](https://github.com/microsoft/qlib/issues/new/choose) or send messages in [gitter](https://gitter.im/Microsoft/qlib).
- If you want to make contributions to `Qlib`, please [create pull requests](https://github.com/microsoft/qlib/compare).
- For other reasons, you are welcome to contact us by email([qlib@microsoft.com](mailto:qlib@microsoft.com)).
- We are recruiting new members(both FTEs and interns), your resumes are welcome!
This project welcomes contributions and suggestions. Most contributions require you to agree to a
Before we released Qlib as an open-source project on Github in Sep 2020, Qlib is an internal project in our group. Unfortunately, the internal commit history is not kept. A lot of members in our group have also contributed a lot to Qlib, which includes Ruihua Wang, Yinda Zhang, Haisu Yu, Shuyu Wang, Bochen Pang, and [Dong Zhou](https://github.com/evanzd/evanzd). Especially thanks to [Dong Zhou](https://github.com/evanzd/evanzd) due to his initial version of Qlib.
## Guidance
This project welcomes contributions and suggestions.
**Here are some
[code standards and development guidance](docs/developer/code_standard_and_dev_guide.rst) for submiting a pull request.**
Making contributions is not a hard thing. Solving an issue(maybe just answering a question raised in [issues list](https://github.com/microsoft/qlib/issues) or [gitter](https://gitter.im/Microsoft/qlib)), fixing/issuing a bug, improving the documents and even fixing a typo are important contributions to Qlib.
For example, if you want to contribute to Qlib's document/code, you can follow the steps in the figure below.
If you don't know how to start to contribute, you can refer to the following examples.
| Type | Examples |
| -- | -- |
| Solving issues | [Answer a question](https://github.com/microsoft/qlib/issues/749); [issuing](https://github.com/microsoft/qlib/issues/765) or [fixing](https://github.com/microsoft/qlib/pull/792) a bug |
| Feature | Implement a [requested feature](https://github.com/microsoft/qlib/projects) like [this](https://github.com/microsoft/qlib/pull/754); [Refactor interfaces](https://github.com/microsoft/qlib/pull/539/files) |
| Dataset | [Add a dataset](https://github.com/microsoft/qlib/pull/733) |
| Models | [Implement a new model](https://github.com/microsoft/qlib/pull/689), [some instructions to contribute models](https://github.com/microsoft/qlib/tree/main/examples/benchmarks#contributing) |
[Good first issues](https://github.com/microsoft/qlib/labels/good%20first%20issue) are labelled to indicate that they are easy to start your contributions.
You can find some impefect implementation in Qlib by `rg 'TODO|FIXME' qlib`
If you would like to become one of Qlib's maintainers to contribute more (e.g. help merge PR, triage issues), please contact us by email([qlib@microsoft.com](mailto:qlib@microsoft.com)). We are glad to help to upgrade your permission.
## License
Most contributions require you to agree to a
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
the right to use your contribution. For details, visit https://cla.opensource.microsoft.com.
- If the error occurs when importing ``qlib`` package with ``PyCharm`` IDE, users can execute the following command in the project root folder to compile Cython files and generate executable files:
..code-block::bash
python setup.py build_ext --inplace
- If the error occurs when importing ``qlib`` package with command ``python`` , users need to change the running directory to ensure that the script does not run in the project directory.
4. BadNamespaceError: / is not a connected namespace
- The ``python-engineio`` version needs to be compatible with the ``python-socketio`` version, reference: https://github.com/miguelgrinberg/python-socketio#version-compatibility
Point-in-time data is a very important consideration when performing any sort of historical market analysis.
For example, let’s say we are backtesting a trading strategy and we are using the past five years of historical data as our input.
Our model is assumed to trade once a day, at the market close, and we’ll say we are calculating the trading signal for 1 January 2020 in our backtest. At that point, we should only have data for 1 January 2020, 31 December 2019, 30 December 2019 etc.
In financial data (especially financial reports), the same piece of data may be amended for multiple times overtime. If we only use the latest version for historical backtesting, data leakage will happen.
Point-in-time database is designed for solving this problem to make sure user get the right version of data at any historical timestamp. It will keep the performance of online trading and historical backtesting the same.
Data Preparation
----------------
Qlib provides a crawler to help users to download financial data and then a converter to dump the data in Qlib format.
Please follow `scripts/data_collector/pit/README.md <https://github.com/microsoft/qlib/tree/main/scripts/data_collector/pit/>`_ to download and convert data.
Besides, you can find some additional usage examples there.
File-based design for PIT data
------------------------------
Qlib provides a file-based storage for PIT data.
For each feature, it contains 4 columns, i.e. date, period, value, _next.
Each row corresponds to a statement.
The meaning of each feature with filename like `XXX_a.data`:
-`date`: the statement's date of publication.
-`period`: the period of the statement. (e.g. it will be quarterly frequency in most of the markets)
- If it is an annual period, it will be an integer corresponding to the year
- If it is an quarterly periods, it will be an integer like `<year><index of quarter>`. The last two decimal digits represents the index of quarter. Others represent the year.
-`value`: the described value
-`_next`: the byte index of the next occurance of the field.
Besides the feature data, an index `XXX_a.index` is included to speed up the querying performance
The statements are soted by the `date` in ascending order from the beginning of the file.
# The data format from XXXX.index. It consists of two parts
# 1) the start index of the data. So the first part of the info will be like
2007
# 2) the remain index data will be like information below
# - The data indicate the **byte index** of first data update of a period.
# - e.g. Because the info at both byte 80 and 100 corresponds to 200704. The byte index of first occurance (i.e. 100) is recorded in the data.
array([0,20,40,60,100,
120,140,160,180,200,
220,240,260,280,300,
320,340,360,380,400,
440,460,480,500,520,
540,560,580,600,620,
640,660,680,700,720,
740,760,780,800,820,
840,860,880,900,920,
940,960,980,1000,1020,
1060,4294967295],dtype=uint32)
Known limitations:
- Currently, the PIT database is designed for quarterly or annually factors, which can handle fundamental data of financial reports in most markets.
- Qlib leverage the file name to identify the type of the data. File with name like `XXX_q.data` corresponds to quarterly data. File with name like `XXX_a.data` corresponds to annual data.
- The caclulation of PIT is not performed in the optimal way. There is great potential to boost the performance of PIT data calcuation.
In quantitative trading practice, designing novel factors that can explain and predict future asset returns are of vital importance to the profitability of a strategy. Such factors are usually called alpha factors, or alphas in short.
@@ -14,12 +15,12 @@ A formulaic alpha, as the name suggests, is a kind of alpha that can be presente
Building Formulaic Alphas in ``Qlib``
======================================
=====================================
In ``Qlib``, users can easily build formulaic alphas.
Example
-----------------
-------
`MACD`, short for moving average convergence/divergence, is a formulaic alpha used in technical analysis of stock prices. It is designed to reveal changes in the strength, direction, momentum, and duration of a trend in a stock's price.
@@ -41,7 +42,7 @@ Example
..math::
DEA = \frac{EMA(DIF, 9)}{CLOSE}
DEA = EMA(DIF, 9)
Users can use ``Data Handler`` to build formulaic alphas `MACD` in qlib:
@@ -49,57 +50,37 @@ Users can use ``Data Handler`` to build formulaic alphas `MACD` in qlib:
``Qlib`` supports dumping the state of ``DataHandler``, ``DataSet``, ``Processor`` and ``Model``, etc. into a disk and reloading them.
Serializable Class
==================
``Qlib`` provides a base class ``qlib.utils.serial.Serializable``, whose state can be dumped into or loaded from disk in `pickle` format.
When users dump the state of a ``Serializable`` instance, the attributes of the instance whose name **does not** start with `_` will be saved on the disk.
However, users can use ``config`` method or override ``default_dump_all`` attribute to prevent this feature.
Users can also override ``pickle_backend`` attribute to choose a pickle backend. The supported value is "pickle" (default and common) and "dill" (dump more things such as function, more information in `here <https://pypi.org/project/dill/>`_).
Example
=======
``Qlib``'s serializable class includes ``DataHandler``, ``DataSet``, ``Processor`` and ``Model``, etc., which are subclass of ``qlib.utils.serial.Serializable``.
Specifically, ``qlib.data.dataset.DatasetH`` is one of them. Users can serialize ``DatasetH`` as follows.
..code-block::Python
##=============dump dataset=============
dataset.to_pickle(path="dataset.pkl")# dataset is an instance of qlib.data.dataset.DatasetH
##=============reload dataset=============
withopen("dataset.pkl","rb")asfile_dataset:
dataset=pickle.load(file_dataset)
..note::
Only state of ``DatasetH`` should be saved on the disk, such as some `mean` and `variance` used for data normalization, etc.
After reloading the ``DatasetH``, users need to reinitialize it. It means that users can reset some states of ``DatasetH`` or ``QlibDataHandler`` such as `instruments`, `start_time`, `end_time` and `segments`, etc., and generate new data according to the states (data is not state and should not be saved on the disk).
A more detailed example is in this `link <https://github.com/microsoft/qlib/tree/main/examples/highfreq>`_.
API
===
Please refer to `Serializable API <../reference/api.html#module-qlib.utils.serial.Serializable>`_.
``Qlib`` supports ``Online`` mode and ``Offline`` mode. Only the ``Offline`` mode is introduced in this document.
@@ -17,12 +18,12 @@ The ``Online`` mode is designed to solve the following problems:
- Make the data can be accessed in a remote way.
Qlib-Server
===============
===========
``Qlib-Server`` is the assorted server system for ``Qlib``, which utilizes ``Qlib`` for basic calculations and provides extensive server system and cache mechanism. With QLibServer, the data provided for ``Qlib`` can be managed in a centralized manner. With ``Qlib-Server``, users can use ``Qlib`` in ``Online`` mode.
Reference
=================
=========
If users are interested in ``Qlib-Server`` and ``Online`` mode, please refer to `Qlib-Server Project <https://github.com/microsoft/qlib-server>`_ and `Qlib-Server Document <https://qlib-server.readthedocs.io/en/latest/>`_.
The `Workflow <../component/introduction.html>`_ part introduces how to run research workflow in a loosely-coupled way. But it can only execute one ``task`` when you use ``qrun``.
To automatically generate and execute different tasks, ``Task Management`` provides a whole process including `Task Generating`_, `Task Storing`_, `Task Training`_ and `Task Collecting`_.
With this module, users can run their ``task`` automatically at different periods, in different losses, or even by different models.The processes of task generation, model training and combine and collect data are shown in the following figure.
Even though the task template is fixed, users can customize their ``TaskGen`` to generate different ``task`` by task template.
Here is the base class of ``TaskGen``:
..autoclass:: qlib.workflow.task.gen.TaskGen
:members:
:noindex:
``Qlib`` provides a class `RollingGen <https://github.com/microsoft/qlib/tree/main/qlib/workflow/task/gen.py>`_ to generate a list of ``task`` of the dataset in different date segments.
This class allows users to verify the effect of data from different periods on the model in one experiment. More information is `here <../reference/api.html#TaskGen>`__.
Task Storing
============
To achieve higher efficiency and the possibility of cluster operation, ``Task Manager`` will store all tasks in `MongoDB <https://www.mongodb.com/>`_.
``TaskManager`` can fetch undone tasks automatically and manage the lifecycle of a set of tasks with error handling.
Users **MUST** finish the configuration of `MongoDB <https://www.mongodb.com/>`_ when using this module.
Users need to provide the MongoDB URL and database name for using ``TaskManager`` in `initialization <../start/initialization.html#Parameters>`_ or make a statement like this.
..code-block::python
fromqlib.configimportC
C["mongo"]={
"task_url":"mongodb://localhost:27017/",# your MongoDB url
Meanwhile, ``Qlib`` provides a module called ``Trainer``.
..autoclass:: qlib.model.trainer.Trainer
:members:
:noindex:
``Trainer`` will train a list of tasks and return a list of model recorders.
``Qlib`` offer two kinds of Trainer, TrainerR is the simplest way and TrainerRM is based on TaskManager to help manager tasks lifecycle automatically.
If you do not want to use ``Task Manager`` to manage tasks, then use TrainerR to train a list of tasks generated by ``TaskGen`` is enough.
`Here <../reference/api.html#Trainer>`_ are the details about different ``Trainer``.
Task Collecting
===============
Before collecting model training results, you need to use the ``qlib.init`` to specify the path of mlruns.
To collect the results of ``task`` after training, ``Qlib`` provides `Collector <../reference/api.html#Collector>`_, `Group <../reference/api.html#Group>`_ and `Ensemble <../reference/api.html#Ensemble>`_ to collect the results in a readable, expandable and loosely-coupled way.
`Collector <../reference/api.html#Collector>`_ can collect objects from everywhere and process them such as merging, grouping, averaging and so on. It has 2 step action including ``collect`` (collect anything in a dict) and ``process_collect`` (process collected dict).
`Group <../reference/api.html#Group>`_ also has 2 steps including ``group`` (can group a set of object based on `group_func` and change them to a dict) and ``reduce`` (can make a dict become an ensemble based on some rule).
`Ensemble <../reference/api.html#Ensemble>`_ can merge the objects in an ensemble.
For example: {C1: object, C2: object} ---``Ensemble``---> object.
You can set the ensembles you want in the ``Collector``'s process_list.
Common ensembles include ``AverageEnsemble`` and ``RollingEnsemble``. Average ensemble is used to ensemble the results of different models in the same time period. Rollingensemble is used to ensemble the results of different models in the same time period
So the hierarchy is ``Collector``'s second step corresponds to ``Group``. And ``Group``'s second step correspond to ``Ensemble``.
For more information, please see `Collector <../reference/api.html#Collector>`_, `Group <../reference/api.html#Group>`_ and `Ensemble <../reference/api.html#Ensemble>`_, or the `example <https://github.com/microsoft/qlib/tree/main/examples/model_rolling/task_manager_rolling.py>`_.
``Intraday Trading`` is designed to test models and strategies, which help users to check the performance of a custom model/strategy.
..note::
``Intraday Trading`` uses ``Order Executor`` to trade and execute orders output by ``Interday Strategy``. ``Order Executor`` is a component in `Qlib Framework <../introduction/introduction.html#framework>`_, which can execute orders. ``Vwap Executor`` and ``Close Executor`` is supported by ``Qlib`` now. In the future, ``Qlib`` will support ``HighFreq Executor`` also.
Example
===========================
Users need to generate a `prediction score`(a pandas DataFrame) with MultiIndex<instrument, datetime> and a `score` column. And users need to assign a strategy used in backtest, if strategy is not assigned,
a `TopkDropoutStrategy` strategy with `(topk=50, n_drop=5, risk_degree=0.95, limit_threshold=0.0095)` will be used.
If ``Strategy`` module is not users' interested part, `TopkDropoutStrategy` is enough.
The simple example of the default strategy is as follows.
To know more about backtesting with a specific ``Strategy``, please refer to `Strategy <strategy.html>`_.
To know more about the prediction score `pred_score` output by ``Interday Model``, please refer to `Interday Model: Model Training & Prediction <model.html>`_.
Prediction Score
-----------------
The `prediction score` is a pandas DataFrame. Its index is <instrument(str), datetime(pd.Timestamp)> and it must
contains a `score` column.
A prediction sample is shown as follows.
..code-block::python
instrumentdatetimescore
SH6000002019-01-04-0.505488
SZ0025312019-01-04-0.320391
SZ0009992019-01-040.583808
SZ3005692019-01-040.819628
SZ0016962019-01-04-0.137140
......
SZ0009962019-04-30-1.027618
SH6031272019-04-300.225677
SH6031262019-04-300.462443
SH6031332019-04-30-0.302460
SZ3007602019-04-30-0.126383
``Interday Model`` module can make predictions, please refer to `Interday Model: Model Training & Prediction <model.html>`_.
Backtest Result
------------------
The backtest results are in the following form:
..code-block::python
risk
excess_return_without_costmean0.000605
std0.005481
annualized_return0.152373
information_ratio1.751319
max_drawdown-0.059055
excess_return_with_costmean0.000410
std0.005478
annualized_return0.103265
information_ratio1.187411
max_drawdown-0.075024
-`excess_return_without_cost`
- `mean`
Mean value of the `CAR` (cumulative abnormal return) without cost
- `std`
The `Standard Deviation` of `CAR` (cumulative abnormal return) without cost.
- `annualized_return`
The `Annualized Rate` of `CAR` (cumulative abnormal return) without cost.
- `information_ratio`
The `Information Ratio` without cost. please refer to `Information Ratio – IR <https://www.investopedia.com/terms/i/informationratio.asp>`_.
- `max_drawdown`
The `Maximum Drawdown` of `CAR` (cumulative abnormal return) without cost, please refer to `Maximum Drawdown (MDD) <https://www.investopedia.com/terms/m/maximum-drawdown-mdd.asp>`_.
-`excess_return_with_cost`
-`mean`
Mean value of the `CAR` (cumulative abnormal return) series with cost
-`std`
The `Standard Deviation` of `CAR` (cumulative abnormal return) series with cost.
-`annualized_return`
The `Annualized Rate` of `CAR` (cumulative abnormal return) with cost.
-`information_ratio`
The `Information Ratio` with cost. please refer to `Information Ratio – IR <https://www.investopedia.com/terms/i/informationratio.asp>`_.
-`max_drawdown`
The `Maximum Drawdown` of `CAR` (cumulative abnormal return) with cost, please refer to `Maximum Drawdown (MDD) <https://www.investopedia.com/terms/m/maximum-drawdown-mdd.asp>`_.
Reference
==============
To know more about ``Intraday Trading``, please refer to `Intraday Trading <../reference/api.html#module-qlib.contrib.evaluate>`_.
``Data Layer`` provides user-friendly APIs to manage and retrieve data. It provides high-performance data infrastructure.
@@ -14,93 +15,279 @@ The introduction of ``Data Layer`` includes the following parts.
- Data Preparation
- Data API
- Data Loader
- Data Handler
- Dataset
- Cache
- Data and Cache File Structure
Here is a typical example of Qlib data workflow
- Users download data and converting data into Qlib format(with filename suffix `.bin`). In this step, typically only some basic data are stored on disk(such as OHLCV).
- Creating some basic features based on Qlib's expression Engine(e.g. "Ref($close, 60) / $close", the return of last 60 trading days). Supported operators in the expression engine can be found `here <https://github.com/microsoft/qlib/blob/main/qlib/data/ops.py>`__. This step is typically implemented in Qlib's `Data Loader <https://qlib.readthedocs.io/en/latest/component/data.html#data-loader>`_ which is a component of `Data Handler <https://qlib.readthedocs.io/en/latest/component/data.html#data-handler>`_ .
- If users require more complicated data processing (e.g. data normalization), `Data Handler <https://qlib.readthedocs.io/en/latest/component/data.html#data-handler>`_ support user-customized processors to process data(some predefined processors can be found `here <https://github.com/microsoft/qlib/blob/main/qlib/data/dataset/processor.py>`__). The processors are different from operators in expression engine. It is designed for some complicated data processing methods which is hard to supported in operators in expression engine.
- At last, `Dataset <https://qlib.readthedocs.io/en/latest/component/data.html#dataset>`_ is responsible to prepare model-specific dataset from the processed data of Data Handler
Data Preparation
============================
================
Qlib Format Data
------------------
----------------
We've specially designed a data structure to manage financial data, please refer to the `File storage design section in Qlib paper <https://arxiv.org/abs/2009.11189>`_ for detailed information.
Such data will be stored with filename suffix `.bin` (We'll call them `.bin` file, `.bin` format, or qlib format). `.bin` file is designed for scientific computing on finance data
Such data will be stored with filename suffix `.bin` (We'll call them `.bin` file, `.bin` format, or qlib format). `.bin` file is designed for scientific computing on finance data.
``Qlib`` provides two different off-the-shelf datasets, which can be accessed through this `link <https://github.com/microsoft/qlib/blob/main/qlib/contrib/data/handler.py>`__:
Also, ``Qlib`` provides a high-frequency dataset. Users can run a high-frequency dataset example through this `link <https://github.com/microsoft/qlib/tree/main/examples/highfreq>`__.
Qlib Format Dataset
--------------------
``Qlib`` has provided an off-the-shelf dataset in `.bin` format, users could use the script ``scripts/get_data.py`` to download the dataset as follows.
-------------------
``Qlib`` has provided an off-the-shelf dataset in `.bin` format, users could use the script ``scripts/get_data.py`` to download the China-Stock dataset as follows. User can also use numpy to load `.bin` file to validate data.
The price volume data look different from the actual dealing price because of they are **adjusted** (`adjusted price <https://www.investopedia.com/terms/a/adjusted_closing_price.asp>`_). And then you may find that the adjusted price may be different from different data sources. This is because different data sources may vary in the way of adjusting prices. Qlib normalize the price on first trading day of each stock to 1 when adjusting them.
Users can leverage `$factor` to get the original trading price (e.g. `$close / $factor` to get the original close price).
Here are some discussions about the price adjusting of Qlib.
In addition to China-Stock data, ``Qlib`` also includes a US-Stock dataset, which can be downloaded with the following command:
..code-block::bash
python scripts/get_data.py qlib_data --target_dir ~/.qlib/qlib_data/us_data --region us
After running the above command, users can find china-stock and us-stock data in ``Qlib`` format in the ``~/.qlib/qlib_data/cn_data`` directory and ``~/.qlib/qlib_data/us_data`` directory respectively.
``Qlib`` also provides the scripts in ``scripts/data_collector`` to help users crawl the latest data on the Internet and convert it to qlib format.
When ``Qlib`` is initialized with this dataset, users could build and evaluate their own models with it. Please refer to `Initialization <../start/initialization.html>`_ for more details.
Converting CSV Format into Qlib Format
-------------------------------------------
Automatic update of daily frequency data
----------------------------------------
``Qlib`` has provided the script ``scripts/dump_bin.py`` to convert data in CSV format into `.bin` files (Qlib format).
**It is recommended that users update the data manually once (\-\-trading_date 2021-05-25) and then set it to update automatically.**
For more information refer to: `yahoo collector <https://github.com/microsoft/qlib/tree/main/scripts/data_collector/yahoo#Automatic-update-of-daily-frequency-data>`_
Users can download the china-stock data in CSV format as follows for reference to the CSV format.
- Automatic update of data to the "qlib" directory each trading day(Linux)
Supposed that users prepare their CSV format data in the directory ``~/.qlib/csv_data/my_data``, they can run the following command to start the conversion.
``Qlib`` has provided the script ``scripts/dump_bin.py`` to convert **any** data in CSV or Parquet format into `.bin` files (``Qlib`` format) as long as they are in the correct format.
Besides downloading the prepared demo data, users could download demo data directly from the Collector as follows for reference to the CSV format.
Supposed that users prepare their CSV or Parquet format data in the directory ``~/.qlib/my_data``, they can run the following command to start the conversion.
For other supported parameters when dumping the data into `.bin` file, users can refer to the information by running the following commands:
..code-block::bash
python scripts/dump_bin.py dump_all --help
After conversion, users can find their Qlib format data in the directory `~/.qlib/qlib_data/`.
..note::
The arguments of `--include_fields` should correspond with the column names of CSV files. The columns names of dataset provided by ``Qlib`` should include open, close, high, low, volume and factor at least.
The arguments of `--include_fields` should correspond with the column names of CSV or Parquet files. The columns names of dataset provided by ``Qlib`` should include open, close, high, low, volume and factor at least.
In the convention of `Qlib` data processing, `open, close, high, low, volume, money and factor` will be set to NaN if the stock is suspended.
If you want to use your own alpha-factor which can't be calculate by OCHLV, like PE, EPS and so on, you could add it to the CSV or Parquet files with OHCLV together and then dump it to the Qlib format data.
China-Stock Mode & US-Stock Mode
--------------------------------
Checking the health of the data
-------------------------------
``Qlib`` provides a script to check the health of the data.
- The main points to check are as follows
- Check if any data is missing in the DataFrame.
- Check if there are any large step changes above the threshold in the OHLCV columns.
- Check if any of the required columns (OLHCV) are missing in the DataFrame.
- Check if the 'factor' column is missing in the DataFrame.
- You can run the following commands to check whether the data is healthy or not.
``Qlib`` defines `stock pool <https://github.com/microsoft/qlib/blob/main/examples/benchmarks/LightGBM/workflow_config_lightgbm_Alpha158.yaml#L4>`_ as stock list and their date ranges. Predefined stock pools (e.g. csi300) may be imported as follows.
``Qlib`` now provides two different stock modes for users: China-Stock Mode & US-Stock Mode. Here are some different settings of these two modes:
============== ================= ================
Region Trade Unit Limit Threshold
============== ================= ================
China 100 0.099
US 1 None
============== ================= ================
The `trade unit` defines the unit number of stocks can be used in a trade, and the `limit threshold` defines the bound set to the percentage of ups and downs of a stock.
- If users use ``Qlib`` in china-stock mode, china-stock data is required. Users can use ``Qlib`` in china-stock mode according to the following steps:
- Download china-stock in qlib format, please refer to section `Qlib Format Dataset <#qlib-format-dataset>`_.
- Initialize ``Qlib`` in china-stock mode
Supposed that users download their Qlib format data in the directory ``~/.qlib/csv_data/cn_data``. Users only need to initialize ``Qlib`` as follows.
Supposed that users download their Qlib format data in the directory ``~/.qlib/qlib_data/cn_data``. Users only need to initialize ``Qlib`` as follows.
- If users use ``Qlib`` in US-stock mode, US-stock data is required. ``Qlib``does not provide a script to download US-stock data. Users can use ``Qlib`` in US-stock mode according to the following steps:
- Prepare data in CSV format
- Convert data from CSV format to Qlib format, please refer to section `Converting CSV Format into Qlib Format <#converting-csv-format-into-qlib-format>`_.
- If users use ``Qlib`` in US-stock mode, US-stock data is required. ``Qlib``also provides a script to download US-stock data. Users can use ``Qlib`` in US-stock mode according to the following steps:
- Download us-stock in qlib format, please refer to section `Qlib Format Dataset <#qlib-format-dataset>`_.
- Initialize ``Qlib`` in US-stock mode
Supposed that users prepare their Qlib format data in the directory ``~/.qlib/csv_data/us_data``. Users only need to initialize ``Qlib`` as follows.
Supposed that users prepare their Qlib format data in the directory ``~/.qlib/qlib_data/us_data``. Users only need to initialize ``Qlib`` as follows.
PRs for new data source are highly welcome! Users could commit the code to crawl data as a PR like `the examples here <https://github.com/microsoft/qlib/tree/main/scripts>`_. And then we will use the code to create data cache on our server which other users could use directly.
Data API
========================
========
Data Retrieval
---------------
--------------
Users can use APIs in ``qlib.data`` to retrieve data, please refer to `Data Retrieval <../start/getdata.html>`_.
Feature
------------------
-------
``Qlib`` provides `Feature` and `ExpressionOps` to fetch the features according to users' needs.
@@ -126,11 +318,12 @@ Feature
-`ExpressionOps`
`ExpressionOps` will use operator for feature construction.
To know more about ``Operator``, please refer to `Operator API <../reference/api.html#module-qlib.data.ops>`_.
Also, ``Qlib`` supports users to define their own custom ``Operator``, an example has been given in ``tests/test_register_ops.py``.
To know more about ``Feature``, please refer to `Feature API <../reference/api.html#module-qlib.data.base>`_.
Filter
-------------------
------
``Qlib`` provides `NameDFilter` and `ExpressionDFilter` to filter the instruments according to users' needs.
-`NameDFilter`
@@ -140,138 +333,209 @@ Filter
Expression dynamic instrument filter. Filter the instruments based on a certain expression. An expression rule indicating a certain feature field is required.
-`basic features filter`: rule_expression = '$close/$open>5'
-`cross-sectional features filter` : rule_expression = '$rank($close)<10'
-`cross-sectional features filter`\: rule_expression = '$rank($close)<10'
-`time-sequence features filter`: rule_expression = '$Ref($close, 3)>100'
Here is a simple example showing how to use filter in a basic ``Qlib`` workflow configuration file:
To know more about ``Filter``, please refer to `Filter API <../reference/api.html#module-qlib.data.filter>`_.
Reference
-------------
---------
To know more about ``Data API``, please refer to `Data API <../reference/api.html#data>`_.
Data Handler
=================
Users can use ``Data Handler`` in an automatic workflow by ``Estimator``, refer to `Estimator: Workflow Management <estimator.html>`_ for more details.
Data Loader
===========
Also, ``Data Handler``can be used as an independent module, by which users can easily preprocess data(standardization, remove NaN, etc.) and build datasets. It is a subclass of ``qlib.contrib.estimator.handler.BaseDataHandler``, which provides some interfaces as follows.
``Data Loader``in ``Qlib`` is designed to load raw data from the original data source. It will be loaded and used in the ``DataHandler`` module.
Base Class & Interface
----------------------
Qlib provides a base class `qlib.contrib.estimator.BaseDataHandler <../reference/api.html#qlib.contrib.estimator.handler.BaseDataHandler>`_, which provides the following interfaces:
-`setup_feature`
Implement the interface to load the data features.
-`setup_label`
Implement the interface to load the data labels and calculate the users' labels.
-`setup_processed_data`
Implement the interface for data preprocessing, such as preparing feature columns, discarding blank lines, and so on.
Qlib also provides two functions to help users init the data handler, users can override them for users' needs.
-`_init_kwargs`
Users can init the kwargs of the data handler in this function, some kwargs may be used when init the raw df.
Kwargs are the other attributes in data.args, like dropna_label, dropna_feature
-`_init_raw_df`
Users can init the raw df, feature names, and label names of data handler in this function.
If the index of feature df and label df are not the same, users need to override this method to merge them (e.g. inner, left, right merge).
If users want to load features and labels by config, users can inherit ``qlib.contrib.estimator.handler.ConfigDataHandler``, ``Qlib`` also provides some preprocess method in this subclass.
If users want to use qlib data, `QLibDataHandler` is recommended. Users can inherit their custom class from `QLibDataHandler`, which is also a subclass of `ConfigDataHandler`.
Usage
QlibDataLoader
--------------
``Data Handler`` can be used as a single module, which provides the following mehtods:
The ``QlibDataLoader`` class in ``Qlib`` is such an interface that allows users to load raw data from the ``Qlib`` data source.
-`get_split_data`
- According to the start and end dates, return features and labels of the pandas DataFrame type used for the 'Model'
StaticDataLoader
----------------
-`get_rolling_data`
- According to the start and end dates, and `rolling_period`, an iterator is returned, which can be used to traverse the features and labels used for rolling.
The ``StaticDataLoader`` class in ``Qlib`` is such an interface that allows users to load raw data from file or as provided.
Interface
---------
Here are some interfaces of the ``QlibDataLoader`` class:
..autoclass:: qlib.data.dataset.loader.DataLoader
:members:
:noindex:
API
---
To know more about ``Data Loader``, please refer to `Data Loader API <../reference/api.html#module-qlib.data.dataset.loader>`_.
Data Handler
============
The ``Data Handler`` module in ``Qlib`` is designed to handler those common data processing methods which will be used by most of the models.
Users can use ``Data Handler`` in an automatic workflow by ``qrun``, refer to `Workflow: Workflow Management <workflow.html>`_ for more details.
DataHandlerLP
-------------
In addition to use ``Data Handler`` in an automatic workflow with ``qrun``, ``Data Handler`` can be used as an independent module, by which users can easily preprocess data (standardization, remove NaN, etc.) and build datasets.
In order to achieve so, ``Qlib`` provides a base class `qlib.data.dataset.DataHandlerLP <../reference/api.html#qlib.data.dataset.handler.DataHandlerLP>`_. The core idea of this class is that: we will have some learnable ``Processors`` which can learn the parameters of data processing(e.g., parameters for zscore normalization). When new data comes in, these `trained```Processors`` can then process the new data and thus processing real-time data in an efficient way becomes possible. More information about ``Processors`` will be listed in the next subsection.
Interface
---------
Here are some important interfaces that ``DataHandlerLP`` provides:
If users want to load features and labels by config, users can define a new handler and call the static method `parse_config_to_fields` of ``qlib.contrib.data.handler.Alpha158``.
Also, users can pass ``qlib.contrib.data.processor.ConfigSectionProcessor`` that provides some preprocess methods for features defined by config into the new handler.
Processor
---------
The ``Processor`` module in ``Qlib`` is designed to be learnable and it is responsible for handling data processing such as `normalization` and `drop none/nan features/labels`.
``Qlib`` provides the following ``Processors``:
-``DropnaProcessor``: `processor` that drops N/A features.
-``DropnaLabel``: `processor` that drops N/A labels.
-``TanhProcess``: `processor` that uses `tanh` to process noise data.
-``ProcessInf``: `processor` that handles infinity values, it will be replaces by the mean of the column.
-``Fillna``: `processor` that handles N/A values, which will fill the N/A value by 0 or other given number.
-``MinMaxNorm``: `processor` that applies min-max normalization.
-``ZscoreNorm``: `processor` that applies z-score normalization.
-``RobustZScoreNorm``: `processor` that applies robust z-score normalization.
-``CSZScoreNorm``: `processor` that applies cross sectional z-score normalization.
-``CSRankNorm``: `processor` that applies cross sectional rank normalization.
-``CSZFillna``: `processor` that fills N/A values in a cross sectional way by the mean of the column.
Users can also create their own `processor` by inheriting the base class of ``Processor``. Please refer to the implementation of all the processors for more information (`Processor Link <https://github.com/microsoft/qlib/blob/main/qlib/data/dataset/processor.py>`_).
To know more about ``Processor``, please refer to `Processor API <../reference/api.html#module-qlib.data.dataset.processor>`_.
Example
--------------
-------
``Data Handler`` can be run with ``estimator`` by modifying the configuration file, and can also be used as a single module.
``Data Handler`` can be run with ``qrun`` by modifying the configuration file, and can also be used as a single module.
Know more about how to run ``Data Handler`` with ``Estimator``, please refer to `Estimator: Workflow Management <estimator.html>`_
Know more about how to run ``Data Handler`` with ``qrun``, please refer to `Workflow: Workflow Management <workflow.html>`_
Qlib provides implemented data handler `Alpha158`. The following example shows how to run `Alpha158` as a single module.
..note:: Users need to initialize ``Qlib`` with `qlib.init` first, please refer to `initialization <../start/initialization.html>`_.
..note::(x_train, y_train, x_validate, y_validate, x_test, y_test) can be used as arguments for the `fit`, `predic``, and `score` methods of the ``Interday Model`` , please refer to `Model <model.html#base-class-interface>`_.
Also, the above example has been given in ``examples.estimator.train_backtest_analyze.ipynb``.
..note::In the ``Alpha158``, ``Qlib`` uses the label `Ref($close, -2)/Ref($close, -1) - 1` that means the change from T+1 to T+2, rather than `Ref($close, -1)/$close - 1`, of which the reason is that when getting the T day close price of a china stock, the stock can be bought on T+1 day and sold on T+2 day.
API
---------
---
To know more about ``Data Handler``, please refer to `Data Handler API <../reference/api.html#module-qlib.data.dataset.handler>`_.
Dataset
=======
The ``Dataset`` module in ``Qlib`` aims to prepare data for model training and inferencing.
The motivation of this module is that we want to maximize the flexibility of different models to handle data that are suitable for themselves. This module gives the model the flexibility to process their data in an unique way. For instance, models such as ``GBDT`` may work well on data that contains `nan` or `None` value, while neural networks such as ``MLP`` will break down on such data.
If user's model need process its data in a different way, user could implement his own ``Dataset`` class. If the model's
data processing is not special, ``DatasetH`` can be used directly.
The ``DatasetH`` class is the `dataset` with `Data Handler`. Here is the most important interface of the class:
..autoclass:: qlib.data.dataset.__init__.DatasetH
:members:
:noindex:
API
---
To know more about ``Dataset``, please refer to `Dataset API <../reference/api.html#dataset>`_.
To know more about ``Data Handler``, please refer to `Data Handler API <../reference/api.html#module-qlib.contrib.estimator.handler>`_.
Cache
==========
=====
``Cache`` is an optional module that helps accelerate providing data by saving some frequently-used data as cache file. ``Qlib`` provides a `Memcache` class to cache the most-frequently-used data in memory, an inheritable `ExpressionCache` class, and an inheritable `DatasetCache` class.
Global Memory Cache
---------------------
-------------------
`Memcache` is a global memory cache mechanism that composes of three `MemCacheUnit` instances to cache **Calendar**, **Instruments**, and **Features**. The `MemCache` is defined globally in `cache.py` as `H`. Users can use `H['c'], H['i'], H['f']` to get/set `memcache`.
..autoclass:: qlib.data.cache.MemCacheUnit
:members:
:noindex:
..autoclass:: qlib.data.cache.MemCache
:members:
:noindex:
ExpressionCache
-----------------
---------------
`ExpressionCache` is a cache mechanism that saves expressions such as **Mean($close, 5)**. Users can inherit this base class to define their own cache mechanism that saves expressions according to the following steps.
@@ -282,11 +546,12 @@ The following shows the details about the interfaces:
..autoclass:: qlib.data.cache.ExpressionCache
:members:
:noindex:
``Qlib`` has currently provided implemented disk cache `DiskExpressionCache` which inherits from `ExpressionCache` . The expressions data will be stored in the disk.
DatasetCache
-----------------
------------
`DatasetCache` is a cache mechanism that saves datasets. A certain dataset is regulated by a stock pool configuration (or a series of instruments, though not recommended), a list of expressions or static feature fields, the start time, and end time for the collected features and the frequency. Users can inherit this base class to define their own cache mechanism that saves datasets according to the following steps.
@@ -297,17 +562,18 @@ The following shows the details about the interfaces:
..autoclass:: qlib.data.cache.DatasetCache
:members:
:noindex:
``Qlib`` has currently provided implemented disk cache `DiskDatasetCache` which inherits from `DatasetCache` . The datasets' data will be stored in the disk.
Data and Cache File Structure
==================================
=============================
We've specially designed a file structure to manage data and cache, please refer to the `File storage design section in Qlib paper <https://arxiv.org/abs/2009.11189>`_ for detailed information. The file structure of data and cache is listed as follows.
..code-block::json
..code-block::
- data/
[raw data] updated by data providers
@@ -336,4 +602,3 @@ We've specially designed a file structure to manage data and cache, please refer
- .meta : an assorted meta file recording the stockpool config, field names and visit times
- .index : an assorted index file recording the line index of all calendars
The components in `Qlib Framework <../introduction/introduction.html#framework>`_ are designed in a loosely-coupled way. Users could build their own Quant research workflow with these components like `Example <https://github.com/microsoft/qlib/blob/main/examples/train_and_backtest.py>`_
Besides, ``Qlib`` provides more user-friendly interfaces named ``Estimator`` to automatically run the whole workflow defined by configuration. A concrete execution of the whole workflow is called an `experiment`.
With ``Estimator``, user can easily run an `experiment`, which includes the following steps:
- Data
- Loading
- Processing
- Slicing
- Model
- Training and inference(static or rolling)
- Saving & loading
- Evaluation(Back-testing)
For each `experiment`, ``Qlib`` will capture the model training details, performance evaluation results and basic information (e.g. names, ids). The captured data will be stored in backend-storage (disk or database).
Complete Example
===================
Before getting into details, here is a complete example of ``Estimator``, which defines the workflow in typical Quant research.
Below is a typical config file of ``Estimator``.
..code-block::YAML
experiment:
name:estimator_example
observer_type:file_storage
mode:train
model:
class:LGBModel
module_path:qlib.contrib.model.gbdt
args:
loss:mse
colsample_bytree:0.8879
learning_rate:0.0421
subsample:0.8789
lambda_l1:205.6999
lambda_l2:580.9768
max_depth:8
num_leaves:210
num_threads:20
data:
class:Alpha158
args:
dropna_label:True
filter:
market:csi500
trainer:
class:StaticTrainer
args:
rolling_period:360
train_start_date:2007-01-01
train_end_date:2014-12-31
validate_start_date:2015-01-01
validate_end_date:2016-12-31
test_start_date:2017-01-01
test_end_date:2020-08-01
strategy:
class:TopkDropoutStrategy
args:
topk:50
n_drop:5
backtest:
normal_backtest_args:
verbose:False
limit_threshold:0.095
account:100000000
benchmark:SH000905
deal_price:close
open_cost:0.0005
close_cost:0.0015
min_cost:5
qlib_data:
# when testing, please modify the following parameters according to the specific environment
provider_uri:"~/.qlib/qlib_data/cn_data"
region:"cn"
After saving the config into `configuration.yaml`, users could start the workflow and test their ideas with a single command below.
..code-block::bash
estimator -c configuration.yaml
..note::`estimator` will be placed in your $PATH directory when installing ``Qlib``.
Configuration File
===================
Let's get into details of ``Estimator`` in this section.
Before using ``estimator``, users need to prepare a configuration file. The following content shows how to prepare each part of the configuration file.
Experiment Section
--------------------
At first, the configuration file needs to contain a section named `experiment` about the basic information. This section describes how `estimator` tracks and persists current `experiment`. ``Qlib`` used `sacred`, a lightweight open-source tool, to configure, organize, generate logs, and manage experiment results. Partial behaviors of `sacred` will base on the `experiment` section.
Following files will be saved by `sacred` after `estimator` finish an `experiment`:
-`run`, the experiment information object, usually contains some meta information such as the experiment name, experiment date, etc.
Here is the typical configuration of `experiment section`
..code-block::YAML
experiment:
name:test_experiment
observer_type:mongo
mongo_url:mongodb://MONGO_URL
db_name:public
finetune:false
exp_info_path:/home/test_user/exp_info.json
mode:test
loader:
id:677
The meaning of each field is as follows:
-`name`
The experiment name, str type, `sacred <https://github.com/IDSIA/sacred>_` will use this experiment name as an identifier for some important internal processes. Users can find this field in `run` object of `sacred`. The default value is `test_experiment`.
-`observer_type`
Observer type, str type, there are two choices which include `file_storage` and `mongo` respectively. If `file_storage` is selected, all the above-mentioned managed contents will be stored in the `dir` directory, separated by the number of times of experiments as a subfolder. If it is `mongo`, the content will be stored in the database. The default is `file_storage`.
- For `file_storage` observer.
-`dir`
Directory URL, str type, directory for `file_storage` observer type, files captured and managed by sacred with `file_storage` observer will be saved to this directory, which is the same directory as `config.json` by default.
- For `mongo` observer.
-`mongo_url`
Database URL, str type, required if the observer type is `mongo`.
-`db_name`
Database name, str type, required if the observer type is `mongo`.
-`finetune`
``Estimator``'s behaviors to train models will base on this flag.
If you just want to train models from scratch each time instead of based on existing models, please leave `finetune=false`. Otherwise please read the
details below.
The following table is the processing logic for different situations.
Train - Need to provide model (Static or Rolling) - No need to provide model - Need to provide model (Static or Rolling) - Need to provide model (Static or Rolling)
- The args in model section will be - The args in model section will be - The args in model section will be - The args in model section will be
used for finetuning used for training used for finetuning used for finetuning
- Update based on the provided model - Train model from scratch - Update based on the provided model - Based on the provided model update
and parameters and parameters - Train model from scratch
- **Each rolling time slice is based on** - **Train each rolling time slice**
**a model updated from the previous****separately**
**time**
Test - Model must exist, otherwise an exception will be raised.
- For `StaticTrainer`, users need to train a model and record 'exp_info' for 'Test'.
- For `RollingTrainer`, users need to train a set of models until the latest time, and record 'exp_info' for 'Test'.
2. provide model: from `loader.model_index`, load the index of the model(starting from 0).
3. If `loader.model_index` is None:
- In 'Static Finetune=True', if provide 'Rolling', use the last model to update.
- For `RollingTrainer` with Finetune=True.
- If `StaticTrainer` is used in loader, the model will be used for initialization for finetuning.
- If `RollingTrainer` is used in loader, the existing models will be used without any modification and the new models will be initialized with the model in the last period and finetune one by one.
-`exp_info_path`
save path of experiment info, str type, save the experiment info and model `prediction score` after the experiment is finished. Optional parameter, the default value is `<config_file_dir>/ex_name/exp_info.json`.
-`mode`
`train` or `test`, str type.
-`test mode` is designed for inference. Under `test mode`, it will load the model according to the parameters of `loader` and skip model training.
-`train model` is the default value. It will train new models by default and
Please note that when it fails to load model, it will fall back to `fit` model.
..note::
if users choose ` test mode`, they need to make sure:
- The loader of `test_start_date` must be less than or equal to the current `test_start_date`.
- If other parameters of the `loader` model args are different, a warning will appear.
-`loader`
If you just want to train models from scratch each time instead of based on existing models, please ignore `loader` section. Otherwise please read the
details below.
The `loader` section only works when the `mode` is `test` or `finetune` is `true`.
-`model_index`
Model index, int type. The index of the loaded model in loader_models (starting at 0) for the first `finetune`. The default value is None.
-`exp_info_path`
Loader model experiment info path, str type. If the field exists, the following parameters will be parsed from `exp_info_path`, and the following parameters will not work. One of this field and `id` must exist at least .
-`id`
The experiment id of the model that needs to be loaded, int type. If the `mode` is `test`, this value is required. This field and `exp_info_path` must exist one.
-`name`
The experiment name of the model that needs to be loaded, str type. The default value is the current experiment `name`.
-`observer_type`
The experiment observer type of the model that needs to be loaded, str type. The default value is the current experiment `observer_type`.
..note:: The observer type is a concept of the `sacred` module, which determines how files, standard input, and output which are managed by sacred are stored.
-`file_storage`
If `observer_type` is `file_storage`, the config may be as follows.
..code-block::YAML
experiment:
name:test_experiment
dir:<path to a directory># default is dir of `config.yml`
observer_type:file_storage
-`mongo`
If `observer_type` is `mongo`, the config may be as follows.
..code-block::YAML
experiment:
name:test_experiment
observer_type:mongo
mongo_url:mongodb://MONGO_URL
db_name:public
Users need to indicate `mongo_url` and `db_name` for a mongo observer.
..note::
If users choose the mongo observer, they need to make sure:
- Have an environment with the mongodb installed and a mongo database dedicated to storing the results of the experiments.
- The python environment (the version of python and package) to run the experiments and the one to fetch the results are consistent.
Model Section
-----------------
Users can use a specified model by configuration with hyper-parameters.
Custom Models
~~~~~~~~~~~~~~~~~
Qlib supports custom models, but it must be a subclass of the `qlib.contrib.model.Model`, the config for a custom model may be as following.
..code-block::YAML
model:
class:SomeModel
module_path:/tmp/my_experment/custom_model.py
args:
loss:binary
The class `SomeModel` should be in the module `custom_model`, and ``Qlib`` could parse the `module_path` to load the class.
To know more about ``Interday Model``, please refer to `Interday Model: Training & Prediction <model.html>`_.
Data Section
-----------------
``Data Handler`` can be used to load raw data, prepare features and label columns, preprocess data (standardization, remove NaN, etc.), split training, validation, and test sets. It is a subclass of `qlib.contrib.estimator.handler.BaseDataHandler`.
Users can use the specified data handler by config as follows.
..code-block::YAML
data:
class:Alpha158
args:
start_date:2005-01-01
end_date:2018-04-30
dropna_label:True
filter:
market:csi500
filter_pipeline:
-
class:NameDFilter
module_path:qlib.filter
args:
name_rule_re:S(?!Z3)
fstart_time:2018-01-01
fend_time:2018-12-11
-
class:ExpressionDFilter
module_path:qlib.filter
args:
rule_expression:$open/$factor<=45
fstart_time:2018-01-01
fend_time:2018-12-11
-`class`
Data handler class, str type, which should be a subclass of `qlib.contrib.estimator.handler.BaseDataHandler`, and implements 5 important interfaces for loading features, loading raw data, preprocessing raw data, slicing train, validation, and test data. The default value is `ALPHA360`. If users want to write a data handler to retrieve the data in ``Qlib``, `QlibDataHandler` is suggested.
-`module_path`
The module path, str type, absolute url is also supported, indicates the path of the `class` implementation of the data processor class. The default value is `qlib.contrib.estimator.handler`.
-`args`
Parameters used for ``Data Handler`` initialization.
-`train_start_date`
Training start time, str type, the default value is `2005-01-01`.
-`start_date`
Data start date, str type.
-`end_date`
Data end date, str type. the data from start_date to end_date decides which part of data will be loaded in `datahandler`, users can only use these data in the following parts.
-`dropna_feature` (Optional in args)
Drop Nan feature, bool type, the default value is False.
-`dropna_label` (Optional in args)
Drop Nan label, bool type, the default value is True. Some multi-label tasks will use this.
-`normalize_method` (Optional in args)
Normalize data by a given method. str type. ``Qlib`` gives two normalizing methods, `MinMax` and `Std`.
If users want to build their own method, please override `_process_normalize_feature`.
-`filter`
Dynamically filtering the stocks based on the filter pipeline.
-`market`
index name, str type, the default value is `csi500`.
-`filter_pipeline`
Filter rule list, list type, the default value is []. Can be customized according to users' needs.
-`class`
Filter class name, str type.
-`module_path`
The module path, str type.
-`args`
The filter class parameters, these parameters are set according to the `class`, and all the parameters as kwargs to `class`.
Custom Data Handler
~~~~~~~~~~~~~~~~~~~~~~
Qlib support custom data handler, but it must be a subclass of the ``qlib.contrib.estimator.handler.BaseDataHandler``, the config for custom data handler may be as follows.
The class `SomeDataHandler` should be in the module `custom_data_handler`, and ``Qlib`` could parse the `module_path` to load the class.
If users want to load features and labels by config, they can inherit ``qlib.contrib.estimator.handler.ConfigDataHandler``, ``Qlib`` also has provided some preprocess methods in this subclass.
If users want to use qlib data, `QLibDataHandler` is recommended, from which users can inherit the custom class. `QLibDataHandler` is also a subclass of `ConfigDataHandler`.
To know more about ``Data Handler``, please refer to `Data Framework&Usage <data.html>`_.
Trainer Section
-----------------
Users can specify the trainer ``Trainer`` by the config file, which is a subclass of ``qlib.contrib.estimator.trainer.BaseTrainer`` and implement three important interfaces for training the model, restoring the model, and getting model predictions as follows.
-`train`
Implement this interface to train the model.
-`load`
Implement this interface to recover the model from disk.
-`get_pred`
Implement this interface to get model prediction results.
Qlib have provided two implemented trainer,
-`StaticTrainer`
The static trainer will be trained using the training, validation, and test data of the data processor static slicing.
-`RollingTrainer`
The rolling trainer will use the rolling iterator of the data processor to split data for rolling training.
Users can specify `trainer` with the configuration file:
..code-block::YAML
trainer:
class:StaticTrainer# or RollingTrainer
args:
rolling_period:360
train_start_date:2005-01-01
train_end_date:2014-12-31
validate_start_date:2015-01-01
validate_end_date:2016-06-30
test_start_date:2016-07-01
test_end_date:2017-07-31
-`class`
Trainer class, which should be a subclass of `qlib.contrib.estimator.trainer.BaseTrainer`, and needs to implement three important interfaces, the default value is `StaticTrainer`.
-`module_path`
The module path, str type, absolute url is also supported, indicates the path of the trainer class implementation.
-`args`
Parameters used for ``Trainer`` initialization.
-`rolling_period`
The rolling period, integer type, indicates how many time steps need rolling when rolling the data. The default value is `60`. Only used in `RollingTrainer`.
-`train_start_date`
Training start time, str type.
-`train_end_date`
Training end time, str type.
-`validate_start_date`
Validation start time, str type.
-`validate_end_date`
Validation end time, str type.
-`test_start_date`
Test start time, str type.
-`test_end_date`
Test end time, str type. If `test_end_date` is `-1` or greater than the last date of the data, the last date of the data will be used as `test_end_date`.
Custom Trainer
~~~~~~~~~~~~~~~~~~
Qlib supports custom trainer, but it must be a subclass of the `qlib.contrib.estimator.trainer.BaseTrainer`, the config for a custom trainer may be as following:
..code-block::YAML
trainer:
class:SomeTrainer
module_path:/tmp/my_experment/custom_trainer.py
args:
train_start_date:2005-01-01
train_end_date:2014-12-31
validate_start_date:2015-01-01
validate_end_date:2016-06-30
test_start_date:2016-07-01
test_end_date:2017-07-31
The class `SomeTrainer` should be in the module `custom_trainer`, and ``Qlib`` could parse the `module_path` to load the class.
Strategy Section
-----------------
Users can specify strategy through a config file, for example:
..code-block::YAML
strategy :
class:TopkDropoutStrategy
args:
topk:50
n_drop:5
-`class`
The strategy class, str type, should be a subclass of `qlib.contrib.strategy.strategy.BaseStrategy`. The default value is `TopkDropoutStrategy`.
-`module_path`
The module location, str type, absolute url is also supported, and absolute path is also supported, indicates the location of the policy class implementation.
-`args`
Parameters used for ``Trainer`` initialization.
-`topk`
The number of stocks in the portfolio
-`n_drop`
Number of stocks to be replaced in each trading date
Custom Strategy
^^^^^^^^^^^^^^^^^^^
Qlib supports custom strategy, but it must be a subclass of the ``qlib.contrib.strategy.strategy.BaseStrategy``, the config for custom strategy may be as following:
..code-block::YAML
strategy :
class:SomeStrategy
module_path:/tmp/my_experment/custom_strategy.py
The class `SomeStrategy` should be in the module `custom_strategy`, and ``Qlib`` could parse the `module_path` to load the class.
To know more about ``Strategy``, please refer to `Strategy <strategy.html>`_.
Backtest Section
-----------------
Users can specify `backtest` through a config file, for example:
..code-block::YAML
backtest :
normal_backtest_args:
topk:50
benchmark:SH000905
account:500000
deal_price:close
min_cost:5
subscribe_fields:
- $close
- $change
- $factor
-`normal_backtest_args`
Normal backtest parameters. All the parameters in this section will be passed to the ``qlib.contrib.evaluate.backtest`` function in the form of `**kwargs`.
-`benchmark`
Stock index symbol, str, or list type, the default value is `None`.
..note::
* If `benchmark` is None, it will use the average change of the day of all stocks in 'pred' as the 'bench'.
* If `benchmark` is list, it will use the daily average change of the stock pool in the list as the 'bench'.
* If `benchmark` is str, it will use the daily change as the 'bench'.
-`account`
Backtest initial cash, integer type. The `account` in `strategy` section is deprecated. It only works when `account` is not set in `backtest` section. It will be overridden by `account` in the `backtest` section. The default value is 1e9.
-`deal_price`
Order transaction price field, str type, the default value is close.
-`min_cost`
Min transaction cost, float type, the default value is 5.
-`subscribe_fields`
Subscribe quote fields, array type, the default value is [`deal_price`, $close, $change, $factor].
Qlib Data Section
--------------------
The `qlib_data` field describes the parameters of qlib initialization.
..code-block::YAML
qlib_data:
# when testing, please modify the following parameters according to the specific environment
provider_uri:"~/.qlib/qlib_data/cn_data"
region:"cn"
-`provider_uri`
The local directory where the data loaded by 'get_data.py' is stored.
-`region`
- If region == ``qlib.config.REG_CN``, 'qlib' will be initialized in US-stock mode.
- If region == ``qlib.config.REG_US``, 'qlib' will be initialized in china-stock mode.
Please refer to `Initialization <../start/initialization.html>`_.
Experiment Result
===================
Form of Experimental Result
----------------------------
The result of the experiment is also the result of the ``Intraday Trading(Backtest)``, please refer to `Intraday Trading: Model&Strategy Testing <backtest.html>`_.
Get Experiment Result
----------------------------
Base Class & Interface
~~~~~~~~~~~~~~~~~~~~~~~
Users can check the experiment results from file storage directly, or check the experiment results from the database, or get the experiment results through two interfaces of a base class `Fetcher` provided by ``Qlib``.
The `Fetcher` provides the following interface
- `get_experiments(self, exp_name=None):`
The interface takes one parameters. The `exp_name` is the experiment name, the default is all experiments. Users can get the returned dictionary with a list of ids and test end date as follows.
..code-block::JSON
{
"ex_a":[
{
"id":1,
"test_end_date":"2017-01-01"
}
],
"ex_b":[
...
]
}
-`get_experiment(exp_name, exp_id, fields=None)`
The interface takes three parameters. The first parameter is the experiment name, the second parameter is the experiment id, and the third parameter is a list of fields. The default value of `fields` is None, which means all fields.
The `FileFetcher` is a subclass of `Fetcher`, which could fetch files from `mongo` observer. Users should initialize the fetcher with `mongo_url`. The following is an example:
Daily trading (e.g. portfolio management) and intraday trading (e.g. orders execution) are two hot topics in Quant investment and are usually studied separately.
To get the join trading performance of daily and intraday trading, they must interact with each other and run backtest jointly.
In order to support the joint backtest strategies at multiple levels, a corresponding framework is required. None of the publicly available high-frequency trading frameworks considers multi-level joint trading, which makes the backtesting aforementioned inaccurate.
Besides backtesting, the optimization of strategies from different levels is not standalone and can be affected by each other.
For example, the best portfolio management strategy may change with the performance of order executions(e.g. a portfolio with higher turnover may become a better choice when we improve the order execution strategies).
To achieve overall good performance, it is necessary to consider the interaction of strategies at a different levels.
Therefore, building a new framework for trading on multiple levels becomes necessary to solve the various problems mentioned above, for which we designed a nested decision execution framework that considers the interaction of strategies.
..image:: ../_static/img/framework.svg
The design of the framework is shown in the yellow part in the middle of the figure above. Each level consists of ``Trading Agent`` and ``Execution Env``. ``Trading Agent`` has its own data processing module (``Information Extractor``), forecasting module (``Forecast Model``) and decision generator (``Decision Generator``). The trading algorithm generates the decisions by the ``Decision Generator`` based on the forecast signals output by the ``Forecast Module``, and the decisions generated by the trading algorithm are passed to the ``Execution Env``, which returns the execution results.
The frequency of the trading algorithm, decision content and execution environment can be customized by users (e.g. intraday trading, daily-frequency trading, weekly-frequency trading), and the execution environment can be nested with finer-grained trading algorithm and execution environment inside (i.e. sub-workflow in the figure, e.g. daily-frequency orders can be turned into finer-grained decisions by splitting orders within the day). The flexibility of the nested decision execution framework makes it easy for users to explore the effects of combining different levels of trading strategies and break down the optimization barriers between different levels of the trading algorithm.
The optimization for the nested decision execution framework can be implemented with the support of `QlibRL <./rl/overall.html>`_. To know more about how to use the QlibRL, go to API Reference: `RL API <../reference/api.html#rl>`_.
Example
=======
An example of a nested decision execution framework for high-frequency can be found `here <https://github.com/microsoft/qlib/blob/main/examples/nested_decision_execution/workflow.py>`_.
Besides, the above examples, here are some other related works about high-frequency trading in Qlib.
-`Prediction with high-frequency data <https://github.com/microsoft/qlib/tree/main/examples/highfreq#benchmarks-performance-predicting-the-price-trend-in-high-frequency-data>`_
-`Examples <https://github.com/microsoft/qlib/blob/main/examples/orderbook_data/>`_ to extract features from high-frequency data without fixed frequency.
-`A paper <https://github.com/microsoft/qlib/tree/high-freq-execution#high-frequency-execution>`_ for high-frequency trading.
``Meta Controller`` provides guidance to ``Forecast Model``, which aims to learn regular patterns among a series of forecasting tasks and use learned patterns to guide forthcoming forecasting tasks. Users can implement their own meta-model instance based on ``Meta Controller`` module.
Meta Task
=========
A `Meta Task` instance is the basic element in the meta-learning framework. It saves the data that can be used for the `Meta Model`. Multiple `Meta Task` instances may share the same `Data Handler`, controlled by `Meta Dataset`. Users should use `prepare_task_data()` to obtain the data that can be directly fed into the `Meta Model`.
..autoclass:: qlib.model.meta.task.MetaTask
:members:
Meta Dataset
============
`Meta Dataset` controls the meta-information generating process. It is on the duty of providing data for training the `Meta Model`. Users should use `prepare_tasks` to retrieve a list of `Meta Task` instances.
`Meta Model` instance is the part that controls the workflow. The usage of the `Meta Model` includes:
1. Users train their `Meta Model` with the `fit` function.
2. The `Meta Model` instance guides the workflow by giving useful information via the `inference` function.
..autoclass:: qlib.model.meta.model.MetaModel
:members:
Meta Task Model
---------------
This type of meta-model may interact with task definitions directly. Then, the `Meta Task Model` is the class for them to inherit from. They guide the base tasks by modifying the base task definitions. The function `prepare_tasks` can be used to obtain the modified base task definitions.
..autoclass:: qlib.model.meta.model.MetaTaskModel
:members:
Meta Guide Model
----------------
This type of meta-model participates in the training process of the base forecasting model. The meta-model may guide the base forecasting models during their training to improve their performances.
``Qlib`` provides an implementation of ``Meta Model`` module, ``DDG-DA``,
which adapts to the market dynamics.
``DDG-DA`` includes four steps:
1. Calculate meta-information and encapsulate it into ``Meta Task`` instances. All the meta-tasks form a ``Meta Dataset`` instance.
2. Train ``DDG-DA`` based on the training data of the meta-dataset.
3. Do the inference of the ``DDG-DA`` to get guide information.
4. Apply guide information to the forecasting models to improve their performances.
The `above example <https://github.com/microsoft/qlib/tree/main/examples/benchmarks_dynamic/DDG-DA>`_ can be found in ``examples/benchmarks_dynamic/DDG-DA/workflow.py``.
``Interday Model`` is designed to make the `prediction score` about stocks. Users can use the ``Interday Model`` in an automatic workflow by ``Estimator``, please refer to `Estimator: Workflow Management <estimator.html>`_.
``Forecast Model`` is designed to make the `prediction score` about stocks. Users can use the ``Forecast Model`` in an automatic workflow by ``qrun``, please refer to `Workflow: Workflow Management <workflow.html>`_.
Because the components in ``Qlib`` are designed in a loosely-coupled way, ``Interday Model`` can be used as an independent module also.
Because the components in ``Qlib`` are designed in a loosely-coupled way, ``Forecast Model`` can be used as an independent module also.
Base Class & Interface
======================
``Qlib`` provides a base class `qlib.contrib.model.base.Model <../reference/api.html#module-qlib.contrib.model.base>`_ from which all models should inherit.
``Qlib`` provides a base class `qlib.model.base.Model <../reference/api.html#module-qlib.model.base>`_ from which all models should inherit.
The base class provides the following interfaces:
-`__init__(**kwargs)`
- Initialization.
- If users use ``Estimator`` to start an `experiment`, the parameter of `__init__` method shoule be consistent with the hyperparameters in the configuration file.
The following example explains the value of `x_train`:
``Qlib`` also provides a base class `qlib.model.base.ModelFT <../reference/api.html#qlib.model.base.ModelFT>`_, which includes the method for finetuning the model.
`x_train` is a pandas DataFrame, whose index is MultiIndex <instrument(str), datetime(pd.Timestamp)>. Each column of `x_train` corresponds to a feature, and the column name is the feature name.
..note::
The number and names of the columns are determined by the data handler, please refer to `Data Handler <data.html#data-handler>`_ and `Estimator Data Section <estimator.html#data-section>`_.
-`y_train`, pd.DataFrame type, train label
The following example explains the value of `y_train`:
..code-block::YAML
LABEL
instrument datetime
SH600004 2012-01-04 -0.798456
2012-01-05-1.366716
2012-01-06-0.491026
2012-01-090.296900
2012-01-100.501426
... ...
SZ300273 2014-12-25 -0.465540
2014-12-260.233864
2014-12-290.471368
2014-12-300.411914
2014-12-311.342723
`y_train` is a pandas DataFrame, whose index is MultiIndex <instrument(str), datetime(pd.Timestamp)>. The `LABEL` column represents the value of train label.
..note::
The number and names of the columns are determined by the ``Data Handler``, please refer to `Data Handler <data.html#data-handler>`_.
-`x_valid`, pd.DataFrame type, validation feature
The format of `x_valid` is same as `x_train`
-`y_valid`, pd.DataFrame type, validation label
The format of `y_valid` is same as `y_train`
-`w_train`(Optional args, default is None), pd.DataFrame type, train weight
`w_train` is a pandas DataFrame, whose shape and index is same as `x_train`. The float value in `w_train` represents the weight of the feature at the same position in `x_train`.
-`w_train`(Optional args, default is None), pd.DataFrame type, validation weight
`w_train` is a pandas DataFrame, whose shape and index is the same as `x_valid`. The float value in `w_train` represents the weight of the feature at the same position in `x_train`.
-`predict(self, x_test, **kwargs)`
- Predict test data 'x_test'
- Parameter:
- `x_test`, pd.DataFrame type, test features
The form of `x_test` is same as `x_train` in 'fit' method.
The format of `x_test` is same as `x_train` in `fit` method.
- `x_test`, pd.DataFrame type, test label
The format of `y_test` is same as `y_train` in `fit` method.
-`w_test`, pd.DataFrame type, test weight
The format of `w_test` is same as `w_train` in `fit` method.
- Return: float type, evaluation score
For other interfaces such as `save`, `load`, `finetune`, please refer to `Model API <../reference/api.html#module-qlib.contrib.model.base>`_.
For other interfaces such as `finetune`, please refer to `Model API <../reference/api.html#module-qlib.model.base>`_.
Example
==================
=======
``Qlib`` provides ``LightGBM`` and``DNN`` models as the baseline, the following steps show how to run`` LightGBM`` as an independent module.
``Qlib``'s `Model Zoo` includes models such as ``LightGBM``, ``MLP``,``LSTM``, etc.. These models are treated as the baselines of ``Forecast Model``. The following steps show how to run`` LightGBM`` as an independent module.
- Initialize ``Qlib`` with `qlib.init` first, please refer to `Initialization <../start/initialization.html>`_.
- Run the following code to get the `prediction score``pred_score`
.. code-block:: Python
from qlib.contrib.estimator.handler import Alpha158
from qlib.contrib.model.gbdt import LGBModel
from qlib.contrib.data.handler import Alpha158
from qlib.utils import init_instance_by_config, flatten_dict
from qlib.workflow import R
from qlib.workflow.record_temp import SignalRecord, PortAnaRecord
`Alpha158` is the data handler provided by ``Qlib``, please refer to `Data Handler <data.html#data-handler>`_.
`SignalRecord` is the `Record Template` in ``Qlib``, please refer to `Workflow <recorder.html#record-template>`_.
Also, the above example has been given in ``examples/train_backtest_analyze.ipynb``.
Technically, the meaning of the model prediction depends on the label setting designed by user.
By default, the meaning of the score is normally the rating of the instruments by the forecasting model. The higher the score, the more profit the instruments.
Custom Model
===================
============
Qlib supports custom models. If users are interested in customizing their own models and integrating the models into ``Qlib``, please refer to `Custom Model Integration <../start/integration.html>`_.
API
===================
Please refer to `Model API <../reference/api.html#module-qlib.contrib.model.base>`_.
===
Please refer to `Model API <../reference/api.html#module-qlib.model.base>`_.
In addition to backtesting, one way to test a model is effective is to make predictions in real market conditions or even do real trading based on those predictions.
``Online Serving`` is a set of modules for online models using the latest data,
which including `Online Manager <#Online Manager>`_, `Online Strategy <#Online Strategy>`_, `Online Tool <#Online Tool>`_, `Updater <#Updater>`_.
`Here <https://github.com/microsoft/qlib/tree/main/examples/online_srv>`_ are several examples for reference, which demonstrate different features of ``Online Serving``.
If you have many models or `task` needs to be managed, please consider `Task Management <../advanced/task_management.html>`_.
The `examples <https://github.com/microsoft/qlib/tree/main/examples/online_srv>`_ are based on some components in `Task Management <../advanced/task_management.html>`_ such as ``TrainerRM`` or ``Collector``.
**NOTE**: User should keep his data source updated to support online serving. For example, Qlib provides `a batch of scripts <https://github.com/microsoft/qlib/blob/main/scripts/data_collector/yahoo/README.md#automatic-update-of-daily-frequency-datafrom-yahoo-finance>`_ to help users update Yahoo daily data.
Known limitations currently
- Currently, the daily updating prediction for the next trading day is supported. But generating orders for the next trading day is not supported due to the `limitations of public data <https://github.com/microsoft/qlib/issues/215#issuecomment-766293563>_`
``Qlib`` contains an experiment management system named ``QlibRecorder``, which is designed to help users handle experiment and analyse results in an efficient way.
There are three components of the system:
-`ExperimentManager`
a class that manages experiments.
-`Experiment`
a class of experiment, and each instance of it is responsible for a single experiment.
-`Recorder`
a class of recorder, and each instance of it is responsible for a single run.
Here is a general view of the structure of the system:
..code-block::
ExperimentManager
- Experiment 1
- Recorder 1
- Recorder 2
- ...
- Experiment 2
- Recorder 1
- Recorder 2
- ...
- ...
This experiment management system defines a set of interface and provided a concrete implementation ``MLflowExpManager``, which is based on the machine learning platform: ``MLFlow`` (`link <https://mlflow.org/>`_).
If users set the implementation of ``ExpManager`` to be ``MLflowExpManager``, they can use the command `mlflow ui` to visualize and check the experiment results. For more information, please refer to the related documents `here <https://www.mlflow.org/docs/latest/cli.html#mlflow-ui>`_.
Qlib Recorder
=============
``QlibRecorder`` provides a high level API for users to use the experiment management system. The interfaces are wrapped in the variable ``R`` in ``Qlib``, and users can directly use ``R`` to interact with the system. The following command shows how to import ``R`` in Python:
..code-block::Python
fromqlib.workflowimportR
``QlibRecorder`` includes several common API for managing `experiments` and `recorders` within a workflow. For more available APIs, please refer to the following section about `Experiment Manager`, `Experiment` and `Recorder`.
Here are the available interfaces of ``QlibRecorder``:
..autoclass:: qlib.workflow.__init__.QlibRecorder
:members:
Experiment Manager
==================
The ``ExpManager`` module in ``Qlib`` is responsible for managing different experiments. Most of the APIs of ``ExpManager`` are similar to ``QlibRecorder``, and the most important API will be the ``get_exp`` method. User can directly refer to the documents above for some detailed information about how to use the ``get_exp`` method.
..autoclass:: qlib.workflow.expm.ExpManager
:members:get_exp, list_experiments
:noindex:
For other interfaces such as `create_exp`, `delete_exp`, please refer to `Experiment Manager API <../reference/api.html#experiment-manager>`_.
Experiment
==========
The ``Experiment`` class is solely responsible for a single experiment, and it will handle any operations that are related to an experiment. Basic methods such as `start`, `end` an experiment are included. Besides, methods related to `recorders` are also available: such methods include `get_recorder` and `list_recorders`.
..autoclass:: qlib.workflow.exp.Experiment
:members:get_recorder, list_recorders
:noindex:
For other interfaces such as `search_records`, `delete_recorder`, please refer to `Experiment API <../reference/api.html#experiment>`_.
``Qlib`` also provides a default ``Experiment``, which will be created and used under certain situations when users use the APIs such as `log_metrics` or `get_exp`. If the default ``Experiment`` is used, there will be related logged information when running ``Qlib``. Users are able to change the name of the default ``Experiment`` in the config file of ``Qlib`` or during ``Qlib``'s `initialization <../start/initialization.html#parameters>`_, which is set to be '`Experiment`'.
Recorder
========
The ``Recorder`` class is responsible for a single recorder. It will handle some detailed operations such as ``log_metrics``, ``log_params`` of a single run. It is designed to help user to easily track results and things being generated during a run.
Here are some important APIs that are not included in the ``QlibRecorder``:
For other interfaces such as `save_objects`, `load_object`, please refer to `Recorder API <../reference/api.html#recorder>`_.
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 `prediction` results of the model.
-``SigAnaRecord``: This class generates the `IC`, `ICIR`, `Rank IC` and `Rank ICIR` of the model.
Here is a simple example of what is done in ``SigAnaRecord``, which users can refer to if they want to calculate IC, Rank IC, Long-Short Return with their own prediction and label.
-``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>`_.
Here is a simple example of what is done in ``PortAnaRecord``, which users can refer to if they want to do backtest based on their own prediction and label.
``Aanalysis`` is designed to show the graphical reports of ``Intraday Trading`` , which helps users to evaluate and analyse investment portfolios visually. The following are some graphics to view:
``Analysis`` is designed to show the graphical reports of ``Intraday Trading`` , which helps users to evaluate and analyse investment portfolios visually. The following are some graphics to view:
- analysis_position
- report_graph
@@ -19,8 +20,11 @@ Introduction
- model_performance_graph
All of the accumulated profit metrics(e.g. return, max drawdown) in Qlib are calculated by summation.
This avoids the metrics or the plots being skewed exponentially over time.
Graphical Reports
===================
=================
Users can run the following code to get all supported reports.
@@ -37,16 +41,17 @@ Users can run the following code to get all supported reports.
The `Pearson correlation coefficient` series between `label` and `prediction score`.
In the above example, the `label` is formulated as `Ref($close, -1)/$close -1`. Please refer to `Data Featrue <data.html#feature>`_ for more details.
In the above example, the `label` is formulated as `Ref($close, -2)/Ref($close, -1)-1`. Please refer to `Data Feature <data.html#feature>`_ for more details.
-`rank_ic`
The `Spearman's rank correlation coefficient` series between `label` and `prediction score`.
QlibRL contains a full set of components that cover the entire lifecycle of an RL pipeline, including building the simulator of the market, shaping states & actions, training policies (strategies), and backtesting strategies in the simulated environment.
QlibRL is basically implemented with the support of Tianshou and Gym frameworks. The high-level structure of QlibRL is demonstrated below:
..image:: ../../_static/img/QlibRL_framework.png
:width:600
:align:center
Here, we briefly introduce each component in the figure.
EnvWrapper
------------
EnvWrapper is the complete capsulation of the simulated environment. It receives actions from outside (policy/strategy/agent), simulates the changes in the market, and then replies rewards and updated states, thus forming an interaction loop.
In QlibRL, EnvWrapper is a subclass of gym.Env, so it implements all necessary interfaces of gym.Env. Any classes or pipelines that accept gym.Env should also accept EnvWrapper. Developers do not need to implement their own EnvWrapper to build their own environment. Instead, they only need to implement 4 components of the EnvWrapper:
-`Simulator`
The simulator is the core component responsible for the environment simulation. Developers could implement all the logic that is directly related to the environment simulation in the Simulator in any way they like. In QlibRL, there are already two implementations of Simulator for single asset trading: 1) ``SingleAssetOrderExecution``, which is built based on Qlib's backtest toolkits and hence considers a lot of practical trading details but is slow. 2) ``SimpleSingleAssetOrderExecution``, which is built based on a simplified trading simulator, which ignores a lot of details (e.g. trading limitations, rounding) but is quite fast.
-`State interpreter`
The state interpreter is responsible for "interpret" states in the original format (format provided by the simulator) into states in a format that the policy could understand. For example, transform unstructured raw features into numerical tensors.
-`Action interpreter`
The action interpreter is similar to the state interpreter. But instead of states, it interprets actions generated by the policy, from the format provided by the policy to the format that is acceptable to the simulator.
-`Reward function`
The reward function returns a numerical reward to the policy after each time the policy takes an action.
EnvWrapper will organically organize these components. Such decomposition allows for better flexibility in development. For example, if the developers want to train multiple types of policies in the same environment, they only need to design one simulator and design different state interpreters/action interpreters/reward functions for different types of policies.
QlibRL has well-defined base classes for all these 4 components. All the developers need to do is define their own components by inheriting the base classes and then implementing all interfaces required by the base classes. The API for the above base components can be found `here <../../reference/api.html#module-qlib.rl>`__.
Policy
------------
QlibRL directly uses Tianshou's policy. Developers could use policies provided by Tianshou off the shelf, or implement their own policies by inheriting Tianshou's policies.
Training Vessel & Trainer
-------------------------
As stated by their names, training vessels and trainers are helper classes used in training. A training vessel is a ship that contains a simulator/interpreters/reward function/policy, and it controls algorithm-related parts of training. Correspondingly, the trainer is responsible for controlling the runtime parts of training.
As you may have noticed, a training vessel itself holds all the required components to build an EnvWrapper rather than holding an instance of EnvWrapper directly. This allows the training vessel to create duplicates of EnvWrapper dynamically when necessary (for example, under parallel training).
With a training vessel, the trainer could finally launch the training pipeline by simple, Scikit-learn-like interfaces (i.e., ``trainer.fit()``).
The API for Trainer and TrainingVessel and can be found `here <../../reference/api.html#module-qlib.rl.trainer>`__.
The RL module is designed in a loosely-coupled way. Currently, RL examples are integrated with concrete business logic.
But the core part of RL is much simpler than what you see.
To demonstrate the simple core of RL, `a dedicated notebook <https://github.com/microsoft/qlib/tree/main/examples/rl/simple_example.ipynb>`__ for RL without business loss is created.
QlibRL can help users quickly get started and conveniently implement quantitative strategies based on reinforcement learning(RL) algorithms. For different user groups, we recommend the following guidance to use QlibRL.
Beginners to Reinforcement Learning Algorithms
==============================================
Whether you are a quantitative researcher who wants to understand what RL can do in trading or a learner who wants to get started with RL algorithms in trading scenarios, if you have limited knowledge of RL and want to shield various detailed settings to quickly get started with RL algorithms, we recommend the following sequence to learn qlibrl:
- Learn the fundamentals of RL in `part1 <https://qlib.readthedocs.io/en/latest/component/rl/overall.html#reinforcement-learning>`_.
- Understand the trading scenarios where RL methods can be applied in `part2 <https://qlib.readthedocs.io/en/latest/component/rl/overall.html#potential-application-scenarios-in-quantitative-trading>`_.
- Run the examples in `part3 <https://qlib.readthedocs.io/en/latest/component/rl/quickstart.html>`_ to solve trading problems using RL.
- If you want to further explore QlibRL and make some customizations, you need to first understand the framework of QlibRL in `part4 <https://qlib.readthedocs.io/en/latest/component/rl/framework.html>`_ and rewrite specific components according to your needs.
Reinforcement Learning Algorithm Researcher
==============================================
If you are already familiar with existing RL algorithms and dedicated to researching RL algorithms but lack domain knowledge in the financial field, and you want to validate the effectiveness of your algorithms in financial trading scenarios, we recommend the following steps to get started with QlibRL:
- Understand the trading scenarios where RL methods can be applied in `part2 <https://qlib.readthedocs.io/en/latest/component/rl/overall.html#potential-application-scenarios-in-quantitative-trading>`_.
- Choose an RL application scenario (currently, QlibRL has implemented two scenario examples: order execution and algorithmic trading). Run the example in `part3 <https://qlib.readthedocs.io/en/latest/component/rl/quickstart.html>`_ to get it working.
- Modify the `policy <https://github.com/microsoft/qlib/blob/main/qlib/rl/order_execution/policy.py>`_ part to incorporate your own RL algorithm.
Quantitative Researcher
=======================
If you have a certain level of financial domain knowledge and coding skills, and you want to explore the application of RL algorithms in the investment field, we recommend the following steps to explore QlibRL:
- Learn the fundamentals of RL in `part1 <https://qlib.readthedocs.io/en/latest/component/rl/overall.html#reinforcement-learning>`_.
- Understand the trading scenarios where RL methods can be applied in `part2 <https://qlib.readthedocs.io/en/latest/component/rl/overall.html#potential-application-scenarios-in-quantitative-trading>`_.
- Run the examples in `part3 <https://qlib.readthedocs.io/en/latest/component/rl/quickstart.html>`_ to solve trading problems using RL.
- Understand the framework of QlibRL in `part4 <https://qlib.readthedocs.io/en/latest/component/rl/framework.html>`_.
- Choose a suitable RL algorithm based on the characteristics of the problem you want to solve (currently, QlibRL supports PPO and DQN algorithms based on tianshou).
- Design the MDP (Markov Decision Process) process based on market trading rules and the problem you want to solve. Refer to the example in order execution and make corresponding modifications to the following modules: `State <https://github.com/microsoft/qlib/blob/main/qlib/rl/order_execution/state.py#L70>`_, `Metrics <https://github.com/microsoft/qlib/blob/main/qlib/rl/order_execution/state.py#L18>`_, `ActionInterpreter <https://github.com/microsoft/qlib/blob/main/qlib/rl/order_execution/interpreter.py#L199>`_, `StateInterpreter <https://github.com/microsoft/qlib/blob/main/qlib/rl/order_execution/interpreter.py#L68>`_, `Reward <https://github.com/microsoft/qlib/blob/main/qlib/rl/order_execution/reward.py>`_, `Observation <https://github.com/microsoft/qlib/blob/main/qlib/rl/order_execution/interpreter.py#L44>`_, `Simulator <https://github.com/microsoft/qlib/blob/main/qlib/rl/order_execution/simulator_simple.py>`_.
Different from supervised learning tasks such as classification tasks and regression tasks. Another important paradigm in machine learning is Reinforcement Learning(RL),
which attempts to optimize an accumulative numerical reward signal by directly interacting with the environment under a few assumptions such as Markov Decision Process(MDP).
As demonstrated in the following figure, an RL system consists of four elements, 1)the agent 2) the environment the agent interacts with 3) the policy that the agent follows to take actions on the environment and 4)the reward signal from the environment to the agent.
In general, the agent can perceive and interpret its environment, take actions and learn through reward, to seek long-term and maximum overall reward to achieve an optimal solution.
..image:: ../../_static/img/RL_framework.png
:width:300
:align:center
RL attempts to learn to produce actions by trial and error.
By sampling actions and then observing which one leads to our desired outcome, a policy is obtained to generate optimal actions.
In contrast to supervised learning, RL learns this not from a label but from a time-delayed label called a reward.
This scalar value lets us know whether the current outcome is good or bad.
In a word, the target of RL is to take actions to maximize reward.
The Qlib Reinforcement Learning toolkit (QlibRL) is an RL platform for quantitative investment, which provides support to implement the RL algorithms in Qlib.
Potential Application Scenarios in Quantitative Trading
RL methods have demonstrated remarkable achievements in various applications, including game playing, resource allocation, recommendation systems, marketing, and advertising.
In the context of investment, which involves continuous decision-making, let's consider the example of the stock market. Investors strive to optimize their investment returns by effectively managing their positions and stock holdings through various buying and selling behaviors.
Furthermore, investors carefully evaluate market conditions and stock-specific information before making each buying or selling decision. From an investor's perspective, this process can be viewed as a continuous decision-making process driven by interactions with the market. RL algorithms offer a promising approach to tackle such challenges.
Here are several scenarios where RL holds potential for application in quantitative investment.
Order Execution
---------------
The order execution task is to execute orders efficiently while considering multiple factors, including optimal prices, minimizing trading costs, reducing market impact, maximizing order fullfill rates, and achieving execution within a specified time frame. RL can be applied to such tasks by incorporating these objectives into the reward function and action selection process. Specifically, the RL agent interacts with the market environment, observes the state from market information, and makes decisions on next step execution. The RL algorithm learns an optimal execution strategy through trial and error, aiming to maximize the expected cumulative reward, which incorporates the desired objectives.
- General Setting
- Environment: The environment represents the financial market where order execution takes place. It encompasses variables such as the order book dynamics, liquidity, price movements, and market conditions.
- State: The state refers to the information available to the RL agent at a given time step. It typically includes features such as the current order book state (bid-ask spread, order depth), historical price data, historical trading volume, market volatility, and any other relevant information that can aid in decision-making.
- Action: The action is the decision made by the RL agent based on the observed state. In order execution, actions can include selecting the order size, price, and timing of execution.
- Reward: The reward is a scalar signal that indicates the performance of the RL agent's action in the environment. The reward function is designed to encourage actions that lead to efficient and cost-effective order execution. It typically considers multiple objectives, such as maximizing price advantages, minimizing trading costs (including transaction fees and slippage), reducing market impact (the effect of the order on the market price) and maximizing order fullfill rates.
- Scenarios
- Single-asset order execution: Single-asset order execution focuses on the task of executing a single order for a specific asset, such as a stock or a cryptocurrency. The primary objective is to execute the order efficiently while considering factors such as maximizing price advantages, minimizing trading costs, reducing market impact, and achieving a high fullfill rate. The RL agent interacts with the market environment and makes decisions on order size, price, and timing of execution for that particular asset. The goal is to learn an optimal execution strategy for the single asset, maximizing the expected cumulative reward while considering the specific dynamics and characteristics of that asset.
- Multi-asset order execution: Multi-asset order execution expands the order execution task to involve multiple assets or securities. It typically involves executing a portfolio of orders across different assets simultaneously or sequentially. Unlike single-asset order execution, the focus is not only on the execution of individual orders but also on managing the interactions and dependencies between different assets within the portfolio. The RL agent needs to make decisions on the order sizes, prices, and timings for each asset in the portfolio, considering their interdependencies, cash constraints, market conditions, and transaction costs. The goal is to learn an optimal execution strategy that balances the execution efficiency for each asset while considering the overall performance and objectives of the portfolio as a whole.
The choice of settings and RL algorithm depends on the specific requirements of the task, available data, and desired performance objectives.
Portfolio Construction
----------------------
Portfolio construction is a process of selecting and allocating assets in an investment portfolio. RL provides a framework to optimize portfolio management decisions by learning from interactions with the market environment and maximizing long-term returns while considering risk management.
- General Setting
- State: The state represents the current information about the market and the portfolio. It typically includes historical prices and volumes, technical indicators, and other relevant data.
- Action: The action corresponds to the decision of allocating capital to different assets in the portfolio. It determines the weights or proportions of investments in each asset.
- Reward: The reward is a metric that evaluates the performance of the portfolio. It can be defined in various ways, such as total return, risk-adjusted return, or other objectives like maximizing Sharpe ratio or minimizing drawdown.
- Scenarios
- Stock market: RL can be used to construct portfolios of stocks, where the agent learns to allocate capital among different stocks.
- Cryptocurrency market: RL can be applied to construct portfolios of cryptocurrencies, where the agent learns to make allocation decisions.
- Foreign exchange (Forex) market: RL can be used to construct portfolios of currency pairs, where the agent learns to allocate capital across different currencies based on exchange rate data, economic indicators, and other factors.
Similarly, the choice of basic setting and algorithm depends on the specific requirements of the problem and the characteristics of the market.
QlibRL provides an example of an implementation of a single asset order execution task and the following is an example of the config file to train with QlibRL.
..code-block::yaml
simulator:
# Each step contains 30mins
time_per_step:30
# Upper bound of volume, should be null or a float between 0 and 1, if it is a float, represent upper bound is calculated by the percentage of the market volume
vol_limit:null
env:
# Concurrent environment workers.
concurrency:1
# dummy or subproc or shmem. Corresponding to `parallelism in tianshou <https://tianshou.readthedocs.io/en/master/api/tianshou.env.html#vectorenv>`_.
parallel_mode:dummy
action_interpreter:
class:CategoricalActionInterpreter
kwargs:
# Candidate actions, it can be a list with length L: [a_1, a_2,..., a_L] or an integer n, in which case the list of length n+1 is auto-generated, i.e., [0, 1/n, 2/n,..., n/n].
values:14
# Total number of steps (an upper-bound estimation)
max_step:8
module_path:qlib.rl.order_execution.interpreter
state_interpreter:
class:FullHistoryStateInterpreter
kwargs:
# Number of dimensions in data.
data_dim:6
# Equal to the total number of records. For example, in SAOE per minute, data_ticks is the length of the day in minutes.
data_ticks:240
# The total number of steps (an upper-bound estimation). For example, 390min / 30min-per-step = 13 steps.
max_step:8
# Provider of the processed data.
processed_data_provider:
class:PickleProcessedDataProvider
module_path:qlib.rl.data.pickle_styled
kwargs:
data_dir:./data/pickle_dataframe/feature
module_path:qlib.rl.order_execution.interpreter
reward:
class:PAPenaltyReward
kwargs:
# The penalty for a large volume in a short time.
penalty:100.0
module_path:qlib.rl.order_execution.reward
data:
source:
order_dir:./data/training_order_split
data_dir:./data/pickle_dataframe/backtest
# number of time indexes
total_time:240
# start time index
default_start_time:0
# end time index
default_end_time:240
proc_data_dim:6
num_workers:0
queue_size:20
network:
class:Recurrent
module_path:qlib.rl.order_execution.network
policy:
class:PPO
kwargs:
lr:0.0001
module_path:qlib.rl.order_execution.policy
runtime:
seed:42
use_cuda:false
trainer:
max_epoch:2
# Number of episodes collected in each training iteration
# the volume limits of selling, "current" means that this is a real-time value and will not accumulate over time
sell:["current","$close"]
strategies:
30min:
class:TWAPStrategy
module_path:qlib.contrib.strategy.rule_strategy
kwargs:{}
1day:
class:SAOEIntStrategy
module_path:qlib.rl.order_execution.strategy
kwargs:
state_interpreter:
class:FullHistoryStateInterpreter
module_path:qlib.rl.order_execution.interpreter
kwargs:
max_step:8
data_ticks:240
data_dim:6
processed_data_provider:
class:PickleProcessedDataProvider
module_path:qlib.rl.data.pickle_styled
kwargs:
data_dir:./data/pickle_dataframe/feature
action_interpreter:
class:CategoricalActionInterpreter
module_path:qlib.rl.order_execution.interpreter
kwargs:
values:14
max_step:8
network:
class:Recurrent
module_path:qlib.rl.order_execution.network
kwargs:{}
policy:
class:PPO
module_path:qlib.rl.order_execution.policy
kwargs:
lr:1.0e-4
# Local path to the latest model. The model is generated during training, so please run training first if you want to run backtest with a trained policy. You could also remove this parameter file to run backtest with a randomly initialized policy.
weight_file:./checkpoints/latest.pth
# Concurrent environment workers.
concurrency:5
With the above config files, you can start training the agent by the following command:
In that case, :class:`~qlib.rl.order_execution.simulator_qlib.SingleAssetOrderExecution` and :class:`~qlib.rl.order_execution.simulator_simple.SingleAssetOrderExecutionSimple` as examples for simulator, :class:`qlib.rl.order_execution.interpreter.FullHistoryStateInterpreter` and :class:`qlib.rl.order_execution.interpreter.CategoricalActionInterpreter` as examples for interpreter, :class:`qlib.rl.order_execution.policy.PPO` as an example for policy, and :class:`qlib.rl.order_execution.reward.PAPenaltyReward` as an example for reward.
For the single asset order execution task, if developers have already defined their simulator/interpreters/reward function/policy, they could launch the training and backtest pipeline by simply modifying the corresponding settings in the config files.
The details about the example can be found `here <https://github.com/microsoft/qlib/blob/main/examples/rl/README.md>`_.
In the future, we will provide more examples for different scenarios such as RL-based portfolio construction.
``Interday Strategy`` is designed to adopt different trading strategies, which means that users can adopt different algorithms to generate investment portfolios based on the prediction scores of the ``Interday Model``. Users can use the ``Interday Strategy`` in an automatic workflow by ``Estimator``, please refer to `Estimator: Workflow Management <estimator.html>`_.
``Portfolio Strategy`` is designed to adopt different portfolio strategies, which means that users can adopt different algorithms to generate investment portfolios based on the prediction scores of the ``Forecast Model``. Users can use the ``Portfolio Strategy`` in an automatic workflow by ``Workflow`` module, please refer to `Workflow: Workflow Management <workflow.html>`_.
Because the components in ``Qlib`` are designed in a loosely-coupled way, ``Interday Strategy`` can be used as an independent module also.
Because the components in ``Qlib`` are designed in a loosely-coupled way, ``Portfolio Strategy`` can be used as an independent module also.
``Qlib`` provides several implemented trading strategies. Also, ``Qlib`` supports custom strategy, users can customize strategies according to their own needs.
``Qlib`` provides several implemented portfolio strategies. Also, ``Qlib`` supports custom strategy, users can customize strategies according to their own requirements.
After users specifying the models(forecasting signals) and strategies, running backtest will help users to check the performance of a custom model(forecasting signals)/strategy.
Base Class & Interface
======================
BaseStrategy
------------------
------------
Qlib provides a base class ``qlib.contrib.strategy.BaseStrategy``. All strategy classes need to inherit the base class and implement its interface.
Qlib provides a base class ``qlib.strategy.base.BaseStrategy``. All strategy classes need to inherit the base class and implement its interface.
-`get_risk_degree`
Return the proportion of your total value you will use in investment. Dynamically risk_degree will result in Market timing.
-`generate_order_list`
Rerturn the order list.
-`generate_trade_decision`
generate_trade_decision is a key interface that generates trade decisions in each trading bar.
The frequency to call this method depends on the executor frequency("time_per_step"="day" by default). But the trading frequency can be decided by users' implementation.
For example, if the user wants to trading in weekly while the `time_per_step` is "day" in executor, user can return non-empty TradeDecision weekly(otherwise return empty like `this <https://github.com/microsoft/qlib/blob/main/qlib/contrib/strategy/signal_strategy.py#L132>`_ ).
Users can inherit `BaseStrategy` to customize their strategy class.
WeightStrategyBase
--------------------
------------------
Qlib alse provides a class ``qlib.contrib.strategy.WeightStrategyBase`` that is a subclass of `BaseStrategy`.
Qlib also provides a class ``qlib.contrib.strategy.WeightStrategyBase`` that is a subclass of `BaseStrategy`.
`WeightStrategyBase` only focuses on the target positions, and automatically generates an order list based on positions. It provides the `generate_target_weight_position` interface.
-`generate_target_weight_position`
- According to the current position and trading date to generate the target position. The cash is not considered.
- According to the current position and trading date to generate the target position. The cash is not considered in
the output weight distribution.
- Return the target position.
..note::
@@ -57,64 +60,253 @@ Implemented Strategy
Qlib provides a implemented strategy classes named `TopkDropoutStrategy`.
TopkDropoutStrategy
------------------
-------------------
`TopkDropoutStrategy` is a subclass of `BaseStrategy` and implement the interface `generate_order_list` whose process is as follows.
- Adopt the ``Topk-Drop`` algorithm to calculate the target amount of each stock
.. note::
``Topk-Drop`` algorithm:
There are two parameters for the ``Topk-Drop`` algorithm:
-`Topk`: The number of stocks held
-`Drop`: The number of stocks sold on each trading day
Currently, the number of held stocks is `Topk`.
On each trading day, the `Drop` number of held stocks with the worst `prediction score` will be sold, and the same number of unheld stocks with the best `prediction score` will be bought.
In general, the number of stocks currently held is `Topk`, with the exception of being zero at the beginning period of trading.
For each trading day, let $d$ be the number of the instruments currently held and with a rank $\gt K$ when ranked by the prediction scores from high to low.
Then `d` number of stocks currently held with the worst `prediction score` will be sold, and the same number of unheld stocks with the best `prediction score` will be bought.
In general, $d=$`Drop`, especially when the pool of the candidate instruments is large, $K$ is large, and `Drop` is small.
In most cases, ``TopkDrop`` algorithm sells and buys `Drop` stocks every trading day, which yields a turnover rate of 2$\times$`Drop`/$K$.
The following images illustrate a typical scenario.
..image:: ../_static/img/topk_drop.png
:alt:Topk-Drop
``TopkDrop`` algorithm sells `Drop` stocks every trading day, which guarantees a fixed turnover rate.
- Generate the order list from the target amount
EnhancedIndexingStrategy
------------------------
`EnhancedIndexingStrategy` Enhanced indexing combines the arts of active management and passive management,
with the aim of outperforming a benchmark index (e.g., S&P 500) in terms of portfolio return while controlling
the risk exposure (a.k.a. tracking error).
For more information, please refer to `qlib.contrib.strategy.signal_strategy.EnhancedIndexingStrategy`
and `qlib.contrib.strategy.optimizer.enhanced_indexing.EnhancedIndexingOptimizer`.
Usage & Example
====================
``Interday Strategy`` can be specified in the ``Intraday Trading(Backtest)``, the example is as follows.
===============
First, user can create a model to get trading signals(the variable name is ``pred_score`` in following cases).
Prediction Score
----------------
The `prediction score` is a pandas DataFrame. Its index is <datetime(pd.Timestamp), instrument(str)> and it must
``Forecast Model`` module can make predictions, please refer to `Forecast Model: Model Training & Prediction <model.html>`_.
Normally, the prediction score is the output of the models. But some models are learned from a label with a different scale. So the scale of the prediction score may be different from your expectation(e.g. the return of instruments).
Qlib didn't add a step to scale the prediction score to a unified scale due to the following reasons.
- Because not every trading strategy cares about the scale(e.g. TopkDropoutStrategy only cares about the order). So the strategy is responsible for rescaling the prediction score(e.g. some portfolio-optimization-based strategies may require a meaningful scale).
- The model has the flexibility to define the target, loss, and data processing. So we don't think there is a silver bullet to rescale it back directly barely based on the model's outputs. If you want to scale it back to some meaningful values(e.g. stock returns.), an intuitive solution is to create a regression model for the model's recent outputs and your recent target values.
Running backtest
----------------
- In most cases, users could backtest their portfolio management strategy with ``backtest_daily``.
.. code-block:: python
from pprint import pprint
import qlib
import pandas as pd
from qlib.utils.time import Freq
from qlib.utils import flatten_dict
from qlib.contrib.evaluate import backtest_daily
from qlib.contrib.evaluate import risk_analysis
from qlib.contrib.strategy import TopkDropoutStrategy
- If users would like to control their strategies in a more detailed(e.g. users have a more advanced version of executor), user could follow this example.
pprint(f"The following are analysis results of the excess return without cost({analysis_freq}).")
pprint(analysis["excess_return_without_cost"])
pprint(f"The following are analysis results of the excess return with cost({analysis_freq}).")
pprint(analysis["excess_return_with_cost"])
To know more about the `prediction score` `pred_score` output by ``Interday Model``, please refer to `Interday Model: Model Training & Prediction <model.html>`_.
To know more about ``Intraday Trading``, please refer to `Intraday Trading: Model&Strategy Testing <backtest.html>`_.
Result
------
The backtest results are in the following form:
..code-block::python
risk
excess_return_without_costmean0.000605
std0.005481
annualized_return0.152373
information_ratio1.751319
max_drawdown-0.059055
excess_return_with_costmean0.000410
std0.005478
annualized_return0.103265
information_ratio1.187411
max_drawdown-0.075024
-`excess_return_without_cost`
- `mean`
Mean value of the `CAR` (cumulative abnormal return) without cost
- `std`
The `Standard Deviation` of `CAR` (cumulative abnormal return) without cost.
- `annualized_return`
The `Annualized Rate` of `CAR` (cumulative abnormal return) without cost.
- `information_ratio`
The `Information Ratio` without cost. please refer to `Information Ratio – IR <https://www.investopedia.com/terms/i/informationratio.asp>`_.
- `max_drawdown`
The `Maximum Drawdown` of `CAR` (cumulative abnormal return) without cost, please refer to `Maximum Drawdown (MDD) <https://www.investopedia.com/terms/m/maximum-drawdown-mdd.asp>`_.
-`excess_return_with_cost`
-`mean`
Mean value of the `CAR` (cumulative abnormal return) series with cost
-`std`
The `Standard Deviation` of `CAR` (cumulative abnormal return) series with cost.
-`annualized_return`
The `Annualized Rate` of `CAR` (cumulative abnormal return) with cost.
-`information_ratio`
The `Information Ratio` with cost. please refer to `Information Ratio – IR <https://www.investopedia.com/terms/i/informationratio.asp>`_.
-`max_drawdown`
The `Maximum Drawdown` of `CAR` (cumulative abnormal return) with cost, please refer to `Maximum Drawdown (MDD) <https://www.investopedia.com/terms/m/maximum-drawdown-mdd.asp>`_.
Reference
===================
To know more about ``Interday Strategy``, please refer to `Strategy API <../reference/api.html#module-qlib.contrib.strategy.strategy>`_.
=========
To know more about the `prediction score` `pred_score` output by ``Forecast Model``, please refer to `Forecast Model: Model Training & Prediction <model.html>`_.
The components in `Qlib Framework <../introduction/introduction.html#framework>`_ are designed in a loosely-coupled way. Users could build their own Quant research workflow with these components like `Example <https://github.com/microsoft/qlib/blob/main/examples/workflow_by_code.py>`_.
Besides, ``Qlib`` provides more user-friendly interfaces named ``qrun`` to automatically run the whole workflow defined by configuration. Running the whole workflow is called an `execution`.
With ``qrun``, user can easily start an `execution`, which includes the following steps:
- Data
- Loading
- Processing
- Slicing
- Model
- Training and inference
- Saving & loading
- Evaluation
- Forecast signal analysis
- Backtest
For each `execution`, ``Qlib`` has a complete system to tracking all the information as well as artifacts generated during training, inference and evaluation phase. For more information about how ``Qlib`` handles this, please refer to the related document: `Recorder: Experiment Management <../component/recorder.html>`_.
Complete Example
================
Before getting into details, here is a complete example of ``qrun``, which defines the workflow in typical Quant research.
Below is a typical config file of ``qrun``.
..code-block::YAML
qlib_init:
provider_uri:"~/.qlib/qlib_data/cn_data"
region:cn
market:&marketcsi300
benchmark:&benchmarkSH000300
data_handler_config:&data_handler_config
start_time:2008-01-01
end_time:2020-08-01
fit_start_time:2008-01-01
fit_end_time:2014-12-31
instruments:*market
port_analysis_config:&port_analysis_config
strategy:
class:TopkDropoutStrategy
module_path:qlib.contrib.strategy.strategy
kwargs:
topk:50
n_drop:5
signal:<PRED>
backtest:
start_time:2017-01-01
end_time:2020-08-01
account:100000000
benchmark:*benchmark
exchange_kwargs:
limit_threshold:0.095
deal_price:close
open_cost:0.0005
close_cost:0.0015
min_cost:5
task:
model:
class:LGBModel
module_path:qlib.contrib.model.gbdt
kwargs:
loss:mse
colsample_bytree:0.8879
learning_rate:0.0421
subsample:0.8789
lambda_l1:205.6999
lambda_l2:580.9768
max_depth:8
num_leaves:210
num_threads:20
dataset:
class:DatasetH
module_path:qlib.data.dataset
kwargs:
handler:
class:Alpha158
module_path:qlib.contrib.data.handler
kwargs:*data_handler_config
segments:
train:[2008-01-01,2014-12-31]
valid:[2015-01-01,2016-12-31]
test:[2017-01-01,2020-08-01]
record:
- class:SignalRecord
module_path:qlib.workflow.record_temp
kwargs:{}
- class:PortAnaRecord
module_path:qlib.workflow.record_temp
kwargs:
config:*port_analysis_config
After saving the config into `configuration.yaml`, users could start the workflow and test their ideas with a single command below.
..code-block::bash
qrun configuration.yaml
If users want to use ``qrun`` under debug mode, please use the following command:
`qrun` will be placed in your $PATH directory when installing ``Qlib``.
..note::
The symbol `&` in `yaml` file stands for an anchor of a field, which is useful when another fields include this parameter as part of the value. Taking the configuration file above as an example, users can directly change the value of `market` and `benchmark` without traversing the entire configuration file.
Configuration File
==================
Let's get into details of ``qrun`` in this section.
Before using ``qrun``, users need to prepare a configuration file. The following content shows how to prepare each part of the configuration file.
The design logic of the configuration file is very simple. It predefines fixed workflows and provide this yaml interface to users to define how to initialize each component.
It follow the design of `init_instance_by_config <https://github.com/microsoft/qlib/blob/2aee9e0145decc3e71def70909639b5e5a6f4b58/qlib/utils/__init__.py#L264>`_ . It defines the initialization of each component of Qlib, which typically include the class and the initialization arguments.
For example, the following yaml and code are equivalent.
..code-block::YAML
model:
class:LGBModel
module_path:qlib.contrib.model.gbdt
kwargs:
loss:mse
colsample_bytree:0.8879
learning_rate:0.0421
subsample:0.8789
lambda_l1:205.6999
lambda_l2:580.9768
max_depth:8
num_leaves:210
num_threads:20
..code-block::python
fromqlib.contrib.model.gbdtimportLGBModel
kwargs={
"loss":"mse",
"colsample_bytree":0.8879,
"learning_rate":0.0421,
"subsample":0.8789,
"lambda_l1":205.6999,
"lambda_l2":580.9768,
"max_depth":8,
"num_leaves":210,
"num_threads":20,
}
LGBModel(kwargs)
Qlib Init Section
-----------------
At first, the configuration file needs to contain several basic parameters which will be used for qlib initialization.
..code-block::YAML
provider_uri:"~/.qlib/qlib_data/cn_data"
region:cn
The meaning of each field is as follows:
-`provider_uri`
Type: str. The URI of the Qlib data. For example, it could be the location where the data loaded by ``get_data.py`` are stored.
-`region`
- If `region` == "us", ``Qlib`` will be initialized in US-stock mode.
- If `region` == "cn", ``Qlib`` will be initialized in China-stock mode.
..note::
The value of `region` should be aligned with the data stored in `provider_uri`.
Task Section
------------
The `task` field in the configuration corresponds to a `task`, which contains the parameters of three different subsections: `Model`, `Dataset` and `Record`.
Model Section
~~~~~~~~~~~~~
In the `task` field, the `model` section describes the parameters of the model to be used for training and inference. For more information about the base ``Model`` class, please refer to `Qlib Model <../component/model.html>`_.
..code-block::YAML
model:
class:LGBModel
module_path:qlib.contrib.model.gbdt
kwargs:
loss:mse
colsample_bytree:0.8879
learning_rate:0.0421
subsample:0.8789
lambda_l1:205.6999
lambda_l2:580.9768
max_depth:8
num_leaves:210
num_threads:20
The meaning of each field is as follows:
-`class`
Type: str. The name for the model class.
-`module_path`
Type: str. The path for the model in qlib.
-`kwargs`
The keywords arguments for the model. Please refer to the specific model implementation for more information: `models <https://github.com/microsoft/qlib/blob/main/qlib/contrib/model>`_.
..note::
``Qlib`` provides a util named: ``init_instance_by_config`` to initialize any class inside ``Qlib`` with the configuration includes the fields: `class`, `module_path` and `kwargs`.
Dataset Section
~~~~~~~~~~~~~~~
The `dataset` field describes the parameters for the ``Dataset`` module in ``Qlib`` as well those for the module ``DataHandler``. For more information about the ``Dataset`` module, please refer to `Qlib Data <../component/data.html#dataset>`_.
The keywords arguments configuration of the ``DataHandler`` is as follows:
..code-block::YAML
data_handler_config:&data_handler_config
start_time:2008-01-01
end_time:2020-08-01
fit_start_time:2008-01-01
fit_end_time:2014-12-31
instruments:*market
Users can refer to the document of `DataHandler <../component/data.html#datahandler>`_ for more information about the meaning of each field in the configuration.
Here is the configuration for the ``Dataset`` module which will take care of data preprocessing and slicing during the training and testing phase.
..code-block::YAML
dataset:
class:DatasetH
module_path:qlib.data.dataset
kwargs:
handler:
class:Alpha158
module_path:qlib.contrib.data.handler
kwargs:*data_handler_config
segments:
train:[2008-01-01,2014-12-31]
valid:[2015-01-01,2016-12-31]
test:[2017-01-01,2020-08-01]
Record Section
~~~~~~~~~~~~~~
The `record` field is about the parameters the ``Record`` module in ``Qlib``. ``Record`` is responsible for tracking training process and results such as `information Coefficient (IC)` and `backtest` in a standard format.
The following script is the configuration of `backtest` and the `strategy` used in `backtest`:
..code-block::YAML
port_analysis_config:&port_analysis_config
strategy:
class:TopkDropoutStrategy
module_path:qlib.contrib.strategy.strategy
kwargs:
topk:50
n_drop:5
signal:<PRED>
backtest:
limit_threshold:0.095
account:100000000
benchmark:*benchmark
deal_price:close
open_cost:0.0005
close_cost:0.0015
min_cost:5
For more information about the meaning of each field in configuration of `strategy` and `backtest`, users can look up the documents: `Strategy <../component/strategy.html>`_ and `Backtest <../component/backtest.html>`_.
Here is the configuration details of different `Record Template` such as ``SignalRecord`` and ``PortAnaRecord``:
..code-block::YAML
record:
- class:SignalRecord
module_path:qlib.workflow.record_temp
kwargs:{}
- class:PortAnaRecord
module_path:qlib.workflow.record_temp
kwargs:
config:*port_analysis_config
For more information about the ``Record`` module in ``Qlib``, user can refer to the related document: `Record <../component/recorder.html#record-template>`_.
Please use the `Numpydoc Style <https://stackoverflow.com/a/24385103>`_.
Continuous Integration
======================
Continuous Integration (CI) tools help you stick to the quality standards by running tests every time you push a new commit and reporting the results to a pull request.
When you submit a PR request, you can check whether your code passes the CI tests in the "check" section at the bottom of the web page.
1. Qlib will check the code format with black. The PR will raise error if your code does not align to the standard of Qlib(e.g. a common error is the mixed use of space and tab).
You can fix the bug by inputting the following code in the command line.
..code-block::bash
pip install black
python -m black . -l 120
2. Qlib will check your code style pylint. The checking command is implemented in [github action workflow](https://github.com/microsoft/qlib/blob/0e8b94a552f1c457cfa6cd2c1bb3b87ebb3fb279/.github/workflows/test.yml#L66).
Sometime pylint's restrictions are not that reasonable. You can ignore specific errors like this
3. Qlib will check your code style flake8. The checking command is implemented in [github action workflow](https://github.com/microsoft/qlib/blob/0e8b94a552f1c457cfa6cd2c1bb3b87ebb3fb279/.github/workflows/test.yml#L73).
You can fix the bug by inputing the following code in the command line.
4. Qlib has integrated pre-commit, which will make it easier for developers to format their code.
Just run the following two commands, and the code will be automatically formatted using black and flake8 when the git commit command is executed.
..code-block::bash
pip install -e .[dev]
pre-commit install
=================================
Development Guidance
=================================
As a developer, you often want make changes to `Qlib` and hope it would reflect directly in your environment without reinstalling it. You can install `Qlib` in editable mode with following command.
The `[dev]` option will help you to install some related packages when developing `Qlib` (e.g. pytest, sphinx)
There is a **Dockerfile** file in the root directory of the project from which you can build the docker image. There are two build methods in Dockerfile to choose from.
When executing the build command, use the ``--build-arg`` parameter to control the image version. The ``--build-arg`` parameter defaults to ``yes``, which builds the ``stable`` version of the qlib image.
1.For the ``stable`` version, use ``pip install pyqlib`` to build the qlib image.
1. There is a **build_docker_image.sh** file in the root directory of your project, which can be used to automatically build docker images and upload them to your docker hub repository(Optional, configuration required).
..code-block::bash
sh build_docker_image.sh
>>> Do you want to build the nightly version of the qlib image? (default is stable)(yes/no):
>>> Is it uploaded to docker hub? (default is no)(yes/no):
2. If you want to upload the built image to your docker hub repository, you need to edit your **build_docker_image.sh** file first, fill in ``docker_user`` in the file, and then execute this file.
How to use qlib images
======================
1. Start a new Docker container
..code-block::bash
docker run -it --name <container name> -v <Mounted local directory>:/app <image name>
2. At this point you are in the docker environment and can run the qlib scripts. An example:
* In windows, mount path must be not exist path and root path,
@@ -159,13 +160,11 @@ Limitations
2. The rolling operation expression with parameter `0` can not be updated rightly under mechanism of the client-server framework.
API
********************
***
The client is based on `python-socketio <https://python-socketio.readthedocs.io>`_ which is a framework that supports WebSocket client for Python language. The client can only propose requests and receive results, which do not include any calculating procedure.
Welcome to use Tuner, this document is based on that you can use Estimator proficiently and correctly.
@@ -31,7 +31,7 @@ Let's see an example,
First make sure you have the latest version of `qlib` installed.
Then, you need to privide a configuration to setup the experiment.
Then, you need to provide a configuration to setup the experiment.
We write a simple configuration example as following,
..code-block::YAML
@@ -93,7 +93,6 @@ We write a simple configuration example as following,
fend_time:2018-12-11
backtest:
normal_backtest_args:
verbose:False
limit_threshold:0.095
account:500000
benchmark:SH000905
@@ -218,13 +217,13 @@ The tuner pipeline contains different tuners, and the `tuner` program will proce
Each part represents a tuner, and its modules which are to be tuned. Space in each part is the hyper-parameters' space of a certain module, you need to create your searching space and modify it in `/qlib/contrib/tuner/space.py`. We use `hyperopt` package to help us to construct the space, you can see the detail of how to use it in https://github.com/hyperopt/hyperopt/wiki/FMin .
- model
You need to provide the `class` and the `space` of the model. If the model is user's own implementation, you need to privide the `module_path`.
You need to provide the `class` and the `space` of the model. If the model is user's own implementation, you need to provide the `module_path`.
- trainer
You need to proveide the `class` of the trainer. If the trainer is user's own implementation, you need to privide the `module_path`.
You need to provide the `class` of the trainer. If the trainer is user's own implementation, you need to provide the `module_path`.
- strategy
You need to provide the `class` and the `space` of the strategy. If the strategy is user's own implementation, you need to privide the `module_path`.
You need to provide the `class` and the `space` of the strategy. If the strategy is user's own implementation, you need to provide the `module_path`.
- data_label
The label of the data, you can search which kinds of labels will lead to a better result. This part is optional, and you only need to provide `space`.
@@ -274,7 +273,7 @@ You need to use the same dataset to evaluate your different `estimator` experime
About the data and backtest
~~~~~~~~~~~~~~~~~~~~~~~~~~~
`data` and `backtest` are all same in the whole `tuner` experiment. Different `estimator` experiments must use the same data and backtest method. So, these two parts of config are same with that in `estimator` configuration. You can see the precise defination of these parts in `estimator` introduction. We only provide an example here.
`data` and `backtest` are all same in the whole `tuner` experiment. Different `estimator` experiments must use the same data and backtest method. So, these two parts of config are same with that in `estimator` configuration. You can see the precise definition of these parts in `estimator` introduction. We only provide an example here.
..code-block::YAML
@@ -306,7 +305,6 @@ About the data and backtest
fend_time:2018-12-11
backtest:
normal_backtest_args:
verbose:False
limit_threshold:0.095
account:500000
benchmark:SH000905
@@ -324,4 +322,3 @@ What we save are as following:
- Local optimal parameters of each tuner
- Config file of this `tuner` experiment
- Every `estimator` experiments result in the process
``Qlib`` is an AI-oriented quantitative investment platform, which aims to realize the potential, empower the research, and create the value of AI technologies in quantitative investment.
With ``Qlib``, users can easily try their ideas to create better Quant investment strategies.
Framework
===================
=========
..image:: ../_static/img/framework.png
..image:: ../_static/img/framework.svg
:align:center
At the module level, Qlib is a platform that consists of above components. The components are designed as loose-coupled modules and each component could be used stand-alone.
This dataset is created by public data collected by crawler scripts in ``scripts/data_collector/``, which have been released in the same repository. Users could create the same dataset with it.
To kown more about `prepare data`, please refer to `Data Preparation <../component/data.html#data-preparation>`_.
To known more about `prepare data`, please refer to `Data Preparation <../component/data.html#data-preparation>`_.
Auto Quant Research Workflow
====================================
============================
``Qlib`` provides a tool named ``Estimator`` to run the whole workflow automatically (including building dataset, training models, backtest and evaluation). Users can start an auto quant research workflow and have a graphical reports analysis according to the following steps:
``Qlib`` provides a tool named ``qrun`` to run the whole workflow automatically (including building dataset, training models, backtest and evaluation). Users can start an auto quant research workflow and have a graphical reports analysis according to the following steps:
- Quant Research Workflow:
- Run ``Estimator`` with `estimator_config.yaml` as following.
- Run ``qrun`` with a config file of the LightGBM model `workflow_config_lightgbm.yaml` as following.
..code-block::
cd examples # Avoid running program under the directory contains `qlib`
The result of ``Estimator`` is as follows, which is also the result of ``Intraday Trading``. Please refer to `Intraday Trading <../component/backtest.html>`_. for more details about the result.
-Workflow result
The result of ``qrun`` is as follows, which is also the typical result of ``Forecast model(alpha)``. Please refer to `Intraday Trading <../component/backtest.html>`_. for more details about the result.
..code-block::python
@@ -77,17 +79,17 @@ Auto Quant Research Workflow
max_drawdown-0.075024
To know more about `Estimator`, please refer to `Estimator: Workflow Management <../component/estimator.html>`_.
To know more about `workflow` and `qrun`, please refer to `Workflow: Workflow Management <../component/workflow.html>`_.
- Graphical Reports Analysis:
- Run ``examples/estimator/analyze_from_estimator.ipynb`` with jupyter notebook
Users can have portfolio analysis or prediction score (model prediction) analysis by run ``examples/estimator/analyze_from_estimator.ipynb``.
- Run ``examples/workflow_by_code.ipynb`` with jupyter notebook
Users can have portfolio analysis or prediction score (model prediction) analysis by run ``examples/workflow_by_code.ipynb``.
- Graphical Reports
Users can get graphical reports about the analysis, please refer to `Aanalysis: Evaluation & Results Analysis <../component/report.html>`_ for more details.
Users can get graphical reports about the analysis, please refer to `Analysis: Evaluation & Results Analysis <../component/report.html>`_ for more details.
Custom Model Integration
===============================================
========================
``Qlib`` provides ``lightGBM`` and ``Dnn`` model as the baseline of ``Interday Model``. In addition to the default model, users can integrate their own custom models into ``Qlib``. If users are interested in the custom model, please refer to `Custom Model Integration <../start/integration.html>`_.
``Qlib`` provides a batch of models (such as ``lightGBM`` and ``MLP`` models) as examples of ``Forecast Model``. In addition to the default model, users can integrate their own custom models into ``Qlib``. If users are interested in the custom model, please refer to `Custom Model Integration <../start/integration.html>`_.
For more details about features, please refer `Feature API <../component/data.html>`_.
..note:: When calling `D.features()` at the client, use parameter `disk_cache=0` to skip dataset cache, use `disk_cache=1` to generate and use dataset cache. In addition, when calling at the server, users can use `disk_cache=2` to update the dataset cache.
When you are building complicated expressions, implementing all the expressions in a single string may not be easy.
Please follow the steps below to initialize ``Qlib``.
-Download and prepare the Data: execute the following command to download stock data. Please pay `attention` that the data is collected from `Yahoo Finance <https://finance.yahoo.com/lookup>`_ and the data might not be perfect. We recommend users to prepare their own data if they have high-quality datasets. Please refer to `Data <../component/data.html#converting-csv-format-into-qlib-format>` for more information about customized dataset.
Download and prepare the Data: execute the following command to download stock data. Please pay `attention` that the data is collected from `Yahoo Finance <https://finance.yahoo.com/lookup>`_ and the data might not be perfect. We recommend users to prepare their own data if they have high-quality datasets. Please refer to `Data <../component/data.html#converting-csv-format-into-qlib-format>`_ for more information about customized dataset.
@@ -34,17 +37,19 @@ Please follow the steps below to initialize ``Qlib``.
Parameters
-------------------
Besides `provider_uri` and `region`, `qlib.init` has other parameters. The following are several important parameters of `qlib.init`:
Besides `provider_uri` and `region`, `qlib.init` has other parameters.
The following are several important parameters of `qlib.init` (`Qlib` has a lot of config. Only part of parameters are limited here. More detailed setting can be found `here <https://github.com/microsoft/qlib/blob/main/qlib/config.py>`_):
-`provider_uri`
Type: str. The URI of the Qlib data. For example, it could be the location where the data loaded by ``get_data.py`` are stored.
Currently: ``qlib.config.REG_US`` ('us') and ``qlib.config.REG_CN`` ('cn') is supported. Different value of `region` will result in different stock market mode.
Currently: ``qlib.constant.REG_US`` ('us') and ``qlib.constant.REG_CN`` ('cn') is supported. Different value of `region` will result in different stock market mode.
- ``qlib.constant.REG_US``: US stock market.
- ``qlib.constant.REG_CN``: China stock market.
Different modse will result in different trading limitations and costs.
Different modes will result in different trading limitations and costs.
The region is just `shortcuts for defining a batch of configurations <https://github.com/microsoft/qlib/blob/528f74af099bf6156e9480bcd2bb28e453231212/qlib/config.py#L249>`_, which include minimal trading order unit (``trade_unit``), trading limitation (``limit_threshold``) , etc. It is not a necessary part and users can set the key configurations manually if the existing region setting can't meet their requirements.
-`redis_host`
Type: str, optional parameter(default: "127.0.0.1"), host of `redis`
The lock and cache mechanism relies on redis.
@@ -58,3 +63,35 @@ Besides `provider_uri` and `region`, `qlib.init` has other parameters. The follo
..note::
If Qlib fails to connect redis via `redis_host` and `redis_port`, cache mechanism will not be used! Please refer to `Cache <../component/data.html#cache>`_ for details.
-`exp_manager`
Type: dict, optional parameter, the setting of `experiment manager` to be used in qlib. Users can specify an experiment manager class, as well as the tracking URI for all the experiments. However, please be aware that we only support input of a dictionary in the following style for `exp_manager`. For more information about `exp_manager`, users can refer to `Recorder: Experiment Management <../component/recorder.html>`_.
..code-block::Python
# For example, if you want to set your tracking_uri to a <specific folder>, you can initialize qlib below
Type: dict, optional parameter, the setting of `MongoDB <https://www.mongodb.com/>`_ which will be used in some features such as `Task Management <../advanced/task_management.html>`_, with high performance and clustered processing.
Users need to follow the steps in `installation <https://www.mongodb.com/try/download/community>`_ to install MongoDB firstly and then access it via a URI.
Users can access mongodb with credential by setting "task_url" to a string like `"mongodb://%s:%s@%s" % (user, pwd, host + ":" + port)`.
"task_url":"mongodb://localhost:27017/",# your mongo url
"task_db_name":"rolling_db",# the database name of Task Management
})
-`logging_level`
The logging level for the system.
-`kernels`
The number of processes used when calculating features in Qlib's expression engine. It is very helpful to set it to 1 when you are debuggin an expression calculating exception
``Qlib`` provides ``lightGBM`` and``Dnn`` model as the baseline of ``Interday Model``. In addition to the default model, users can integrate their own custom models into ``Qlib``.
``Qlib``'s `Model Zoo` includes models such as ``LightGBM``, ``MLP``,``LSTM``, etc.. These models are examples of ``Forecast Model``. In addition to the default models ``Qlib`` provide, users can integrate their own custom models into ``Qlib``.
Users can integrate their own custom models according to the following steps.
- Define a custom model class, which should be a subclass of the `qlib.contrib.model.base.Model <../reference/api.html#module-qlib.contrib.model.base>`_.
- Define a custom model class, which should be a subclass of the `qlib.model.base.Model <../reference/api.html#module-qlib.model.base>`_.
- Write a configuration file that describes the path and parameters of the custom model.
- Test the custom model.
Custom Model Class
===========================
The Custom models need to inherit `qlib.contrib.model.base.Model <../reference/api.html#module-qlib.contrib.model.base>`_ and override the methods in it.
==================
The Custom models need to inherit `qlib.model.base.Model <../reference/api.html#module-qlib.model.base>`_ and override the methods in it.
- Override the `__init__` method
-``Qlib`` passes the initialized parameters to the \_\_init\_\_ method.
- The parameter must be consistent with the hyperparameters in the configuration file.
- Code Example: In the following example, the hyperparameter filed of the configuration file should contain parameters such as `loss:mse`.
- The hyperparameters of model in the configuration must be consistent with those defined in the `__init__` method.
- Code Example: In the following example, the hyperparameters of model in the configuration file should contain parameters such as `loss:mse`.
..code-block::Python
def__init__(self,loss='mse',**kwargs):
@@ -31,80 +32,82 @@ The Custom models need to inherit `qlib.contrib.model.base.Model <../reference/a
self._model=None
- Override the `fit` method
- ``Qlib`` calls the fit method to train the model
- The parameters must include training feature `x_train`, training label `y_train`, test feature `x_valid`, test label `y_valid` at least.
- The parameters could include some optional parameters with default values, such as train weight `w_train`, test weight `w_valid` and `num_boost_round = 1000`.
- ``Qlib`` calls the fit method to train the model.
- The parameters must include training feature `dataset`, which is designed in the interface.
- The parameters could include some `optional` parameters with default values, such as `num_boost_round = 1000` for `GBDT`.
- Code Example: In the following example, `num_boost_round = 1000` is an optional parameter.
- This method is optional to the users. When users want to use this method on their own models, they should inherit the ``ModelFT`` base class, which includes the interface of `finetune`.
- The parameters must include the parameter `dataset`.
- Code Example: In the following example, users will use `LightGBM` as the model and finetune it.
- Override the `save` method & `load` method
- The `save` method parameter includes the a `filename` that represents an absolute path, user need to save model into the path.
- The `load` method parameter includes the a `buffer` read from the `filename` passed in the `save` method, users need to load model from the `buffer`.
.. - Override the `score` method(This step is optional)
.. - The parameters include the test features and test labels.
.. - Return the evaluation score of the model. It's recommended to adopt the loss between labels and `prediction score`.
.. - Code Example: In the following example, users need to calculate the weighted loss with test data `x_test`, test label `y_test` and the weight `w_test`.
# Based on existing model and finetune by train more rounds
dtrain,_=self._prepare_data(dataset)
self.model=lgb.train(
self.params,
dtrain,
num_boost_round=num_boost_round,
init_model=self.model,
valid_sets=[dtrain],
valid_names=["train"],
verbose_eval=verbose_eval,
)
Configuration File
=======================
==================
The configuration file is described in detail in the `estimator<../component/estimator.html#complete-example>`_ document. In order to integrate the custom model into ``Qlib``, users need to modify the "model" field in the configuration file.
The configuration file is described in detail in the `Workflow<../component/workflow.html#complete-example>`_ document. In order to integrate the custom model into ``Qlib``, users need to modify the "model" field in the configuration file. The configuration describes which models to use and how we can initialize it.
- Example: The following example describes the `model` field of configuration file about the custom lightgbm model mentioned above, where `module_path` is the module path, `class` is the class name, and `args` is the hyperparameter passed into the __init__ method. All parameters in the field is passed to `self._params` by `\*\*kwargs` in `__init__` except `loss = mse`.
@@ -124,23 +127,23 @@ The configuration file is described in detail in the `estimator <../component/es
num_leaves: 210
num_threads: 20
Users could find configuration file of the baseline of the ``Model`` in ``qlib/examples/estimator/estimator_config.yaml`` and ``qlib/examples/estimator/estimator_config_dnn.yaml``
Users could find configuration file of the baselines of the ``Model`` in ``examples/benchmarks``. All the configurations of different models are listed under the corresponding model folder.
Model Testing
=====================
Assuming that the configuration file is ``examples/estimator/estimator_config.yaml``, users can run the following command to test the custom model:
=============
Assuming that the configuration file is ``examples/benchmarks/LightGBM/workflow_config_lightgbm.yaml``, users can run the following command to test the custom model:
..code-block::bash
cd examples # Avoid running program under the directory contains `qlib`
..note::``estimator`` is a built-in command of ``Qlib``.
..note::``qrun`` is a built-in command of ``Qlib``.
Also, ``Model`` can also be tested as a single module. An example has been given in ``examples/train_backtest_analyze.ipynb``.
Also, ``Model`` can also be tested as a single module. An example has been given in ``examples/workflow_by_code.ipynb``.
Reference
=====================
=========
To know more about ``Interday Model``, please refer to `Interday Model: Model Training & Prediction <../component/model.html>`_ and `Model API <../reference/api.html#module-qlib.contrib.model.base>`_.
To know more about ``Forecast Model``, please refer to `Forecast Model: Model Training & Prediction <../component/model.html>`_ and `Model API <../reference/api.html#module-qlib.model.base>`_.
- NOTE: Current version of implementation is just a simplified version of ALSTM. It is an LSTM with attention.
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.