From 28d455693ae9c1900f384161ec44978d99d13292 Mon Sep 17 00:00:00 2001 From: Pigbibi <20649888+Pigbibi@users.noreply.github.com> Date: Thu, 9 Jul 2026 04:17:40 +0800 Subject: [PATCH 1/2] feat(rebalance): record execution telemetry via PerformanceMonitor Persist IBKR execution summaries after each strategy cycle using QuantPlatformKit try_record_platform_execution(). Co-Authored-By: Claude Co-authored-by: Cursor --- application/rebalance_service.py | 32 ++++++++++++++++++++++++++++++++ pyproject.toml | 2 +- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/application/rebalance_service.py b/application/rebalance_service.py index d2b4d84..079f67d 100644 --- a/application/rebalance_service.py +++ b/application/rebalance_service.py @@ -24,6 +24,7 @@ localize_notification_text as _base_localize_notification_text, translator_uses_zh as _base_translator_uses_zh, ) +from quant_platform_kit.strategy_lifecycle.performance_monitor import try_record_platform_execution from quant_platform_kit.common.port_adapters import CallableNotificationPort, CallablePortfolioPort @@ -37,6 +38,31 @@ _DETAIL_FIELD_SPLIT_RE = re.compile(r"\s+(?=[^\s=::]+[=::])") +def _record_platform_execution_telemetry( + signal_metadata: Mapping[str, object] | None, + execution_summary: Mapping[str, object] | None, +) -> None: + metadata = signal_metadata if isinstance(signal_metadata, Mapping) else {} + profile = str(metadata.get("strategy_profile") or "").strip() + if not profile: + return + summary = dict(execution_summary or {}) + try_record_platform_execution( + profile, + { + "platform": "ibkr", + "mode": summary.get("mode"), + "execution_status": summary.get("execution_status"), + "no_op_reason": summary.get("no_op_reason") or metadata.get("no_op_reason"), + "orders_submitted": list(summary.get("orders_submitted") or ()), + "orders_filled": list(summary.get("orders_filled") or ()), + "orders_skipped": list(summary.get("orders_skipped") or ()), + "trade_date": summary.get("trade_date") or metadata.get("trade_date"), + }, + domain=str(metadata.get("domain") or ""), + ) + + def _format_text(value, *, fallback: str) -> str: text = str(value).strip() if value is not None else "" return text or fallback @@ -885,6 +911,7 @@ def run_strategy_core( extra_notification_lines=config.extra_notification_lines, ) ) + _record_platform_execution_telemetry(signal_metadata, {}) return StrategyCycleResult( result="OK - no-op" if notification_suppressed else "OK - heartbeat", signal_metadata=dict(signal_metadata or {}), @@ -969,6 +996,10 @@ def run_strategy_core( extra_notification_lines=config.extra_notification_lines, ) ) + _record_platform_execution_telemetry( + signal_metadata, + {"action_done": False, "no_op_reason": "execution_already_recorded"}, + ) return StrategyCycleResult( result="OK - no-op" if notification_suppressed else "OK - heartbeat", signal_metadata=dict(signal_metadata or {}), @@ -1063,6 +1094,7 @@ def run_strategy_core( ), flush=True, ) + _record_platform_execution_telemetry(signal_metadata, dict(execution_summary or {})) return StrategyCycleResult( result="OK - executed", signal_metadata=dict(signal_metadata or {}), diff --git a/pyproject.toml b/pyproject.toml index 3a7e027..d5a1654 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ dependencies = [ "google-cloud-secret-manager", "google-cloud-storage", "yfinance", - "quant-platform-kit @ git+https://github.com/QuantStrategyLab/QuantPlatformKit.git@f1d2c323b2a96383acec83a07bbf1816938c4650", + "quant-platform-kit @ git+https://github.com/QuantStrategyLab/QuantPlatformKit.git@724fb81e5bc7423cae5e073c3094c33ed1dba1d4", "us-equity-strategies @ git+https://github.com/QuantStrategyLab/UsEquityStrategies.git@17ddb86c72d44b2c7b78ba7a10d8f71b21180166", "hk-equity-strategies @ git+https://github.com/QuantStrategyLab/HkEquityStrategies.git@b6a8ac2ad3c8110b5ea74fb059c8206388d63bcd", ] From 98a877e3e87784162e8e10c75c44083de7485aaa Mon Sep 17 00:00:00 2001 From: Pigbibi <20649888+Pigbibi@users.noreply.github.com> Date: Thu, 9 Jul 2026 05:10:32 +0800 Subject: [PATCH 2/2] fix(ci): align QPK pin with canonical 0af622a after #199 merge Co-Authored-By: Claude Co-authored-by: Cursor --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index d5a1654..a7338a1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ dependencies = [ "google-cloud-secret-manager", "google-cloud-storage", "yfinance", - "quant-platform-kit @ git+https://github.com/QuantStrategyLab/QuantPlatformKit.git@724fb81e5bc7423cae5e073c3094c33ed1dba1d4", + "quant-platform-kit @ git+https://github.com/QuantStrategyLab/QuantPlatformKit.git@0af622ac9d47f7ef93f9379f9ded314c27a344ff", "us-equity-strategies @ git+https://github.com/QuantStrategyLab/UsEquityStrategies.git@17ddb86c72d44b2c7b78ba7a10d8f71b21180166", "hk-equity-strategies @ git+https://github.com/QuantStrategyLab/HkEquityStrategies.git@b6a8ac2ad3c8110b5ea74fb059c8206388d63bcd", ]