first commit
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
#!/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())
|
||||
|
||||
Reference in New Issue
Block a user