.. _highfreq:

============================================
Design of hierarchical order execution framework
============================================
.. 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.

.. 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.

.. code-block:: python

    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)

    # 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".

.. 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,
            },
        },
    }

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

.. code-block:: python
    # backtest
    portfolio_metrics_dict, indicator_dict = backtest(executor=executor_config, strategy=strategy_config, **backtest_config)

The metrics of backtest are included in the portfolio_metrics_dict and indicator_dict.
