42 lines
1.4 KiB
Python
42 lines
1.4 KiB
Python
|
|
import gzip, csv
|
||
|
|
from collections import defaultdict
|
||
|
|
|
||
|
|
f = gzip.open('shadow_decisions.csv.gz', 'rt')
|
||
|
|
reader = csv.DictReader(f)
|
||
|
|
|
||
|
|
# 只看 BTC, 5m, 实际入场了 (would_enter=1)
|
||
|
|
rows = [r for r in reader if r['symbol'] == 'BTCUSDT' and r['timeframe'] == '5m' and r['would_enter'] == '1']
|
||
|
|
f.close()
|
||
|
|
|
||
|
|
print(f"BTC 5m entries: {len(rows)}")
|
||
|
|
|
||
|
|
# 各策略胜率
|
||
|
|
print("\n===== 各策略胜率 (BTC 5m) =====")
|
||
|
|
stats = defaultdict(lambda: [0, 0, 0.0])
|
||
|
|
for r in rows:
|
||
|
|
cfg = r['config_name']
|
||
|
|
stats[cfg][0] += 1
|
||
|
|
stats[cfg][1] += 1 if r['win'] == '1' else 0
|
||
|
|
try:
|
||
|
|
stats[cfg][2] += float(r['realized_pnl']) if r['realized_pnl'] else 0
|
||
|
|
except:
|
||
|
|
pass
|
||
|
|
|
||
|
|
for cfg, (total, wins, pnl) in sorted(stats.items(), key=lambda x: -x[1][1] / max(x[1][0], 1)):
|
||
|
|
wr = wins / total * 100
|
||
|
|
print(f" {cfg:40s} {wins:4d}/{total:<4d} WR={wr:5.1f}% PnL={pnl:+.2f}")
|
||
|
|
|
||
|
|
# 总体
|
||
|
|
total_wins = sum(s[1] for s in stats.values())
|
||
|
|
total_entries = sum(s[0] for s in stats.values())
|
||
|
|
total_pnl = sum(s[2] for s in stats.values())
|
||
|
|
print(f"\n 总计: {total_wins}/{total_entries} WR={total_wins/total_entries*100:.1f}% PnL={total_pnl:+.2f}")
|
||
|
|
|
||
|
|
# 按 side 统计
|
||
|
|
print("\n===== 按方向统计 =====")
|
||
|
|
sides = defaultdict(lambda: [0, 0])
|
||
|
|
for r in rows:
|
||
|
|
sides[r['side']][0] += 1
|
||
|
|
sides[r['side']][1] += 1 if r['win'] == '1' else 0
|
||
|
|
for side, (total, wins) in sides.items():
|
||
|
|
print(f" {side}: {wins}/{total} WR={wins/total*100:.1f}%")
|