diff --git a/static/app.html b/static/app.html index f9fc5c7..f6343f4 100644 --- a/static/app.html +++ b/static/app.html @@ -448,6 +448,74 @@ function fmtCompactNumber(v) { if (abs >= 1e3) return (v / 1e3).toFixed(1) + 'K'; return v.toFixed(abs >= 100 ? 0 : abs >= 10 ? 1 : 2); } +var MARKET_REGIME_LABELS = { + risk_off: '避险期', + btc_main_uptrend: 'BTC 主导上涨', + altcoin_rotation: '山寨轮动期', + sideways_chop: '震荡拉锯期', + meme_frenzy: 'Meme 过热期', + unknown: '市场环境待确认' +}; +var MARKET_RISK_LABELS = { + low: '低风险', + medium: '中等风险', + high: '高风险', + critical: '极高风险' +}; +var DECISION_LABELS = { + confirmed: '已确认', + rejected: '未通过', + observe: '观察中', + wait_pullback: '等待回踩', + buy_now: '入场窗口', + weak_observe: '弱观察', + invalid: '已失效' +}; +var MODULE_LABELS = { + confirm_burst: '爆发确认', + confirm_static_accumulation: '蓄力确认', + confirm_event: '事件确认', + strategy: '策略判断', + screener: '初筛', + tracker: '跟踪', + paper_trader: '策略交易' +}; +var FLAG_LABELS = { + market_regime: '市场环境', + market_risk: '市场风险', + global_risk: '全局风险', + risk_reward_bad: '盈亏比不足', + false_breakout: '假突破风险', + liquidity_risk: '流动性风险', + funding_overheat: '资金费率过热', + overextended: '短线涨幅过大', + entry_quality_low: '买点质量偏低' +}; +function regimeLabel(v) { + v = String(v || ''); + return MARKET_REGIME_LABELS[v] || cleanDisplayText(v).replace(/_/g, ' '); +} +function riskLabel(v) { + v = String(v || ''); + return MARKET_RISK_LABELS[v] || cleanDisplayText(v).replace(/_/g, ' '); +} +function translateInternalToken(token) { + token = String(token == null ? '' : token).trim(); + if (!token) return ''; + if (DECISION_LABELS[token]) return DECISION_LABELS[token]; + if (MODULE_LABELS[token]) return MODULE_LABELS[token]; + if (MARKET_REGIME_LABELS[token]) return MARKET_REGIME_LABELS[token]; + if (MARKET_RISK_LABELS[token]) return MARKET_RISK_LABELS[token]; + var kv = token.match(/^([a-zA-Z0-9_]+):(.*)$/); + if (kv) { + var key = kv[1], value = kv[2]; + if (key === 'market_regime') return '市场环境:' + regimeLabel(value); + if (key === 'market_risk') return '市场风险:' + riskLabel(value); + if (key === 'global_risk') return '全局风险:' + riskLabel(value); + return (FLAG_LABELS[key] || key.replace(/_/g, ' ')) + ':' + translateInternalToken(value); + } + return FLAG_LABELS[token] || cleanDisplayText(token).replace(/_/g, ' '); +} function scoreComponentsFrom(r) { var ep = (r && r.entry_plan) || {}; var mc = (r && r.market_context) || {}; @@ -480,13 +548,15 @@ function renderRegimeBrief(r) { if (!rg || !rg.regime) return ''; var reasons = Array.isArray(rg.reasons) ? rg.reasons : []; var cls = String(rg.regime || '') + ' ' + String(rg.risk_level || ''); - return '
'+esc(rg.label || rg.regime || '市场环境')+' · '+esc(rg.risk_level || 'medium')+''+esc(reasons[0] || '市场环境已记录到策略上下文')+'
'; + return '
'+esc(rg.label || regimeLabel(rg.regime) || '市场环境')+' · '+esc(riskLabel(rg.risk_level || 'medium'))+''+esc(reasons[0] || '市场环境已记录到策略上下文')+'
'; } function renderDecisionLogBrief(r) { var log = decisionLogFrom(r); if (!log || !log.decision) return ''; - var flags = Array.isArray(log.risk_flags) ? log.risk_flags.slice(0,2).join(' · ') : ''; - return '
'+esc(log.decision)+' · '+esc(log.module || 'strategy')+(flags ? ' · '+esc(flags) : '')+'
'; + var flags = Array.isArray(log.risk_flags) + ? log.risk_flags.slice(0,3).map(translateInternalToken).filter(Boolean).join(' · ') + : ''; + return '
'+esc(translateInternalToken(log.decision))+' · '+esc(translateInternalToken(log.module || 'strategy'))+(flags ? ' · '+esc(flags) : '')+'
'; } function renderStrategyDiagnostics(r) { var html = renderScoreComponents(r) + renderRegimeBrief(r) + renderDecisionLogBrief(r);