harb/onchain/analysis/distill_deep.py

228 lines
7.9 KiB
Python
Raw Permalink Normal View History

#!/usr/bin/env python3
"""Deep distillation: reduce profitable runs to essential attack pattern.
Strategy: Track cumulative net position and floor movement.
The "attack" is the net effect: how much ETH in, how much KRK accumulated,
how many recenters, how far floor moved, and final extraction.
"""
import csv
import glob
import os
from collections import defaultdict
def analyze_run(path):
"""Analyze a single profitable run deeply."""
rows = []
with open(path) as f:
reader = csv.DictReader(f)
for row in reader:
rows.append(row)
init_eth = final_eth = 0
total_buys = total_sells = 0
total_buy_eth = 0
total_sell_krk = 0
recenters = 0
stakes = unstakes = 0
floor_ticks = []
tick_history = []
# Track phases: accumulation vs extraction
phase_transitions = []
net_eth_spent = 0 # cumulative ETH spent buying
for row in rows:
action = row['action']
amount = int(row.get('amount', 0))
floor_lower = int(row.get('floor_lower', 0))
tick = int(row.get('tick', 0))
eth_bal = int(row.get('eth_balance', 0))
krk_bal = int(row.get('kraiken_balance', 0))
if action == 'INIT':
init_eth = eth_bal
init_tick = tick
elif action == 'FINAL':
final_eth = eth_bal
final_krk = krk_bal
elif action == 'BUY':
total_buys += 1
total_buy_eth += amount
elif action == 'SELL':
total_sells += 1
total_sell_krk += amount
elif action == 'RECENTER':
recenters += 1
floor_ticks.append(floor_lower)
elif action == 'STAKE':
stakes += 1
elif action == 'UNSTAKE':
unstakes += 1
if floor_lower != 0:
tick_history.append((action, tick, floor_lower, eth_bal / 1e18, krk_bal / 1e18))
pnl = (final_eth - init_eth) / 1e18
# Floor movement analysis
floor_range = 0
floor_direction = 0
if len(floor_ticks) >= 2:
floor_range = max(floor_ticks) - min(floor_ticks)
floor_direction = floor_ticks[-1] - floor_ticks[0]
# Find the key inflection: when does trader switch from accumulation to extraction?
# Track ETH balance trajectory
eth_trajectory = []
for row in rows:
if row['action'] in ('BUY', 'SELL', 'RECENTER', 'INIT', 'FINAL'):
eth_trajectory.append((row['action'], int(row.get('eth_balance', 0)) / 1e18))
# Find min ETH point (maximum investment before extraction)
min_eth = min(e for _, e in eth_trajectory)
min_eth_idx = next(i for i, (_, e) in enumerate(eth_trajectory) if e == min_eth)
# Phases: before min_eth = accumulation, after = mixed/extraction
accum_buys = sum(1 for a, _ in eth_trajectory[:min_eth_idx] if a == 'BUY')
accum_sells = sum(1 for a, _ in eth_trajectory[:min_eth_idx] if a == 'SELL')
accum_recenters = sum(1 for a, _ in eth_trajectory[:min_eth_idx] if a == 'RECENTER')
return {
'file': os.path.basename(path),
'pnl': pnl,
'init_eth': init_eth / 1e18,
'final_eth': final_eth / 1e18,
'total_buys': total_buys,
'total_sells': total_sells,
'total_buy_eth': total_buy_eth / 1e18,
'recenters': recenters,
'stakes': stakes,
'unstakes': unstakes,
'floor_range': floor_range,
'floor_direction': floor_direction,
'min_eth': min_eth,
'max_investment': eth_trajectory[0][1] - min_eth,
'accum_buys': accum_buys,
'accum_recenters': accum_recenters,
}
def main():
csvs = sorted(glob.glob('analysis/fuzz-b*.csv'))
results = []
for path in csvs:
try:
r = analyze_run(path)
if r['pnl'] > 0:
results.append(r)
except Exception as e:
pass
print(f"Analyzed {len(results)} profitable runs\n")
# Group by batch
batches = defaultdict(list)
for r in results:
batch = r['file'].split('-')[1]
batches[batch].append(r)
# Overall statistics
print("=" * 90)
print("DISTILLED ATTACK PATTERNS")
print("=" * 90)
print(f"\n{'Metric':<30s} {'Min':>10s} {'Avg':>10s} {'Max':>10s} {'Median':>10s}")
print("-" * 70)
for metric in ['pnl', 'recenters', 'floor_range', 'total_buys', 'total_sells', 'total_buy_eth', 'max_investment']:
vals = sorted([r[metric] for r in results])
avg = sum(vals) / len(vals)
med = vals[len(vals)//2]
print(f"{metric:<30s} {min(vals):>10.1f} {avg:>10.1f} {max(vals):>10.1f} {med:>10.1f}")
# The essential pattern
print("\n" + "=" * 90)
print("THE ESSENTIAL ATTACK PATTERN")
print("=" * 90)
# Cluster by PnL
high_profit = [r for r in results if r['pnl'] > 100]
low_profit = [r for r in results if 0 < r['pnl'] <= 100]
for label, group in [("HIGH PROFIT (>100 ETH)", high_profit), ("LOW PROFIT (1-100 ETH)", low_profit)]:
if not group:
continue
print(f"\n### {label}: {len(group)} runs")
avg = lambda key: sum(r[key] for r in group) / len(group)
print(f" Avg PnL: {avg('pnl'):+.1f} ETH")
print(f" Avg recenters: {avg('recenters'):.0f}")
print(f" Avg floor range: {avg('floor_range'):.0f} ticks")
print(f" Avg total buys: {avg('total_buys'):.0f} ({avg('total_buy_eth'):.0f} ETH)")
print(f" Avg total sells: {avg('total_sells'):.0f}")
print(f" Avg max investment:{avg('max_investment'):.0f} ETH")
print(f" Avg stakes: {avg('stakes'):.0f}")
# Per-batch summary
print("\n" + "=" * 90)
print("PER-BATCH ATTACK RATES")
print("=" * 90)
batch_info = {
'b2': 'buy-heavy CI=0 AS=10% AW=20',
'b3': 'sell-heavy CI=0 AS=10% AW=20',
'b4': 'wider AS=50% AW=50',
'b5': '5000 trades',
'b6': 'CI=10% AS=10% AW=20',
'b7': 'AS=30% AW=40 buybias=60',
'b8': 'AS=100% AW=80',
'b9': 'low DD=10%',
'b10': 'high DD=100%',
'b11': '3000 trades',
'b12': 'buy 90%',
'b13': 'CI=20%',
'b14': 'max AW=100',
'b15': 'baseline repeat',
'b16': 'AS=20% AW=30',
'b17': 'CI=5%',
'b18': '4000 trades',
'b19': '3000 buybias=65',
'b20': 'baseline big',
}
print(f"\n{'Batch':<8s} {'Params':<35s} {'Prof':>5s} {'Avg PnL':>10s} {'Avg Rec':>8s} {'Avg Floor':>10s}")
print("-" * 80)
for batch_id in sorted(batches.keys(), key=lambda x: int(x[1:])):
runs = batches[batch_id]
info = batch_info.get(batch_id, '?')
avg_pnl = sum(r['pnl'] for r in runs) / len(runs)
avg_rec = sum(r['recenters'] for r in runs) / len(runs)
avg_floor = sum(r['floor_range'] for r in runs) / len(runs)
print(f"{batch_id:<8s} {info:<35s} {len(runs):>5d} {avg_pnl:>+10.1f} {avg_rec:>8.0f} {avg_floor:>10.0f}")
# Distilled archetype
print("\n" + "=" * 90)
print("DISTILLED ARCHETYPE (what the attacker actually does)")
print("=" * 90)
avg_all = lambda key: sum(r[key] for r in results) / len(results)
print(f"""
1. ACCUMULATE: Buy ~{avg_all('total_buy_eth'):.0f} ETH worth of KRK over ~{avg_all('total_buys'):.0f} trades
(This crashes the price and triggers recenters)
2. RECENTERS: ~{avg_all('recenters'):.0f} recenters fire during the sequence
Floor moves ~{avg_all('floor_range'):.0f} ticks closer to current price
(Each recenter repositions floor, packing ETH into reachable range)
3. EXTRACT: Sell all KRK (~{avg_all('total_sells'):.0f} sell trades)
Final sell drains floor's concentrated ETH reserve
NET: Trader invests ~{avg_all('max_investment'):.0f} ETH at peak, extracts {avg_all('pnl'):+.0f} ETH profit
STAKING: {avg_all('stakes'):.0f} stakes / {avg_all('unstakes'):.0f} unstakes NO CORRELATION with profit
""")
if __name__ == '__main__':
main()