feat: merge v53_alt+v53_btc into unified v53 strategy (all 4 symbols, per-symbol gates)
This commit is contained in:
parent
546fae39d0
commit
42cb230337
@ -1,6 +1,6 @@
|
||||
{
|
||||
"enabled": true,
|
||||
"enabled_strategies": ["v51_baseline", "v52_8signals", "v53_alt", "v53_btc"],
|
||||
"enabled_strategies": ["v51_baseline", "v52_8signals", "v53"],
|
||||
"initial_balance": 10000,
|
||||
"risk_per_trade": 0.02,
|
||||
"max_positions": 4,
|
||||
|
||||
@ -42,7 +42,7 @@ logger = logging.getLogger("signal-engine")
|
||||
SYMBOLS = ["BTCUSDT", "ETHUSDT", "XRPUSDT", "SOLUSDT"]
|
||||
LOOP_INTERVAL = 15 # 秒(从5改15,CPU降60%,信号质量无影响)
|
||||
STRATEGY_DIR = os.path.join(os.path.dirname(__file__), "strategies")
|
||||
DEFAULT_STRATEGY_FILES = ["v51_baseline.json", "v52_8signals.json", "v53_alt.json", "v53_btc.json"]
|
||||
DEFAULT_STRATEGY_FILES = ["v51_baseline.json", "v52_8signals.json", "v53.json"]
|
||||
|
||||
|
||||
def load_strategy_configs() -> list[dict]:
|
||||
@ -453,23 +453,15 @@ class SymbolState:
|
||||
track = strategy_cfg.get("track", "ALT")
|
||||
|
||||
# ─── Track Router ───────────────────────────────────────────
|
||||
# V5.3策略按track路由到专属评分逻辑
|
||||
# v53_alt → ALT轨(ETH/XRP/SOL),55/25/15/5,删确认层
|
||||
# v53_btc → BTC轨,gate-control逻辑
|
||||
# v53 → 统一评分(BTC/ETH/XRP/SOL)
|
||||
# v53_alt / v53_btc → 兼容旧策略名,转发到 _evaluate_v53()
|
||||
# v51/v52 → 原有代码路径(兼容,不修改)
|
||||
if track == "ALT" and strategy_name.startswith("v53"):
|
||||
# 检查symbol限制(v53_alt只跑ALT,不跑BTC)
|
||||
if strategy_name.startswith("v53"):
|
||||
allowed_symbols = strategy_cfg.get("symbols", [])
|
||||
if allowed_symbols and self.symbol not in allowed_symbols:
|
||||
snap = snapshot or self.build_evaluation_snapshot(now_ms)
|
||||
return self._empty_result(strategy_name, snap)
|
||||
return self._evaluate_v53_alt(now_ms, strategy_cfg, snapshot)
|
||||
if track == "BTC" and strategy_name.startswith("v53"):
|
||||
# v53_btc只跑BTC
|
||||
if self.symbol != "BTCUSDT":
|
||||
snap = snapshot or self.build_evaluation_snapshot(now_ms)
|
||||
return self._empty_result(strategy_name, snap)
|
||||
return self._evaluate_v53_btc(now_ms, strategy_cfg, snapshot)
|
||||
return self._evaluate_v53(now_ms, strategy_cfg, snapshot)
|
||||
# ─── 原有V5.1/V5.2评分逻辑(保持不变)────────────────────────
|
||||
strategy_cfg = strategy_cfg or {}
|
||||
strategy_name = strategy_cfg.get("name", "v51_baseline")
|
||||
@ -725,13 +717,17 @@ class SymbolState:
|
||||
"signal": None, "direction": None, "score": 0, "tier": None, "factors": {},
|
||||
}
|
||||
|
||||
def _evaluate_v53_alt(self, now_ms: int, strategy_cfg: dict, snapshot: Optional[dict] = None) -> dict:
|
||||
def _evaluate_v53(self, now_ms: int, strategy_cfg: dict, snapshot: Optional[dict] = None) -> dict:
|
||||
"""
|
||||
V5.3 ALT轨评分(ETH/XRP/SOL)
|
||||
权重:Direction 55 | Crowding 25 | Environment 15 | Auxiliary 5
|
||||
删除独立确认层,解决CVD双重计分问题
|
||||
V5.3 统一评分(BTC/ETH/XRP/SOL)
|
||||
架构:四层评分 55/25/15/5 + per-symbol 四门控制
|
||||
- 门1:波动率下限(atr/price)
|
||||
- 门2:CVD共振(fast+mid同向)
|
||||
- 门3:OBI否决(实时WebSocket,fallback DB)
|
||||
- 门4:期现背离否决(实时WebSocket,fallback DB)
|
||||
BTC额外:whale_cvd_ratio(>$100k巨鲸CVD)
|
||||
"""
|
||||
strategy_name = strategy_cfg.get("name", "v53_alt")
|
||||
strategy_name = strategy_cfg.get("name", "v53")
|
||||
strategy_threshold = int(strategy_cfg.get("threshold", 75))
|
||||
flip_threshold = int(strategy_cfg.get("flip_threshold", 85))
|
||||
|
||||
@ -741,34 +737,31 @@ class SymbolState:
|
||||
price = snap["price"]
|
||||
atr = snap["atr"]
|
||||
atr_value = snap.get("atr_value", atr)
|
||||
atr_pct = snap["atr_pct"]
|
||||
cvd_fast_accel = snap["cvd_fast_accel"]
|
||||
environment_score_raw = snap["environment_score"]
|
||||
|
||||
result = self._empty_result(strategy_name, snap)
|
||||
|
||||
if self.warmup or price == 0 or atr == 0:
|
||||
return result
|
||||
|
||||
last_signal_ts = self.last_signal_ts.get(strategy_name, 0)
|
||||
in_cooldown = now_ms - last_signal_ts < COOLDOWN_MS
|
||||
|
||||
# ── Per-symbol 四门参数(从 strategy_cfg.symbol_gates 读取)──────────
|
||||
# ── Per-symbol 四门参数 ────────────────────────────────────
|
||||
symbol_gates = (strategy_cfg.get("symbol_gates") or {}).get(self.symbol, {})
|
||||
min_vol = float(symbol_gates.get("min_vol_threshold", 0.003))
|
||||
whale_usd = float(symbol_gates.get("whale_threshold_usd", 50000))
|
||||
obi_veto = float(symbol_gates.get("obi_veto_threshold", 0.35))
|
||||
spd_veto = float(symbol_gates.get("spot_perp_divergence_veto", 0.005))
|
||||
min_vol = float(symbol_gates.get("min_vol_threshold", 0.002))
|
||||
whale_usd = float(symbol_gates.get("whale_threshold_usd", 50000))
|
||||
obi_veto = float(symbol_gates.get("obi_veto_threshold", 0.35))
|
||||
spd_veto = float(symbol_gates.get("spot_perp_divergence_veto", 0.005))
|
||||
|
||||
gate_block = None # 门控否决原因,None = 全部通过
|
||||
gate_block = None
|
||||
|
||||
# 门1:波动率下限
|
||||
atr_pct_price = atr / price if price > 0 else 0
|
||||
if atr_pct_price < min_vol:
|
||||
gate_block = f"low_vol({atr_pct_price:.4f}<{min_vol})"
|
||||
|
||||
# ── Direction Layer(55分)──────────────────────────────────
|
||||
# cvd_resonance(30分):fast+mid同向 = 有效方向
|
||||
# 门2:CVD共振(方向门)
|
||||
if cvd_fast > 0 and cvd_mid > 0:
|
||||
direction = "LONG"
|
||||
cvd_resonance = 30
|
||||
@ -780,25 +773,35 @@ class SymbolState:
|
||||
else:
|
||||
direction = "LONG" if cvd_fast > 0 else "SHORT"
|
||||
cvd_resonance = 0
|
||||
no_direction = True # gate: 方向不一致 → 直接不开仓
|
||||
no_direction = True
|
||||
if not gate_block:
|
||||
gate_block = "no_direction_consensus"
|
||||
|
||||
# 门2:鲸鱼推力(大单净方向需与信号方向一致)
|
||||
# 门3:鲸鱼否决(BTC用whale_cvd_ratio,ALT用大单对立)
|
||||
if not gate_block and not no_direction:
|
||||
whale_aligned = any(
|
||||
(direction == "LONG" and lt[2] == 0 and lt[1] * price >= whale_usd) or
|
||||
(direction == "SHORT" and lt[2] == 1 and lt[1] * price >= whale_usd)
|
||||
for lt in self.recent_large_trades
|
||||
)
|
||||
whale_adverse = any(
|
||||
(direction == "LONG" and lt[2] == 1 and lt[1] * price >= whale_usd) or
|
||||
(direction == "SHORT" and lt[2] == 0 and lt[1] * price >= whale_usd)
|
||||
for lt in self.recent_large_trades
|
||||
)
|
||||
# 有明确对立大单时否决(没有大单时不否决,给机会)
|
||||
if whale_adverse and not whale_aligned:
|
||||
gate_block = f"whale_adverse(>${whale_usd/1000:.0f}k)"
|
||||
if self.symbol == "BTCUSDT":
|
||||
# BTC:巨鲸CVD净方向与信号方向冲突时否决
|
||||
whale_cvd = self.whale_cvd_ratio if self._whale_trades else to_float(self.market_indicators.get("tiered_cvd_whale")) or 0.0
|
||||
whale_threshold_pct = float(symbol_gates.get("whale_flow_threshold_pct", 0.5)) / 100
|
||||
if (direction == "LONG" and whale_cvd < -whale_threshold_pct) or \
|
||||
(direction == "SHORT" and whale_cvd > whale_threshold_pct):
|
||||
gate_block = f"whale_cvd_veto({whale_cvd:.3f})"
|
||||
else:
|
||||
# ALT:recent_large_trades 里有对立大单则否决
|
||||
whale_adverse = any(
|
||||
(direction == "LONG" and lt[2] == 1 and lt[1] * price >= whale_usd) or
|
||||
(direction == "SHORT" and lt[2] == 0 and lt[1] * price >= whale_usd)
|
||||
for lt in self.recent_large_trades
|
||||
)
|
||||
whale_aligned = any(
|
||||
(direction == "LONG" and lt[2] == 0 and lt[1] * price >= whale_usd) or
|
||||
(direction == "SHORT" and lt[2] == 1 and lt[1] * price >= whale_usd)
|
||||
for lt in self.recent_large_trades
|
||||
)
|
||||
if whale_adverse and not whale_aligned:
|
||||
gate_block = f"whale_adverse(>${whale_usd/1000:.0f}k)"
|
||||
|
||||
# 门3:OBI否决(优先实时WebSocket值,fallback DB)
|
||||
# 门4:OBI否决(实时WS优先,fallback DB)
|
||||
obi_raw = self.rt_obi if self.rt_obi != 0.0 else to_float(self.market_indicators.get("obi_depth_10"))
|
||||
if not gate_block and not no_direction and obi_raw is not None:
|
||||
if direction == "LONG" and obi_raw < -obi_veto:
|
||||
@ -806,14 +809,16 @@ class SymbolState:
|
||||
elif direction == "SHORT" and obi_raw > obi_veto:
|
||||
gate_block = f"obi_veto({obi_raw:.3f}>{obi_veto})"
|
||||
|
||||
# 门4:期现背离否决(优先实时WebSocket值,fallback DB)
|
||||
# 门5:期现背离否决(实时WS优先,fallback DB)
|
||||
spot_perp_div = self.rt_spot_perp_div if self.rt_spot_perp_div != 0.0 else to_float(self.market_indicators.get("spot_perp_divergence"))
|
||||
if not gate_block and not no_direction and spot_perp_div is not None:
|
||||
if (direction == "LONG" and spot_perp_div < -spd_veto) or \
|
||||
(direction == "SHORT" and spot_perp_div > spd_veto):
|
||||
gate_block = f"spd_veto({spot_perp_div:.4f})"
|
||||
|
||||
# p99_flow_alignment(0/10/20分)
|
||||
gate_passed = gate_block is None
|
||||
|
||||
# ── Direction Layer(55分)─────────────────────────────────
|
||||
has_adverse_p99 = any(
|
||||
(direction == "LONG" and lt[2] == 1) or (direction == "SHORT" and lt[2] == 0)
|
||||
for lt in self.recent_large_trades
|
||||
@ -822,25 +827,17 @@ class SymbolState:
|
||||
(direction == "LONG" and lt[2] == 0) or (direction == "SHORT" and lt[2] == 1)
|
||||
for lt in self.recent_large_trades
|
||||
)
|
||||
if has_aligned_p99:
|
||||
p99_flow = 20
|
||||
elif not has_adverse_p99:
|
||||
p99_flow = 10
|
||||
else:
|
||||
p99_flow = 0
|
||||
|
||||
# cvd_accel_bonus(0/5分)
|
||||
p99_flow = 20 if has_aligned_p99 else (10 if not has_adverse_p99 else 0)
|
||||
accel_bonus = 5 if (
|
||||
(direction == "LONG" and cvd_fast_accel > 0) or
|
||||
(direction == "SHORT" and cvd_fast_accel < 0)
|
||||
) else 0
|
||||
|
||||
direction_score = min(cvd_resonance + p99_flow + accel_bonus, 55)
|
||||
|
||||
# ── Crowding Layer(25分)──────────────────────────────────
|
||||
# ── Crowding Layer(25分)─────────────────────────────────
|
||||
long_short_ratio = to_float(self.market_indicators.get("long_short_ratio"))
|
||||
if long_short_ratio is None:
|
||||
ls_score = 7 # 缺失给中间分
|
||||
ls_score = 7
|
||||
elif (direction == "SHORT" and long_short_ratio > 2.0) or (direction == "LONG" and long_short_ratio < 0.5):
|
||||
ls_score = 15
|
||||
elif (direction == "SHORT" and long_short_ratio > 1.5) or (direction == "LONG" and long_short_ratio < 0.7):
|
||||
@ -858,13 +855,12 @@ class SymbolState:
|
||||
top_trader_score = 10 if top_trader_position >= 0.55 else (0 if top_trader_position <= 0.45 else 5)
|
||||
else:
|
||||
top_trader_score = 10 if top_trader_position <= 0.45 else (0 if top_trader_position >= 0.55 else 5)
|
||||
|
||||
crowding_score = min(ls_score + top_trader_score, 25)
|
||||
|
||||
# ── Environment Layer(15分)────────────────────────────────
|
||||
environment_score = round(environment_score_raw / 15 * 15) # 已是0~15
|
||||
# ── Environment Layer(15分)──────────────────────────────
|
||||
environment_score = round(environment_score_raw / 15 * 15)
|
||||
|
||||
# ── Auxiliary Layer(5分)──────────────────────────────────
|
||||
# ── Auxiliary Layer(5分)────────────────────────────────
|
||||
coinbase_premium = to_float(self.market_indicators.get("coinbase_premium"))
|
||||
if coinbase_premium is None:
|
||||
aux_score = 2
|
||||
@ -877,23 +873,24 @@ class SymbolState:
|
||||
|
||||
total_score = min(direction_score + crowding_score + environment_score + aux_score, 100)
|
||||
total_score = max(0, round(total_score, 1))
|
||||
|
||||
# 门控否决时归零分、清方向
|
||||
gate_passed = gate_block is None
|
||||
if not gate_passed:
|
||||
total_score = 0
|
||||
|
||||
# whale_cvd for BTC display
|
||||
whale_cvd_display = (self.whale_cvd_ratio if self._whale_trades else to_float(self.market_indicators.get("tiered_cvd_whale"))) if self.symbol == "BTCUSDT" else None
|
||||
|
||||
result.update({
|
||||
"score": total_score,
|
||||
"direction": direction if (not no_direction and gate_passed) else None,
|
||||
"atr_value": atr_value,
|
||||
"factors": {
|
||||
"track": "ALT",
|
||||
"track": "BTC" if self.symbol == "BTCUSDT" else "ALT",
|
||||
"gate_passed": gate_passed,
|
||||
"gate_block": gate_block,
|
||||
"atr_pct_price": round(atr_pct_price, 5),
|
||||
"obi_raw": obi_raw,
|
||||
"spot_perp_div": spot_perp_div,
|
||||
"whale_cvd_ratio": whale_cvd_display,
|
||||
"direction": {
|
||||
"score": direction_score, "max": 55,
|
||||
"cvd_resonance": cvd_resonance, "p99_flow": p99_flow, "accel_bonus": accel_bonus,
|
||||
@ -920,114 +917,16 @@ class SymbolState:
|
||||
self.last_signal_dir[strategy_name] = direction
|
||||
return result
|
||||
|
||||
def _evaluate_v53_alt(self, now_ms: int, strategy_cfg: dict, snapshot: Optional[dict] = None) -> dict:
|
||||
"""已废弃,由 _evaluate_v53() 统一处理,保留供兼容"""
|
||||
return self._evaluate_v53(now_ms, strategy_cfg, snapshot)
|
||||
|
||||
def _evaluate_v53_btc(self, now_ms: int, strategy_cfg: dict, snapshot: Optional[dict] = None) -> dict:
|
||||
"""
|
||||
V5.3 BTC轨评分(gate-control逻辑)
|
||||
不用线性总分,用条件门控+否决条件决定是否开仓
|
||||
新特征(Phase 2采集后启用):tiered_cvd_whale, obi_depth_10, spot_perp_divergence
|
||||
当前Phase1版本:用已有特征填充,为数据接入预留扩展点
|
||||
"""
|
||||
strategy_name = strategy_cfg.get("name", "v53_btc")
|
||||
btc_gate = strategy_cfg.get("btc_gate", {})
|
||||
min_vol = btc_gate.get("min_vol_threshold", 0.002)
|
||||
obi_veto = btc_gate.get("obi_veto_threshold", 0.30)
|
||||
spot_perp_veto = btc_gate.get("spot_perp_divergence_veto", 0.003)
|
||||
|
||||
snap = snapshot or self.build_evaluation_snapshot(now_ms)
|
||||
cvd_fast = snap["cvd_fast"]
|
||||
cvd_mid = snap["cvd_mid"]
|
||||
price = snap["price"]
|
||||
atr = snap["atr"]
|
||||
atr_value = snap.get("atr_value", atr)
|
||||
atr_pct = snap["atr_pct"]
|
||||
|
||||
result = self._empty_result(strategy_name, snap)
|
||||
if self.warmup or price == 0 or atr == 0:
|
||||
return result
|
||||
|
||||
last_signal_ts = self.last_signal_ts.get(strategy_name, 0)
|
||||
in_cooldown = now_ms - last_signal_ts < COOLDOWN_MS
|
||||
|
||||
block_reason = None
|
||||
|
||||
# Gate 1: 波动率门控(atr_percent_1h = atr/price)
|
||||
atr_pct_price = atr / price if price > 0 else 0
|
||||
if atr_pct_price < min_vol:
|
||||
block_reason = f"low_vol_regime({atr_pct_price:.4f}<{min_vol})"
|
||||
|
||||
# Gate 2: 方向门控(CVD共振,BTC需要更严格)
|
||||
if not block_reason:
|
||||
if cvd_fast > 0 and cvd_mid > 0:
|
||||
direction = "LONG"
|
||||
elif cvd_fast < 0 and cvd_mid < 0:
|
||||
direction = "SHORT"
|
||||
else:
|
||||
block_reason = "no_direction_consensus"
|
||||
direction = "LONG" if cvd_fast > 0 else "SHORT"
|
||||
|
||||
else:
|
||||
direction = "LONG" if cvd_fast > 0 else "SHORT"
|
||||
|
||||
# Gate 3: OBI否决 — 优先用实时WebSocket值,回退DB值
|
||||
obi_raw = self.rt_obi if self.rt_obi != 0.0 else to_float(self.market_indicators.get("obi_depth_10"))
|
||||
if not block_reason and obi_raw is not None:
|
||||
# obi_raw: 正值=买单占优,负值=卖单占优,[-1,1]
|
||||
if direction == "LONG" and obi_raw < -obi_veto:
|
||||
block_reason = f"obi_imbalance_veto(obi={obi_raw:.3f})"
|
||||
elif direction == "SHORT" and obi_raw > obi_veto:
|
||||
block_reason = f"obi_imbalance_veto(obi={obi_raw:.3f})"
|
||||
|
||||
# Gate 4: 期现背离否决 — 优先用实时WebSocket值,回退DB值
|
||||
spot_perp_div = self.rt_spot_perp_div if self.rt_spot_perp_div != 0.0 else to_float(self.market_indicators.get("spot_perp_divergence"))
|
||||
if not block_reason and spot_perp_div is not None:
|
||||
# spot_perp_div: 绝对背离率,如0.005=0.5%
|
||||
if abs(spot_perp_div) > spot_perp_veto:
|
||||
# 背离方向与信号方向相反时否决
|
||||
if (direction == "LONG" and spot_perp_div < -spot_perp_veto) or \
|
||||
(direction == "SHORT" and spot_perp_div > spot_perp_veto):
|
||||
block_reason = f"spot_perp_divergence_veto({spot_perp_div:.4f})"
|
||||
|
||||
# 所有门控通过后,用ALT评分作为BTC综合评分(暂用,待Phase2换专属特征)
|
||||
gate_passed = block_reason is None
|
||||
|
||||
# 复用ALT评分作为参考分(不影响门控决策,仅供记录)
|
||||
# whale_cvd_ratio 优先用实时计算值
|
||||
whale_cvd = self.whale_cvd_ratio if self._whale_trades else to_float(self.market_indicators.get("tiered_cvd_whale"))
|
||||
alt_result = self._evaluate_v53_alt(now_ms, strategy_cfg, snap)
|
||||
total_score = alt_result["score"] if gate_passed else 0
|
||||
|
||||
result.update({
|
||||
"score": total_score,
|
||||
"direction": direction if gate_passed else None,
|
||||
"atr_value": atr_value,
|
||||
"factors": {
|
||||
"track": "BTC",
|
||||
"gate_passed": gate_passed,
|
||||
"block_reason": block_reason,
|
||||
"atr_pct_price": round(atr_pct_price, 5),
|
||||
"obi_raw": obi_raw,
|
||||
"spot_perp_div": spot_perp_div,
|
||||
"whale_cvd_ratio": whale_cvd,
|
||||
"alt_score_ref": alt_result["score"],
|
||||
# 透传ALT层分数供前端展示
|
||||
"direction": (alt_result.get("factors") or {}).get("direction"),
|
||||
"crowding": (alt_result.get("factors") or {}).get("crowding"),
|
||||
"environment": (alt_result.get("factors") or {}).get("environment"),
|
||||
"auxiliary": (alt_result.get("factors") or {}).get("auxiliary"),
|
||||
},
|
||||
})
|
||||
|
||||
strategy_threshold = int(strategy_cfg.get("threshold", 75))
|
||||
if gate_passed and not in_cooldown and total_score >= strategy_threshold:
|
||||
result["signal"] = direction
|
||||
result["tier"] = "standard"
|
||||
|
||||
if result["signal"]:
|
||||
self.last_signal_ts[strategy_name] = now_ms
|
||||
self.last_signal_dir[strategy_name] = direction
|
||||
return result
|
||||
"""已废弃,由 _evaluate_v53() 统一处理,保留供兼容"""
|
||||
return self._evaluate_v53(now_ms, strategy_cfg, snapshot)
|
||||
|
||||
# ─── PG DB操作 ───────────────────────────────────────────────────
|
||||
# ─── PG DB操作 ───────────────────────────────────────────────────
|
||||
|
||||
def load_historical(state: SymbolState, window_ms: int):
|
||||
now_ms = int(time.time() * 1000)
|
||||
@ -1088,18 +987,17 @@ def save_feature_event(ts: int, symbol: str, result: dict, strategy: str):
|
||||
V5.3 专用:每次评分后把 raw features + score 层写入 signal_feature_events。
|
||||
只对 v53_alt / v53_btc 调用,其他策略跳过。
|
||||
"""
|
||||
if strategy not in ("v53_alt", "v53_btc"):
|
||||
if not strategy.startswith("v53"):
|
||||
return
|
||||
f = result.get("factors") or {}
|
||||
track = f.get("track", "ALT")
|
||||
side = result.get("direction") or ("LONG" if result.get("score", 0) >= 0 else "SHORT")
|
||||
# ALT层分
|
||||
score_direction = (f.get("direction") or {}).get("score", 0) if track == "ALT" else None
|
||||
score_crowding = (f.get("crowding") or {}).get("score", 0) if track == "ALT" else None
|
||||
score_env = (f.get("environment") or {}).get("score", 0) if track == "ALT" else None
|
||||
score_aux = (f.get("auxiliary") or {}).get("score", 0) if track == "ALT" else None
|
||||
gate_passed = f.get("gate_passed") if track == "BTC" else True # ALT轨无gate概念,视为通过
|
||||
block_reason = f.get("block_reason") if track == "BTC" else None
|
||||
score_direction = (f.get("direction") or {}).get("score", 0) if track == "ALT" else (f.get("direction") or {}).get("score", 0)
|
||||
score_crowding = (f.get("crowding") or {}).get("score", 0)
|
||||
score_env = (f.get("environment") or {}).get("score", 0)
|
||||
score_aux = (f.get("auxiliary") or {}).get("score", 0)
|
||||
gate_passed = f.get("gate_passed", True)
|
||||
block_reason = f.get("gate_block") or f.get("block_reason")
|
||||
|
||||
with get_sync_conn() as conn:
|
||||
with conn.cursor() as cur:
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
{
|
||||
"name": "v53_alt",
|
||||
"name": "v53",
|
||||
"version": "5.3",
|
||||
"track": "ALT",
|
||||
"description": "V5.3 ALT轨(ETH/XRP/SOL): 55/25/15/5权重,删除确认层,per-symbol四门控制",
|
||||
"description": "V5.3 统一策略(BTC/ETH/XRP/SOL): 四层评分 55/25/15/5 + per-symbol 四门控制",
|
||||
"threshold": 75,
|
||||
"flip_threshold": 85,
|
||||
"weights": {
|
||||
@ -11,25 +10,21 @@
|
||||
"environment": 15,
|
||||
"auxiliary": 5
|
||||
},
|
||||
"direction_sub": {
|
||||
"cvd_resonance": 30,
|
||||
"p99_flow_alignment": 20,
|
||||
"cvd_accel_bonus": 5
|
||||
},
|
||||
"crowding_sub": {
|
||||
"lsr_contrarian": 15,
|
||||
"top_trader_position": 10
|
||||
},
|
||||
"accel_bonus": 5,
|
||||
"tp_sl": {
|
||||
"sl_multiplier": 2.0,
|
||||
"tp1_multiplier": 1.5,
|
||||
"tp2_multiplier": 3.0,
|
||||
"tp_maker": true
|
||||
},
|
||||
"symbols": ["ETHUSDT", "XRPUSDT", "SOLUSDT"],
|
||||
"signals": ["cvd", "p99", "accel", "ls_ratio", "top_trader", "oi", "coinbase_premium"],
|
||||
"symbols": ["BTCUSDT", "ETHUSDT", "XRPUSDT", "SOLUSDT"],
|
||||
"symbol_gates": {
|
||||
"BTCUSDT": {
|
||||
"min_vol_threshold": 0.002,
|
||||
"whale_threshold_usd": 100000,
|
||||
"whale_flow_threshold_pct": 0.5,
|
||||
"obi_veto_threshold": 0.30,
|
||||
"spot_perp_divergence_veto": 0.003
|
||||
},
|
||||
"ETHUSDT": {
|
||||
"min_vol_threshold": 0.003,
|
||||
"whale_threshold_usd": 50000,
|
||||
@ -1,29 +0,0 @@
|
||||
{
|
||||
"name": "v53_btc",
|
||||
"version": "5.3",
|
||||
"track": "BTC",
|
||||
"description": "V5.3 BTC轨: gate-control逻辑(不用线性加分),核心特征=tiered_cvd_whale+obi_depth_10+spot_perp_divergence+atr_percent_1h",
|
||||
"threshold": 75,
|
||||
"flip_threshold": 85,
|
||||
"btc_gate": {
|
||||
"min_vol_threshold": 0.002,
|
||||
"obi_veto_threshold": 0.30,
|
||||
"whale_flow_threshold_pct": 0.5,
|
||||
"spot_perp_divergence_veto": 0.003
|
||||
},
|
||||
"weights": {
|
||||
"direction": 55,
|
||||
"crowding": 25,
|
||||
"environment": 15,
|
||||
"auxiliary": 5
|
||||
},
|
||||
"accel_bonus": 5,
|
||||
"tp_sl": {
|
||||
"sl_multiplier": 2.0,
|
||||
"tp1_multiplier": 1.5,
|
||||
"tp2_multiplier": 3.0,
|
||||
"tp_maker": true
|
||||
},
|
||||
"symbols": ["BTCUSDT"],
|
||||
"signals": ["cvd", "p99", "accel", "ls_ratio", "top_trader", "oi", "coinbase_premium"]
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user