feat: strategy_defs补trend家族(v_next/v8.1=趋势市龙头回调,映射leader_scanner)+候选目录更新(600262切策略有目标了)
This commit is contained in:
@@ -0,0 +1,75 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""补 strategy_defs 的 trend 家族卡(2026-08-18)
|
||||||
|
v_next / v8.1(trend_up 激活的顺势策略,映射 leader_scanner.py)
|
||||||
|
执行:/home/hmo/MoFin/venv/bin/python add_trend_defs.py
|
||||||
|
"""
|
||||||
|
import sqlite3, json, hashlib
|
||||||
|
|
||||||
|
DB = "/home/hmo/MoFin/data/mofin.db"
|
||||||
|
conn = sqlite3.connect(DB, timeout=30)
|
||||||
|
conn.execute("PRAGMA busy_timeout=30000")
|
||||||
|
|
||||||
|
def upsert(s):
|
||||||
|
hp = hashlib.md5((s.get("key_params") or "").encode()).hexdigest()[:12]
|
||||||
|
s2 = dict(s); s2["params_hash"] = hp; s2["updated_at"] = "2026-08-18 21:20:00"; s2["updated_by"] = "add_trend_defs.py"
|
||||||
|
cols = ",".join(s2.keys()); ph = ",".join("?" * len(s2))
|
||||||
|
conn.execute(
|
||||||
|
f"INSERT INTO strategy_defs ({cols}) VALUES ({ph}) ON CONFLICT(strategy_name) DO UPDATE SET "
|
||||||
|
f"display_name=excluded.display_name, aliases=excluded.aliases, market=excluded.market, "
|
||||||
|
f"regime=excluded.regime, family=excluded.family, summary=excluded.summary, "
|
||||||
|
f"entry_logic=excluded.entry_logic, exit_logic=excluded.exit_logic, "
|
||||||
|
f"key_params=excluded.key_params, review_focus=excluded.review_focus, "
|
||||||
|
f"holding_style=excluded.holding_style, status=excluded.status, "
|
||||||
|
f"retired_reason=excluded.retired_reason, superseded_by=excluded.superseded_by, "
|
||||||
|
f"params_hash=excluded.params_hash, needs_review=excluded.needs_review, "
|
||||||
|
f"doc_ref=excluded.doc_ref, scanner_file=excluded.scanner_file, "
|
||||||
|
f"version=excluded.version, updated_at=excluded.updated_at, updated_by=excluded.updated_by",
|
||||||
|
[s2[k] for k in s2])
|
||||||
|
print(f" + {s['strategy_name']} 已写入/更新")
|
||||||
|
|
||||||
|
# v_next:趋势市龙头回调(trend_up 激活,映射 leader_scanner.py)
|
||||||
|
upsert(dict(
|
||||||
|
strategy_name="v_next",
|
||||||
|
display_name="趋势市龙头回调买点",
|
||||||
|
aliases=json.dumps(["v_next", "v_next4", "leader", "bull_trend"]),
|
||||||
|
market="A", regime="trend_up",
|
||||||
|
family="trend_momentum",
|
||||||
|
summary="牛市(trend_up)买入龙头股回调到 MA20 附近的健康回调(dist_ma20∈[-3%,+2%]、RSI 45-65 强势未超买、量能配合、行业趋势共振),不追高。",
|
||||||
|
entry_logic="dist_ma20∈[-3%,+2%](回调到MA20附近,不追高);RSI 45-65(强势但未超买);mcap_q>0.3(龙头非小盘);vol_ratio>0.8(量能配合);trend_aligned=1(趋势共振)。",
|
||||||
|
exit_logic="跌破 MA20 下方 8% 止损(MA20×0.92);+15% 止盈(MA20×1.15,压力位);买入区 MA20×0.98~MA20。",
|
||||||
|
key_params=json.dumps({"dist_ma20_range": [-3,2], "rsi_range": [45,65], "mcap_q_min": 0.3, "vol_ratio_min": 0.8, "trend_aligned": 1, "tp_pct": 0.15, "sl_pct": 0.08, "regime": "trend_up"}),
|
||||||
|
review_focus="①牛市温区是否延续(trend_up→其他=龙头策略失效,需切换)②回调买点是否仍成立(价格还在MA20附近吗)③RSI是否仍强势未超买④量能是否配合⑤跌破MA20止损位合理性",
|
||||||
|
holding_style="趋势持有(龙头主升浪,回调即买点)",
|
||||||
|
status="active", version="v_next",
|
||||||
|
scanner_file="leader_scanner.py",
|
||||||
|
doc_ref="",
|
||||||
|
))
|
||||||
|
|
||||||
|
# v8.1:波段先出再进(trend_up 激活的顺势波段)
|
||||||
|
upsert(dict(
|
||||||
|
strategy_name="v8.1",
|
||||||
|
display_name="顺势波段先出再进",
|
||||||
|
aliases=json.dumps(["v8.1", "v8"]),
|
||||||
|
market="A", regime="trend_up",
|
||||||
|
family="trend_momentum",
|
||||||
|
summary="趋势市顺势波段:上升趋势中回调买入,波段顶部先出、回踩再进(波段先出再进),吃趋势主升的波段利润。",
|
||||||
|
entry_logic="上升趋势(trend_up)中的回调买点;趋势共振 + 技术位支撑买入;避免追高。",
|
||||||
|
exit_logic="波段顶部先出(压力位/超买);回踩支撑再进;跌破趋势线止损。",
|
||||||
|
key_params=json.dumps({"regime": "trend_up", "mode": "swing_band"}),
|
||||||
|
review_focus="①趋势是否延续(trend_up)②当前在波段哪个位置(顶部该出/回调该进)③止损/止盈空间④温区切换风险",
|
||||||
|
holding_style="波段(顺势,先出再进)",
|
||||||
|
status="active", version="v8.1",
|
||||||
|
scanner_file="leader_scanner.py",
|
||||||
|
doc_ref="",
|
||||||
|
))
|
||||||
|
|
||||||
|
# 更新候选目录引用(batch_reassess 的 _CANDIDATES 加 v_next/v8.1)
|
||||||
|
# 在 parse_response 的 _CANDIDATES 里补
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
n = conn.execute("SELECT COUNT(*) FROM strategy_defs").fetchone()[0]
|
||||||
|
print(f"\nstrategy_defs 共 {n} 张卡:")
|
||||||
|
for r in conn.execute("SELECT strategy_name, display_name, regime, status FROM strategy_defs ORDER BY strategy_name").fetchall():
|
||||||
|
print(f" {r[0]} | {r[1]} | {r[2]} | {r[3]}")
|
||||||
|
conn.close()
|
||||||
@@ -378,7 +378,7 @@ def build_prompt(data):
|
|||||||
_strategy_sec = """【策略定义】(无策略记录)
|
_strategy_sec = """【策略定义】(无策略记录)
|
||||||
来源策略未知。请基于技术形态/估值/资金特征判断该股当前最接近的策略画像,并在【策略判断】中说明;
|
来源策略未知。请基于技术形态/估值/资金特征判断该股当前最接近的策略画像,并在【策略判断】中说明;
|
||||||
若判断需要归类到某个策略,从以下候选中选择(禁止自创):
|
若判断需要归类到某个策略,从以下候选中选择(禁止自创):
|
||||||
accumulation(主力建仓) / b_td1_v3(超跌原池优选) / v_mr(弱市深超跌) / hk_pe_mom(港股动量) / hk_pe_oversold(港股超卖) / p_oversold(预测超跌) / s2_panic(恐慌买强势) / leader(龙头回调)"""
|
accumulation(主力建仓) / b_td1_v3(超跌原池优选) / v_mr(弱市深超跌) / hk_pe_mom(港股动量) / hk_pe_oversold(港股超卖) / p_oversold(预测超跌) / s2_panic(恐慌买强势) / leader(龙头回调) / v_next(趋势龙头回调) / v8.1(顺势波段)"""
|
||||||
_sit_sec = f"""【情势体检】(系统确定性计算,非LLM估计)
|
_sit_sec = f"""【情势体检】(系统确定性计算,非LLM估计)
|
||||||
当前温区(A股): {_sit.get('regime_a','unknown')}(7天前: {_sit.get('regime_7d_ago','unknown')})
|
当前温区(A股): {_sit.get('regime_a','unknown')}(7天前: {_sit.get('regime_7d_ago','unknown')})
|
||||||
温区突变: {'是' if _sit.get('regime_a') != _sit.get('regime_7d_ago') and _sit.get('regime_a') not in ('unknown','') else '否'}
|
温区突变: {'是' if _sit.get('regime_a') != _sit.get('regime_7d_ago') and _sit.get('regime_a') not in ('unknown','') else '否'}
|
||||||
@@ -604,7 +604,7 @@ def parse_response(text):
|
|||||||
result["strategy_reason"] = re.sub(r'^\s*【策略失效理由】\s*', '', _sr).strip()[:200]
|
result["strategy_reason"] = re.sub(r'^\s*【策略失效理由】\s*', '', _sr).strip()[:200]
|
||||||
# 更换策略归类(封闭集校验:必须在候选列表内)
|
# 更换策略归类(封闭集校验:必须在候选列表内)
|
||||||
result["strategy_switch_to"] = ""
|
result["strategy_switch_to"] = ""
|
||||||
_CANDIDATES = ("accumulation", "b_td1_v3", "v_mr", "hk_pe_mom", "hk_pe_oversold", "p_oversold", "s2_panic", "leader")
|
_CANDIDATES = ("accumulation", "b_td1_v3", "v_mr", "hk_pe_mom", "hk_pe_oversold", "p_oversold", "s2_panic", "leader", "v_next", "v8.1")
|
||||||
_st = _section_line("更换策略归类")
|
_st = _section_line("更换策略归类")
|
||||||
if _st:
|
if _st:
|
||||||
_body = re.sub(r'^\s*【更换策略归类】\s*', '', _st).strip().lower()
|
_body = re.sub(r'^\s*【更换策略归类】\s*', '', _st).strip().lower()
|
||||||
|
|||||||
Reference in New Issue
Block a user