Skip to content

feat(runtime): add report-only intraday liquidity diagnostics#55

Merged
StackOverFlow11 merged 1 commit into
mainfrom
feat/i5f-intraday-liquidity-diagnostics
Jun 20, 2026
Merged

feat(runtime): add report-only intraday liquidity diagnostics#55
StackOverFlow11 merged 1 commit into
mainfrom
feat/i5f-intraday-liquidity-diagnostics

Conversation

@StackOverFlow11

Copy link
Copy Markdown
Owner

Summary

P-I5f: an opt-in, report-only execution liquidity diagnostic for the
intraday tail-rebalance path. For each desired rebalance trade
(|target_weight - current_weight|) it sizes the trade against the SELECTED
execution-minute
1min bar's traded amount (RMB) at a max participation rate and
reports a capacity ratio:

desired_notional      = |target_weight - current_weight| * portfolio_notional
bar_capacity_notional = execution_minute_amount * max_participation_rate
capacity_ratio        = bar_capacity_notional / desired_notional   (>=1 covers the trade)

It uses ONLY the execution-minute bar already chosen by the tail execution model —
never a future bar, daily amount/volume/close, or any EOD proxy.

Report-only: it never changes fills, can_buy/can_sell, blocked reasons,
target weights, achieved holdings, turnover, cost, NAV, factor scores, MMP
grouping, alpha, or portfolio construction. Default-off, so every existing
config validates and behaves byte-identically.

Changed files (7)

  • qt/config.py — nested LiquidityDiagnosticsCfg under intraday (enabled=false
    default; when enabled: positive portfolio_notional, max_participation_rate in
    (0,1], and only mode=report_only — each with a readable error).
  • runtime/backtest/engine.pyadditive, default-off record_rebalance_plan
    flag + rebalance_plan_log() capturing the exact (target, current) weights the
    engine used. Default False keeps the loop byte-identical (no plan rows, no
    behaviour change).
  • runtime/backtest/event_models.py — additive accessors exposing the raw up/down
    limit blocked-key sets, so the diagnostic skips already-blocked trades without
    reclassifying their original reason.
  • runtime/intraday_liquidity.py (new) — pure formula primitives + the report-only
    builder.
  • qt/intraday_tail_framework.py — wires the diagnostic into the intraday-tail
    report path only when enabled; new section states it did not alter fills/NAV.
  • config/phase_i5f_intraday_liquidity_diagnostics.yaml (new) — SSE50 smoke based on
    the I5b config; illustrative 10,000,000 RMB sizing.
  • tests/test_i5f_intraday_liquidity.py (new, 17 tests).

Smoke (cache-only minute, real SSE50)

run-phase-i5a-intraday --config config/phase_i5f_intraday_liquidity_diagnostics.yaml

  • periods=3, covered=58/58, stk_mins_live_calls=0, final_nav=0.976448.
  • final_nav=0.976448 is byte-identical to the accepted I5b smoke → enabling
    the diagnostic did not move the book (report-only confirmed end-to-end).
  • diagnostics: 43 desired trades, 1 feasibility-blocked (the I5b up-limit buy,
    reason kept), 0 missing-capacity, 42 inspected, 20 below 1.0x;
    capacity ratio min 0.122 / p10 0.222 / median 1.104 / p90 2.730.
  • No alpha/performance/tradability claim — a single execution minute on SSE50
    large-caps often can't absorb a 1M RMB trade at 5% participation; that's the point.

Gates (all green)

  • targeted tests/test_intraday_execution.py test_i5b_execution_feasibility.py test_i5d_mmp_quintile.py: pass.
  • full pytest -p no:cacheprovider: 696 passed (678 baseline + 17 new I5f tests
    • 1 from the test_cache_config.py config-glob auto-covering the new config).
  • ruff: clean · validate-config: 19/19 OK · run-phase0: ic_mean=0.9600,
    annual_return=0.8408
    unchanged.
  • git diff --check main...HEAD: clean; no merge markers.
  • secret scan: real token value 0 hits in changed files / report / log / smoke
    output; report/log contain no .config.json / tushare.token.

Report-only invariants (tested)

  • enabling the plan log does NOT change NAV / turnover / cost / holdings vs disabled
    (engine assert_frame_equal);
  • capacity uses the execution-minute amount only (a later same-day minute's huge
    amount is ignored);
  • existing missing-bar / missing-price / raw stk_limit blocks keep their original
    reasons and are never reclassified as liquidity blocks.

Non-goals honored

No partial-fill / volume-cap enforcement; no change to simulate_fills /
SimExecution / BacktestEngine / IntradayTailEventModel behaviour beyond
additive + default-off; no MMP research or I5d/I5e rerun; no daily-volume proxy; no
D6 / schema registry / cache refactor; no progress-doc edits (AGENTS.md /
CLAUDE.md / contract untouched — separate post-acceptance goal); PR #38
untouched
.

⚠️ Do not merge until Codex acceptance.

P-I5f: an opt-in, REPORT-ONLY execution liquidity diagnostic for the intraday
tail-rebalance path. For each desired rebalance trade (|target_weight -
current_weight|) it sizes the trade against the SELECTED execution-minute 1min
bar's traded amount (RMB) at a max participation rate and reports a capacity
ratio. It uses ONLY the execution-minute bar already chosen by the tail execution
model — never a future bar, daily amount/volume/close, or any EOD proxy.

Report-only: it never changes fills, can_buy/can_sell, blocked reasons, target
weights, achieved holdings, turnover, cost, NAV, factor scores, MMP grouping,
alpha, or portfolio construction. Default-off, so every existing config validates
and behaves byte-identically.

- qt/config.py: nested LiquidityDiagnosticsCfg under intraday (enabled=false
  default; when enabled requires positive portfolio_notional, participation in
  (0,1], and only mode=report_only — each with a readable error).
- runtime/backtest/engine.py: additive, default-off record_rebalance_plan flag +
  rebalance_plan_log() capturing the (target, current) weights the engine used;
  default False keeps the loop byte-identical (no plan rows, no behaviour change).
- runtime/backtest/event_models.py: additive accessors exposing the raw up/down
  limit blocked-key sets so the diagnostic skips already-blocked trades without
  reclassifying their original reason.
- runtime/intraday_liquidity.py (new): pure formula primitives + the report-only
  builder (feasibility-blocked excluded with original reason kept; missing/NaN/<=0
  amount reported as missing capacity data; zero desired trade skipped).
- qt/intraday_tail_framework.py: wires the diagnostic into the intraday-tail report
  path only when enabled; new report section states it did not alter fills/NAV.
- config/phase_i5f_intraday_liquidity_diagnostics.yaml (new): SSE50 smoke based on
  the I5b config, illustrative 10,000,000 RMB sizing.
- tests/test_i5f_intraday_liquidity.py (new): formula, config validation, and
  report-only invariants (enabling the plan log does not change NAV/turnover/cost/
  holdings; capacity uses the execution-minute amount only; existing blocks keep
  their original reasons).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant