# -*- coding: utf-8 -*-
"""分析每次开仓前后的equity变化，判断盈亏，回算最优权重"""
import re
from collections import defaultdict

import os as _os; LOG = _os.path.join(_os.path.dirname(_os.path.dirname(_os.path.dirname(_os.path.abspath(__file__)))), "my_trader.log")
DATE = "2026-04-15"

WEIGHTS = {
    "TR":0.10,"OB":0.06,"TK":0.12,"OI":0.05,
    "FR":0.02,"MP":0.01,"VD":0.09,"BTC":0.07,
    "GM":0.06,"IV":0.01,"EX":0.07,"LC":0.15,
    "MR":0.06,"NEWS":0.13,"SM":0.00,
}
FK = ["TR","OB","TK","OI","FR","MP","VD","BTC","GM","IV","EX","LC","MR","SM"]

factor_re = re.compile(
    r"(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}).*"
    r"TR:([+-][0-9.]+) OB:([+-][0-9.]+) FR:([+-][0-9.]+) TK:([+-][0-9.]+) "
    r"OI:([+-][0-9.]+) MP:([+-][0-9.]+) VD:([+-][0-9.]+) BTC:([+-][0-9.]+) "
    r"GM:([+-][0-9.]+) IV:([+-][0-9.]+) EX:([+-][0-9.]+) LC:([+-][0-9.]+) "
    r"MR:([+-][0-9.]+) SM:([+-][0-9.]+).*=> ([+-][0-9.]+) -> (LONG|SHORT|WAIT)"
)
equity_re  = re.compile(r"(\d{2}:\d{2}:\d{2}).*Cycle \d+: equity=\$([0-9.]+)")
open_re    = re.compile(r"触发 (LONG|SHORT)|触发.*执行开仓")
pos_re     = re.compile(r"\[持仓\] ETH (long|short) ([0-9.]+)张 @ \$([0-9.]+) P.L:\$([+-][0-9.]+)")
close_re   = re.compile(r"止损触发|止盈触发|平仓成功|TP.*成交|SL.*成交")

lines = open(LOG, encoding="utf-8", errors="replace").readlines()

# 解析所有事件
all_events = []  # (ts_str, type, data)
prev_factor = None

for i, line in enumerate(lines):
    if DATE not in line:
        continue
    ts = line[11:19]

    # equity点
    m = equity_re.search(line)
    if m:
        all_events.append((m.group(1), "equity", float(m.group(2))))

    # 因子行
    mf = factor_re.search(line)
    if mf:
        fkeys = ["TR","OB","FR","TK","OI","MP","VD","BTC","GM","IV","EX","LC","MR","SM"]
        fvals = {k: float(v) for k, v in zip(fkeys, mf.groups()[1:15])}
        score = float(mf.group(15))
        direction = mf.group(16)
        prev_factor = {"f": fvals, "score": score, "dir": direction}

    # 开仓
    if ("触发" in line and "执行开仓" in line) and prev_factor:
        all_events.append((ts, "open", {**prev_factor, "ts": ts}))

    # 持仓PnL
    mp = pos_re.search(line)
    if mp:
        all_events.append((ts, "pos", {
            "side": mp.group(1), "qty": float(mp.group(2)),
            "entry": float(mp.group(3)), "pnl": float(mp.group(4))
        }))

# 提取equity序列
eq_seq = [(t, v) for t, typ, v in all_events if typ == "equity"]
opens  = [(t, d) for t, typ, d in all_events if typ == "open"]

def find_eq_at(ts, after_sec=300):
    """找ts之后约after_sec秒的equity"""
    h, m, s = int(ts[:2]), int(ts[3:5]), int(ts[6:])
    base = h*3600 + m*60 + s
    target = base + after_sec
    for eq_ts, eq_val in eq_seq:
        eh, em, es = int(eq_ts[:2]), int(eq_ts[3:5]), int(eq_ts[6:])
        et = eh*3600 + em*60 + es
        if et >= target:
            return eq_val, eq_ts
    return None, None

def find_eq_before(ts):
    h, m, s = int(ts[:2]), int(ts[3:5]), int(ts[6:])
    base = h*3600 + m*60 + s
    prev_val = None
    for eq_ts, eq_val in eq_seq:
        eh, em, es = int(eq_ts[:2]), int(eq_ts[3:5]), int(eq_ts[6:])
        et = eh*3600 + em*60 + es
        if et <= base:
            prev_val = eq_val
        else:
            break
    return prev_val

