66import os
77import time
88import traceback
9- from datetime import datetime
9+ from datetime import datetime , timezone
1010
1111from flask import Flask
1212
2929 build_sender ,
3030 build_translator ,
3131)
32+ from quant_platform_kit .common .runtime_reports import (
33+ append_runtime_report_error ,
34+ build_runtime_report_base ,
35+ finalize_runtime_report ,
36+ persist_runtime_report ,
37+ )
3238from runtime_logging import RuntimeLogContext , build_run_id , emit_runtime_log
3339from quant_platform_kit .longbridge import (
3440 build_contexts ,
@@ -114,6 +120,35 @@ def log_runtime_event(log_context, event, **fields):
114120 )
115121
116122
123+ def build_execution_report (log_context ):
124+ return build_runtime_report_base (
125+ platform = log_context .platform ,
126+ deploy_target = log_context .deploy_target ,
127+ service_name = log_context .service_name ,
128+ strategy_profile = STRATEGY_PROFILE ,
129+ strategy_domain = RUNTIME_SETTINGS .strategy_domain ,
130+ account_scope = log_context .account_scope ,
131+ account_region = log_context .account_region ,
132+ run_id = log_context .run_id ,
133+ run_source = "cloud_run" ,
134+ started_at = datetime .now (timezone .utc ),
135+ summary = {
136+ "managed_symbols" : list (MANAGED_SYMBOLS ),
137+ "account_prefix" : ACCOUNT_PREFIX ,
138+ },
139+ )
140+
141+
142+ def persist_execution_report (report ):
143+ persisted = persist_runtime_report (
144+ report ,
145+ base_dir = os .getenv ("EXECUTION_REPORT_OUTPUT_DIR" ),
146+ gcs_prefix_uri = os .getenv ("EXECUTION_REPORT_GCS_URI" ),
147+ gcp_project_id = PROJECT_ID ,
148+ )
149+ return persisted .gcs_uri or persisted .local_path
150+
151+
117152def is_filled_status (status ):
118153 return notifications_is_filled_status (status )
119154
@@ -228,6 +263,7 @@ def resolve_rebalance_plan(*, indicators, account_state):
228263
229264def run_strategy ():
230265 log_context = RUNTIME_LOG_CONTEXT .with_run (build_run_id ())
266+ report = build_execution_report (log_context )
231267 try :
232268 log_runtime_event (
233269 log_context ,
@@ -253,6 +289,13 @@ def run_strategy():
253289 "outside_market_hours" ,
254290 message = "Outside market hours; skip execution" ,
255291 )
292+ finalize_runtime_report (
293+ report ,
294+ status = "skipped" ,
295+ diagnostics = {
296+ "skip_reason" : "market_closed" ,
297+ },
298+ )
256299 print (with_prefix ("Outside market hours; skip." ), flush = True )
257300 return
258301 run_rebalance_cycle (
@@ -276,13 +319,21 @@ def run_strategy():
276319 estimate_max_purchase_quantity = estimate_max_purchase_quantity ,
277320 submit_order_with_alert = submit_order_with_alert ,
278321 )
322+ finalize_runtime_report (report , status = "ok" )
279323 log_runtime_event (
280324 log_context ,
281325 "strategy_cycle_completed" ,
282326 message = "Strategy execution completed" ,
283327 )
284328
285329 except Exception as exc :
330+ append_runtime_report_error (
331+ report ,
332+ stage = "strategy_cycle" ,
333+ message = str (exc ),
334+ error_type = type (exc ).__name__ ,
335+ )
336+ finalize_runtime_report (report , status = "error" )
286337 log_runtime_event (
287338 log_context ,
288339 "strategy_cycle_failed" ,
@@ -294,6 +345,12 @@ def run_strategy():
294345 err = traceback .format_exc ()
295346 print (with_prefix (f"Strategy error:\n { err } " ), flush = True )
296347 send_tg_message (f"{ t ('error_title' )} \n { err } " )
348+ finally :
349+ try :
350+ report_path = persist_execution_report (report )
351+ print (f"execution_report { report_path } " , flush = True )
352+ except Exception as persist_exc :
353+ print (f"failed to persist execution report: { persist_exc } " , flush = True )
297354
298355@app .route ("/" , methods = ["POST" , "GET" ])
299356def handle_trigger ():
0 commit comments