Skip to content

Strategy-aware wallet drill-down: price + performance charts - #2

Merged
KhaledElzarw merged 1 commit into
mainfrom
feat/wallet-drilldown-analytics
Jul 22, 2026
Merged

Strategy-aware wallet drill-down: price + performance charts#2
KhaledElzarw merged 1 commit into
mainfrom
feat/wallet-drilldown-analytics

Conversation

@KhaledElzarw

Copy link
Copy Markdown
Owner

Summary

Turns the wallet drill-down modal into a real analytics view with a small number of rich charts (per the "fewer charts that do more" preference).

  • Price · indicators · trades — candlesticks via self-hosted TradingView Lightweight Charts (vendored so the strict script-src 'self' CSP is satisfied) + the indicators the wallet's own strategy uses (computed from live strategy params) + buy/sell markers coloured by win/loss + live resting ladder & avg cost.
  • Performance — one multi-series chart (balance / realized P&L / unrealized P&L / fees) with colour-matched, clickable legend toggles.
  • Exposure chart + Activity stat strip (trades, wins/losses, win rate, avg win/loss, profit factor).
  • Strategy panel — rendered generically from whatever the backend returns for the wallet's current strategy, so excluding/reassigning a wallet changes it automatically (grid → ladder/spacing/inventory/regime; oscillators → thresholds; committee → cadence).

Data

All time series are reconstructed deterministically from each wallet's own fills over the retained candle window — nothing is fabricated; empty wallets render a flat line. Reconciles to within $0.03 of the headline equity. New read-only endpoints /wallets/{id}/chart and /wallets/{id}/timeseries.

Safety

Stays within the A14 posture: no innerHTML; all colours via CSS classes (style-src 'self' forbids inline styles); chart code guarded so the jsdom/static unit tests (no charting lib) still pass. Vendored library documented in dashboard/static/vendor/NOTICE.md (Apache-2.0, pinned v4.2.3).

Tests

920 passing (903 existing + 17 new in tests/tradebot/test_chart_analytics.py).

🤖 Generated with Claude Code

Turn the wallet drill-down modal into an analytics view:

- Price panel (self-hosted TradingView Lightweight Charts, satisfies the
  strict CSP): candlesticks + the indicators the wallet's OWN strategy uses,
  computed from live strategy params, plus buy/sell trade markers coloured by
  win/loss (realized P&L) and the live resting ladder + avg cost.
- Performance panel: one multi-series chart (balance / realized / unrealized /
  fees) with colour-matched, clickable legend toggles.
- Exposure panel + activity stat strip (trades, wins/losses, win rate, avg
  win/loss, profit factor).
- Strategy panel: metric blocks rendered generically from whatever the backend
  returns for the wallet's CURRENT strategy, so excluding/reassigning a wallet
  changes the panel automatically. Grid wallets show ladder/spacing/inventory/
  regime; oscillators show their thresholds; committee wallets show cadence.

Backend reconstructs balance/P&L/fees/exposure per closed candle from the
wallet's own fills (nothing fabricated; empty wallets render a flat line). New
read-only endpoints /wallets/{id}/chart and /wallets/{id}/timeseries; the view
retains the candle window and adds strategy_metrics/activity/reason_breakdown.

Frontend stays within the A14 posture: no innerHTML, all colours via CSS
classes (style-src 'self' forbids inline styles), charts guarded so unit tests
with no charting library still pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@KhaledElzarw
KhaledElzarw merged commit 200ca74 into main Jul 22, 2026
10 of 14 checks passed
@KhaledElzarw
KhaledElzarw deleted the feat/wallet-drilldown-analytics branch July 22, 2026 02:50

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1dcee56c44

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +471 to +477
const chart = LightweightCharts.createChart(container, {
...CHART_THEME,
width: container.clientWidth || 760,
height,
handleScale: true,
handleScroll: true,
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Permit the chart library's required layout styles

When the dashboard is served by create_app, every response has style-src 'self', but Lightweight Charts 4.2.3 lays out its generated table and canvases through inline element.style mutations (visible throughout the vendored asset). Browsers enforce those as inline styles, so this createChart path is blocked or left without the positioning and dimensions needed to render, making the new charts blank or malformed under the application's normal CSP; the chart integration needs a CSP-compatible styling approach or an appropriately scoped policy change.

Useful? React with 👍 / 👎.

Comment thread tradebot/api/devserver.py

return InMemoryPortfolioView(
portfolio=portfolio, mark_price=mark, now=now,
candles=tuple(market),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Refresh retained candles along with the live mark

In --live mode this stores only the startup candle tuple, while start_market_refresher subsequently updates only view.mark_price and view.now. After the next closed candle, /chart, /timeseries, and the strategy metrics therefore remain permanently frozen at startup even though the wallet snapshot is marked at the newer price, producing contradictory and stale analytics whenever the detail panel is reopened; the retained candle window must be advanced by the live refresher as well.

Useful? React with 👍 / 👎.

Comment on lines +126 to +129
_line(candles, lambda c: ind.donchian_high(c, s.entry_period, exclude_last=False),
id="dc_up", label=f"Donchian {s.entry_period} high", pane="price", color=C_CHANNEL),
_line(candles, lambda c: ind.donchian_low(c, s.exit_period, exclude_last=False),
id="dc_dn", label=f"Donchian {s.exit_period} low", pane="price", color=C_STOP),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Plot Donchian channels from prior candles

For a DonchianBreakout wallet, the strategy calls donchian_high/low with their default exclude_last=True, so its actual trigger is the channel formed before the current candle and the current close can cross it. These overlays force exclude_last=False, causing the line to incorporate and move with the current candle's high/low; breakout and trailing-exit markers can consequently appear not to have crossed the displayed threshold. Use the same exclusion semantics as the strategy.

Useful? React with 👍 / 👎.

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