Commit Graph
13 Commits
Author SHA1 Message Date
jackyu66git ab48e207a5 Fix 3 arbitrage logic issues from code review
Issue #1 (critical): reProfit false positive on price reversal
  executeEntry used CalcNetProfit which auto-swaps prices when
  hlP < bgP. If prices flipped between scan and execution, reProfit
  reported positive even when direction was now wrong.
  Fix: use netProfit() with explicit direction + verify spread
  direction hasn't flipped (hlP <= bgP prevents BG->HL when
  HL is no longer more expensive).

Issue #2 (medium): Scale-in was paper-only, didn't place orders
  Now actually places additional orders on both legs via new
  placeOrderAt(). Test mode uses mock fills. Live mode sends
  real API orders. AmountUSD properly tracks total deployed
  capital. Partial fill handled gracefully (don't close main leg).

Issue #3 (minor): closeLeg missing ExitTime on mock mode
2026-05-03 18:19:25 +08:00
jackyu66git 931855e1f5 Cleanup: remove dead code after P3 refactor 2026-05-03 18:13:11 +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 da561325d7 Revert B#6: netProfit must NOT delegate to CalcNetProfit
CalcNetProfit (helpers.go) has internal price-swap logic — when
price2 < price1 it swaps buy/sell sides. ScanArbWithFees relies
on netProfit being a pure strict-direction calculation (callers
try both directions via addPair). Delegation caused double-swap:
both netProfit calls in addPair returned positive profit, but
direction1's struct reported wrong exchange pair, leading to
potential loss-making trades.

Keep both formulas as independent implementations with explicit
comments warning against future merging attempts.
2026-05-03 17:55:39 +08:00
jackyu66git 277c34c3bd Remove Aevo exchange (retired)
- Delete exchange/aevo.go (AevoWS, aevoTickerMsg, aevoTickerData, etc.)
- scanner.go: remove ExAevo constant, fee rates, scan pair entries, shortName mapping
- main.go: remove aevoSymbols collection loop and TrackedSymbol usage
2026-05-03 17:50:42 +08:00
jackyu66git eb74495470 Fix 8 bugs from code review
B#1 — sigCh shared across goroutines, SIGINT unreliable
  → context.WithCancel: main loop cancels ctx on SIGINT,
    4 WS goroutines select on ctx.Done() instead of shared sigCh

B#3 — restoreOpenPositions missing LastScaleAt
  → Set LastScaleAt = tr.OpenedAt on restore so scale-in cooldown works

B#4 — dYdX heartbeat goroutine leaks on reconnect
  → Added stopHeartbeat chan + heartbeatMu mutex; close old channel
    before spawning new heartbeat goroutine

B#5 — GetBitgetSize fmt.Sprintf rounds up, may exceed amountUSD
  → Added math.Floor(sz*multiplier)/multiplier before format to round
    DOWN to nearest valid step size for every coin

B#6 — netProfit and CalcNetProfit duplicate formula
  → scanner.go netProfit now delegates to exchange.CalcNetProfit

B#7 — Aevo Run callback only 2 params, incompatible with startExchange
  → Changed to 4-arg callback func(coin, price, bid, ask) with bid=ask=0

B#8 — parseFloat uses fmt.Sscanf (slow, locale-sensitive)
  → Replaced with strconv.ParseFloat

B#9 — dYdX receives hlSymbols instead of its own symbol list
  → Added dydxSymbols var, built from c.HL like other exchanges
2026-05-03 17:48:06 +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
jackyu66git 0c1eaedcb6 Fix: remove DB from git tracking, add to gitignore 2026-05-03 17:28:30 +08:00
jackyu66git b09314f317 Phase 1: SQLite persistence layer
- Add modernc.org/sqlite (pure Go, no CGO)
- db/ package: trades, orders, config_log tables + CRUD
- Trade persistence: every closed trade saved to SQLite
- Restart recovery: open positions restored from DB
- Automatic migration on startup
2026-05-03 17:28:08 +08:00
jackyu66git 189fc0d9b6 Add HOT/WARM/COLD data tier to design doc 2026-05-03 17:16:01 +08:00
jackyu66git 8861304390 Add complete dashboard design doc: SQLite schema, REST API, SSE, frontend layout 2026-05-03 17:13:24 +08:00
jackyu66git 128ed07aee Add README with architecture, config, and trading logic documentation 2026-05-03 16:56:44 +08:00
jackyu66git 719f0a061d Initial commit 2026-05-03 16:54:36 +08:00