diff --git a/backend/__pycache__/main.cpython-310.pyc b/backend/__pycache__/main.cpython-310.pyc deleted file mode 100644 index dc1700c..0000000 Binary files a/backend/__pycache__/main.cpython-310.pyc and /dev/null differ diff --git a/backend/main.py b/backend/main.py index 0881daa..2517927 100644 --- a/backend/main.py +++ b/backend/main.py @@ -426,13 +426,29 @@ async def get_signal_latest(user: dict = Depends(get_current_user)): result = {} for sym in ["BTCUSDT", "ETHUSDT"]: row = await async_fetchrow( - "SELECT ts, cvd_fast, cvd_mid, cvd_day, cvd_fast_slope, atr_5m, atr_percentile, " - "vwap_30m, price, p95_qty, p99_qty, score, signal " - "FROM signal_indicators WHERE symbol = $1 ORDER BY ts DESC LIMIT 1", + "SELECT to_jsonb(si) AS data FROM signal_indicators si WHERE symbol = $1 ORDER BY ts DESC LIMIT 1", sym ) if row: - result[sym.replace("USDT", "")] = row + result[sym.replace("USDT", "")] = row["data"] + return result + + +@app.get("/api/signals/market-indicators") +async def get_market_indicators(user: dict = Depends(get_current_user)): + """返回最新的market_indicators数据(V5.1新增4个数据源)""" + result = {} + for sym in ["BTCUSDT", "ETHUSDT"]: + indicators = {} + for ind_type in ["long_short_ratio", "top_trader_position", "open_interest_hist", "coinbase_premium"]: + row = await async_fetchrow( + "SELECT value, timestamp_ms FROM market_indicators WHERE symbol = $1 AND indicator_type = $2 ORDER BY timestamp_ms DESC LIMIT 1", + sym, + ind_type, + ) + if row: + indicators[ind_type] = {"value": row["value"], "ts": row["timestamp_ms"]} + result[sym.replace("USDT", "")] = indicators return result diff --git a/frontend/app/signals/page.tsx b/frontend/app/signals/page.tsx index 978c0d2..b7efa9a 100644 --- a/frontend/app/signals/page.tsx +++ b/frontend/app/signals/page.tsx @@ -37,6 +37,26 @@ interface LatestIndicator { p99_qty: number; score: number; signal: string | null; + tier?: "light" | "standard" | "heavy" | null; + factors?: { + direction?: { score?: number }; + crowding?: { score?: number }; + environment?: { score?: number }; + confirmation?: { score?: number }; + auxiliary?: { score?: number }; + } | null; +} + +interface MarketIndicatorValue { + value: number; + ts: number; +} + +interface MarketIndicatorSet { + long_short_ratio?: MarketIndicatorValue; + top_trader_position?: MarketIndicatorValue; + open_interest_hist?: MarketIndicatorValue; + coinbase_premium?: MarketIndicatorValue; } const WINDOWS = [ @@ -57,6 +77,75 @@ function fmt(v: number, decimals = 1): string { return v.toFixed(decimals); } +function pct(v: number, digits = 1): string { + return `${(v * 100).toFixed(digits)}%`; +} + +function LayerScore({ label, score, max, colorClass }: { label: string; score: number; max: number; colorClass: string }) { + const ratio = Math.max(0, Math.min((score / max) * 100, 100)); + return ( +
多空比 (L/S)
+Long: {(ls / (1 + ls) * 100).toFixed(1)}%
+Short: {(100 - (ls / (1 + ls) * 100)).toFixed(1)}%
+大户持仓
+大户做多: {(top * 100).toFixed(1)}%
+方向: {top >= 0.55 ? "多头占优" : top <= 0.45 ? "空头占优" : "中性"}
+OI变化
+{pct(oi, 2)}
+活跃度: {oi >= 0.03 ? "高" : oi > 0 ? "中" : "低"}
+Coinbase Premium
+= 0 ? "text-emerald-600" : "text-red-500"}`}>{premium >= 0 ? "+" : ""}{pct(premium, 2)}
+机构: {premium > 0.0005 ? "偏多" : premium < -0.0005 ? "偏空" : "中性"}
+加分
-{data.score}/60
+总分
+{data.score}/100
+档位: {data.tier === "heavy" ? "加仓" : data.tier === "standard" ? "标准" : data.tier === "light" ? "轻仓" : "不开仓"}
CVD三轨 + ATR + VWAP + 大单阈值 → 做多/做空信号
+五层100分评分 + 市场拥挤度 + 环境确认
信号逻辑:CVD_fast方向 + CVD_mid方向 + VWAP位置 = 核心3条件。加分:ATR扩张(+25) + 无反向大单(+20) + 资金费率(+15)。
-仓位:0-15分→2%仓 / 20-40分→5%仓 / 45-60分→8%仓。冷却10分钟,时间止损30分钟。
+V5.1评分逻辑:方向层45分 + 拥挤层20分 + 环境层15分 + 确认层15分 + 辅助层5分(方向加速可额外+5)。
+开仓档位:<60不开仓,60-74轻仓,75-84标准仓位,≥85允许加仓;信号冷却10分钟。