fix(b3b): None-safe backtest-verdict rendering in cockpit templates + detail-page verdict test

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
jgrusewski
2026-06-18 18:55:30 +02:00
parent 2c94c65953
commit 72dd1e1e9f
3 changed files with 13 additions and 5 deletions

View File

@@ -18,7 +18,7 @@
<td>
{% if f.bt_status %}
<span class="badge {{ f.bt_status }}">{{ f.bt_status }}</span>
<span class="muted" style="font-size:11px">Sh {{ '%.2f'|format(f.bt_sharpe) }} / DSR {{ '%.2f'|format(f.bt_dsr) }}</span>
<span class="muted" style="font-size:11px">Sh {{ '%.2f'|format(f.bt_sharpe) if f.bt_sharpe is not none else '—' }} / DSR {{ '%.2f'|format(f.bt_dsr) if f.bt_dsr is not none else '—' }}</span>
{% else %}
<span class="muted"></span>
{% endif %}

View File

@@ -12,10 +12,10 @@
{% if d.bt_status %}
<h3>backtest verdict <span class="badge {{ d.bt_status }}">{{ d.bt_status }}</span>
<span class="muted">as of {{ d.bt_as_of or '—' }}</span></h3>
<p><span class="{{ 'pos' if d.bt_cagr >= 0 else 'neg' }}">CAGR {{ '%+.1f'|format(100*d.bt_cagr) }}%</span>
· vol {{ '%.1f'|format(100*d.bt_ann_vol) }}% · Sharpe {{ '%.2f'|format(d.bt_sharpe) }}
· maxDD {{ '%.1f'|format(100*d.bt_maxdd) }}% · DSR {{ '%.2f'|format(d.bt_dsr) }}
· OOS Sharpe {{ '%.2f'|format(d.bt_oos_sharpe) }}</p>
<p><span class="{{ 'pos' if (d.bt_cagr or 0) >= 0 else 'neg' }}">CAGR {{ '%+.1f'|format(100*d.bt_cagr) if d.bt_cagr is not none else '—' }}%</span>
· vol {{ '%.1f'|format(100*d.bt_ann_vol) if d.bt_ann_vol is not none else '—' }}% · Sharpe {{ '%.2f'|format(d.bt_sharpe) if d.bt_sharpe is not none else '—' }}
· maxDD {{ '%.1f'|format(100*d.bt_maxdd) if d.bt_maxdd is not none else '—' }}% · DSR {{ '%.2f'|format(d.bt_dsr) if d.bt_dsr is not none else '—' }}
· OOS Sharpe {{ '%.2f'|format(d.bt_oos_sharpe) if d.bt_oos_sharpe is not none else '—' }}</p>
{% endif %}
<h3>per-period returns &amp; rolling mean <span class="muted">(raw — no normalization)</span></h3>

View File

@@ -44,6 +44,14 @@ def test_cockpit_shows_backtest_verdict_column() -> None:
assert "DSR" in r.text
def test_strategy_detail_renders_backtest_verdict() -> None:
r = _client().get("/strategy/eqfactor_long")
assert r.status_code == 200
assert "backtest verdict" in r.text # verdict block header present
assert "badge PASS" in r.text # PASS badge rendered
assert "DSR" in r.text # backtest metric label present
def test_strategy_detail_renders() -> None:
r = _client().get("/strategy/combined")
assert r.status_code == 200 and "2026-06-06" in r.text