arbitrage-engine/scripts/bootstrap_eth_xrp_sol_strategies.py

245 lines
9.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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=2ATRTP=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()