245 lines
9.3 KiB
Python
245 lines
9.3 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
bootstrap_eth_xrp_sol_strategies.py
|
||
|
||
基于 v5.3 Optuna 结果 + v53.json 的 symbol_gates,为策略工厂批量创建
|
||
ETH/XRP/SOL 的 54 条单币种策略配置。
|
||
|
||
约定:
|
||
- 仍沿用 BTC 工厂当前的 CVD 组合与 TP 档位:
|
||
* CVD 窗口: (5m,30m), (5m,1h), (15m,1h), (15m,4h), (30m,1h), (30m,4h)
|
||
* TP 档位: 保守 / 平衡 / 激进(sl=2ATR,TP=0.75/1.0/1.5R 与 1.5/2.0/2.5R)
|
||
- 每个 symbol 的门控阈值复刻 v53.json 的 symbol_gates:
|
||
* ETHUSDT: min_vol=0.003, whale_usd=50000, obi=0.35, spd=0.005
|
||
* XRPUSDT: min_vol=0.0025, whale_usd=30000, obi=0.40, spd=0.006
|
||
* SOLUSDT: min_vol=0.004, whale_usd=20000, obi=0.45, spd=0.008
|
||
- 五门开关与 BTC 工厂当前配置保持一致:
|
||
* 波动率门 / CVD 门 / 巨鲸门 / OBI 门:启用
|
||
* 期现门:关闭(仅写入阈值,保留以后启用的空间)
|
||
- 权重与开仓阈值取自 optuna_results_v3_cn.xlsx 中各 symbol 的 v53/v53_fast Top1:
|
||
* ETHUSDT (v53): dir=51, env=18, aux=28, mom=3, threshold=75
|
||
* XRPUSDT (v53): dir=58, env=8, aux=32, mom=2, threshold=80
|
||
* SOLUSDT (v53_fast): dir=38, env=42, aux=8, mom=12, threshold=65
|
||
|
||
注意:
|
||
- 如果某个 display_name 已存在于 strategies 表,将跳过,不会重复插入。
|
||
- 连接参数走 backend.db.get_sync_conn(),运行脚本时请设置:
|
||
PG_HOST=127.0.0.1 PG_PORT=9470 PG_DB=arb_engine PG_USER=arb PG_PASS=...
|
||
或在服务器上直接使用 Cloud SQL 内网地址。
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import os
|
||
import sys
|
||
from dataclasses import dataclass
|
||
|
||
# 确保可以从 backend 导入 db.get_sync_conn
|
||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "backend"))
|
||
from db import get_sync_conn # type: ignore
|
||
|
||
|
||
@dataclass
|
||
class SymbolProfile:
|
||
symbol: str
|
||
weight_direction: int
|
||
weight_env: int
|
||
weight_aux: int
|
||
weight_momentum: int
|
||
entry_score: int
|
||
min_vol: float
|
||
whale_usd_threshold: float
|
||
whale_flow_pct: float
|
||
obi_threshold: float
|
||
spot_perp_threshold: float
|
||
|
||
|
||
# 基于 optuna_results_v3_cn.xlsx Top1 Summary + v53.json symbol_gates
|
||
SYMBOL_PROFILES: list[SymbolProfile] = [
|
||
SymbolProfile(
|
||
symbol="ETHUSDT",
|
||
weight_direction=51,
|
||
weight_env=18,
|
||
weight_aux=28,
|
||
weight_momentum=3,
|
||
entry_score=75,
|
||
min_vol=0.003,
|
||
whale_usd_threshold=50_000,
|
||
whale_flow_pct=0.5, # ALT 分支主要用 whale_usd_threshold,此处保持默认
|
||
obi_threshold=0.35,
|
||
spot_perp_threshold=0.005,
|
||
),
|
||
SymbolProfile(
|
||
symbol="XRPUSDT",
|
||
weight_direction=58,
|
||
weight_env=8,
|
||
weight_aux=32,
|
||
weight_momentum=2,
|
||
entry_score=80,
|
||
min_vol=0.0025,
|
||
whale_usd_threshold=30_000,
|
||
whale_flow_pct=0.5,
|
||
obi_threshold=0.40,
|
||
spot_perp_threshold=0.006,
|
||
),
|
||
SymbolProfile(
|
||
symbol="SOLUSDT",
|
||
weight_direction=38,
|
||
weight_env=42,
|
||
weight_aux=8,
|
||
weight_momentum=12,
|
||
entry_score=65,
|
||
min_vol=0.004,
|
||
whale_usd_threshold=20_000,
|
||
whale_flow_pct=0.5,
|
||
obi_threshold=0.45,
|
||
spot_perp_threshold=0.008,
|
||
),
|
||
]
|
||
|
||
|
||
# 与 BTC 工厂一致的 CVD 组合
|
||
CVD_COMBOS: list[tuple[str, str]] = [
|
||
("5m", "30m"),
|
||
("5m", "1h"),
|
||
("15m", "1h"),
|
||
("15m", "4h"),
|
||
("30m", "1h"),
|
||
("30m", "4h"),
|
||
]
|
||
|
||
|
||
# TP 档位:保守 / 平衡 / 激进(统一 sl_multiplier=2.0)
|
||
TP_PROFILES: dict[str, dict[str, float]] = {
|
||
"保守": {"sl_atr_multiplier": 2.0, "tp1_ratio": 0.75, "tp2_ratio": 1.5},
|
||
"平衡": {"sl_atr_multiplier": 2.0, "tp1_ratio": 1.0, "tp2_ratio": 2.0},
|
||
"激进": {"sl_atr_multiplier": 2.0, "tp1_ratio": 1.5, "tp2_ratio": 2.5},
|
||
}
|
||
|
||
|
||
def build_display_name(symbol: str, fast_win: str, slow_win: str, tp_label: str) -> str:
|
||
"""
|
||
生成与 BTC 工厂一致的 display_name,例如:
|
||
BTC_CVD5x30m_TP保守 → ETH_CVD5x30m_TP保守
|
||
"""
|
||
base = symbol.replace("USDT", "")
|
||
fast_label = fast_win.replace("m", "") # "5m" → "5"
|
||
return f"{base}_CVD{fast_label}x{slow_win}_TP{tp_label}"
|
||
|
||
|
||
def main() -> None:
|
||
created = 0
|
||
skipped = 0
|
||
|
||
with get_sync_conn() as conn:
|
||
with conn.cursor() as cur:
|
||
for profile in SYMBOL_PROFILES:
|
||
sym = profile.symbol
|
||
for fast_win, slow_win in CVD_COMBOS:
|
||
for tp_label, tp_cfg in TP_PROFILES.items():
|
||
display_name = build_display_name(sym, fast_win, slow_win, tp_label)
|
||
|
||
# 避免重复插入:按 display_name 检查
|
||
cur.execute(
|
||
"SELECT 1 FROM strategies WHERE display_name=%s",
|
||
(display_name,),
|
||
)
|
||
if cur.fetchone():
|
||
skipped += 1
|
||
continue
|
||
|
||
cur.execute(
|
||
"""
|
||
INSERT INTO strategies (
|
||
display_name,
|
||
symbol,
|
||
direction,
|
||
cvd_fast_window,
|
||
cvd_slow_window,
|
||
weight_direction,
|
||
weight_env,
|
||
weight_aux,
|
||
weight_momentum,
|
||
entry_score,
|
||
gate_vol_enabled,
|
||
vol_atr_pct_min,
|
||
gate_cvd_enabled,
|
||
gate_whale_enabled,
|
||
whale_usd_threshold,
|
||
whale_flow_pct,
|
||
gate_obi_enabled,
|
||
obi_threshold,
|
||
gate_spot_perp_enabled,
|
||
spot_perp_threshold,
|
||
sl_atr_multiplier,
|
||
tp1_ratio,
|
||
tp2_ratio,
|
||
timeout_minutes,
|
||
flip_threshold
|
||
)
|
||
VALUES (
|
||
%s, -- display_name
|
||
%s, -- symbol
|
||
%s, -- direction
|
||
%s, -- cvd_fast_window
|
||
%s, -- cvd_slow_window
|
||
%s, -- weight_direction
|
||
%s, -- weight_env
|
||
%s, -- weight_aux
|
||
%s, -- weight_momentum
|
||
%s, -- entry_score
|
||
%s, -- gate_vol_enabled
|
||
%s, -- vol_atr_pct_min
|
||
%s, -- gate_cvd_enabled
|
||
%s, -- gate_whale_enabled
|
||
%s, -- whale_usd_threshold
|
||
%s, -- whale_flow_pct
|
||
%s, -- gate_obi_enabled
|
||
%s, -- obi_threshold
|
||
%s, -- gate_spot_perp_enabled
|
||
%s, -- spot_perp_threshold
|
||
%s, -- sl_atr_multiplier
|
||
%s, -- tp1_ratio
|
||
%s, -- tp2_ratio
|
||
%s, -- timeout_minutes
|
||
%s -- flip_threshold
|
||
)
|
||
""",
|
||
(
|
||
display_name,
|
||
sym,
|
||
"both", # 方向:多空双向
|
||
fast_win,
|
||
slow_win,
|
||
profile.weight_direction,
|
||
profile.weight_env,
|
||
profile.weight_aux,
|
||
profile.weight_momentum,
|
||
profile.entry_score,
|
||
True, # gate_vol_enabled
|
||
profile.min_vol,
|
||
True, # gate_cvd_enabled
|
||
True, # gate_whale_enabled
|
||
profile.whale_usd_threshold,
|
||
profile.whale_flow_pct,
|
||
True, # gate_obi_enabled
|
||
profile.obi_threshold,
|
||
False, # gate_spot_perp_enabled(与当前 BTC 工厂一致,先关闭)
|
||
profile.spot_perp_threshold,
|
||
tp_cfg["sl_atr_multiplier"],
|
||
tp_cfg["tp1_ratio"],
|
||
tp_cfg["tp2_ratio"],
|
||
240, # timeout_minutes,沿用 BTC 工厂
|
||
80, # flip_threshold,沿用 v5.4 设计
|
||
),
|
||
)
|
||
created += 1
|
||
|
||
conn.commit()
|
||
|
||
print(f"[bootstrap] created={created}, skipped={skipped}")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|