#!/usr/bin/env python3 """ 一次性修复历史交易记录标签: 将 trade_records 里“止损但实际盈利”的记录改为“保本止盈”. 默认条件(可通过参数修改): - monitor_type = 下单监控 - result = 止损 - pnl_amount > 0 用法示例: 1) 仅预览(不落库): python scripts/fix_breakeven_labels.py --db ./crypto.db --dry-run 2) 执行修复: python scripts/fix_breakeven_labels.py --db ./crypto.db --apply """ from __future__ import annotations import argparse import sqlite3 import sys from pathlib import Path def parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser(description="Fix historical stop-loss records with positive pnl.") parser.add_argument("--db", required=True, help="Path to sqlite db file, e.g. ./crypto.db") parser.add_argument("--monitor-type", default="下单监控", help="Filter by monitor_type (default: 下单监控)") parser.add_argument("--from-result", default="止损", help="Source result label (default: 止损)") parser.add_argument("--to-result", default="保本止盈", help="Target result label (default: 保本止盈)") parser.add_argument("--dry-run", action="store_true", help="Preview only, no write") parser.add_argument("--apply", action="store_true", help="Execute update") return parser.parse_args() def main() -> int: args = parse_args() db_path = Path(args.db).expanduser().resolve() if not db_path.exists(): print(f"[ERR] DB not found: {db_path}") return 1 if args.dry_run and args.apply: print("[ERR] --dry-run and --apply are mutually exclusive.") return 1 if not args.dry_run and not args.apply: print("[INFO] No mode provided, defaulting to --dry-run.") args.dry_run = True conn = sqlite3.connect(str(db_path)) conn.row_factory = sqlite3.Row cur = conn.cursor() where_sql = """ monitor_type = ? AND result = ? AND CAST(COALESCE(pnl_amount, 0) AS REAL) > 0 """ params = (args.monitor_type, args.from_result) cur.execute(f"SELECT COUNT(*) AS c FROM trade_records WHERE {where_sql}", params) will_change = int(cur.fetchone()["c"]) print(f"[INFO] Candidate rows: {will_change}") if will_change == 0: print("[INFO] Nothing to update.") conn.close() return 0 cur.execute( f""" SELECT id, symbol, result, pnl_amount, closed_at FROM trade_records WHERE {where_sql} ORDER BY id DESC LIMIT 10 """, params, ) sample = cur.fetchall() print("[INFO] Sample (latest 10):") for r in sample: print( f" id={r['id']} symbol={r['symbol']} result={r['result']} " f"pnl={r['pnl_amount']} closed_at={r['closed_at']}" ) if args.dry_run: print("[DRY-RUN] No write executed.") conn.close() return 0 cur.execute( f"UPDATE trade_records SET result=? WHERE {where_sql}", (args.to_result, *params), ) changed = int(cur.rowcount) conn.commit() conn.close() print(f"[DONE] Updated rows: {changed}") return 0 if __name__ == "__main__": sys.exit(main())