mirror of
https://github.com/microsoft/qlib.git
synced 2026-07-06 20:41:09 +08:00
adapting strategies to latest interfaces.
This commit is contained in:
@@ -10,6 +10,8 @@ from tqdm.auto import tqdm
|
||||
def backtest_loop(start_time, end_time, trade_strategy: BaseStrategy, trade_executor: BaseExecutor):
|
||||
"""backtest funciton for the interaction of the outermost strategy and executor in the nested decision execution
|
||||
|
||||
please refer to the docs of `collect_data_loop`
|
||||
|
||||
Returns
|
||||
-------
|
||||
report: Report
|
||||
@@ -28,8 +30,11 @@ def collect_data_loop(start_time, end_time, trade_strategy: BaseStrategy, trade_
|
||||
----------
|
||||
start_time : pd.Timestamp|str
|
||||
closed start time for backtest
|
||||
**NOTE**: This will be applied to the outmost executor's calendar.
|
||||
end_time : pd.Timestamp|str
|
||||
closed end time for backtest
|
||||
**NOTE**: This will be applied to the outmost executor's calendar.
|
||||
E.g. Executor[day](Executor[1min]), setting `end_time == 20XX0301` will include all the minutes on 20XX0301
|
||||
trade_strategy : BaseStrategy
|
||||
the outermost portfolio strategy
|
||||
trade_executor : BaseExecutor
|
||||
|
||||
@@ -3,6 +3,8 @@ import warnings
|
||||
import pandas as pd
|
||||
from typing import Union
|
||||
|
||||
from qlib.backtest.report import Indicator
|
||||
|
||||
from .order import Order, BaseTradeDecision
|
||||
from .exchange import Exchange
|
||||
from .utils import TradeCalendarManager, CommonInfrastructure, LevelInfrastructure
|
||||
@@ -174,7 +176,7 @@ class BaseExecutor:
|
||||
else:
|
||||
raise ValueError("generate_report should be True if you want to generate report")
|
||||
|
||||
def get_trade_indicator(self):
|
||||
def get_trade_indicator(self) -> Indicator:
|
||||
"""get the trade indicator instance, which has pa/pos/ffr info."""
|
||||
return self.trade_account.indicator
|
||||
|
||||
@@ -279,7 +281,7 @@ class NestedExecutor(BaseExecutor):
|
||||
trade_decision = updated_trade_decision
|
||||
# NEW UPDATE
|
||||
# create a hook for inner strategy to update outter decision
|
||||
self.inner_strategy.alter_decision(trade_decision)
|
||||
self.inner_strategy.alter_outer_trade_decision(trade_decision)
|
||||
|
||||
_inner_trade_decision = self.inner_strategy.generate_trade_decision(_inner_execute_result)
|
||||
|
||||
@@ -287,7 +289,7 @@ class NestedExecutor(BaseExecutor):
|
||||
_inner_execute_result = yield from self.inner_executor.collect_data(trade_decision=_inner_trade_decision)
|
||||
|
||||
execute_result.extend(_inner_execute_result)
|
||||
inner_order_indicators.append(self.inner_executor.get_trade_indicator().get_order_indicator)
|
||||
inner_order_indicators.append(self.inner_executor.get_trade_indicator().get_order_indicator())
|
||||
|
||||
if hasattr(self, "trade_account"):
|
||||
trade_step = self.trade_calendar.get_trade_step()
|
||||
|
||||
@@ -56,7 +56,7 @@ class BaseTradeDecision:
|
||||
2. After a period of time, the decision are updated and become available
|
||||
3. The inner strategy try to get the decision and start to execute the decision according to `get_range_limit`
|
||||
Case 2:
|
||||
1. The strategy is available at the start of the interval
|
||||
1. The outer strategy's decision is available at the start of the interval
|
||||
2. Same as `case 1.3`
|
||||
"""
|
||||
def __init__(self, strategy: BaseStrategy):
|
||||
@@ -133,14 +133,19 @@ class TradeDecisionWO(BaseTradeDecision):
|
||||
def get_range_limit(self) -> Tuple[int, int]:
|
||||
if self.idx_range is None:
|
||||
# Default to get full index
|
||||
return 0, self.strategy.trade_calendar.get_trade_len() - 1
|
||||
raise NotImplementedError(f"The decision didn't provide an index range")
|
||||
return self.idx_range
|
||||
|
||||
def get_decision(self) -> List[object]:
|
||||
return self.order_list
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"strategy: {self.strategy}; idx_range: {self.idx_range}; order_list[{len(self.order_list)}]"
|
||||
|
||||
|
||||
# TODO: the orders below need to be discussed ------------------------------------
|
||||
# - The classes below are designed for Case 1
|
||||
# - However, Case 1 can't take `order_pool` as the an argument as the constructor function
|
||||
class TradeDecisionWithOrderPool:
|
||||
"""trade decision that made by strategy"""
|
||||
|
||||
|
||||
@@ -395,11 +395,9 @@ class Indicator:
|
||||
)
|
||||
)
|
||||
|
||||
@property
|
||||
def get_order_indicator(self):
|
||||
return self.order_indicator
|
||||
|
||||
@property
|
||||
def get_trade_indicator(self):
|
||||
return self.trade_indicator
|
||||
|
||||
|
||||
@@ -103,6 +103,9 @@ class TradeCalendarManager:
|
||||
"""Get the start_time and end_time for trading"""
|
||||
return self.start_time, self.end_time
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"{self.start_time}[{self.start_index}]~{self.end_time}[{self.end_index}]: [{self.trade_step}/{self.trade_len}]"
|
||||
|
||||
|
||||
class BaseInfrastructure:
|
||||
def __init__(self, **kwargs):
|
||||
|
||||
Reference in New Issue
Block a user