3535)
3636from decision_mapper import map_strategy_decision_to_plan
3737from notifications .telegram import build_sender , build_translator , render_cycle_summary
38+ from quant_platform_kit .common .execution_outcomes import (
39+ filter_execution_blocking_skips ,
40+ is_terminal_funding_block ,
41+ resolve_strategy_run_stage ,
42+ )
3843from quant_platform_kit .common .runtime_inputs import (
3944 build_semiconductor_rotation_indicators_from_history ,
4045 required_semiconductor_rotation_history_lookback ,
4146)
47+ from quant_platform_kit .notifications .events import NotificationPublisher , RenderedNotification
4248from quant_platform_kit .strategy_contracts import build_strategy_evaluation_inputs
4349from runtime_config_support import PlatformRuntimeSettings , load_platform_runtime_settings
4450from strategy_runtime import load_strategy_runtime
4551
4652LIMIT_SELL_DISCOUNT = 0.995
4753LIMIT_BUY_PREMIUM = 1.005
48- EXECUTION_BLOCKING_SKIP_REASONS = frozenset (
49- {
50- "buy_quantity_zero" ,
51- "insufficient_cash_for_whole_share" ,
52- "quote_unavailable" ,
53- "sell_quantity_zero" ,
54- }
55- )
56- TERMINAL_FUNDING_BLOCK_SKIP_REASONS = frozenset ({"insufficient_cash_for_whole_share" })
5754
5855
5956def _utcnow () -> datetime :
@@ -64,41 +61,6 @@ def get_project_id() -> str | None:
6461 return os .getenv ("GOOGLE_CLOUD_PROJECT" )
6562
6663
67- def _execution_blocking_skips (skipped_orders : list [dict [str , Any ]]) -> list [dict [str , Any ]]:
68- return [
69- dict (item )
70- for item in skipped_orders
71- if str (item .get ("reason" ) or "" ) in EXECUTION_BLOCKING_SKIP_REASONS
72- ]
73-
74-
75- def _is_terminal_funding_block (blocking_skips : list [dict [str , Any ]]) -> bool :
76- if not blocking_skips :
77- return False
78- return all (
79- str (item .get ("reason" ) or "" ) in TERMINAL_FUNDING_BLOCK_SKIP_REASONS
80- for item in blocking_skips
81- )
82-
83-
84- def _resolve_strategy_run_stage (
85- * ,
86- dry_run_only : bool ,
87- execution_blocked : bool ,
88- terminal_funding_block : bool ,
89- action_done : bool ,
90- ) -> str :
91- if dry_run_only :
92- return "DRY_RUN_COMPLETED"
93- if terminal_funding_block and not action_done :
94- return "FUNDING_BLOCKED"
95- if execution_blocked and action_done :
96- return "PARTIAL_SUBMITTED"
97- if execution_blocked :
98- return "EXECUTION_BLOCKED"
99- return "SUBMITTED" if action_done else "NO_ACTION"
100-
101-
10264def _series_from_price_history (market_data_port , symbol : str ) -> pd .Series :
10365 series = market_data_port .get_price_series (symbol )
10466 index = pd .DatetimeIndex ([pd .Timestamp (point .as_of ) for point in series .points ])
@@ -179,13 +141,24 @@ def _publish_cycle_notification(
179141 * ,
180142 settings : PlatformRuntimeSettings ,
181143 notification_sender : Callable [[str ], None ] | None = None ,
144+ log_message : Callable [[str ], None ] = print ,
182145) -> bool :
183146 sender = notification_sender
184147 if sender is None :
185148 if not settings .tg_token or not settings .tg_chat_id :
186149 return False
187150 sender = build_sender (settings .tg_token , settings .tg_chat_id )
188- sender (render_cycle_summary (result , lang = settings .notify_lang ))
151+ message = render_cycle_summary (result , lang = settings .notify_lang )
152+ def publish_log (text : str ) -> None :
153+ try :
154+ log_message (text , flush = True )
155+ except TypeError :
156+ log_message (text )
157+
158+ NotificationPublisher (
159+ log_message = publish_log ,
160+ send_message = sender ,
161+ ).publish (RenderedNotification (detailed_text = message , compact_text = message ))
189162 return True
190163
191164
@@ -330,11 +303,11 @@ def run_strategy_cycle(
330303 )
331304 submitted_orders = list (execution_result .submitted_orders )
332305 skipped_orders = list (execution_result .skipped_orders )
333- blocking_skips = _execution_blocking_skips (skipped_orders )
306+ blocking_skips = filter_execution_blocking_skips (skipped_orders )
334307 execution_blocked = bool (blocking_skips )
335- funding_blocked = _is_terminal_funding_block (blocking_skips )
308+ funding_blocked = is_terminal_funding_block (blocking_skips )
336309 terminal_funding_block = funding_blocked and not execution_result .action_done
337- strategy_run_stage = _resolve_strategy_run_stage (
310+ strategy_run_stage = resolve_strategy_run_stage (
338311 dry_run_only = settings .dry_run_only ,
339312 execution_blocked = execution_blocked ,
340313 terminal_funding_block = terminal_funding_block ,
0 commit comments