Commit Graph
7 Commits
Author SHA1 Message Date
jackyu66git 32f06b57d6 move DetailedStats calc out of trader.go into dashboard.go
- Remove DetailedStats struct and GetDetailedStats() method from trader.go
- Add calcDetailedStats() standalone pure function in dashboard.go
- Dashboard calls d.trader.GetClosedTrades() + calcDetailedStats()
- Trading logic now has zero display-oriented calculations
2026-05-03 21:13:11 +08:00
jackyu66git 1e4a3f3b37 Add detailed PnL and duration stats to dashboard 2026-05-03 21:03:40 +08:00
jackyu66git 57344d33f7 fix(dashboard): current spread sign for HL→BG positions
Bug: current spread always computed as (hl-bg)/bg regardless of
position direction. For HL→BG positions, spread should be (bg-hl)/hl
to match entry spread convention.

Fix: check LongLeg.Exchange — if HL→BG, use (bg-hl)/hl instead.
2026-05-03 19:11:34 +08:00
jackyu66git 02b74f1ec0 decouple display from trading: snapMu + RefreshSnapshot/ReadSnapshot
- Add snapMu RWMutex + positionsSnapshot to Trader
- RefreshSnapshot() called from main loop after Tick() — acquires
  t.mu briefly, stores deep copy under snapMu
- ReadSnapshot() returns snapshot copy under snapMu.RLock — never
  touches t.mu, zero contention with trading path
- Dashboard + handleStatus + hourly summary + status log all
  use ReadSnapshot() instead of GetPositionsCopy()
- Trading path (Tick/TryEntry/executeEntry/checkExit/checkScaleIn)
  never blocked by display reads
- Snapshot is at most 1 tick behind live state — acceptable delay
2026-05-03 18:35:47 +08:00
jackyu66git b08d8490fc fix: data race, scale-in PnL, nonce mutex, dead code, hourly check
- 🔴 Data race: Add GetPositionsCopy() returning deep copies (no shared
  ArbPosition pointers). Use it in dashboard broadcastLoop + handleStatus.
- 🟡 Scale-in PnL: Track LongEntryPrices/ShortEntryPrices on ArbPosition,
  compute weighted average (harmonic mean) at exit for accurate PnL.
- 🟢 CalcNetProfit: Delete dead code from exchange/helpers.go.
- 🟢 HL nonce: Add sync.Mutex around lastNonce++ (thread safety).
- 🟢 Hourly check: Change from 5-second window to minute window.
- 🟢 ExitPrice: Test mode closeLeg already handled by checkExit.
2026-05-03 18:31:14 +08:00
jackyu66git beb3611778 Phase 3: Real-time enhancements
P3-1: Scan optimization — only BG↔HL (50+ pair combos → 2)
P3-2: Real-time spread chart — spreadHistory ring buffer +
      /api/spread-history endpoint + Chart.js spread chart
P3-3: Live position PnL — positions SSE now includes
      estimated current profit/loss + current spread
P3-4: Real-time trade events — trader.OnTradeEvent callback
      fires SSE 'trade_open' / 'trade_close' immediately
P3-5: Connection status monitoring — tracks last update time
      per exchange, broadcast via stats.connections + /api/connections

Frontend: spread chart card, PnL column in positions,
          connection status dots in stats bar,
          green/red border flash on trade events
2026-05-03 18:05:19 +08:00
jackyu66git c2489614a7 Phase 2: Web dashboard with SSE real-time push
- dashboard.go: SSE hub + HTTP server + price history ring buffer
- static.go: //go:embed for static files
- web/static/index.html: Full dashboard HTML (6 panels)
- web/static/app.js: SSE client, Chart.js price chart, live table updates
- web/static/style.css: GitHub-style dark theme
- main.go: Start dashboard on :8888 + wire price recording + scan results

Dashboard features:
  - Real-time price table (6 coins × 4 exchanges)
  - Arbitrage opportunities table
  - Open positions view
  - Historical trades table (from SQLite)
  - Chart.js price chart with coin/exchange selector
  - Stats summary (total/converged/diverged/flat)
  - 🚫 Zero external Go dependencies (Chart.js loaded from CDN)
2026-05-03 17:38:26 +08:00