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:
@@ -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)
|
||||||
|
|||||||
@@ -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):
|
||||||
"""
|
"""
|
||||||
|
|||||||
Reference in New Issue
Block a user