print("="*70)
print(f"今日交易分析 ({DATE})")
print("="*70)

if eq_seq:
    first_eq = eq_seq[0][1]
    last_eq  = eq_seq[-1][1]
    max_eq   = max(v for _, v in eq_seq)
    print(f"  开盘: ${first_eq:.4f}  峰值: ${max_eq:.4f}  当前: ${last_eq:.4f}")
    print(f"  净变化: {last_eq-first_eq:+.4f}  峰值回撤: {(max_eq-last_eq)/max_eq*100:.2f}%")

print(f"\n共发现 {len(opens)} 次开仓\n")

# 分析每次开仓
trade_results = []
for i, (ts, data) in enumerate(opens):
    eq_before = find_eq_before(ts)
    eq_after5,  ts5  = find_eq_at(ts, 300)   # 5分钟后
    eq_after15, ts15 = find_eq_at(ts, 900)   # 15分钟后
    eq_after30, ts30 = find_eq_at(ts, 1800)  # 30分钟后

    direction = data["dir"]
    score     = data["score"]
    fvals     = data["f"]

    pnl5  = (eq_after5  - eq_before) if eq_before and eq_after5  else None
    pnl15 = (eq_after15 - eq_before) if eq_before and eq_after15 else None
    pnl30 = (eq_after30 - eq_before) if eq_before and eq_after30 else None

    result_5 = ("盈" if pnl5  > 0 else "亏") if pnl5  is not None else "?"
    result_30= ("盈" if pnl30 > 0 else "亏") if pnl30 is not None else "?"

    print(f"[{i+1}] {ts} {direction} 总分={score:+.3f}")
    if eq_before: print(f"     开仓前equity: ${eq_before:.4f}")
    if pnl5:      print(f"     5min后: {pnl5:+.4f} ({result_5})  15min: {pnl15:+.4f}  30min: {pnl30:+.4f} ({result_30})")

    # 因子贡献排行
    contribs = []
    for k in FK:
        v = fvals.get(k, 0)
        w = WEIGHTS.get(k, 0)
        c = v * w
        contribs.append((k, v, w, c))
    contribs.sort(key=lambda x: abs(x[3]), reverse=True)

    print(f"     主要因子贡献:")
    for k, v, w, c in contribs[:6]:
        mark = "▲" if c > 0 else "▼"
        print(f"       {mark}{k:4}: {v:+.3f}×{w:.2f}={c:+.4f}", end="  ")
    print()

    trade_results.append({
        "ts": ts, "dir": direction, "score": score,
        "fvals": fvals, "pnl30": pnl30,
        "win": pnl30 > 0 if pnl30 is not None else None
    })

# 统计：盈利vs亏损时各因子均值
print("\n" + "="*70)
print("因子贡献度对比：盈利开仓 vs 亏损开仓")
print("="*70)
wins  = [t for t in trade_results if t["win"] is True]
losses= [t for t in trade_results if t["win"] is False]
print(f"盈利次数: {len(wins)}  亏损次数: {len(losses)}")

print(f"\n{'因子':5} {'权重':5} {'盈利时均值':12} {'亏损时均值':12} {'差值':10} {'结论'}")
for k in FK:
    w = WEIGHTS.get(k, 0)
    wa = sum(t["fvals"].get(k,0) for t in wins) /len(wins)  if wins  else 0
    la = sum(t["fvals"].get(k,0) for t in losses)/len(losses) if losses else 0
    diff = wa - la
    if abs(diff) > 0.05:
        note = "盈利时更强" if abs(wa) > abs(la) else "亏损时反向"
    else:
        note = "-"
    print(f"  {k:5} {w:.2f}  {wa:+.4f}      {la:+.4f}      {diff:+.4f}   {note}")

# 权重优化建议
print("\n" + "="*70)
print("权重优化建议（基于今日交易）")
print("="*70)
# 计算每个因子与盈亏的相关性
for k in FK:
    vals = [(t["fvals"].get(k,0), 1 if t["win"] else -1)
            for t in trade_results if t["win"] is not None]
    if not vals:
        continue
    # 方向一致性：正值时方向与盈亏符号一致的比例
    agree = sum(1 for v, w in vals if v * w > 0) / len(vals)
    print(f"  {k:5}: 方向一致率={agree*100:.0f}%  当前权重={WEIGHTS.get(k,0):.2f}")
