178 lines
7.6 KiB
Python
178 lines
7.6 KiB
Python
"""Stable signal taxonomy for recommendation analytics.
|
|
|
|
Display labels are allowed to change often; these codes are the analytics keys
|
|
used by review, signal performance, and candidate-rule generation.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
from typing import Any, Iterable
|
|
|
|
|
|
SIGNAL_CODE_LABELS = {
|
|
"vp_fly_1h_current": "1H当前量价齐飞",
|
|
"volume_consecutive_1h": "1H连续放量",
|
|
"cex_top_gainer_24h": "CEX 24h强势榜异动",
|
|
"vp_fly_1h_stale": "1H历史量价齐飞",
|
|
"short_tf_15m_ignition": "15min短周期启动",
|
|
"short_tf_5m_ignition": "5min极早期启动",
|
|
"short_tf_resonance": "短周期共振",
|
|
"volume_divergence_1h": "1H量价背离",
|
|
"static_accum_4h": "4H静K蓄力",
|
|
"higher_lows_4h": "4H底部抬高",
|
|
"compression_surge_4h": "4H压缩放量",
|
|
"box_breakout_pullback_1h": "1H箱体突破回踩",
|
|
"box_breakout_pullback_4h": "4H箱体突破回踩",
|
|
"breakdown_retest_1h_short": "1H破位反抽做空",
|
|
"retest_reject_15m_short": "15min反抽失败",
|
|
"market_risk_off_short": "弱势环境空头确认",
|
|
"ignition_1h_current": "1H当前起爆点",
|
|
"ignition_4h_current": "4H当前起爆点",
|
|
"ignition_d1_current": "日线当前起爆点",
|
|
"ignition_stale": "历史起爆点",
|
|
"dynamic_k_1h_bull": "1H多头动K",
|
|
"dynamic_k_d1_bull": "日线多头动K",
|
|
"breakout_pullback_d1": "日线突破回踩",
|
|
"breakout_pullback_w1": "周线突破回踩",
|
|
"breakout_15m_current": "15min当前突破",
|
|
"pullback_15m_confirm": "15min回踩确认",
|
|
"strong_resonance_bypass": "强共振旁路",
|
|
"entry_quality_gate": "买点质量闸门",
|
|
"top_trader_long": "大户偏多",
|
|
"sector_rotation": "板块联动",
|
|
"sentiment_resonance": "舆情共振",
|
|
"dex_volume_spike": "DEX 放量",
|
|
"liquidity_add": "流动性增加",
|
|
"liquidity_remove_risk": "流动性撤出风险",
|
|
"exchange_outflow": "交易所流出",
|
|
"exchange_inflow_risk": "交易所流入风险",
|
|
"whale_accumulation": "鲸鱼增持",
|
|
"holder_concentration_risk": "持仓集中风险",
|
|
"smart_money_buying": "聪明钱买入",
|
|
"funding_extreme": "资金费率极端",
|
|
"trend_exhaustion": "趋势衰减",
|
|
"false_breakout": "假突破",
|
|
"high_position_reject": "高位拒绝",
|
|
"risk_reward_bad": "盈亏比不合格",
|
|
# --- 新增因子 v1.8 ---
|
|
"rs_strong": "RS相对强势",
|
|
"rs_weak": "RS相对弱势",
|
|
"rs_independent_strength": "BTC回调中独立走强",
|
|
"oi_buildup": "OI蓄力",
|
|
"oi_healthy_trend": "OI健康增长",
|
|
"oi_divergence_risk": "OI背离风险",
|
|
"funding_negative_contrarian": "资金费率负值反向看多",
|
|
"funding_positive_risk": "资金费率过高风险",
|
|
"tf_alignment_full": "多周期三重对齐",
|
|
"tf_alignment_double": "多周期双重确认",
|
|
"tf_alignment_single_penalty": "仅单周期支持",
|
|
"tf_alignment_conflict_penalty": "多周期方向矛盾",
|
|
# --- 新增因子 v1.8.1: VCP / Volume Profile / 突破质量 ---
|
|
"vcp_bull_breakout": "VCP多头突破",
|
|
"vcp_bull_forming": "VCP多头蓄力",
|
|
"vcp_bear_breakdown": "顶部分配破位",
|
|
"vcp_bear_forming": "顶部分配蓄力",
|
|
"vp_path_clear": "VP路径清晰",
|
|
"vp_path_blocked": "VP路径受阻",
|
|
"breakout_quality_high": "突破质量高",
|
|
"breakout_quality_low": "突破质量低",
|
|
"unknown": "未分类信号",
|
|
}
|
|
|
|
|
|
_PATTERNS = [
|
|
("cex_top_gainer_24h", ("24h强势榜",)),
|
|
("vp_fly_1h_stale", ("历史放量阳线", "历史量价齐飞", "量价齐飞已过期")),
|
|
("vp_fly_1h_current", ("量价齐飞", "量价齐飞K")),
|
|
("short_tf_resonance", ("短周期共振", "5m/15m共振")),
|
|
("short_tf_15m_ignition", ("15min短周期启动", "15m短周期启动", "15min 早期启动")),
|
|
("short_tf_5m_ignition", ("5min极早期启动", "5m极早期启动", "5min 早期启动")),
|
|
("volume_divergence_1h", ("量价背离", "放量但无量价齐飞")),
|
|
("static_accum_4h", ("静K蓄力", "静K旁路")),
|
|
("box_breakout_pullback_1h", ("1H", "箱体", "突破", "回踩")),
|
|
("box_breakout_pullback_4h", ("4H", "箱体", "突破", "回踩")),
|
|
("breakdown_retest_1h_short", ("1H", "破位", "反抽", "做空")),
|
|
("retest_reject_15m_short", ("15min", "反抽失败")),
|
|
("market_risk_off_short", ("risk_off", "空头")),
|
|
("higher_lows_4h", ("底部抬高",)),
|
|
("compression_surge_4h", ("压缩放量",)),
|
|
("ignition_stale", ("历史起爆点", "起爆点已过期", "旧起爆")),
|
|
("ignition_d1_current", ("日线", "起爆点")),
|
|
("ignition_4h_current", ("4H", "起爆点")),
|
|
("ignition_1h_current", ("1H", "起爆点")),
|
|
("dynamic_k_d1_bull", ("日线", "动K")),
|
|
("dynamic_k_1h_bull", ("1H", "动K")),
|
|
("breakout_pullback_d1", ("日线", "突破", "回踩")),
|
|
("breakout_15m_current", ("15min", "突破")),
|
|
("pullback_15m_confirm", ("15min", "回踩确认")),
|
|
("strong_resonance_bypass", ("强共振旁路",)),
|
|
("entry_quality_gate", ("买点质量闸门",)),
|
|
("top_trader_long", ("大户偏多",)),
|
|
("sector_rotation", ("板块联动", "龙头")),
|
|
("sentiment_resonance", ("舆情共振",)),
|
|
("dex_volume_spike", ("DEX", "放量")),
|
|
("liquidity_add", ("流动性", "增加")),
|
|
("liquidity_remove_risk", ("流动性", "撤出")),
|
|
("exchange_outflow", ("交易所", "流出")),
|
|
("exchange_inflow_risk", ("交易所", "流入")),
|
|
("whale_accumulation", ("鲸鱼", "增持")),
|
|
("holder_concentration_risk", ("持仓集中",)),
|
|
("smart_money_buying", ("聪明钱", "买入")),
|
|
("funding_extreme", ("资金费率极端",)),
|
|
("trend_exhaustion", ("衰减", "反转", "阴动K")),
|
|
("false_breakout", ("假突破", "冲高回落")),
|
|
("high_position_reject", ("高位", "追高")),
|
|
("risk_reward_bad", ("risk_reward_ok=false", "rr1=", "盈亏比")),
|
|
# --- 新增因子 v1.8 ---
|
|
("rs_strong", ("RS强势",)),
|
|
("rs_weak", ("RS弱势",)),
|
|
("rs_independent_strength", ("BTC回调", "独立走强")),
|
|
("oi_buildup", ("OI蓄力",)),
|
|
("oi_healthy_trend", ("OI健康增长",)),
|
|
("oi_divergence_risk", ("OI背离风险",)),
|
|
("funding_negative_contrarian", ("资金费率负值", "反向看多")),
|
|
("funding_positive_risk", ("资金费率过高",)),
|
|
("tf_alignment_full", ("三重对齐",)),
|
|
("tf_alignment_double", ("双重确认",)),
|
|
("tf_alignment_single_penalty", ("仅单周期",)),
|
|
("tf_alignment_conflict_penalty", ("方向矛盾",)),
|
|
# --- 新增因子 v1.8.1 ---
|
|
("vcp_bull_breakout", ("VCP突破",)),
|
|
("vcp_bull_forming", ("VCP蓄力",)),
|
|
("vcp_bear_breakdown", ("顶部分配破位",)),
|
|
("vcp_bear_forming", ("顶部分配蓄力",)),
|
|
("vp_path_clear", ("VP路径清晰",)),
|
|
("vp_path_blocked", ("VP路径受阻",)),
|
|
("breakout_quality_high", ("突破质量高", "破位质量高")),
|
|
("breakout_quality_low", ("突破质量低", "破位质量低")),
|
|
]
|
|
|
|
|
|
def signal_code(signal: Any) -> str:
|
|
text = str(signal or "").strip()
|
|
if not text:
|
|
return "unknown"
|
|
normalized = re.sub(r"\s+", "", text)
|
|
for code, needles in _PATTERNS:
|
|
if all(str(needle).replace(" ", "") in normalized for needle in needles):
|
|
return code
|
|
return "unknown"
|
|
|
|
|
|
def signal_label_for_code(code: str) -> str:
|
|
return SIGNAL_CODE_LABELS.get(code or "unknown", SIGNAL_CODE_LABELS["unknown"])
|
|
|
|
|
|
def signal_codes(signals: Iterable[Any]) -> list[str]:
|
|
seen = []
|
|
for sig in signals or []:
|
|
code = signal_code(sig)
|
|
if code not in seen:
|
|
seen.append(code)
|
|
return seen
|
|
|
|
|
|
def signal_labels(signals: Iterable[Any]) -> list[str]:
|
|
return [str(sig) for sig in (signals or []) if str(sig).strip()]
|