28 Commits
Author SHA1 Message Date
jackyu66gitandClaude Opus 4.6 d38782490c feat: 重构为三所价差异动监控系统
删除 HyperLiquid + 全部交易功能,构建自适应 surge 检测器。
- 新增 surge_detector.go: 每币独立滚动窗口基线,检测三所价差异常飙升
- 新增 SpreadCard/SurgeCard 前端组件
- 保留 momentum/trend/cumulative/trend_filter 扫描功能
- 更新文档和配置以反映新系统

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-08 02:01:18 +08:00
jackyu66gitandClaude Opus 4.6 b7767c95ae feat: 添加OKX行情接入+趋势检测+累积变动系统+界面重构
- 新增OKX WebSocket行情连接器,扩展4交易所价格监控
- 新增z-score趋势检测引擎(TrendDetector),识别价格异动/趋势启动
- 新增累积变动跟踪(CumulativeTracker),基于1min/5min多交易所共识
- 趋势事件和累积变动事件持久化到SQLite
- 新增Binance/OKX动量检测字段,扩展前端动量卡片至15列
- 迁移至macOS(darwin-arm64),更新前端依赖
- Dashboard网格重构:非交易卡片置顶,交易卡片置底
- TrackedCoin添加OK字段,添加ExBinance/ExOKX常量
- 前端新增趋势检测卡片、趋势历史卡片、累积变动卡片

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-06 13:26:05 +08:00
jackyu66gitandClaude Opus 4.7 f97ac16b1c feat: 实际成交价追踪 + reduceOnly保护 + 数据库增强
- Bitget GetTradeFee 返回实际成交均价(weighted avg fill price)及手续费, 支持最多5次重试
- HyperLiquid ParseFillFromResponse 提取订单成交均价, 新增 GetSize/GetBalance 方法
- 开仓/加仓/平仓均从交易所获取实际成交价替代WS估算价
- HL 平仓使用 reduceOnly 防止反向开仓
- 所有 OrderID 保存到数据库 orders 表
- 加仓零成交检测及实际手续费获取
- PnL 计算修正为按USD计算手续费
- 新增 GetAllClosedTrades / GetClosedStats 数据库查询
- 服务器重启 restore 未完成交易修复(DBTradeID 缺失)
- 黑名单强平添加 USD PnL/手续费预计算

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-05 02:59:18 +08:00
jackyu66git fd777e6fe0 fix: Bitget 平仓必须传 holdSide 参数
- PlaceMarketOrder 新增 holdSide 参数
- 平仓时(closeLeg)根据 leg.Side 传 holdSide="long"/"short"
- 开仓传空字符串,不受影响
- 修复 BG 持续 'No position to close' (22002) 问题
2026-05-05 00:46:49 +08:00
jackyu66git d01a261828 fix: 删除零成交误判逻辑 + 各种稳定性修复
- 删除: Bitget GetTradeFee 零成交检查(PlaceMarketOrder 成功即成交)
- 修复: GetTradeFee 加 1s 延迟 + 查不到返回 0(用配置估算费兜底)
- 修复: HL InitExchange 在 NewTrader 中提前调用,避免 szDecimals 延迟
- 修复: close_failed 30 次重试上限,超限标记 failed 并清理
- 修复: DB 恢复时校验 Legs 完整性,跳过非法记录
- 修复: checkScaleIn/checkExit nil guard 防 panic
- 修复: config.go 参数调整(手续费、阈值等)
- 移除: scanner.go 中 MEW/USTC 等低流动性币对
- 添加: 更详细的下单日志(szStr、amountUSD、price)
- 添加: bin/ 到 .gitignore
2026-05-05 00:41:39 +08:00
jackyu66git 866f9906b7 fix: HL market order double slippage causing 'Order has invalid size'
Root cause: PlaceMarketOrder manually calculated limitPx=mid*0.5 (sell)
then passed &limitPx to SDK's MarketOpen. SDK treated this as reference
price and applied slippage AGAIN (0.95x), resulting in limitPx=mid*0.475.
Notional value fell below HL's 0 minimum → error.

Fix: pass nil instead of &limitPx, letting SDK get mid price and
apply standard 5% slippage itself.
2026-05-04 23:35:44 +08:00
jackyu66git c04d8ca0da fix: 修正注释位置 && 清理废弃的 GetHLSize 2026-05-04 22:52:45 +08:00
jackyu66git 9d942e9dee fix: HL size 动态格式化(从 Meta 取 szDecimals)
- 新增 HyperLiquidTrade.GetSize(),从 HL Meta.Universe 获取
  每个币的 SzDecimals 运行时格式化订单数量
