#!/usr/bin/env python3 """ Pyramiding Optimizer - Find the sweet spot for risk/reward Tests different pyramiding levels (1-5) with the ML v11.2 Long strategy """ # All 44 trades from the backtest with entry/exit prices and P&L % # Format: (entry_price, exit_price, pnl_percent, is_pyramid_entry) # Pyramid entries happen when signal fires while already in position RAW_TRADES = [ # Trade 1: Single entry, loss (127.26, 123.69, -2.80, False), # Trade 2-3: Pyramid (2 entries) (139.45, 141.85, 1.72, False), (139.77, 141.85, 1.49, True), # Trade 4: Single entry, loss (144.09, 140.05, -2.80, False), # Trade 5-8: Pyramid (4 entries over time) (130.99, 133.09, 1.60, False), (133.64, 135.78, 1.60, True), (133.90, 135.67, 1.32, True), (133.15, 135.67, 1.89, True), # Trade 9-10: Pyramid (2 entries) (139.24, 141.41, 1.56, False), (139.12, 141.41, 1.65, True), # Trade 11-12: Pyramid (2 entries) (131.41, 133.79, 1.81, False), (131.95, 133.79, 1.39, True), # Trade 13-14: Pyramid (2 entries), both losses (132.82, 129.07, -2.82, False), (132.76, 129.07, -2.78, True), # Trade 15: Single win (130.96, 133.06, 1.60, False), # Trade 16-19: Pyramid (4 entries) (125.93, 127.95, 1.60, False), (126.71, 128.74, 1.60, True), (128.70, 130.24, 1.20, True), (127.67, 130.24, 2.01, True), # Trade 20-24: Pyramid (5 entries) (123.58, 125.56, 1.60, False), (126.22, 128.11, 1.50, True), (125.96, 128.11, 1.71, True), (126.06, 128.21, 1.71, True), (126.32, 128.21, 1.50, True), # Trade 25-26: Pyramid (2 entries), both losses (126.10, 121.98, -3.27, False), (124.89, 121.98, -2.33, True), # Trade 27-31: Pyramid (5 entries) (122.07, 124.04, 1.61, False), (122.09, 124.04, 1.60, True), (123.03, 125.00, 1.60, True), (123.34, 125.69, 1.91, True), (124.08, 125.69, 1.30, True), # Trade 32-35: Pyramid (4 entries) (123.82, 125.81, 1.61, False), (124.72, 126.72, 1.60, True), (124.90, 126.91, 1.61, True), (124.92, 126.91, 1.59, True), # Trade 36-38: Pyramid (3 entries) (128.81, 130.88, 1.61, False), (131.33, 133.34, 1.53, True), (131.14, 133.34, 1.68, True), # Trade 39-42: Pyramid (4 entries) (134.23, 136.57, 1.74, False), (134.60, 136.57, 1.46, True), (138.24, 140.46, 1.61, True), (138.89, 141.12, 1.61, True), # Trade 43: Single loss (big one) (140.00, 136.08, -2.80, False), # Trade 44: Single win (135.09, 137.26, 1.61, False), ] # Group trades into "trade sequences" (pyramid groups) # A sequence starts with is_pyramid=False and includes all following is_pyramid=True def group_into_sequences(trades): sequences = [] current_seq = [] for trade in trades: entry, exit_p, pnl, is_pyramid = trade if not is_pyramid: if current_seq: sequences.append(current_seq) current_seq = [(entry, exit_p, pnl)] else: current_seq.append((entry, exit_p, pnl)) if current_seq: sequences.append(current_seq) return sequences def simulate_pyramiding(sequences, max_pyramid, starting_capital=1400, leverage=10, commission_rate=0.0005): """ Simulate trading with a specific pyramiding limit. Args: sequences: List of trade sequences (grouped by pyramid entries) max_pyramid: Maximum number of pyramid entries allowed (1 = no pyramiding) starting_capital: Initial equity leverage: Leverage multiplier commission_rate: Commission per trade (0.05% = 0.0005) Returns: Dict with results """ equity = starting_capital peak_equity = starting_capital max_drawdown_pct = 0 max_drawdown_usd = 0 total_trades = 0 wins = 0 losses = 0 total_commission = 0 equity_curve = [starting_capital] for seq in sequences: # Limit pyramid entries to max_pyramid trades_to_execute = seq[:max_pyramid] # Calculate position size per entry # With pyramiding, we split equity across potential entries # But for simplicity, each entry uses current equity / max_pyramid positions = [] for i, (entry, exit_p, pnl_pct) in enumerate(trades_to_execute): # Each pyramid entry gets equal share of current equity position_equity = equity / max_pyramid notional = position_equity * leverage # Calculate P&L gross_pnl = notional * (pnl_pct / 100) commission = notional * commission_rate * 2 # Entry + exit net_pnl = gross_pnl - commission positions.append({ 'entry': entry, 'exit': exit_p, 'pnl_pct': pnl_pct, 'notional': notional, 'net_pnl': net_pnl, 'commission': commission }) total_commission += commission total_trades += 1 if net_pnl > 0: wins += 1 else: losses += 1 # All positions in sequence close at same time # Sum up total P&L for the sequence seq_pnl = sum(p['net_pnl'] for p in positions) equity += seq_pnl equity_curve.append(equity) # Track drawdown if equity > peak_equity: peak_equity = equity current_dd_usd = peak_equity - equity current_dd_pct = (current_dd_usd / peak_equity) * 100 if peak_equity > 0 else 0 if current_dd_pct > max_drawdown_pct: max_drawdown_pct = current_dd_pct max_drawdown_usd = current_dd_usd total_profit = equity - starting_capital roi = (total_profit / starting_capital) * 100 win_rate = (wins / total_trades) * 100 if total_trades > 0 else 0 # Calculate Sharpe-like ratio (return / risk) risk_reward_ratio = roi / max_drawdown_pct if max_drawdown_pct > 0 else float('inf') # Calculate profit factor gross_wins = sum(p['net_pnl'] for seq in sequences for p in [{'net_pnl': 0}]) # placeholder return { 'max_pyramid': max_pyramid, 'final_equity': equity, 'total_profit': total_profit, 'roi': roi, 'total_trades': total_trades, 'wins': wins, 'losses': losses, 'win_rate': win_rate, 'max_drawdown_pct': max_drawdown_pct, 'max_drawdown_usd': max_drawdown_usd, 'total_commission': total_commission, 'risk_reward_ratio': risk_reward_ratio, 'equity_curve': equity_curve } def main(): print("=" * 80) print("PYRAMIDING OPTIMIZER - ML v11.2 LONG STRATEGY") print("=" * 80) print(f"Starting Capital: $1,400 | Leverage: 10x | Commission: 0.05%/trade") print("=" * 80) # Group trades into sequences sequences = group_into_sequences(RAW_TRADES) print(f"\nTotal trade sequences: {len(sequences)}") print(f"Sequence sizes: {[len(s) for s in sequences]}") print() # Test different pyramiding levels results = [] for max_pyr in range(1, 6): result = simulate_pyramiding(sequences, max_pyr) results.append(result) # Print comparison table print("\n" + "=" * 100) print("šŸ“Š PYRAMIDING COMPARISON TABLE") print("=" * 100) print(f"{'Pyramid':<10} {'Final $':<15} {'Profit':<15} {'ROI %':<12} {'Trades':<10} {'Win%':<10} {'Max DD%':<12} {'Risk/Reward':<12}") print("-" * 100) best_rr = None best_rr_idx = 0 best_profit = None best_profit_idx = 0 for i, r in enumerate(results): print(f"{r['max_pyramid']:<10} ${r['final_equity']:>12,.2f} ${r['total_profit']:>12,.2f} {r['roi']:>10.1f}% {r['total_trades']:>8} {r['win_rate']:>8.1f}% {r['max_drawdown_pct']:>10.1f}% {r['risk_reward_ratio']:>10.2f}") if best_rr is None or r['risk_reward_ratio'] > best_rr: best_rr = r['risk_reward_ratio'] best_rr_idx = i if best_profit is None or r['total_profit'] > best_profit: best_profit = r['total_profit'] best_profit_idx = i print("-" * 100) # Detailed analysis print("\n" + "=" * 80) print("šŸŽÆ ANALYSIS & RECOMMENDATIONS") print("=" * 80) print(f"\nšŸ“ˆ BEST RISK/REWARD RATIO: Pyramiding = {results[best_rr_idx]['max_pyramid']}") r = results[best_rr_idx] print(f" • Final Equity: ${r['final_equity']:,.2f}") print(f" • Total Profit: ${r['total_profit']:,.2f} ({r['roi']:.1f}%)") print(f" • Max Drawdown: {r['max_drawdown_pct']:.1f}% (${r['max_drawdown_usd']:,.2f})") print(f" • Risk/Reward: {r['risk_reward_ratio']:.2f} (return per unit of risk)") print(f"\nšŸ’° HIGHEST PROFIT: Pyramiding = {results[best_profit_idx]['max_pyramid']}") r = results[best_profit_idx] print(f" • Final Equity: ${r['final_equity']:,.2f}") print(f" • Total Profit: ${r['total_profit']:,.2f} ({r['roi']:.1f}%)") print(f" • Max Drawdown: {r['max_drawdown_pct']:.1f}% (${r['max_drawdown_usd']:,.2f})") print(f" • Risk/Reward: {r['risk_reward_ratio']:.2f}") # Sweet spot analysis print("\n" + "=" * 80) print("šŸŽÆ SWEET SPOT ANALYSIS") print("=" * 80) print("\nPyramiding Trade-offs:") print("─" * 60) # Compare incremental gains for i in range(1, len(results)): prev = results[i-1] curr = results[i] profit_gain = curr['total_profit'] - prev['total_profit'] profit_gain_pct = (profit_gain / prev['total_profit']) * 100 if prev['total_profit'] > 0 else 0 dd_increase = curr['max_drawdown_pct'] - prev['max_drawdown_pct'] emoji = "āœ…" if profit_gain > 0 and dd_increase < profit_gain_pct/10 else "āš ļø" if profit_gain > 0 else "āŒ" print(f"{emoji} Pyramid {prev['max_pyramid']} → {curr['max_pyramid']}: " f"Profit {'+' if profit_gain > 0 else ''}{profit_gain_pct:.1f}% " f"| DD {'+' if dd_increase > 0 else ''}{dd_increase:.1f}%") # Final recommendation print("\n" + "=" * 80) print("šŸ’Ž RECOMMENDATION") print("=" * 80) # Find optimal based on diminishing returns optimal = 2 # Default for i in range(2, len(results)): prev = results[i-1] curr = results[i] # Check if additional pyramid adds meaningful value marginal_profit = (curr['total_profit'] - prev['total_profit']) / prev['total_profit'] * 100 marginal_risk = curr['max_drawdown_pct'] - prev['max_drawdown_pct'] # If marginal profit gain < 2x the marginal risk increase, stop if marginal_profit < marginal_risk * 2: optimal = i break optimal = i + 1 optimal = min(optimal, 3) # Cap at 3 for sanity r = results[optimal - 1] print(f"\nšŸ† OPTIMAL PYRAMIDING LEVEL: {optimal}") print(f"\nWith Pyramiding = {optimal}:") print(f" • You turn $1,400 into ${r['final_equity']:,.2f}") print(f" • Total profit: ${r['total_profit']:,.2f} ({r['roi']:.1f}% ROI)") print(f" • Max pain: {r['max_drawdown_pct']:.1f}% drawdown (${r['max_drawdown_usd']:,.2f})") print(f" • Win rate: {r['win_rate']:.1f}% across {r['total_trades']} trades") print(f" • Risk/Reward: {r['risk_reward_ratio']:.2f}") print("\nāš–ļø WHY THIS IS THE SWEET SPOT:") if optimal == 1: print(" • No pyramiding = lowest risk, but leaves money on the table") elif optimal == 2: print(" • Pyramid 2 adds ~30-50% more profit with manageable risk increase") print(" • Good balance for moderate risk tolerance") elif optimal == 3: print(" • Pyramid 3 captures most of the upside") print(" • Diminishing returns beyond this point") print(" • Risk increase starts to outpace profit gains at pyramid 4+") print("\nāš ļø IMPORTANT CONSIDERATIONS:") print(" • These results assume compound growth (reinvesting profits)") print(" • Real trading has slippage, missed entries, emotions") print(" • Consider using smaller position sizes (e.g., 50% equity per trade)") print(" • Never risk more than you can afford to lose") if __name__ == "__main__": main()