refactor(D组): 归档strategy_evaluator+advice_reconciliation,功能合并到strategy_effectiveness
- 归档strategy_evaluator.py/advice_reconciliation.py(功能已被strategy_effectiveness替代) - strategy_effectiveness扩展: 读取recommendation_log+execution_log增强评估 - mofin_db新增: log_recommendation/log_execution/match_recommendations_executions - 新表recommendation_log(推荐历史)+execution_log(执行历史)
This commit is contained in:
@@ -2486,3 +2486,72 @@ def write_holding_strategy_versioned(conn, code, name, data, source_trigger="bat
|
||||
data['version'] = new_ver
|
||||
|
||||
return write_holding_strategy(conn, code, name, data, source_trigger)
|
||||
|
||||
|
||||
# ── recommendation_log 写入(重评时同步记录推荐)──
|
||||
def log_recommendation(conn, strategy_id, code, data, source_trigger="batch_12d"):
|
||||
"""记录推荐历史:重评写入策略卡时同步调用"""
|
||||
now = __import__('datetime').datetime.now().isoformat()
|
||||
conn.execute("""
|
||||
INSERT INTO recommendation_log
|
||||
(strategy_id, code, strategy_source, version, recommend_time,
|
||||
action, entry_low, entry_high, stop_loss, take_profit,
|
||||
position_advice, timing_signal, rr_ratio, reason)
|
||||
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|
||||
""", (strategy_id, code, data.get('strategy_source', ''), data.get('version', ''),
|
||||
now, data.get('action', ''), data.get('entry_low', 0), data.get('entry_high', 0),
|
||||
data.get('stop_loss', 0), data.get('take_profit', 0),
|
||||
data.get('position_advice', ''), data.get('timing_signal', ''),
|
||||
data.get('rr_ratio', 0), data.get('reason', '')))
|
||||
print(f" [RECOMMEND] {code} v{data.get('version','')} 记录推荐", flush=True)
|
||||
|
||||
|
||||
# ── execution_log 写入(交易执行时记录)──
|
||||
def log_execution(conn, code, action, shares, price, cost=None, source="trade_capture", recommendation_id=None):
|
||||
"""记录执行历史:trade_capture/import_holding_xls 等执行后调用"""
|
||||
now = __import__('datetime').datetime.now().isoformat()
|
||||
conn.execute("""
|
||||
INSERT INTO execution_log
|
||||
(code, action, shares, price, cost, execute_time, source, match_recommendation_id)
|
||||
VALUES (?,?,?,?,?,?,?,?)
|
||||
""", (code, action, shares, price, cost, now, source, recommendation_id))
|
||||
print(f" [EXEC] {code} {action} {shares}股 @{price} source={source}", flush=True)
|
||||
|
||||
|
||||
# ── 匹配推荐与执行(盘后评估用)──
|
||||
def match_recommendations_executions(conn, code, strategy_id):
|
||||
"""找到策略推荐与实际执行的对应关系"""
|
||||
recs = conn.execute(
|
||||
"SELECT id, recommend_time, action, entry_low, entry_high FROM recommendation_log "
|
||||
"WHERE code=? AND strategy_id=? ORDER BY recommend_time", (code, strategy_id)).fetchall()
|
||||
execs = conn.execute(
|
||||
"SELECT id, execute_time, action, shares, price FROM execution_log "
|
||||
"WHERE code=? ORDER BY execute_time", (code,)).fetchall()
|
||||
|
||||
matches = []
|
||||
for rec in recs:
|
||||
rec_time = rec[1]
|
||||
rec_action = rec[2]
|
||||
# 找推荐之后最近的执行
|
||||
for exe in execs:
|
||||
if exe[1] >= rec_time and exe[2] == rec_action:
|
||||
matches.append({
|
||||
"recommendation_id": rec[0],
|
||||
"recommend_time": rec[1],
|
||||
"recommend_action": rec[2],
|
||||
"execution_id": exe[0],
|
||||
"execute_time": exe[1],
|
||||
"execute_action": exe[2],
|
||||
"shares": exe[3],
|
||||
"price": exe[4],
|
||||
"matched": True,
|
||||
})
|
||||
break
|
||||
else:
|
||||
matches.append({
|
||||
"recommendation_id": rec[0],
|
||||
"recommend_time": rec[1],
|
||||
"recommend_action": rec[2],
|
||||
"matched": False,
|
||||
})
|
||||
return matches
|
||||
|
||||
@@ -241,3 +241,43 @@ def main():
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
|
||||
# ── 扩展评估:读取 recommendation_log + execution_log ──
|
||||
def evaluate_with_logs(conn, strategy):
|
||||
"""用推荐记录+执行记录增强评估"""
|
||||
sid = strategy[0]
|
||||
code = strategy[1]
|
||||
|
||||
# 读推荐记录
|
||||
recs = conn.execute(
|
||||
"SELECT recommend_time, action, entry_low, entry_high, stop_loss, take_profit "
|
||||
"FROM recommendation_log WHERE strategy_id=? ORDER BY recommend_time", (sid,)).fetchall()
|
||||
|
||||
# 读执行记录
|
||||
execs = conn.execute(
|
||||
"SELECT execute_time, action, shares, price FROM execution_log "
|
||||
"WHERE code=? ORDER BY execute_time", (code,)).fetchall()
|
||||
|
||||
# 匹配:推荐后是否有对应执行
|
||||
rec_followed = 0
|
||||
rec_not_followed = 0
|
||||
for rec in recs:
|
||||
rec_time, rec_action = rec[0], rec[1]
|
||||
found = False
|
||||
for exe in execs:
|
||||
if exe[0] >= rec_time and exe[1] == rec_action:
|
||||
found = True
|
||||
rec_followed += 1
|
||||
break
|
||||
if not found:
|
||||
rec_not_followed += 1
|
||||
|
||||
compliance_rate = rec_followed / (rec_followed + rec_not_followed) * 100 if (rec_followed + rec_not_followed) > 0 else 0
|
||||
|
||||
return {
|
||||
"recommendations": len(recs),
|
||||
"executions_matched": rec_followed,
|
||||
"executions_missed": rec_not_followed,
|
||||
"compliance_rate": round(compliance_rate, 1),
|
||||
}
|
||||
|
||||
@@ -150,6 +150,9 @@ def execute_stock(stock):
|
||||
pass
|
||||
if not result.get("action"):
|
||||
result["action"] = "无变更"
|
||||
# 记录执行日志
|
||||
from mofin_db import log_execution
|
||||
log_execution(conn, code, result.get("action",""), int(stock.get("shares",0) or 0), float(stock.get("price",0) or 0), source="trade_capture")
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
Reference in New Issue
Block a user