Skip to content

Commit 28d4556

Browse files
Pigbibiclaudecursoragent
committed
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 <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 270bfe8 commit 28d4556

2 files changed

Lines changed: 33 additions & 1 deletion

File tree

application/rebalance_service.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
localize_notification_text as _base_localize_notification_text,
2525
translator_uses_zh as _base_translator_uses_zh,
2626
)
27+
from quant_platform_kit.strategy_lifecycle.performance_monitor import try_record_platform_execution
2728
from quant_platform_kit.common.port_adapters import CallableNotificationPort, CallablePortfolioPort
2829

2930

@@ -37,6 +38,31 @@
3738
_DETAIL_FIELD_SPLIT_RE = re.compile(r"\s+(?=[^\s=::]+[=::])")
3839

3940

41+
def _record_platform_execution_telemetry(
42+
signal_metadata: Mapping[str, object] | None,
43+
execution_summary: Mapping[str, object] | None,
44+
) -> None:
45+
metadata = signal_metadata if isinstance(signal_metadata, Mapping) else {}
46+
profile = str(metadata.get("strategy_profile") or "").strip()
47+
if not profile:
48+
return
49+
summary = dict(execution_summary or {})
50+
try_record_platform_execution(
51+
profile,
52+
{
53+
"platform": "ibkr",
54+
"mode": summary.get("mode"),
55+
"execution_status": summary.get("execution_status"),
56+
"no_op_reason": summary.get("no_op_reason") or metadata.get("no_op_reason"),
57+
"orders_submitted": list(summary.get("orders_submitted") or ()),
58+
"orders_filled": list(summary.get("orders_filled") or ()),
59+
"orders_skipped": list(summary.get("orders_skipped") or ()),
60+
"trade_date": summary.get("trade_date") or metadata.get("trade_date"),
61+
},
62+
domain=str(metadata.get("domain") or ""),
63+
)
64+
65+
4066
def _format_text(value, *, fallback: str) -> str:
4167
text = str(value).strip() if value is not None else ""
4268
return text or fallback
@@ -885,6 +911,7 @@ def run_strategy_core(
885911
extra_notification_lines=config.extra_notification_lines,
886912
)
887913
)
914+
_record_platform_execution_telemetry(signal_metadata, {})
888915
return StrategyCycleResult(
889916
result="OK - no-op" if notification_suppressed else "OK - heartbeat",
890917
signal_metadata=dict(signal_metadata or {}),
@@ -969,6 +996,10 @@ def run_strategy_core(
969996
extra_notification_lines=config.extra_notification_lines,
970997
)
971998
)
999+
_record_platform_execution_telemetry(
1000+
signal_metadata,
1001+
{"action_done": False, "no_op_reason": "execution_already_recorded"},
1002+
)
9721003
return StrategyCycleResult(
9731004
result="OK - no-op" if notification_suppressed else "OK - heartbeat",
9741005
signal_metadata=dict(signal_metadata or {}),
@@ -1063,6 +1094,7 @@ def run_strategy_core(
10631094
),
10641095
flush=True,
10651096
)
1097+
_record_platform_execution_telemetry(signal_metadata, dict(execution_summary or {}))
10661098
return StrategyCycleResult(
10671099
result="OK - executed",
10681100
signal_metadata=dict(signal_metadata or {}),

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ dependencies = [
2121
"google-cloud-secret-manager",
2222
"google-cloud-storage",
2323
"yfinance",
24-
"quant-platform-kit @ git+https://github.com/QuantStrategyLab/QuantPlatformKit.git@f1d2c323b2a96383acec83a07bbf1816938c4650",
24+
"quant-platform-kit @ git+https://github.com/QuantStrategyLab/QuantPlatformKit.git@724fb81e5bc7423cae5e073c3094c33ed1dba1d4",
2525
"us-equity-strategies @ git+https://github.com/QuantStrategyLab/UsEquityStrategies.git@17ddb86c72d44b2c7b78ba7a10d8f71b21180166",
2626
"hk-equity-strategies @ git+https://github.com/QuantStrategyLab/HkEquityStrategies.git@b6a8ac2ad3c8110b5ea74fb059c8206388d63bcd",
2727
]

0 commit comments

Comments
 (0)