diff --git a/examples/workflow_by_code.py b/examples/workflow_by_code.py index 92ce6aa34..1708a634e 100644 --- a/examples/workflow_by_code.py +++ b/examples/workflow_by_code.py @@ -66,32 +66,45 @@ if __name__ == "__main__": }, } + # model initialization + model = init_instance_by_config(task["model"]) + dataset = init_instance_by_config(task["dataset"]) + port_analysis_config = { + "executor": { + "class": "SimulatorExecutor", + "module_path": "qlib.backtest.executor", + "kwargs": { + "time_per_step": "day", + "generate_report": True, + }, + }, "strategy": { "class": "TopkDropoutStrategy", - "module_path": "qlib.contrib.strategy.strategy", + "module_path": "qlib.contrib.strategy.model_strategy", "kwargs": { + "model": model, + "dataset": dataset, "topk": 50, "n_drop": 5, }, }, "backtest": { - "verbose": False, - "limit_threshold": 0.095, + "start_time": "2017-01-01", + "end_time": "2020-08-01", "account": 100000000, "benchmark": benchmark, - "deal_price": "close", - "open_cost": 0.0005, - "close_cost": 0.0015, - "min_cost": 5, - "return_order": True, + "exchange_kwargs": { + "freq": "day", + "limit_threshold": 0.095, + "deal_price": "close", + "open_cost": 0.0005, + "close_cost": 0.0015, + "min_cost": 5, + }, }, } - # model initialization - model = init_instance_by_config(task["model"]) - dataset = init_instance_by_config(task["dataset"]) - # NOTE: This line is optional # It demonstrates that the dataset can be used standalone. example_df = dataset.prepare("train") @@ -110,5 +123,5 @@ if __name__ == "__main__": # backtest. If users want to use backtest based on their own prediction, # please refer to https://qlib.readthedocs.io/en/latest/component/recorder.html#record-template. - par = PortAnaRecord(recorder, port_analysis_config) + par = PortAnaRecord(recorder, port_analysis_config, "day") par.generate() diff --git a/qlib/backtest/__init__.py b/qlib/backtest/__init__.py index 33c2cb2d8..1adad91d2 100644 --- a/qlib/backtest/__init__.py +++ b/qlib/backtest/__init__.py @@ -8,6 +8,7 @@ from .backtest import backtest as backtest_func from .backtest import collect_data as data_generator from .utils import CommonInfrastructure +from .order import Order from ..strategy.base import BaseStrategy from ..utils import init_instance_by_config from ..log import get_module_logger diff --git a/qlib/backtest/executor.py b/qlib/backtest/executor.py index 1cc198bf6..e68047e38 100644 --- a/qlib/backtest/executor.py +++ b/qlib/backtest/executor.py @@ -118,6 +118,9 @@ class BaseExecutor: def get_report(self): raise NotImplementedError("get_report is not implemented!") + def get_all_executor(self): + return [self] + class NestedExecutor(BaseExecutor): """ @@ -244,6 +247,9 @@ class NestedExecutor(BaseExecutor): sub_env_report_dict.update({f"{_count}{_freq}": (_report, _positions)}) return sub_env_report_dict + def get_all_executor(self): + return [self, *self.inner_executor.get_all_executor()] + class SimulatorExecutor(BaseExecutor): """Executor that simulate the true market""" diff --git a/qlib/backtest/order.py b/qlib/backtest/order.py index 30cc0c623..e4bf41f1e 100644 --- a/qlib/backtest/order.py +++ b/qlib/backtest/order.py @@ -11,10 +11,11 @@ class Order: stock_id : str amount : float start_time : pd.Timestamp - closed start time for order generation + closed start time for order trading end_time : pd.Timestamp - closed end time for order generation - direction : Order.SELL for sell; Order.BUY for buy + closed end time for order trading + direction : int + Order.SELL for sell; Order.BUY for buy factor : float presents the weight factor assigned in Exchange() """