Last active
May 22, 2023 01:22
-
-
Save Curtis-64/8ed2e708a24bbb18445769e27eef090d to your computer and use it in GitHub Desktop.
Python Monte Carlo Trade Simulator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
copy/paste into Ipython Notebook | |
!pip install sympy | |
import numpy as np | |
import matplotlib.pyplot as plt | |
from sympy import symbols, solve | |
# Define the symbols | |
P_W = symbols('P_W') | |
# Parameters | |
edge = .05 | |
risk_reward = 2 | |
# Solve the equation without the edge, accounting for risk_reward | |
zero_sum_win_ratio = solve(P_W * risk_reward - (1 - P_W), P_W)[0] | |
# Add the edge | |
win_ratio = zero_sum_win_ratio + edge | |
initial_equity = 2400 # initial account equity | |
risk_per_trade_percent = 0.05 # risk per trade as a percentage of the account equity | |
num_trades = 6 * 20 * 1 | |
#num_trades = 100 | |
trailing_dd = 2000 | |
target = 3000 | |
num_sims = 100 | |
min_risk = 50 # minimum risk amount in dollars | |
# Initialize stats | |
max_drawdowns = [] | |
average_drawdowns = [] | |
average_returns = [] | |
average_total_returns_no_dd = [] | |
total_equity = 0 | |
target_hit_counts = 0 | |
trailing_dd_counts = 0 | |
# Initialize a list to store all equity curves | |
all_equity_curves = [] | |
# Monte Carlo simulation | |
for i in range(num_sims): | |
equity = initial_equity | |
high_equity = equity # Initialize high equity with initial equity | |
drawdown = 0 | |
max_dd = 0 | |
total_dd = 0 | |
equity_curve = [] | |
hit_trailing_dd = False # flag to track if trailing drawdown was hit in this simulation | |
for j in range(num_trades): | |
risk_per_trade = max(min_risk, equity * risk_per_trade_percent) # calculate risk per trade based on current equity | |
if np.random.rand() < win_ratio: | |
# Win trade | |
equity += risk_reward * risk_per_trade | |
else: | |
# Lose trade | |
equity -= risk_per_trade | |
high_equity = max(high_equity, equity) # Update high equity | |
drawdown = max(0, high_equity - equity) # Update drawdown | |
max_dd = max(max_dd, drawdown) # Update max drawdown | |
total_dd += drawdown | |
# Stop trading if trailing drawdown is hit | |
if drawdown >= trailing_dd: | |
hit_trailing_dd = True # mark that trailing drawdown was hit in this simulation | |
trailing_dd_counts += 1 | |
break # stop trading for this simulation if trailing drawdown is hit | |
# Stop trading if target is hit | |
if (equity - initial_equity) >= target: | |
target_hit_counts += 1 | |
break # stop trading for this simulation if target is hit | |
equity_curve.append(equity) | |
max_drawdowns.append(max_dd) | |
average_drawdowns.append(total_dd / num_trades) | |
average_returns.append((equity - initial_equity) / num_trades) # Corrected average return calculation | |
total_equity += equity | |
# Store the equity curve for this simulation along with its color | |
if hit_trailing_dd: | |
color = 'red' | |
elif (equity - initial_equity) >= target: | |
color = 'green' | |
else: | |
color = 'yellow' | |
all_equity_curves.append((equity_curve, color)) | |
# Compute y-axis limits for the plots | |
min_equity = min(min(curve) for curve, color in all_equity_curves if curve) | |
max_equity = max(max(curve) for curve, color in all_equity_curves if curve) | |
# Plot each equity curve with the computed y-axis limits | |
for equity_curve, color in all_equity_curves: | |
if equity_curve: # check if equity_curve is not empty | |
plt.plot(equity_curve, color=color) | |
plt.ylim(min_equity, max_equity) | |
plt.show() # display the plot once after all curves have been plotted | |
# Compute stats | |
max_dd_avg = np.mean(max_drawdowns) | |
avg_dd_avg = np.mean(average_drawdowns) | |
avg_return_avg = np.mean(average_returns) | |
avg_total_return_no_dd = np.mean(average_total_returns_no_dd) if average_total_returns_no_dd else 0 | |
average_overall_equity = total_equity / num_sims | |
target_hit_ratio = target_hit_counts / num_sims | |
trailing_dd_ratio = trailing_dd_counts / num_sims # updated to count only simulations that hit trailing drawdown | |
print(f'Zero Sum Win Ratio: {zero_sum_win_ratio}') | |
print(f'Edge: {edge}') | |
print(f'Win Ratio Total: {win_ratio}') | |
print(f'R: {risk_reward}') | |
print(f'% Risk: {risk_per_trade_percent}') | |
print(f'Target: {target}') | |
print(f'Trail DD: {trailing_dd}') | |
print(f'Min $ Risk: {min_risk}') | |
print(f'Number Trades: {num_trades}') | |
print(f'Number Sims: {num_sims}') | |
print(f'Average Maximum Drawdown: {max_dd_avg}') | |
print(f'Average Drawdown: {avg_dd_avg}') | |
print(f'Average Return per Trade: {avg_return_avg}') | |
print(f'Average Total Return (No DD Hit): {avg_total_return_no_dd}') | |
print(f'Average Overall Equity: {average_overall_equity}') | |
print(f'Target Hit Ratio: {target_hit_ratio}') | |
print(f'Trailing Drawdown Hit Ratio: {trailing_dd_ratio}') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment