Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/adaptive_allocation_control_plane.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ quant-adaptive-selection --input selection-input.json --output selection-decisio
- 不读取新闻叙事并直接交易;因子必须来自版本化的数据链。
- 数据过期、状态不明、置信度不足、插件未批准、平台未对账或不健康时 fail-closed。
- 插件只能给出 `0..1` 的风险缩放,不能增加风险或提交订单。
- 只有已获 Shadow 准入、并绑定 immutable release 的候选可以被排名。
- 只有已获 Shadow 准入、并绑定 immutable release 的候选可以被排名;`shadow_candidate`
仅可得到“建议进入 Shadow”的零仓位结论,不能由此启动 runtime。
- P0 不能改变平台、策略、插件挂载、仓位或调度器。

后续 M1 才能把 Shadow 结论呈现给人工;M2/M3 还必须经过独立的 Paper、Canary、
Expand Down
4 changes: 3 additions & 1 deletion src/quant_platform_kit/adaptive_allocation/contracts.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
PLATFORM_HEALTH_SCHEMA = "qsl.platform_health_snapshot.v1"
SELECTION_DECISION_SCHEMA = "qsl.selection_decision.v1"
SHADOW_ONLY_AUTHORITY = "shadow_only"
_SHADOW_ELIGIBLE_STAGES = frozenset({"shadow_active", "paper_active", "live_candidate", "live_enabled"})
_SHADOW_ELIGIBLE_STAGES = frozenset(
{"shadow_candidate", "shadow_active", "paper_active", "live_candidate", "live_enabled"}
)


def _nonblank(value: str, field_name: str) -> str:
Expand Down
5 changes: 4 additions & 1 deletion src/quant_platform_kit/adaptive_allocation/selector.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,10 @@ def select_shadow(

`base_score` and `factor_exposures` must come from a separately validated,
versioned research pipeline. This function intentionally has no market-data
fetcher and does not infer financial features from narratives.
fetcher and does not infer financial features from narratives. A
``shadow_candidate`` that is explicitly approved for Shadow may be ranked
so that P0 can produce a reviewable recommendation, but the result still
cannot start a Shadow runtime or authorize an order.
"""

health_by_platform = {item.platform_id: item for item in platform_health}
Expand Down
15 changes: 15 additions & 0 deletions tests/test_adaptive_allocation.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,21 @@ def test_shadow_selector_rejects_unhealthy_platform_or_missing_required_plugin()
assert "no_healthy_reconciled_shadow_platform" in item.reasons


def test_shadow_selector_can_rank_an_approved_shadow_candidate_without_starting_it():
decision = select_shadow(
decision_id="decision-004",
market_context=_context(),
candidates=[_candidate("candidate_a", 0.7, lifecycle_stage="shadow_candidate")],
platform_health=[_health()],
plugin_adjustments=[PluginRiskAdjustment("market_regime_control", 1.0)],
policy=_policy(),
)

assert decision.recommended_strategy_profile == "candidate_a"
assert decision.no_order is True
assert decision.candidate_decisions[0].proposed_weight == 0.0


def test_plugin_risk_adjustment_cannot_increase_risk():
with pytest.raises(ValueError, match="risk_multiplier"):
PluginRiskAdjustment("market_regime_control", 1.01)