diff --git a/README.md b/README.md index fcfdcc3777..76979526e5 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,7 @@ At the module level, Qlib is a platform that consists of the above components. T | Name | Description | | ------ | ----- | | `Infrastructure` layer | `Infrastructure` layer provides underlying support for Quant research. `DataServer` provides a high-performance infrastructure for users to manage and retrieve raw data. `Trainer` provides a flexible interface to control the training process of models, which enable algorithms to control the training process. | -| `Workflow` layer | `Workflow` layer covers the whole workflow of quantitative investment. `Information Extractor` extracts data for models. `Forecast Model` focuses on producing all kinds of forecast signals (e.g. _alpha_, risk) for other modules. With these signals `Portfolio Generator` will generate the target portfolio and produce orders to be executed by `Order Executor`. | +| `Workflow` layer | `Workflow` layer covers the whole workflow of quantitative investment. `Information Extractor` extracts data for models. `Forecast Model` focuses on producing all kinds of forecast signals (e.g. _alpha_, risk) for other modules. With these signals `Decision Generator` will generate the target trading decisions(i.e. portfolio, orders) to be executed by `Execution Env` (i.e. the trading market). There may be multiple levels of `Trading Agent` and `Execution Env` (e.g. an _order executor trading agent and intraday order execution environment_ could behave like an interday trading environment and nested in _daily portfolio management trading agent and interday trading environment_ ) | | `Interface` layer | `Interface` layer tries to present a user-friendly interface for the underlying system. `Analyser` module will provide users detailed analysis reports of forecasting signals, portfolios and execution results | * The modules with hand-drawn style are under development and will be released in the future. diff --git a/docs/component/backtest.rst b/docs/component/backtest.rst deleted file mode 100644 index e83e1023a8..0000000000 --- a/docs/component/backtest.rst +++ /dev/null @@ -1,114 +0,0 @@ -.. _backtest: - -============================================ -Intraday Trading: Model&Strategy Testing -============================================ -.. currentmodule:: qlib - -Introduction -=================== - -``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 ``Portfolio 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 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. - -.. code-block:: python - - from qlib.contrib.evaluate import backtest - # pred_score is the prediction score - report, positions = backtest(pred_score, topk=50, n_drop=0.5, limit_threshold=0.0095) - -To know more about backtesting with a specific ``Strategy``, please refer to `Portfolio Strategy `_. - -To know more about the prediction score `pred_score` output by ``Forecast Model``, please refer to `Forecast Model: Model Training & Prediction `_. - -Prediction Score ------------------ - -The `prediction score` is a pandas DataFrame. Its index is and it must -contains a `score` column. - -A prediction sample is shown as follows. - -.. code-block:: python - - datetime instrument score - 2019-01-04 SH600000 -0.505488 - 2019-01-04 SZ002531 -0.320391 - 2019-01-04 SZ000999 0.583808 - 2019-01-04 SZ300569 0.819628 - 2019-01-04 SZ001696 -0.137140 - ... ... - 2019-04-30 SZ000996 -1.027618 - 2019-04-30 SH603127 0.225677 - 2019-04-30 SH603126 0.462443 - 2019-04-30 SH603133 -0.302460 - 2019-04-30 SZ300760 -0.126383 - -``Forecast Model`` module can make predictions, please refer to `Forecast Model: Model Training & Prediction `_. - -Backtest Result ------------------- - -The backtest results are in the following form: - -.. code-block:: python - - risk - excess_return_without_cost mean 0.000605 - std 0.005481 - annualized_return 0.152373 - information_ratio 1.751319 - max_drawdown -0.059055 - excess_return_with_cost mean 0.000410 - std 0.005478 - annualized_return 0.103265 - information_ratio 1.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 `_. - - `max_drawdown` - The `Maximum Drawdown` of `CAR` (cumulative abnormal return) without cost, please refer to `Maximum Drawdown (MDD) `_. - -- `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 `_. - - `max_drawdown` - The `Maximum Drawdown` of `CAR` (cumulative abnormal return) with cost, please refer to `Maximum Drawdown (MDD) `_. - - - -Reference -============== - -To know more about ``Intraday Trading``, please refer to `Intraday Trading <../reference/api.html#module-qlib.contrib.evaluate>`_. diff --git a/docs/component/highfreq.rst b/docs/component/highfreq.rst index 13ebb959de..8b1b425879 100644 --- a/docs/component/highfreq.rst +++ b/docs/component/highfreq.rst @@ -1,120 +1,31 @@ .. _highfreq: ============================================ -Design of hierarchical order execution framework +Design of Nested Decision Execution Framework for High-Frequency Trading ============================================ .. currentmodule:: qlib Introduction =================== -In order to support reinforcement learning algorithms for high-frequency trading, a corresponding framework is required. None of the publicly available high-frequency trading frameworks now consider multi-layer trading mechanisms, and the currently designed algorithms cannot directly use existing frameworks. -In addition to supporting the basic intraday multi-layer trading, the linkage with the day-ahead strategy is also a factor that affects the performance evaluation of the strategy. Different day strategies generate different order distributions and different patterns on different stocks. To verify that high-frequency trading strategies perform well on real trading orders, it is necessary to support day-frequency and high-frequency multi-level linkage trading. In addition to more accurate backtesting of high-frequency trading algorithms, if the distribution of day-frequency orders is considered when training a high-frequency trading model, the algorithm can also be optimized more for product-specific day-frequency orders. -Therefore, innovation in the high-frequency trading framework is necessary to solve the various problems mentioned above, for which we designed a hierarchical order execution framework that can link daily-frequency and intra-day trading at different granularities. +Daily trading (e.g. portfolio management) and intraday trading (e.g. orders execution) are two hot topics in Quant investment and usually studied separately. -.. image:: ../_static/img/framework.svg - -The design of the framework is shown in the figure above. At each layer consists of Trading Agent and Execution Env. The Trading Agent has its own data processing module (Information Extractor), forecasting module (Forecast Model) and decision generator (Decision Generator). The trading algorithm generates the corresponding 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. Here the frequency of trading algorithm, decision content and execution environment can be customized by users (e.g. intra-day 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 hierarchical order execution framework is user-defined in terms of hierarchy division and decision frequency, making it easy for users to explore the effects of combining different levels of trading algorithms and breaking down the barriers between different levels of trading algorithm optimization. -In addition to the innovation in the framework, the hierarchical order execution framework also takes into account various details of the real backtesting environment, minimizing the differences with the final real environment as much as possible. At the same time, the framework is designed to unify the interface between online and offline (e.g. data pre-processing level supports using the same set of code to process both offline and online data) to reduce the cost of strategy go-live as much as possible. - -Prepare Data -=================== -.. _data:: ../../examples/highfreq/README.md - - -Example -=========================== - -Here is an example of highfreq execution. +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 in multiple levels, a corresponding framework is required. None of the publicly available high-frequency trading frameworks considers multi-level joint trading, which make the backtesting aforementioned inaccurate. -.. code-block:: python +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 becomes a better choice when we imporve the order execution strategies). +To achieve the overall good performance , it is necessary to consider the interaction of strategies in different level. - import qlib - # init qlib - provider_uri_day = "~/.qlib/qlib_data/cn_data" - provider_uri_1min = "~/.qlib/qlib_data/cn_data_1min" - provider_uri_map = {"1min": provider_uri_1min, "day": provider_uri_day} - qlib.init(provider_uri=provider_uri_day, expression_cache=None, dataset_cache=None) +Therefore, building a new framework for trading in multiple levels becomes necessary to solve the various problems mentioned above, for which we designed a nested decision execution framework that consider the interaction of strategies. - # data freq and backtest time - freq = "1min" - inst_list = D.list_instruments(D.instruments("all"), as_list=True) - start_time = "2020-01-01" - start_time = "2020-01-31" - -When initializing qlib, if the default data is used, then both daily and minute frequency data need to be passed in. - -.. code-block:: python - - # random order strategy config - strategy_config = { - "class": "RandomOrderStrategy", - "module_path": "qlib.contrib.strategy.rule_strategy", - "kwargs": { - "trade_range": TradeRangeByTime("9:30", "15:00"), - "sample_ratio": 1.0, - "volume_ratio": 0.01, - "market": market, - }, - } - -.. code-block:: python - # backtest config - backtest_config = { - "start_time": start_time, - "end_time": end_time, - "account": 100000000, - "benchmark": None, - "exchange_kwargs": { - "freq": freq, - "limit_threshold": 0.095, - "deal_price": "close", - "open_cost": 0.0005, - "close_cost": 0.0015, - "min_cost": 5, - "codes": market, - }, - "pos_type": "InfPosition", # Position with infinitive position - } - -please refer to "../../qlib/backtest". +.. image:: ../_static/img/framework.svg -.. code-block:: python - # excutor config - executor_config = { - "class": "NestedExecutor", - "module_path": "qlib.backtest.executor", - "kwargs": { - "time_per_step": "day", - "inner_executor": { - "class": "SimulatorExecutor", - "module_path": "qlib.backtest.executor", - "kwargs": { - "time_per_step": freq, - "generate_portfolio_metrics": True, - "verbose": False, - # "verbose": True, - "indicator_config": { - "show_indicator": False, - }, - }, - }, - "inner_strategy": { - "class": "TWAPStrategy", - "module_path": "qlib.contrib.strategy.rule_strategy", - }, - "track_data": True, - "generate_portfolio_metrics": True, - "indicator_config": { - "show_indicator": True, - }, - }, - } +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. -NestedExecutor represents not the innermost layer, the initialization parameters should contain inner_executor and inner_strategy. simulatorExecutor represents the current excutor is the innermost layer, the innermost strategy used here is the TWAP strategy, the framework currently also supports the VWAP strategy +The frequency of 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 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 trading algorithm. -.. code-block:: python - # backtest - portfolio_metrics_dict, indicator_dict = backtest(executor=executor_config, strategy=strategy_config, **backtest_config) +Example +=========================== -The metrics of backtest are included in the portfolio_metrics_dict and indicator_dict. +An example of nested decision execution framework for high-frequency can be found `here `_. \ No newline at end of file diff --git a/docs/component/strategy.rst b/docs/component/strategy.rst index 5e58dcf372..f2617a0e0f 100644 --- a/docs/component/strategy.rst +++ b/docs/component/strategy.rst @@ -12,7 +12,9 @@ Introduction 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 portfolio 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 ====================== @@ -82,9 +84,39 @@ TopkDropoutStrategy Usage & Example ==================== -``Portfolio Strategy`` can be specified in the ``Intraday Trading(Backtest)``, the example is as follows. -- daily +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 and it must +contains a `score` column. + +A prediction sample is shown as follows. + +.. code-block:: python + + datetime instrument score + 2019-01-04 SH600000 -0.505488 + 2019-01-04 SZ002531 -0.320391 + 2019-01-04 SZ000999 0.583808 + 2019-01-04 SZ300569 0.819628 + 2019-01-04 SZ001696 -0.137140 + ... ... + 2019-04-30 SZ000996 -1.027618 + 2019-04-30 SH603127 0.225677 + 2019-04-30 SH603126 0.462443 + 2019-04-30 SH603133 -0.302460 + 2019-04-30 SZ300760 -0.126383 + +``Forecast Model`` module can make predictions, please refer to `Forecast Model: Model Training & Prediction `_. + + +Running backtest +----------------- + +- In most cases, users could backtest their portfolio management strategy with ``backtest_daily``. .. code-block:: python @@ -127,7 +159,7 @@ Usage & Example -- nested decision execution +- 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. .. code-block:: python @@ -204,10 +236,51 @@ Usage & Example pprint(analysis["excess_return_with_cost"]) -To know more about the `prediction score` `pred_score` output by ``Forecast Model``, please refer to `Forecast Model: Model Training & Prediction `_. +Result +------------------ + +The backtest results are in the following form: + +.. code-block:: python + + risk + excess_return_without_cost mean 0.000605 + std 0.005481 + annualized_return 0.152373 + information_ratio 1.751319 + max_drawdown -0.059055 + excess_return_with_cost mean 0.000410 + std 0.005478 + annualized_return 0.103265 + information_ratio 1.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 `_. + - `max_drawdown` + The `Maximum Drawdown` of `CAR` (cumulative abnormal return) without cost, please refer to `Maximum Drawdown (MDD) `_. + +- `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 `_. + - `max_drawdown` + The `Maximum Drawdown` of `CAR` (cumulative abnormal return) with cost, please refer to `Maximum Drawdown (MDD) `_. -To know more about ``Intraday Trading``, please refer to `Intraday Trading: Model&Strategy Testing `_. Reference =================== -To know more about ``Portfolio 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 `_. \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst index 803aa97d2d..9ada33bbf1 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -38,8 +38,8 @@ Document Structure Workflow: Workflow Management Data Layer: Data Framework&Usage Forecast Model: Model Training & Prediction - Strategy: Portfolio Management - Intraday Trading: Model&Strategy Testing + Portfolio Management and Backtest + Nested Decision Execution: High-Frequency Trading Qlib Recorder: Experiment Management Analysis: Evaluation & Results Analysis Online Serving: Online Management & Strategy & Tool diff --git a/docs/introduction/introduction.rst b/docs/introduction/introduction.rst index a55edd5eca..ffd7599c4a 100644 --- a/docs/introduction/introduction.rst +++ b/docs/introduction/introduction.rst @@ -34,9 +34,14 @@ Name Description `Workflow` layer `Workflow` layer covers the whole workflow of quantitative investment. `Information Extractor` extracts data for models. `Forecast Model` focuses - on producing all kinds of forecast signals (e.g. _alpha_, risk) for other - modules. With these signals `Portfolio Generator` will generate the target - portfolio and produce orders to be executed by `Order Executor`. + on producing all kinds of forecast signals (e.g. *alpha*, risk) for other + modules. With these signals `Decision Generator` will generate the target + trading decisions(i.e. portfolio, orders) to be executed by `Execution Env` + (i.e. the trading market). There may be multiple levels of `Trading Agent` + and `Execution Env` (e.g. an *order executor trading agent and intraday + order execution environment* could behave like an interday trading + environment and nested in *daily portfolio management trading agent and + interday trading environment* ) `Interface` layer `Interface` layer tries to present a user-friendly interface for the underlying system. `Analyser` module will provide users detailed analysis reports of diff --git a/examples/nested_decision_execution/workflow.py b/examples/nested_decision_execution/workflow.py index 6cd642e427..991deaa9dd 100644 --- a/examples/nested_decision_execution/workflow.py +++ b/examples/nested_decision_execution/workflow.py @@ -110,14 +110,6 @@ class NestedDecisionExecutionWorkflow: - # TODO: add test for nested workflow. - # 1) comparing same backtest - # - Basic test idea: the shared accumulated value are equal in multiple levels - # - Aligning the profit calculation between multiple levels and single levels. - # 2) comparing different backtest - # - Basic test idea: - # - the daily backtest will be similar as multi-level(the data quality makes this gap samller) - market = "csi300" benchmark = "SH000300" data_handler_config = { @@ -265,7 +257,6 @@ def backtest(self): self.port_analysis_config["backtest"]["benchmark"] = self.benchmark with R.start(experiment_name="backtest"): - recorder = R.get_recorder() par = PortAnaRecord( recorder, @@ -301,6 +292,14 @@ def collect_data(self): print(trade_decision) # the code below are for checking, users don't have to care about it + # The tests can be categorized into 2 types + # 1) comparing same backtest + # - Basic test idea: the shared accumulated value are equal in multiple levels + # - Aligning the profit calculation between multiple levels and single levels. + # 2) comparing different backtest + # - Basic test idea: + # - the daily backtest will be similar as multi-level(the data quality makes this gap samller) + def check_diff_freq(self): self._init_qlib() exp = R.get_exp(experiment_name="backtest") diff --git a/qlib/workflow/record_temp.py b/qlib/workflow/record_temp.py index cdc5f63913..ca6a9d6957 100644 --- a/qlib/workflow/record_temp.py +++ b/qlib/workflow/record_temp.py @@ -401,8 +401,8 @@ def _get_report_freq(self, executor_config): if executor_config["kwargs"].get("generate_portfolio_metrics", False): _count, _freq = Freq.parse(executor_config["kwargs"]["time_per_step"]) ret_freq.append(f"{_count}{_freq}") - if "sub_env" in executor_config["kwargs"]: - ret_freq.extend(self._get_report_freq(executor_config["kwargs"]["sub_env"])) + if "inner_executor" in executor_config["kwargs"]: + ret_freq.extend(self._get_report_freq(executor_config["kwargs"]["inner_executor"])) return ret_freq def generate(self, **kwargs):