fix: 详情页5门显示修undefined bug,表单加per-symbol推荐值,切换symbol自动填推荐
This commit is contained in:
parent
2e4c05b2e0
commit
89a6809c20
@ -33,12 +33,19 @@ export default function EditStrategyPage() {
|
|||||||
weight_aux: s.weight_aux,
|
weight_aux: s.weight_aux,
|
||||||
weight_momentum: s.weight_momentum,
|
weight_momentum: s.weight_momentum,
|
||||||
entry_score: s.entry_score,
|
entry_score: s.entry_score,
|
||||||
|
// 门1 波动率
|
||||||
|
gate_vol_enabled: s.gate_vol_enabled,
|
||||||
|
vol_atr_pct_min: s.vol_atr_pct_min,
|
||||||
|
// 门2 CVD共振
|
||||||
|
gate_cvd_enabled: s.gate_cvd_enabled ?? true,
|
||||||
|
// 门3 鲸鱼否决
|
||||||
|
gate_whale_enabled: s.gate_whale_enabled,
|
||||||
|
whale_usd_threshold: s.whale_usd_threshold,
|
||||||
|
whale_flow_pct: s.whale_flow_pct,
|
||||||
|
// 门4 OBI否决
|
||||||
gate_obi_enabled: s.gate_obi_enabled,
|
gate_obi_enabled: s.gate_obi_enabled,
|
||||||
obi_threshold: s.obi_threshold,
|
obi_threshold: s.obi_threshold,
|
||||||
gate_whale_enabled: s.gate_whale_enabled,
|
// 门5 期现背离
|
||||||
whale_cvd_threshold: s.whale_cvd_threshold,
|
|
||||||
gate_vol_enabled: s.gate_vol_enabled,
|
|
||||||
atr_percentile_min: s.atr_percentile_min,
|
|
||||||
gate_spot_perp_enabled: s.gate_spot_perp_enabled,
|
gate_spot_perp_enabled: s.gate_spot_perp_enabled,
|
||||||
spot_perp_threshold: s.spot_perp_threshold,
|
spot_perp_threshold: s.spot_perp_threshold,
|
||||||
sl_atr_multiplier: s.sl_atr_multiplier,
|
sl_atr_multiplier: s.sl_atr_multiplier,
|
||||||
|
|||||||
@ -59,12 +59,19 @@ interface StrategyDetail {
|
|||||||
weight_aux: number;
|
weight_aux: number;
|
||||||
weight_momentum: number;
|
weight_momentum: number;
|
||||||
entry_score: number;
|
entry_score: number;
|
||||||
|
// 门1 波动率
|
||||||
|
gate_vol_enabled: boolean;
|
||||||
|
vol_atr_pct_min: number;
|
||||||
|
// 门2 CVD共振
|
||||||
|
gate_cvd_enabled: boolean;
|
||||||
|
// 门3 鲸鱼否决
|
||||||
|
gate_whale_enabled: boolean;
|
||||||
|
whale_usd_threshold: number;
|
||||||
|
whale_flow_pct: number;
|
||||||
|
// 门4 OBI否决
|
||||||
gate_obi_enabled: boolean;
|
gate_obi_enabled: boolean;
|
||||||
obi_threshold: number;
|
obi_threshold: number;
|
||||||
gate_whale_enabled: boolean;
|
// 门5 期现背离
|
||||||
whale_cvd_threshold: number;
|
|
||||||
gate_vol_enabled: boolean;
|
|
||||||
atr_percentile_min: number;
|
|
||||||
gate_spot_perp_enabled: boolean;
|
gate_spot_perp_enabled: boolean;
|
||||||
spot_perp_threshold: number;
|
spot_perp_threshold: number;
|
||||||
sl_atr_multiplier: number;
|
sl_atr_multiplier: number;
|
||||||
@ -150,13 +157,14 @@ function ConfigTab({ detail, strategyId }: { detail: StrategyDetail; strategyId:
|
|||||||
{row("入场阈值", `${detail.entry_score} 分`)}
|
{row("入场阈值", `${detail.entry_score} 分`)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 四道 Gate */}
|
{/* 五道 Gate */}
|
||||||
<div className="bg-white border border-slate-200 rounded-xl p-4">
|
<div className="bg-white border border-slate-200 rounded-xl p-4">
|
||||||
<h4 className="text-xs font-semibold text-slate-600 mb-2">过滤门控 (Gate)</h4>
|
<h4 className="text-xs font-semibold text-slate-600 mb-2">过滤门控 (Gate)</h4>
|
||||||
{gateRow("Gate1 OBI", detail.gate_obi_enabled, `≥ ${detail.obi_threshold}`)}
|
{gateRow("门1 波动率", detail.gate_vol_enabled, `ATR% ≥ ${((detail.vol_atr_pct_min ?? 0) * 100).toFixed(2)}%`)}
|
||||||
{gateRow("Gate2 大单CVD", detail.gate_whale_enabled, `≥ ${detail.whale_cvd_threshold}`)}
|
{gateRow("门2 CVD共振", detail.gate_cvd_enabled ?? true, "快慢CVD同向")}
|
||||||
{gateRow("Gate3 ATR%", detail.gate_vol_enabled, `≥ ${detail.atr_percentile_min}%`)}
|
{gateRow("门3 鲸鱼否决", detail.gate_whale_enabled, `USD ≥ $${((detail.whale_usd_threshold ?? 50000) / 1000).toFixed(0)}k`)}
|
||||||
{gateRow("Gate4 现货溢价", detail.gate_spot_perp_enabled, `≤ ${detail.spot_perp_threshold}`)}
|
{gateRow("门4 OBI否决", detail.gate_obi_enabled, `阈值 ${detail.obi_threshold}`)}
|
||||||
|
{gateRow("门5 期现背离", detail.gate_spot_perp_enabled, `溢价 ≤ ${((detail.spot_perp_threshold ?? 0.005) * 100).toFixed(2)}%`)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 风控参数 */}
|
{/* 风控参数 */}
|
||||||
@ -235,12 +243,14 @@ export default function StrategyDetailPage() {
|
|||||||
weight_aux: s.weight_aux,
|
weight_aux: s.weight_aux,
|
||||||
weight_momentum: s.weight_momentum,
|
weight_momentum: s.weight_momentum,
|
||||||
entry_score: s.entry_score,
|
entry_score: s.entry_score,
|
||||||
|
gate_vol_enabled: s.gate_vol_enabled,
|
||||||
|
vol_atr_pct_min: s.vol_atr_pct_min,
|
||||||
|
gate_cvd_enabled: s.gate_cvd_enabled,
|
||||||
|
gate_whale_enabled: s.gate_whale_enabled,
|
||||||
|
whale_usd_threshold: s.whale_usd_threshold,
|
||||||
|
whale_flow_pct: s.whale_flow_pct,
|
||||||
gate_obi_enabled: s.gate_obi_enabled,
|
gate_obi_enabled: s.gate_obi_enabled,
|
||||||
obi_threshold: s.obi_threshold,
|
obi_threshold: s.obi_threshold,
|
||||||
gate_whale_enabled: s.gate_whale_enabled,
|
|
||||||
whale_cvd_threshold: s.whale_cvd_threshold,
|
|
||||||
gate_vol_enabled: s.gate_vol_enabled,
|
|
||||||
atr_percentile_min: s.atr_percentile_min,
|
|
||||||
gate_spot_perp_enabled: s.gate_spot_perp_enabled,
|
gate_spot_perp_enabled: s.gate_spot_perp_enabled,
|
||||||
spot_perp_threshold: s.spot_perp_threshold,
|
spot_perp_threshold: s.spot_perp_threshold,
|
||||||
sl_atr_multiplier: s.sl_atr_multiplier,
|
sl_atr_multiplier: s.sl_atr_multiplier,
|
||||||
|
|||||||
@ -73,6 +73,44 @@ export const DEFAULT_FORM: StrategyFormData = {
|
|||||||
description: "",
|
description: "",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ─── Per-symbol 推荐值 ────────────────────────────────────────────────────────
|
||||||
|
// 来自 v53.json symbol_gates,与 signal_engine.py 默认值保持一致
|
||||||
|
export const SYMBOL_RECOMMENDED: Record<string, Partial<StrategyFormData>> = {
|
||||||
|
BTCUSDT: {
|
||||||
|
vol_atr_pct_min: 0.002, // ATR需>价格0.2%
|
||||||
|
whale_usd_threshold: 100000, // 鲸鱼单>10万USD
|
||||||
|
whale_flow_pct: 0.5, // BTC鲸鱼流量>50%才否决
|
||||||
|
obi_threshold: 0.30, // OBI阈值宽松(BTC流动性好)
|
||||||
|
spot_perp_threshold: 0.003, // 期现溢价<0.3%
|
||||||
|
},
|
||||||
|
ETHUSDT: {
|
||||||
|
vol_atr_pct_min: 0.003, // ETH波动需更大
|
||||||
|
whale_usd_threshold: 50000,
|
||||||
|
whale_flow_pct: 0.5,
|
||||||
|
obi_threshold: 0.35,
|
||||||
|
spot_perp_threshold: 0.005,
|
||||||
|
},
|
||||||
|
SOLUSDT: {
|
||||||
|
vol_atr_pct_min: 0.004, // SOL波动更剧烈,需更高阈值
|
||||||
|
whale_usd_threshold: 20000,
|
||||||
|
whale_flow_pct: 0.5,
|
||||||
|
obi_threshold: 0.45, // SOL OBI噪音多,需更严
|
||||||
|
spot_perp_threshold: 0.008,
|
||||||
|
},
|
||||||
|
XRPUSDT: {
|
||||||
|
vol_atr_pct_min: 0.0025,
|
||||||
|
whale_usd_threshold: 30000,
|
||||||
|
whale_flow_pct: 0.5,
|
||||||
|
obi_threshold: 0.40,
|
||||||
|
spot_perp_threshold: 0.006,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export function applySymbolDefaults(form: StrategyFormData, symbol: string): StrategyFormData {
|
||||||
|
const rec = SYMBOL_RECOMMENDED[symbol] || SYMBOL_RECOMMENDED["BTCUSDT"];
|
||||||
|
return { ...form, symbol, ...rec };
|
||||||
|
}
|
||||||
|
|
||||||
// ─── Helper Components ────────────────────────────────────────────────────────
|
// ─── Helper Components ────────────────────────────────────────────────────────
|
||||||
function FieldLabel({ label, hint }: { label: string; hint?: string }) {
|
function FieldLabel({ label, hint }: { label: string; hint?: string }) {
|
||||||
return (
|
return (
|
||||||
@ -256,7 +294,14 @@ export default function StrategyForm({ mode, initialData, strategyId, onSuccess,
|
|||||||
<FieldLabel label="交易对" />
|
<FieldLabel label="交易对" />
|
||||||
<SelectInput
|
<SelectInput
|
||||||
value={form.symbol}
|
value={form.symbol}
|
||||||
onChange={(v) => set("symbol", v)}
|
onChange={(v) => {
|
||||||
|
if (mode === "create") {
|
||||||
|
// 新建时切换币种自动填入推荐值
|
||||||
|
setForm((prev) => applySymbolDefaults(prev, v));
|
||||||
|
} else {
|
||||||
|
set("symbol", v);
|
||||||
|
}
|
||||||
|
}}
|
||||||
options={[
|
options={[
|
||||||
{ label: "BTC/USDT", value: "BTCUSDT" },
|
{ label: "BTC/USDT", value: "BTCUSDT" },
|
||||||
{ label: "ETH/USDT", value: "ETHUSDT" },
|
{ label: "ETH/USDT", value: "ETHUSDT" },
|
||||||
@ -376,13 +421,23 @@ export default function StrategyForm({ mode, initialData, strategyId, onSuccess,
|
|||||||
<div className="bg-white border border-slate-200 rounded-xl p-4">
|
<div className="bg-white border border-slate-200 rounded-xl p-4">
|
||||||
<h3 className="text-sm font-semibold text-slate-700 mb-3">过滤门控(Gate)</h3>
|
<h3 className="text-sm font-semibold text-slate-700 mb-3">过滤门控(Gate)</h3>
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
|
{/* 推荐值提示 */}
|
||||||
|
{(() => {
|
||||||
|
const rec = SYMBOL_RECOMMENDED[form.symbol];
|
||||||
|
if (!rec) return null;
|
||||||
|
return (
|
||||||
|
<div className="text-xs text-slate-500 bg-slate-50 rounded-lg px-3 py-2">
|
||||||
|
📌 {form.symbol.replace("USDT","")} 推荐值:ATR%≥{((rec.vol_atr_pct_min??0)*100).toFixed(2)}%,鲸鱼≥${((rec.whale_usd_threshold??50000)/1000).toFixed(0)}k,OBI阈值{rec.obi_threshold}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})()}
|
||||||
<GateRow
|
<GateRow
|
||||||
label="门1:波动率门 (ATR%价格)"
|
label="门1:波动率门 (ATR%价格)"
|
||||||
hint="ATR占价格比例低于阈值时不开仓,过滤低波动时段"
|
hint="ATR占价格比例低于阈值时不开仓,过滤低波动时段"
|
||||||
enabled={form.gate_vol_enabled}
|
enabled={form.gate_vol_enabled}
|
||||||
onToggle={() => set("gate_vol_enabled", !form.gate_vol_enabled)}
|
onToggle={() => set("gate_vol_enabled", !form.gate_vol_enabled)}
|
||||||
>
|
>
|
||||||
<FieldLabel label="ATR% 最低阈值" hint="如0.002=价格0.2%,BTC默认0.002,ETH默认0.003" />
|
<FieldLabel label="ATR% 最低阈值" hint={`推荐:BTC=0.002, ETH=0.003, SOL=0.004, XRP=0.0025(当前${form.symbol.replace("USDT","")}推荐${SYMBOL_RECOMMENDED[form.symbol]?.vol_atr_pct_min??0.002})`} />
|
||||||
<NumberInput value={form.vol_atr_pct_min} onChange={(v) => set("vol_atr_pct_min", v)} min={0.0001} max={0.02} step={0.0005} />
|
<NumberInput value={form.vol_atr_pct_min} onChange={(v) => set("vol_atr_pct_min", v)} min={0.0001} max={0.02} step={0.0005} />
|
||||||
</GateRow>
|
</GateRow>
|
||||||
<GateRow
|
<GateRow
|
||||||
@ -397,9 +452,9 @@ export default function StrategyForm({ mode, initialData, strategyId, onSuccess,
|
|||||||
enabled={form.gate_whale_enabled}
|
enabled={form.gate_whale_enabled}
|
||||||
onToggle={() => set("gate_whale_enabled", !form.gate_whale_enabled)}
|
onToggle={() => set("gate_whale_enabled", !form.gate_whale_enabled)}
|
||||||
>
|
>
|
||||||
<FieldLabel label="大单USD阈值 (ALT)" hint="超过此USD金额视为鲸鱼单,ETH默认5万,BTC默认10万" />
|
<FieldLabel label="大单USD阈值 (ALT)" hint={`推荐:BTC=10万, ETH=5万, SOL=2万, XRP=3万(当前推荐$${((SYMBOL_RECOMMENDED[form.symbol]?.whale_usd_threshold??50000)/1000).toFixed(0)}k)`} />
|
||||||
<NumberInput value={form.whale_usd_threshold} onChange={(v) => set("whale_usd_threshold", v)} min={1000} max={1000000} step={5000} />
|
<NumberInput value={form.whale_usd_threshold} onChange={(v) => set("whale_usd_threshold", v)} min={1000} max={1000000} step={5000} />
|
||||||
<FieldLabel label="鲸鱼CVD流量阈值 (BTC)" hint="0~1,BTC鲸鱼净方向比例超过此值才否决,默认0.5" />
|
<FieldLabel label="鲸鱼CVD流量阈值 (BTC)" hint="0~1,BTC鲸鱼净方向比例超过此值才否决,推荐0.5" />
|
||||||
<NumberInput value={form.whale_flow_pct} onChange={(v) => set("whale_flow_pct", v)} min={0} max={1} step={0.05} />
|
<NumberInput value={form.whale_flow_pct} onChange={(v) => set("whale_flow_pct", v)} min={0} max={1} step={0.05} />
|
||||||
</GateRow>
|
</GateRow>
|
||||||
<GateRow
|
<GateRow
|
||||||
@ -408,7 +463,7 @@ export default function StrategyForm({ mode, initialData, strategyId, onSuccess,
|
|||||||
enabled={form.gate_obi_enabled}
|
enabled={form.gate_obi_enabled}
|
||||||
onToggle={() => set("gate_obi_enabled", !form.gate_obi_enabled)}
|
onToggle={() => set("gate_obi_enabled", !form.gate_obi_enabled)}
|
||||||
>
|
>
|
||||||
<FieldLabel label="OBI 否决阈值" hint="0.1(宽松) ~ 0.9(严格),默认0.35" />
|
<FieldLabel label="OBI 否决阈值" hint={`推荐:BTC=0.30(宽松), ETH=0.35, SOL=0.45(严格)(当前推荐${SYMBOL_RECOMMENDED[form.symbol]?.obi_threshold??0.35})`} />
|
||||||
<NumberInput value={form.obi_threshold} onChange={(v) => set("obi_threshold", v)} min={0.1} max={0.9} step={0.05} />
|
<NumberInput value={form.obi_threshold} onChange={(v) => set("obi_threshold", v)} min={0.1} max={0.9} step={0.05} />
|
||||||
</GateRow>
|
</GateRow>
|
||||||
<GateRow
|
<GateRow
|
||||||
@ -417,7 +472,7 @@ export default function StrategyForm({ mode, initialData, strategyId, onSuccess,
|
|||||||
enabled={form.gate_spot_perp_enabled}
|
enabled={form.gate_spot_perp_enabled}
|
||||||
onToggle={() => set("gate_spot_perp_enabled", !form.gate_spot_perp_enabled)}
|
onToggle={() => set("gate_spot_perp_enabled", !form.gate_spot_perp_enabled)}
|
||||||
>
|
>
|
||||||
<FieldLabel label="溢价率阈值" hint="0.0005~0.01,溢价超过此值不开仓,默认0.005" />
|
<FieldLabel label="溢价率阈值" hint={`推荐:BTC=0.003, ETH=0.005, SOL=0.008(当前推荐${SYMBOL_RECOMMENDED[form.symbol]?.spot_perp_threshold??0.005})`} />
|
||||||
<NumberInput value={form.spot_perp_threshold} onChange={(v) => set("spot_perp_threshold", v)} min={0.0005} max={0.01} step={0.0005} />
|
<NumberInput value={form.spot_perp_threshold} onChange={(v) => set("spot_perp_threshold", v)} min={0.0005} max={0.01} step={0.0005} />
|
||||||
</GateRow>
|
</GateRow>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user