Skip to content

sim report: word an empty-side R profit factor as insights does (#1000) - #1003

Merged
eaitbrahim merged 4 commits into
mainfrom
fix/1000-sim-edge-pf
Oct 13, 2026
Merged

eaitbrahim merged 4 commits into
mainfrom
fix/1000-sim-edge-pf

Conversation

@eaitbrahim

Copy link
Copy Markdown
Contributor

Closes #1000

What changed

The keel sim report's edge table printed the engine's raw Profit factor (R): inf when the R sample had no losing trade, and 0.000 when it held only scratches or a zero-R win. Those cells now use the wording that insights summary, the Rules page and rules backtest already use (#986/#998):

R sample before after
wins only inf n/a (no losses yet)
scratches only 0.000 n/a (no wins or losses yet)
zero-R win, no loss 0.000 n/a (no losses yet)
losses only 0.000 0.000 (a measured value, unchanged)
no R at all n/a n/a (unchanged)
  • insights.profit_factor_r_reason_of(stats) sits next to profit_factor_reason_of. It calls the same _profit_factor_reason on the R sample (n_trades - n_excluded_no_risk) and decides each side by counting n_wins_r / n_losses_r, as the issue asks. It never reads a zero.
  • report._profit_factor_r_cell renders the cell through undefined_reading, so the wording has one source and is not copied.
  • BacktestResult / profit_factor_r, the promotion gates and pool_stats are unchanged. The test checks that the engine value is still Infinity after rendering.

Ruling

Change the display rather than keep inf. The old _r_cell docstring called inf deliberate, so I checked each reason it could still hold:

  • Machine-read output: nothing parses the edge-table Markdown. The only readers are tests and people, and the figures stay on BacktestResult.
  • Column width or sorting: none applies to a Markdown table.
  • Units: a profit factor is a ratio, so an empty side means the same thing in R as in money.

None of these holds, so the docstring is updated. inf remains only for the degenerate case where both sides have trades but the losing R sums to zero.

Tests

  • test_edge_section_words_an_empty_side_profit_factor_as_insights_does: one test covering all seven rows above plus the pooled row. It also asserts the fixtures' raw engine values first, so no case passes vacuously.
  • Mutation-checked 5 pins: reading a zero instead of counting (win side and loss side), printing the raw cell, dropping the no-R guard, and dropping the reason branch. Every mutant failed the suite, and each mutated source was confirmed to differ from the saved copy with cmp.
  • Full pytest: 8459 passed, 3 skipped. mypy, ruff check and ruff format --check are clean.

🤖 Generated with Claude Code

The edge table's `Profit factor (R)` printed the engine's raw `inf` for an R sample with
no losing trade and `0.000` for one of scratches only (or a zero-R win). It now prints
`n/a (no losses yet)` / `n/a (no wins or losses yet)` through `undefined_reading` and a
new shared `insights.profit_factor_r_reason_of`, whose sides are decided by counting the
R sample (`n_wins_r` / `n_losses_r`), not by reading a zero. An all-losses 0 keeps its
number; a row with no R stays a bare `n/a`. `BacktestResult` is unchanged; `_r_cell`'s
docstring now says the `inf` it keeps is only the degenerate zero-R-loss case.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@eaitbrahim eaitbrahim left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review of #1003 (issue #1000). The wording is right: it matches rules backtest and insights summary for every case. Sides are decided by counting, and BacktestResult and the gates are unchanged. No other surface renders profit_factor_r, and nothing parses the edge table. Three comments below: one minor (layering) and two docstring nits.

Comment thread keel/sim/report.py Outdated
Comment thread keel/sim/report.py Outdated
Comment thread keel/commands/insights.py Outdated
eaitbrahim and others added 3 commits October 13, 2026 17:57
…ocstrings (#1000)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@eaitbrahim
eaitbrahim merged commit 53f42c1 into main Oct 13, 2026
4 checks passed
@eaitbrahim
eaitbrahim deleted the fix/1000-sim-edge-pf branch October 13, 2026 23:48
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.

sim report edge table: profit factor (R) prints inf / 0.000 for an empty side

1 participant