-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathanalyze_zero_fee.py
More file actions
98 lines (79 loc) · 3.78 KB
/
analyze_zero_fee.py
File metadata and controls
98 lines (79 loc) · 3.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import json
import glob
import os
import pandas as pd
LOG_DIR = "logs/whale_paper_trader"
def load_recent_trades(n=10):
files = glob.glob(os.path.join(LOG_DIR, "trades_*.json"))
files.sort(key=os.path.getmtime, reverse=True)
recent_files = files[:n]
all_trades = []
for f in recent_files:
try:
with open(f, 'r') as file:
data = json.load(file)
trades = data.get('trades', [])
all_trades.extend(trades)
except:
pass
return all_trades
def analyze_zero_fee(trades):
if not trades:
print("❌ No trades to analyze.")
return
df = pd.DataFrame(trades)
# In the logs, 'pnl_pct' is typically the Gross PnL % (Leverage Adjusted) BEFORE fees
# (Because net_pnl_usdt is separate).
# Let's Verify: Trade 84: pnl_pct 0.54, fee 3.92, net -3.37.
# 0.5% profit on $100 is $0.50. So pnl_pct IS Gross.
print(f"\n🚀 dYdX ZERO FEE SIMULATION (Based on recent 10 sessions)")
print("=" * 60)
# 1. Total Potential
total_gross_pnl = df['pnl_pct'].sum()
gross_win_rate = (df['pnl_pct'] > 0).mean() * 100
print(f" Total Trades Considered: {len(df)}")
print(f" Gross Win Rate: {gross_win_rate:.1f}%")
print(f" Total Theoretical Profit: +{total_gross_pnl:.1f}% (Accumulated PnL%)")
print(f" Avg Profit per Trade: +{df['pnl_pct'].mean():.3f}%")
# 2. Strategy Analysis (Which entry logic is best?)
def get_dominant_strategy(probs):
if not isinstance(probs, dict) or not probs: return "UNKNOWN"
return max(probs, key=probs.get)
df['dom_strategy'] = df['strategy_probs'].apply(get_dominant_strategy)
print(f"\n🏆 BEST STRATEGIES (Entries)")
strat_stats = df.groupby('dom_strategy').agg({
'pnl_pct': ['count', 'sum', 'mean', lambda x: (x > 0).mean() * 100]
})
strat_stats.columns = ['Count', 'Total PnL%', 'Avg PnL%', 'Win Rate%']
# Filter reasonable sample size
strat_stats = strat_stats[strat_stats['Count'] > 2].sort_values('Total PnL%', ascending=False)
print(strat_stats)
# 3. Scalping Viability (Duration Analysis)
print(f"\n⚡ SCALPING VIABILITY (Duration)")
df['duration_bin'] = pd.cut(df['hold_seconds'], bins=[0, 10, 60, 300, 99999],
labels=['Ultra-Scalp (<10s)', 'Scalp (10s-1m)', 'Swing (1m-5m)', 'Hold (>5m)'])
dur_stats = df.groupby('duration_bin', observed=False).agg({
'pnl_pct': ['count', 'sum', 'mean', lambda x: (x > 0).mean() * 100]
})
dur_stats.columns = ['Count', 'Total PnL%', 'Avg PnL%', 'Win Rate%']
print(dur_stats)
# 4. Exit Logic (Management)
print(f"\n🚪 EXIT STYLE PERFORMANCE")
exit_stats = df.groupby('status').agg({
'pnl_pct': ['count', 'sum', 'mean', lambda x: (x > 0).mean() * 100]
})
exit_stats.columns = ['Count', 'Total PnL%', 'Avg PnL%', 'Win Rate%']
print(exit_stats.sort_values('Total PnL%', ascending=False))
print("\n💡 CONCLUSION FOR dYdX:")
best_dur = dur_stats['Avg PnL%'].idxmax()
best_strat = strat_stats.index[0] if not strat_stats.empty else "N/A"
if dur_stats.loc['Ultra-Scalp (<10s)', 'Avg PnL%'] > 0:
print(f" ✅ YES! <10s Scalping is profitable!")
print(f" Avg Trade: +{dur_stats.loc['Ultra-Scalp (<10s)', 'Avg PnL%']:.3f}%")
print(f" Win Rate: {dur_stats.loc['Ultra-Scalp (<10s)', 'Win Rate%']:.1f}%")
print(" -> With 0 fees, you can run the bot 'as is' and make money.")
else:
print(f" ⚠️ Even with 0 fees, ultra-scalping might be risky (Avg PnL negative).")
print(f" 💪 Best Approach: {best_strat} holding for {best_dur}")
if __name__ == "__main__":
analyze_zero_fee(load_recent_trades(10))