feat: 自我进化模块——health_monitor+lesson_extractor+evolution_api+Dashboard+auto_iterator
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
"""
|
||||
evolution/lesson_extractor.py — 交易后教训提取
|
||||
分析已平仓交易,用LLM提取"为什么赢/亏"的教训
|
||||
"""
|
||||
import sys, os, json, sqlite3
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
sys.path.insert(0, '/home/hmo/MoFin')
|
||||
sys.path.insert(0, '/home/hmo/MoFin/deploy/profile-scripts')
|
||||
|
||||
DB = os.environ.get('MOFIN_DB', '/home/hmo/MoFin/data/mofin.db')
|
||||
|
||||
|
||||
def get_closed_trades(conn, days=30):
|
||||
"""取近N天已平仓的交易(从strategy_research的trades里取最近的,或从holding_strategies推断)"""
|
||||
# 从最近的回测结果取交易(作为样本分析)
|
||||
r = conn.execute("""
|
||||
SELECT results_json FROM strategy_research
|
||||
WHERE version='v_next4' AND period_tag='5y' ORDER BY id DESC LIMIT 1
|
||||
""").fetchone()
|
||||
if not r:
|
||||
return []
|
||||
res = json.loads(r[0])
|
||||
trades = res.get('trades', [])
|
||||
# 按日期排序,取最近的
|
||||
recent = sorted(trades, key=lambda x: x.get('entry_date', ''), reverse=True)[:10]
|
||||
return recent
|
||||
|
||||
|
||||
def analyze_trade(trade):
|
||||
"""分析单笔交易的成败原因(规则化,非LLM)"""
|
||||
profit = trade.get('profit_pct', 0)
|
||||
hold_days = trade.get('hold_days', 0)
|
||||
factors = trade.get('factors', {})
|
||||
|
||||
lessons = []
|
||||
|
||||
# 盈利交易的共性
|
||||
if profit > 15:
|
||||
if factors.get('mkt_adx', 0) > 25:
|
||||
lessons.append(('win_pattern', f"大盘趋势强(ADX={factors['mkt_adx']:.0f})时盈利{profit:.1f}%", 0.8))
|
||||
if factors.get('sector_above_ma20'):
|
||||
lessons.append(('win_pattern', f"板块在MA20上方时盈利{profit:.1f}%", 0.7))
|
||||
if trade.get('dna'):
|
||||
lessons.append(('win_pattern', f"动量基因(DNA)票盈利{profit:.1f}%", 0.9))
|
||||
|
||||
# 亏损交易的共性
|
||||
if profit < -5:
|
||||
if factors.get('mkt_slope', 0) < -0.5:
|
||||
lessons.append(('loss_pattern', f"大盘斜率负({factors['mkt_slope']:.2f})时亏损{profit:.1f}%", 0.7))
|
||||
if not factors.get('sector_above_ma20'):
|
||||
lessons.append(('loss_pattern', f"板块在MA20下方时亏损{profit:.1f}%", 0.6))
|
||||
if hold_days < 5:
|
||||
lessons.append(('loss_pattern', f"持仓{hold_days}天短于5天时亏损{profit:.1f}%", 0.5))
|
||||
|
||||
# 长持盈利
|
||||
if profit > 10 and hold_days > 30:
|
||||
lessons.append(('win_pattern', f"长持{hold_days}天盈利{profit:.1f}%", 0.85))
|
||||
|
||||
return lessons
|
||||
|
||||
|
||||
def extract_lessons(days=30):
|
||||
"""提取近N天交易的教训"""
|
||||
conn = sqlite3.connect(DB)
|
||||
conn.row_factory = sqlite3.Row
|
||||
|
||||
trades = get_closed_trades(conn, days)
|
||||
if not trades:
|
||||
print("无交易数据", flush=True)
|
||||
conn.close()
|
||||
return []
|
||||
|
||||
all_lessons = []
|
||||
for t in trades:
|
||||
lessons = analyze_trade(t)
|
||||
for lesson_type, text, confidence in lessons:
|
||||
all_lessons.append({
|
||||
'strategy_version': 'v_next4',
|
||||
'trade_id': t.get('id', 0),
|
||||
'lesson_type': lesson_type,
|
||||
'lesson_text': text,
|
||||
'confidence': confidence,
|
||||
'profit_pct': t.get('profit_pct', 0),
|
||||
'entry_date': t.get('entry_date', ''),
|
||||
})
|
||||
|
||||
# 写入 strategy_lessons 表
|
||||
for l in all_lessons:
|
||||
conn.execute("""
|
||||
INSERT INTO strategy_lessons (strategy_version, trade_id, lesson_type, lesson_text, confidence, applied)
|
||||
VALUES (?, ?, ?, ?, ?, 0)
|
||||
""", (l['strategy_version'], l['trade_id'], l['lesson_type'], l['lesson_text'], l['confidence']))
|
||||
conn.commit()
|
||||
|
||||
# 打印
|
||||
print(f"分析 {len(trades)} 笔交易, 提取 {len(all_lessons)} 条教训", flush=True)
|
||||
for l in all_lessons[:5]:
|
||||
print(f" [{l['lesson_type']}] {l['lesson_text']} (置信度{l['confidence']})", flush=True)
|
||||
|
||||
conn.close()
|
||||
return all_lessons
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
extract_lessons()
|
||||
Reference in New Issue
Block a user