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>
This commit is contained in:
jackyu66git
2026-05-06 13:26:05 +08:00
co-authored by Claude Opus 4.6
parent 047571921e
commit b7767c95ae
24 changed files with 2705 additions and 273 deletions
+62
View File
@@ -52,6 +52,17 @@ type Config struct {
// Entry sanity check: reject if price moved beyond this % in the wrong direction
ReversalTolerancePct float64
// Momentum scanning mode
MomentumEnabled bool
MomentumThresholdPct float64
// Trend detection mode
TrendEnabled bool
TrendBaselineWindow int // ticks for EMA volatility baseline (default: 600 = 30s)
TrendAnomalyMul float64 // z-score multiplier for alert threshold (default: 3.0)
TrendConfirmTicks int // ticks needed for state confirmation (default: 3)
TrendAlertCooldown int64 // ms cooldown between alerts for same coin (default: 60000)
// Bitget API
BitgetAPIKey string
BitgetAPISecret string
@@ -79,6 +90,17 @@ type jsonConfig struct {
InitialCapital float64 `json:"initial_capital"`
ExcludedCoins []string `json:"excluded_coins"`
// Momentum scanning
MomentumEnabled bool `json:"momentum_enabled"`
MomentumThresholdPct float64 `json:"momentum_threshold_pct"`
// Trend detection
TrendEnabled bool `json:"trend_enabled"`
TrendBaselineWindow int `json:"trend_baseline_window"`
TrendAnomalyMul float64 `json:"trend_anomaly_mul"`
TrendConfirmTicks int `json:"trend_confirm_ticks"`
TrendAlertCooldown int64 `json:"trend_alert_cooldown_ms"`
// New: exchange fees
TakerFeeBitget float64 `json:"taker_fee_bitget"`
TakerFeeHyperLiquid float64 `json:"taker_fee_hyperliquid"`
@@ -158,6 +180,17 @@ func LoadConfig() *Config {
ExcludedCoins: jsonCfg.ExcludedCoins,
// Momentum scanning
MomentumEnabled: getBool("MOMENTUM_ENABLED", jsonCfg.MomentumEnabled),
MomentumThresholdPct: getFloat("MOMENTUM_THRESHOLD_PCT", jsonCfg.MomentumThresholdPct),
// Trend detection
TrendEnabled: getBool("TREND_ENABLED", jsonCfg.TrendEnabled),
TrendBaselineWindow: int(getFloat("TREND_BASELINE_WINDOW", float64(jsonCfg.TrendBaselineWindow))),
TrendAnomalyMul: getFloat("TREND_ANOMALY_MUL", jsonCfg.TrendAnomalyMul),
TrendConfirmTicks: int(getFloat("TREND_CONFIRM_TICKS", float64(jsonCfg.TrendConfirmTicks))),
TrendAlertCooldown: int64(getFloat("TREND_ALERT_COOLDOWN_MS", float64(jsonCfg.TrendAlertCooldown))),
BitgetAPIKey: getEnv("BITGET_API_KEY", ""),
BitgetAPISecret: getEnv("BITGET_API_SECRET", ""),
BitgetPassphrase: getEnv("BITGET_PASSPHRASE", ""),
@@ -194,6 +227,15 @@ func loadJSONConfig() jsonConfig {
// Scale-in parameters
ScaleStepPct: 0.10, // 0.10% spread widening per scale level
ScaleCooldownSec: 5, // 5 seconds between scales
// Momentum scanning
MomentumThresholdPct: 0.25, // 0.25% change flags momentum
// Trend detection
TrendBaselineWindow: 600, // ~30s at 50ms tick
TrendAnomalyMul: 3.0, // 3 sigma z-score threshold
TrendConfirmTicks: 3, // 3 consecutive ticks for confirmation
TrendAlertCooldown: 60000, // 1 min cooldown
}
data, err := os.ReadFile("config.json")
@@ -267,11 +309,31 @@ func loadJSONConfig() jsonConfig {
def.ExcludedCoins = cfg.ExcludedCoins
}
if cfg.MomentumThresholdPct != 0 {
def.MomentumThresholdPct = cfg.MomentumThresholdPct
}
// Trend detection JSON overrides
if cfg.TrendBaselineWindow != 0 {
def.TrendBaselineWindow = cfg.TrendBaselineWindow
}
if cfg.TrendAnomalyMul != 0 {
def.TrendAnomalyMul = cfg.TrendAnomalyMul
}
if cfg.TrendConfirmTicks != 0 {
def.TrendConfirmTicks = cfg.TrendConfirmTicks
}
if cfg.TrendAlertCooldown != 0 {
def.TrendAlertCooldown = cfg.TrendAlertCooldown
}
// Boolean fields: zero default is false, so use OR logic
// When JSON has true → true || false = true (override)
// When JSON has false → false || false = false (keep default)
def.TestMode = cfg.TestMode || def.TestMode
def.TradeEnabled = cfg.TradeEnabled || def.TradeEnabled
def.MomentumEnabled = cfg.MomentumEnabled || def.MomentumEnabled
def.TrendEnabled = cfg.TrendEnabled || def.TrendEnabled
return def
}