← Back
import json
from collections import defaultdict

with open('/home/app/trading-bot-bybit/data/trade_log.json') as f:
    trades = json.load(f)

closes = [t for t in trades if t.get('event') == 'DCA_CLOSE']
print(f'Total closed trades: {len(closes)}\n')

SCALE = 1.3; MAX_SO = 4; LEV = 3

trade_data = []
for t in closes:
    sos = t.get('safety_orders_filled', 0)
    pnl = t['pnl_usdt']
    reason = t['reason']
    invested = t.get('total_invested', 0)
    entry = t.get('avg_entry', 0)
    close_p = t.get('close_price', 0)
    side = t['side']
    if entry > 0 and close_p > 0:
        if side == 'BUY':
            pnl_pct = (close_p - entry) / entry * 100
        else:
            pnl_pct = (entry - close_p) / entry * 100
    else:
        pnl_pct = (pnl / invested * 100) if invested > 0 else 0
    trade_data.append({
        'pnl_pct': pnl_pct, 'sos': sos, 'reason': reason,
        'symbol': t['symbol'], 'pnl_usd': pnl, 'invested': invested,
    })

def calc_invested(bo, sos_filled):
    total = bo
    for i in range(sos_filled):
        total += bo * (SCALE ** i)
    return total

def calc_pnl_with_fees(pnl_pct_gross, bo, sos_filled, reason):
    invested = calc_invested(bo, sos_filled)
    notional = invested * LEV
    gross = notional * pnl_pct_gross / 100
    entry_fee = bo * LEV * 0.00055
    so_fees = sum(bo * (SCALE ** i) * LEV * 0.0002 for i in range(sos_filled))
    exit_rate = 0.0002 if reason == 'TP%' else 0.00055
    exit_fee = notional * exit_rate
    return gross - entry_fee - so_fees - exit_fee

bo_sizes = [3, 4, 5, 7, 10, 15, 20]
all_trades = trade_data
last_54 = trade_data[-54:]

print('=' * 100)
print('PROFIT SIMULATION: Different BO sizes')
print('SO = BO, scale 1.3x, max 4 SOs, 3x leverage')
print('=' * 100)

header = f"  {'BO':>5} | {'Max/Deal':>9} | {'6 Deals':>9} | {'All 244':>10} | {'Last 54':>10} | {'Avg/trade':>10} | {'Daily ~':>10}"
print(f"\n{header}")
print("  " + '-' * 80)

for bo in bo_sizes:
    max_deal = calc_invested(bo, MAX_SO)
    max_6 = max_deal * 6
    pnl_all = sum(calc_pnl_with_fees(t['pnl_pct'], bo, t['sos'], t['reason']) for t in all_trades)
    pnl_last = sum(calc_pnl_with_fees(t['pnl_pct'], bo, t['sos'], t['reason']) for t in last_54)
    avg = pnl_all / len(all_trades)
    daily = pnl_last * 2
    print(f"   ${bo:<3} | ${max_deal:>7.0f} | ${max_6:>7.0f} | ${pnl_all:>+8.2f} | ${pnl_last:>+8.2f} | ${avg:>+8.4f} | ${daily:>+8.2f}")

# Detailed last 54
print(f"\n{'=' * 100}")
print("LAST 54 TRADES (post SL 10% + Time Stop + SO Guard) — by reason")
print('=' * 100)

for bo in [3, 4, 5, 7, 10]:
    max_deal = calc_invested(bo, MAX_SO)
    by_reason = defaultdict(lambda: {'count': 0, 'pnl': 0, 'wins': 0})
    for t in last_54:
        pnl = calc_pnl_with_fees(t['pnl_pct'], bo, t['sos'], t['reason'])
        by_reason[t['reason']]['count'] += 1
        by_reason[t['reason']]['pnl'] += pnl
        if pnl > 0: by_reason[t['reason']]['wins'] += 1
    total = sum(d['pnl'] for d in by_reason.values())
    print(f"\n  BO ${bo} | Total: ${total:+.2f} | Max/deal: ${max_deal:.0f} | 6 deals: ${max_deal*6:.0f}")
    for r in ['TP%', 'Z-TP', 'SL', 'TIME-STOP', 'SO-GUARD']:
        d = by_reason.get(r)
        if not d: continue
        wr = d['wins'] / d['count'] * 100
        print(f"    {r:<12} {d['count']:>3}x  WR {wr:>5.1f}%  PnL ${d['pnl']:+.2f}")

# Top losers
print(f"\n{'=' * 100}")
print("TOP LOSERS scaled (last 54 trades)")
print('=' * 100)

worst = sorted(last_54, key=lambda t: t['pnl_pct'])[:7]
line = f"  {'Symbol':<15} {'SOs':>4} {'PnL%':>7}  |  {'BO$3':>8} {'BO$4':>8} {'BO$5':>8} {'BO$7':>8} {'BO$10':>8}"
print(f"\n{line}")
print("  " + "-" * 80)
for t in worst:
    pnls = [calc_pnl_with_fees(t['pnl_pct'], bo, t['sos'], t['reason']) for bo in [3, 4, 5, 7, 10]]
    pnl_str = '  '.join(f'${p:>+6.2f}' for p in pnls)
    print(f"  {t['symbol']:<15} {t['sos']:>4} {t['pnl_pct']:>+6.1f}%  | {pnl_str}")

# Balance
print(f"\n{'=' * 100}")
print("BALANCE REQUIREMENT")
print('=' * 100)
line2 = f"  {'BO':>5} | {'Per Deal':>9} | {'6 Deals':>9} | {'+20% buf':>10} | {'$70':>6} | {'$100':>6} | {'$150':>6}"
print(f"\n{line2}")
print("  " + "-" * 65)
for bo in bo_sizes:
    max_d = calc_invested(bo, MAX_SO)
    six = max_d * 6
    buf = six * 1.2
    f70 = 'ok' if buf <= 70 else 'NO'
    f100 = 'ok' if buf <= 100 else 'NO'
    f150 = 'ok' if buf <= 150 else 'NO'
    print(f"   ${bo:<3} | ${max_d:>7.0f} | ${six:>7.0f} | ${buf:>8.0f} |  {f70:>4} |  {f100:>4} |  {f150:>4}")

📜 Git History

dd32dfdchore: initial commit — version control setup5 weeks ago
Show last diff
Loading...