- 替代硬编码的 exchange.GetHLSize() switch case
- trader.go 中 placeOrder/placeOrderAt 两处调用切换为新方法
- 新增 TryEntry 价格<=0 检查,过滤异常数据
2026-05-04 22:50:24 +08:00
jackyu66git 9163d7fd30 切换到实盘环境
- HL: WS/REST 从 testnet 切换到 mainnet
- BG: 删除 paptrading header(实盘 key 不以 bg_ 前缀区分)
- config: 调整交易参数
- scanner: 更新跟踪币种列表
2026-05-04 22:24:30 +08:00
jackyu66git 411365b66e fix: correct HL fee parsing (OrderStatus not statuses[]) and add productType to BG fills query 2026-05-04 20:06:27 +08:00
jackyu66git 6e9b982c66 config: lower threshold 0.10->0.05, arb 0.03->0.02, amount 0->0 2026-05-04 19:31:08 +08:00
jackyu66git 6baae85eaa feat: actual exchange fees for entry orders
- BitgetTrade: added GetTradeFee() queries /mix/order/fills
- HyperLiquidTrade: added GetTradeFee() parses MarketOpen response
- trader.placeOrder() now returns (errMsg, actualFeeUSD)
- executeEntry uses actual fee from exchange, falls back to estimate
2026-05-04 18:35:33 +08:00
jackyu66git 0aa9923067 fix: full arb table + net profit columns in price view
- ArbTable: removed slice(0,10) cap, shows all 42 opps (21x2)
- PriceTable: added net_bg_to_hl and net_hl_to_bg columns
- Backend SSE: sends net profit for both directions per coin
2026-05-04 18:26:49 +08:00
jackyu66git 5f6578c179 feat: add 17 new cross-exchange pairs (BG↔HL)
Added: ALGO, PYTH, SAND, ADA, HBAR, IOTA, MINA, FET, WLD,
       SUI, APT, NEAR, FIL, DYDX, JUP, TIA, MOVE

Removed: pixel and VET (fake 195% spreads on testnet)

Also updated GetHLSize() to handle szDecimals for all new coins.
2026-05-04 18:05:53 +08:00
jackyu66git 49da6fd35b fix: HL balance now reads spot USDC via SpotUserState
HL testnet USDC lives in the spot account, not the perp clearinghouse.
GetBalance() was calling UserState() (perp clearinghouseState), which
returned /usr/bin/bash. Switched to SpotUserState() and parse USDC.total - USDC.hold.

Also cleaned up .gitignore to exclude .env, binary, logs, data/.
2026-05-04 17:48:14 +08:00
jackyu66git 156ce22474 feat: HL EVM signing via sonirico/go-hyperliquid SDK - testnet orders work 2026-05-04 16:21:57 +08:00
jackyu66git 8b8d4140f9 refactor: HL EVM signing via sonirico/go-hyperliquid SDK 2026-05-04 16:15:51 +08:00
jackyu66git c5c4c7394f fix: HL testnet - add API wallet address to signed orders, 3-param constructor 2026-05-04 15:39:31 +08:00
jackyu66git 30436bbe75 fix: BG paper trading API - tradeSide param, correct host, marginMode 2026-05-04 15:28:08 +08:00
jackyu66git e5ea78ffd2 feat: real trading mode, auto-stop after 5 trades, HL testnet support
- config.json: test_mode=false, ready for sim/testnet trading
- trader.go: auto-stop after 5 real trades, exchange response logging,
  Stop()/Start() API, shuttingDown flag for graceful stop
- dashboard.go: POST /api/stop + POST /api/start endpoints,
  trading status in SSE stats
- exchange/hyperliquid.go: switch HL WS to testnet endpoint
- exchange/hyperliquid_trade.go: switch REST to testnet endpoint,
  support base64 + 32-byte EVM private keys
- main.go: listen on trader.StopCh (graceful, no process exit)
- scanner.go: trim TrackedCoins to only 6 core coins (DOGE/LINK/ONDO/OP/WIF/ARB)
- .gitignore: ignore main binary
2026-05-04 14:31:52 +08:00
jackyu66git 21a3f9a962 feat: 所有参数移至config.json, 重构退出逻辑, 清理遗留接口
- 将所有硬编码参数迁移到 config.json (手续费率、止盈/止损阈值、
  超时、腿间隔、加仓步进等)
- 退出条件: 净利 >= take_profit_pct 止盈, 价差 <= 0 平仓
- 删除 Binance/dYdX 遗留代码
- 更新 README 文档
- Dashboard: 双交易所价格表、黑名单UI、按币名排序持仓
- Bitget WS: 文本ping保活
- 数据库: 重置, 无历史仓位
2026-05-04 01:46:17 +08:00
jackyu66git 2ed6ffc747 fix: Bitget WS keepalive — send text ping, not WebSocket PingMessage
Bitget v2 WS requires a text message "ping" every 30s, not a WebSocket
PingMessage control frame (opcode 0x9). Using the wrong ping type caused
a silent failure: connection stays up and subscription succeeds, but NO
ticker data is pushed — zero errors, zero reconnection logs.

Changes:
- connector.go: Add TextPing bool flag, send text 'ping' when set
- bitget.go: Set TextPing=true, handle text 'pong', add debug logging
- scanner.go: Expand to 179 overlapping Bitget+HL coins
2026-05-04 00:33:03 +08:00
jackyu66git cf6548c37f fix: 4 bugfixes for production readiness
1. GetHLSize: add minimum size checks (prevent size=0 when price > amount)
2. executeEntry: orphan position warning when leg1 close also fails after leg2
3. checkExit: keep position as close_failed on failure, retryClose on each Tick
4. persistTrade: sync instead of goroutine (prevent data loss on exit)
2026-05-03 23:13:44 +08:00
jackyu66git 915b316ca7 fix: HL size floor, random scan jitter 50-250ms
- GetHLSize: change rounding from Sprintf (round-to-nearest)
  to math.Floor (floor), consistent with GetBitgetSize
- Scan interval: fixed 200ms → random 50-250ms to avoid
  lock-step with HyperLiquid's ~200ms allMids push cycle
- README: update architecture diagram, trading logic, config note
2026-05-03 22:25:01 +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 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 719f0a061d Initial commit 2026-05-03 16:54:36 +08:00