# -*- coding: utf-8 -*-
"""ProfitTarget simulation

Automatically generated by Colab.

Original file is located at
    https://colab.research.google.com/drive/1v8vVATArNHju8g3PnDMiAHJlLvNkv0Yk
"""



import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

# Parameters
initial_balance = 1000
target_balance = 200000
win_rate = 0.76  # 37%
tgtBalance = f'${target_balance:,}'
initialBal = f'${initial_balance:,}'

# Time horizon
years = 3
trades_per_year = 250  # roughly 1 trade per day
total_trades = trades_per_year * years

# Reward-Risk Ratio (to be varied in simulation)
reward_risk_ratios = np.arange(0.5, 5.5, 0.5)

# Risk per trade (to be varied in simulation)
risk_percents = np.arange(0.5, 10.5, 0.5) / 100

# Monte Carlo simulation settings
num_simulations = 500
np.random.seed(84)  # for reproducibility

# Function to simulate a single equity curve
def simulate_equity_curve(win_rate, rr, risk_percent, initial_balance, total_trades):
    balance = initial_balance
    equity_curve = [balance]
    max_drawdown = 0
    peak = balance
    current_drawdown = 0
    consecutive_losses = 0
    max_consecutive_losses = 0

    for _ in range(total_trades):
        if np.random.rand() < win_rate:
            balance += balance * risk_percent * rr
            consecutive_losses = 0
        else:
            balance -= balance * risk_percent
            consecutive_losses += 1
            max_consecutive_losses = max(max_consecutive_losses, consecutive_losses)

        peak = max(peak, balance)
        current_drawdown = (peak - balance) / peak
        max_drawdown = max(max_drawdown, current_drawdown)

        equity_curve.append(balance)

        if balance <= 0:
            break  # account blown

    return equity_curve, max_drawdown, max_consecutive_losses

# Run Monte Carlo simulation across parameter grid
results = []

for rr in reward_risk_ratios:
    for risk_percent in risk_percents:
        balances = []
        drawdowns = []
        consecutive_losses = []
        for _ in range(num_simulations):
            eq_curve, max_dd, max_losses = simulate_equity_curve(
                win_rate, rr, risk_percent, initial_balance, total_trades
            )
            balances.append(eq_curve[-1])
            drawdowns.append(max_dd)
            consecutive_losses.append(max_losses)

        success_rate = np.mean(np.array(balances) >= target_balance)

        results.append({
            'RR': rr,
            'Risk%': risk_percent * 100,
            'Success Rate': success_rate,
            'Median Final Balance': f'${np.median(balances):,.2f}',
            'Median Max Drawdown%': f'{np.median(drawdowns)*100:.2f}%',
            'Median Max Consecutive Losses': np.median(consecutive_losses)
        })

# Convert results to structured array for easier plotting
import pandas as pd

df_results = pd.DataFrame(results)

# Plot: Heatmap of success rate vs RR and Risk%
# Use keyword arguments for pivot
pivot_success = df_results.pivot(index='Risk%', columns='RR', values='Success Rate')

plt.figure(figsize=(10, 6))
sns.heatmap(pivot_success, annot=True, fmt=".2%", cmap='YlGnBu')
plt.title(f'Success Rate to Reach {tgtBalance} in {total_trades} trades\n(Win Rate = {win_rate*100:.1f}%, Initial Balance = {initialBal})')
plt.xlabel("Reward-Risk Ratio")
plt.ylabel("Risk % per Trade")
plt.tight_layout()
plt.show()

print("\n\n\n")
# Find the "best" combination with at least 10% success rate
optimal_combos = df_results[df_results['Success Rate'] >= 0.50].sort_values(by='Success Rate', ascending=True)

# Show top 5 optimal combinations
print(f"First 5 success rate>50% to Reach {tgtBalance} in {total_trades} trades:")
display(optimal_combos.head().style.background_gradient(cmap='YlGnBu'))
print("\n\n\n")


#Part 2: Graphs of drawdowns, losing streaks and number of trades to achieve target

# Results storage
results = {}

for rr_ratio in reward_risk_ratios:
    avg_max_drawdown = []
    avg_losing_streak = []
    median_trades_to_target = []

    for risk_frac in risk_percents:
        max_drawdowns = []
        max_losing_streaks = []
        trades_to_target = []

        for _ in range(num_simulations):
            equity = initial_balance
            peak_equity = initial_balance
            losing_streak = 0
            max_losing_streak = 0
            max_dd = 0
            history = []

            for t in range(total_trades):
                risk_amount = equity * risk_frac
                if np.random.rand() < win_rate:
                    pnl = risk_amount * rr_ratio
                    losing_streak = 0
                else:
                    pnl = -risk_amount
                    losing_streak += 1

                equity += pnl
                peak_equity = max(peak_equity, equity)
                drawdown = (peak_equity - equity) / peak_equity * 100
                max_dd = max(max_dd, drawdown)
                max_losing_streak = max(max_losing_streak, losing_streak)
                history.append(equity)

                if equity >= target_balance:
                    trades_to_target.append(t + 1)
                    break
            else:
                trades_to_target.append(total_trades)


            max_drawdowns.append(max_dd)
            max_losing_streaks.append(max_losing_streak)


        # Store averages
        avg_max_drawdown.append(np.mean(max_drawdowns))
        avg_losing_streak.append(np.mean(max_losing_streaks))
        median_trades_to_target.append(np.median(trades_to_target))


    # Save results for this R:R
    results[rr_ratio] = {
        "risk_percents": risk_percents * 100,
        "avg_drawdown": avg_max_drawdown,
        "avg_losing_streak": avg_losing_streak,
        "median_trades_to_target": median_trades_to_target
    }



# Plot average drawdown
plt.figure(figsize=(9, 5))
for rr_ratio in reward_risk_ratios:
    plt.plot(results[rr_ratio]["risk_percents"], results[rr_ratio]["avg_drawdown"], marker='o', label=f'R:R {rr_ratio}')
plt.title(f'Target= {tgtBalance} in {total_trades} trades (Win Rate = {win_rate*100:.1f}%)\nAverage Max Drawdown vs % Risk per Trade')
plt.xlabel('% Risk per Trade')
plt.ylabel('Avg Max Drawdown (%)')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()

print("\n\n\n")
# Plot average losing streak
plt.figure(figsize=(9, 5))
for rr_ratio in reward_risk_ratios:
    plt.plot(results[rr_ratio]["risk_percents"], results[rr_ratio]["avg_losing_streak"], marker='o', label=f'R:R {rr_ratio}')
plt.title(f'Target= {tgtBalance} in {total_trades} trades (Win Rate = {win_rate*100:.1f}%)\nAverage Losing Streak vs % Risk per Trade')
plt.xlabel('% Risk per Trade')
plt.ylabel('Average Losing Streak (trades)')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()

print("\n\n\n")
# Plot trades to target
plt.figure(figsize=(9, 5))
for rr_ratio in reward_risk_ratios:
    plt.plot(results[rr_ratio]["risk_percents"], results[rr_ratio]["median_trades_to_target"], marker='o', label=f'R:R {rr_ratio}')
plt.title(f'Target= {tgtBalance} in {total_trades} trades (Win Rate = {win_rate*100:.1f}%)\nMedian Trades Needed to Reach Target vs % Risk per Trade')
plt.xlabel('% Risk per Trade')
plt.ylabel(f'Median Trades to Reach {tgtBalance}')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()