├── README.md ├── LICENSE └── MT4_Results_To_MonteCarlo.py /README.md: -------------------------------------------------------------------------------- 1 | # Execute MonteCarlo Simulation on MetaTrader 4 Strategy Results 2 | 3 | ## What does this do 4 | 5 | The following python script allows Forex traders who run backtests through the MetaTrader 4 platform to run a Montecarlo Simulation on their results. 6 | 7 | This script will do the following: 8 | 9 | 1. Convert your `.htm` file to a `.csv` (this is because MT4 does not output results in a usable format). 10 | 2. Run a MonteCarlo Simulation on the results and provide you with the simulation results. 11 | 12 | ## To Run 13 | 14 | Put this script in the same folder as the backtest results (typically `StrategyTester.htm`) and then execute `py MT4_Results_To_MonteCarlo.py` and it will do the rest. 15 | 16 | ## Requirements 17 | 18 | * Python 3.4+ 19 | * pip 20 | * `pip install pandas` 21 | * `pip install numpy` 22 | * `pip install pandas_montecarlo` 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Alexander Whipp 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MT4_Results_To_MonteCarlo.py: -------------------------------------------------------------------------------- 1 | import re 2 | import pandas_montecarlo 3 | import pandas as pd 4 | import numpy as np 5 | 6 | toExclude = "" 7 | toFind = "class=mspt" 8 | fileName = "StrategyTester" 9 | dd = -0.1 10 | target = 0.1 11 | multiplier = 1 12 | 13 | # The amount for the initial value 14 | initial = 1000 15 | 16 | # Max number of simulations 17 | simLimit = 18500 18 | 19 | # Read the MT4 Results HTM to memory 20 | with open(fileName + ".htm", "r") as f: 21 | lines = f.readlines() 22 | 23 | # Convert the HTM file to a legible CSV 24 | with open(fileName + ".csv", "w") as f: 25 | for line in lines: 26 | if toExclude not in line and toFind in line: 27 | line = re.sub(r"<.*?>\s?\<.*?\>", ",", line) 28 | line = line.split(",") 29 | if initial == 1000: 30 | initial = float(line[-2]) 31 | f.write(line[-3] + ',' + line[-2] + '\n') 32 | 33 | # Creates a Panda dataframe with the results and adds the log returns 34 | df = pd.read_csv(fileName + '.csv', names=['P/L', 'balance']) 35 | df['pct_change'] = df.balance.pct_change() 36 | df['log_ret'] = np.log(df.balance) - np.log(df.balance.shift(1)) 37 | 38 | # Generates the number of simulations based on the number of trades squared 39 | simCount = int((len(df.index)*len(df.index)) * multiplier) 40 | if simCount > simLimit: 41 | simCount = simLimit 42 | 43 | # Runs the simulations 44 | mc = df['log_ret'].montecarlo(sims=simCount, bust=dd, goal=target) 45 | 46 | # Returns percentage statistics on the simulations 47 | print("===============") 48 | print(mc.stats) 49 | print("Profit:", initial*(1+mc.stats['min'])) 50 | print("Max Drawdown:", initial*(1+mc.stats['maxdd'])) 51 | print("Under ", str(dd*100) ,"% drawdown:", mc.stats['bust'] * 100) 52 | print("Over ", str(target*100) ,"% target:", mc.stats['goal'] * 100) 53 | print("===============") 54 | 55 | # Plots the MonteCarlo Simulation 56 | mc.plot(title="Log Returns at " + str(simCount) + " Simulations") 57 | --------------------------------------------------------------------------------