From 4fb460351bc1107e14f735b1786e9e9ffff05343 Mon Sep 17 00:00:00 2001 From: Pigbibi <20649888+Pigbibi@users.noreply.github.com> Date: Wed, 17 Jun 2026 02:39:40 +0800 Subject: [PATCH] Delegate market regime manual notifications --- docs/market-regime-control-plan.md | 6 ++++++ docs/market-regime-control-plan.zh-CN.md | 4 ++++ .../strategy_plugin_runner.py | 14 ++++++++++++++ tests/test_strategy_plugin_runner.py | 10 ++++++++++ 4 files changed, 34 insertions(+) diff --git a/docs/market-regime-control-plan.md b/docs/market-regime-control-plan.md index d253438..eeb6042 100644 --- a/docs/market-regime-control-plan.md +++ b/docs/market-regime-control-plan.md @@ -180,6 +180,12 @@ the human notification body: - Human notification copy should contain only the situation and suggested action; it should not display internal governance fields such as `position_control_allowed`, `execution_controls`, route codes, or veto codes. +- `market_regime_control` strategy artifacts set + `execution_controls.manual_review_notification_delegated = true` and + `manual_review_notification_target = market_regime_notification`. When + multiple strategies mount the same plugin, the manual-review plugin bot should + consume the single notification-target artifact instead of emitting one alert + per strategy artifact. SOXL/SOXX is now in the strategy-level `market_regime_control` consumption registry for automation-approved deterministic fields. It also keeps the diff --git a/docs/market-regime-control-plan.zh-CN.md b/docs/market-regime-control-plan.zh-CN.md index a03ece7..f5bc3db 100644 --- a/docs/market-regime-control-plan.zh-CN.md +++ b/docs/market-regime-control-plan.zh-CN.md @@ -103,6 +103,10 @@ - `notification_only`、TACO、panic reversal、AI audit 和通用通知只用于人工查看。 - 专用插件告警 bot 只发布人工复核或 notification-only 插件信号。如果策略消费了已通过自动化证据批准的 `defend` 或 `delever` 路线,并实际产生仓位影响,面向用户的通知应由该策略运行结果承载。 +- `market_regime_control` 的 strategy artifact 会写入 + `execution_controls.manual_review_notification_delegated = true` 和 + `manual_review_notification_target = market_regime_notification`。因此多个策略同时挂载同一插件时, + 人工复核插件 bot 只消费统一 notification target artifact,避免 TQQQ/SOXL 等策略重复推送同一类市场状态提醒。 - 人工通知正文只写“情况说明”和“建议操作”,不展示 `position_control_allowed`、 `execution_controls`、route code 或 veto code 等内部治理字段。 diff --git a/src/quant_strategy_plugins/strategy_plugin_runner.py b/src/quant_strategy_plugins/strategy_plugin_runner.py index e974643..f0a9853 100644 --- a/src/quant_strategy_plugins/strategy_plugin_runner.py +++ b/src/quant_strategy_plugins/strategy_plugin_runner.py @@ -93,6 +93,7 @@ class PluginConsumptionPolicy: since_version: str description: str intended_strategy_role: str | None = None + manual_review_notification_target: str | None = None @dataclass(frozen=True) @@ -116,6 +117,7 @@ class PluginNotificationTargetPolicy: evidence_status=EVIDENCE_AUTOMATION_APPROVED, since_version="strategy_plugins.v1", description="Backtested automatic macro/crisis risk controls for the TQQQ growth-income strategy.", + manual_review_notification_target=GENERAL_MARKET_REGIME_NOTIFICATION_TARGET, ), PluginConsumptionPolicy( plugin=PLUGIN_MARKET_REGIME_CONTROL, @@ -125,6 +127,7 @@ class PluginNotificationTargetPolicy: evidence_status=EVIDENCE_NOTIFICATION_ONLY, since_version="strategy_plugins.v1", description="Pending 25-30 year market-regime-control validation for broad ETF rotation.", + manual_review_notification_target=GENERAL_MARKET_REGIME_NOTIFICATION_TARGET, ), PluginConsumptionPolicy( plugin=PLUGIN_MARKET_REGIME_CONTROL, @@ -134,6 +137,7 @@ class PluginNotificationTargetPolicy: evidence_status=EVIDENCE_NOTIFICATION_ONLY, since_version="strategy_plugins.v1", description="Pending 25-30 year market-regime-control validation for the Russell 1000 defensive sleeve.", + manual_review_notification_target=GENERAL_MARKET_REGIME_NOTIFICATION_TARGET, ), PluginConsumptionPolicy( plugin=PLUGIN_MARKET_REGIME_CONTROL, @@ -143,6 +147,7 @@ class PluginNotificationTargetPolicy: evidence_status=EVIDENCE_NOTIFICATION_ONLY, since_version="strategy_plugins.v1", description="Pending 25-30 year market-regime-control validation for the mega-cap leader rotation profile.", + manual_review_notification_target=GENERAL_MARKET_REGIME_NOTIFICATION_TARGET, ), PluginConsumptionPolicy( plugin=PLUGIN_MARKET_REGIME_CONTROL, @@ -152,6 +157,7 @@ class PluginNotificationTargetPolicy: evidence_status=EVIDENCE_AUTOMATION_APPROVED, since_version="strategy_plugins.v1", description="Backtested automatic macro/crisis risk controls for the SOXL/SOXX trend-income strategy.", + manual_review_notification_target=GENERAL_MARKET_REGIME_NOTIFICATION_TARGET, ), PluginConsumptionPolicy( plugin=PLUGIN_CRISIS_RESPONSE_SHADOW, @@ -1504,6 +1510,14 @@ def _apply_plugin_contract( execution_controls["notification_allowed"] = bool(consumption_policy.notification_allowed) execution_controls["position_control_allowed"] = bool(consumption_policy.position_control_allowed) execution_controls["consumption_evidence_status"] = consumption_policy.evidence_status + if consumption_policy.manual_review_notification_target: + delegated_notification_target = consumption_policy.manual_review_notification_target + execution_controls["manual_review_notification_delegated"] = True + execution_controls["manual_review_notification_target"] = delegated_notification_target + execution_controls["manual_review_notification_delegate"] = ( + f"notification_target:{delegated_notification_target}" + ) + execution_controls["manual_review_notification_authority"] = "plugin_notification_target" if consumption_policy.position_control_allowed: execution_controls["capital_impact"] = "strategy_opt_in" execution_controls["strategy_runtime_metadata_allowed"] = True diff --git a/tests/test_strategy_plugin_runner.py b/tests/test_strategy_plugin_runner.py index dc88a1d..be1ad9e 100644 --- a/tests/test_strategy_plugin_runner.py +++ b/tests/test_strategy_plugin_runner.py @@ -660,6 +660,7 @@ def test_strategy_plugin_runner_runs_general_market_regime_notification(tmp_path assert payload["execution_controls"]["strategy_runtime_metadata_allowed"] is False assert payload["execution_controls"]["position_control_allowed"] is False assert payload["execution_controls"]["consumption_evidence_status"] == EVIDENCE_NOTIFICATION_ONLY + assert "manual_review_notification_delegated" not in payload["execution_controls"] assert payload["notification_target_policy"]["notification_target"] == GENERAL_MARKET_REGIME_NOTIFICATION_TARGET assert payload["notification"]["localized_messages"]["en-US"].startswith("No notification required") assert "notification target" in payload["notification"]["localized_messages"]["en-US"] @@ -696,6 +697,15 @@ def test_strategy_plugin_runner_runs_unified_market_regime_control_for_soxl(tmp_ assert payload["execution_controls"]["strategy_runtime_metadata_allowed"] is True assert payload["execution_controls"]["capital_impact"] == "strategy_opt_in" assert payload["execution_controls"]["position_control_shadow_only"] is False + assert payload["execution_controls"]["manual_review_notification_delegated"] is True + assert ( + payload["execution_controls"]["manual_review_notification_target"] + == GENERAL_MARKET_REGIME_NOTIFICATION_TARGET + ) + assert ( + payload["execution_controls"]["manual_review_notification_delegate"] + == f"notification_target:{GENERAL_MARKET_REGIME_NOTIFICATION_TARGET}" + ) volatility_delever_context = payload["position_control"]["volatility_delever_context"] assert volatility_delever_context["actionable_for_position_control"] is True assert volatility_delever_context["retention_profiles"]["soxl_step_rebound_0.25_0.50"]["retention_ratio"] == 0.0