1
0
mirror of https://github.com/microsoft/qlib.git synced 2026-07-14 16:26:55 +08:00

Supporting skip empty decisions

This commit is contained in:
Young
2021-07-06 12:08:53 +00:00
parent dd8231edeb
commit 6fd50a5bfa
2 changed files with 33 additions and 16 deletions

View File

@@ -191,6 +191,7 @@ class NestedExecutor(BaseExecutor):
generate_report: bool = False, generate_report: bool = False,
verbose: bool = False, verbose: bool = False,
track_data: bool = False, track_data: bool = False,
skip_empty_decision: bool = True,
trade_exchange: Exchange = None, trade_exchange: Exchange = None,
common_infra: CommonInfrastructure = None, common_infra: CommonInfrastructure = None,
**kwargs, **kwargs,
@@ -206,6 +207,11 @@ class NestedExecutor(BaseExecutor):
exchange that provides market info, used to generate report exchange that provides market info, used to generate report
- If generate_report is None, trade_exchange will be ignored - If generate_report is None, trade_exchange will be ignored
- Else If `trade_exchange` is None, self.trade_exchange will be set with common_infra - Else If `trade_exchange` is None, self.trade_exchange will be set with common_infra
skip_empty_decision: bool
Will the executor skip the inner loop when the decision is empty.
It should be False in following cases
- The decisions may be updated by steps
- The inner executor may not follow the decisions from the outer strategy
""" """
self.inner_executor = init_instance_by_config( self.inner_executor = init_instance_by_config(
inner_executor, common_infra=common_infra, accept_types=BaseExecutor inner_executor, common_infra=common_infra, accept_types=BaseExecutor
@@ -214,6 +220,8 @@ class NestedExecutor(BaseExecutor):
inner_strategy, common_infra=common_infra, accept_types=BaseStrategy inner_strategy, common_infra=common_infra, accept_types=BaseStrategy
) )
self._skip_empty_decision = skip_empty_decision
super(NestedExecutor, self).__init__( super(NestedExecutor, self).__init__(
time_per_step=time_per_step, time_per_step=time_per_step,
start_time=start_time, start_time=start_time,
@@ -259,26 +267,32 @@ class NestedExecutor(BaseExecutor):
def collect_data(self, trade_decision: BaseTradeDecision, return_value=None): def collect_data(self, trade_decision: BaseTradeDecision, return_value=None):
if self.track_data: if self.track_data:
yield trade_decision yield trade_decision
self._init_sub_trading(trade_decision)
execute_result = [] execute_result = []
inner_order_indicators = [] inner_order_indicators = []
_inner_execute_result = None
while not self.inner_executor.finished():
# outter strategy have chance to update decision each iterator
updated_trade_decision = trade_decision.update(self.inner_executor.trade_calendar)
if updated_trade_decision is not None:
trade_decision = updated_trade_decision
# NEW UPDATE
# create a hook for inner strategy to update outter decision
self.inner_strategy.alter_outer_trade_decision(trade_decision)
_inner_trade_decision = self.inner_strategy.generate_trade_decision(_inner_execute_result) if not (trade_decision.empty() and self._skip_empty_decision):
_inner_execute_result = None
self._init_sub_trading(trade_decision)
while not self.inner_executor.finished():
# outter strategy have chance to update decision each iterator
updated_trade_decision = trade_decision.update(self.inner_executor.trade_calendar)
if updated_trade_decision is not None:
trade_decision = updated_trade_decision
# NEW UPDATE
# create a hook for inner strategy to update outter decision
self.inner_strategy.alter_outer_trade_decision(trade_decision)
# NOTE: Trade Calendar will step forward in the follow line _inner_trade_decision = self.inner_strategy.generate_trade_decision(_inner_execute_result)
_inner_execute_result = yield from self.inner_executor.collect_data(trade_decision=_inner_trade_decision)
execute_result.extend(_inner_execute_result) # NOTE: Trade Calendar will step forward in the follow line
inner_order_indicators.append(self.inner_executor.trade_account.get_trade_indicator().get_order_indicator()) _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.trade_account.get_trade_indicator().get_order_indicator()
)
trade_step = self.trade_calendar.get_trade_step() trade_step = self.trade_calendar.get_trade_step()
trade_start_time, trade_end_time = self.trade_calendar.get_step_time(trade_step) trade_start_time, trade_end_time = self.trade_calendar.get_step_time(trade_step)

View File

@@ -197,7 +197,7 @@ class BaseTradeDecision:
Example: Example:
[]: []:
Decision not available Decision not available
concrete_decision: [concrete_decision]:
available available
""" """
raise NotImplementedError(f"This type of input is not supported") raise NotImplementedError(f"This type of input is not supported")
@@ -236,6 +236,9 @@ class BaseTradeDecision:
""" """
raise NotImplementedError(f"Please implement the `func` method") raise NotImplementedError(f"Please implement the `func` method")
def empty(self) -> bool:
return len(self.get_decision()) == 0
class TradeDecisionWO(BaseTradeDecision): class TradeDecisionWO(BaseTradeDecision):
""" """