Skip to content

feat(insights): read-only insights + journaling reporting surface - #149

Merged
eaitbrahim merged 2 commits into
mainfrom
feat/insights-journaling
Jul 24, 2026
Merged

feat(insights): read-only insights + journaling reporting surface#149
eaitbrahim merged 2 commits into
mainfrom
feat/insights-journaling

Conversation

@eaitbrahim

Copy link
Copy Markdown
Contributor

What

Adds a read-only insights/journaling reporting surface — a pure view over the existing keel.db, in the same spirit as keel tui. Turns the slow, months-long paper-forward evidence accrual into something legible.

Two subcommands under a new keel insights group:

  • keel insights summary [--json] [--rule KIND] [--mode paper|live] — per-rule track record (n, win rate, R:R, expectancy, profit factor, max DD), an account/drawdown summary projected from gather_status, and a "distance to the promotion gate" view: how many more trades and which floors each paper rule still needs before it could be promoted to live.
  • keel insights journal [--json] [--rule] [--asset] [--limit] [--since] [--until] [--include-open] — chronological per-trade log with fee-honest net P&L, R-multiples, win/loss/open/scratch outcome, and DCA rows flagged "no stop — excluded from R/expectancy."

Design

  • Read-only, zero new write paths. No orders, no rails/guards, no mutation of rule status / equity / agent_state. Repository gains no new methods — every read goes through existing get_rules / get_trade_outcomes / track_record / gather_status.
  • Pure VIEW, not a re-derivation. Rail-11 / drawdown / promotion floors are projected from existing outputs. Gate distance reuses can_promote + floor_for_class(promotion_class_of(rule)) verbatim — so the trend_follow floor (min_trades=100) is read, never hardcoded.
  • Testable core + thin click I/O, mirroring keel/commands/status.py / tui.py. Decimal throughout; --json is valid json.loads-able (full-precision Decimals via default=str, no disclaimer footer); human render quantizes money/ratios to 2dp.
  • Honest at small samples: an explicit "n<30: not yet statistically distinguishable from random entry" note; never implies a proven edge below the gate.
  • Self-contained: no TUI panel integration (deferred), no CTS/signals accessor (no clean join key; out of scope).

Tests

tests/commands/test_insights.py — 31 new tests (empty-DB-first, gate distance, DCA r_multiple=None, --limit pre-count, --include-open count line, small-sample note, ratio quantization, --json validity for both subcommands). Full suite: 1597 passed, ruff clean.

Review

Designed (Opus), built TDD (Sonnet), then reviewed end-to-end by an independent fresh-context Opus agent. Review found and this branch fixes: (1) journal count line was counting open rows as "closed" (showing N of M), (2) full-precision Decimal leaking into the human render, plus (3) the missing regression test. Verdict after fixes: read-only airtight, gate/promotion reuse correct.

🤖 Generated with Claude Code

eaitbrahim and others added 2 commits July 24, 2026 19:10
Adds a strictly read-only `keel insights` command group -- `summary` (per-rule
promotion-gate distance projected off `paper.track_record`/`strategy.promotion`,
plus an account-level view of `gather_status`) and `journal` (a filterable,
fee-honest trade journal off `trade_outcomes`, enriched with R-multiples where a
matching paper trade can be found). Both support `--json` (no trailing prose) and
the shared DISCLAIMER footer in human mode.

Removes the unused Phase-4 `insights` stub command that this supersedes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Two render-only fixes from independent review, no data-layer changes:

- render_journal's "showing N of total_count closed trades" line counted
  --include-open's appended outcome="open" rows in N, so it could read e.g.
  "showing 4 of 3 closed trades". N now excludes open rows and an
  "(+K open)" suffix is appended when any were shown.
- render_summary/render_journal now quantize Decimal money/ratio fields to
  2dp for human display (via a shared _quantized/_money/_ratio helper that
  passes non-finite Decimals and sentinel strings through unchanged).
  --json is untouched -- json.dumps(..., default=str) still emits full
  precision -- and gate.blocking_reasons stays verbatim from
  promotion.can_promote, as intended.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@eaitbrahim
eaitbrahim merged commit 69c13ec into main Jul 24, 2026
1 check passed
@eaitbrahim
eaitbrahim deleted the feat/insights-journaling branch July 24, 2026 23:27
@eaitbrahim eaitbrahim added the feature New capability (groups under Features) label Jul 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New capability (groups under Features)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant