├── Chapter_01 └── Requierements.ipynb ├── Chapter_03 ├── Backtest.py └── Chapter_3_course.ipynb ├── Chapter_04 ├── Backtest.py └── Chapter_4_course.ipynb ├── Chapter_05 └── Chapter_5_course.ipynb ├── Chapter_06 ├── Backtest.py ├── Chapter_06_course.ipynb └── Data_csv.zip ├── Chapter_07 ├── Backtest.py ├── Chapter_7_coursre.ipynb ├── MT5.py └── Pairs_Trading_app.ipynb ├── Chapter_08 ├── ARIMA_app.ipynb ├── Backtest.py ├── Chapter_8_course.ipynb └── MT5.py ├── Chapter_09 ├── Backtest.py ├── Chapter_9_course.ipynb ├── Lin_Reg_App.ipynb ├── Log_Reg_App.ipynb ├── MT5.py ├── Models │ ├── EURUSD.joblib │ ├── NAS100.joblib │ ├── US2000.joblib │ ├── US500.joblib │ ├── USDCAD.joblib │ └── XAUUSD.joblib └── __pycache__ │ └── Backtest.cpython-39.pyc ├── Chapter_10 └── Chapter_10_course.ipynb ├── Chapter_11 ├── Backtest.py ├── Chapter_11_course.ipynb ├── MT5.py ├── Models │ ├── Alphabet_Inc_C_(GOOG.O).a_cla.joblib │ ├── Alphabet_Inc_C_(GOOG.O).a_reg.joblib │ ├── EURUSD.joblib │ ├── EURUSD_cla.joblib │ ├── EURUSD_reg.joblib │ ├── NAS100.joblib │ ├── NAS100_cla.joblib │ ├── NAS100_reg.joblib │ ├── US2000.joblib │ ├── US2000_cla.joblib │ ├── US2000_reg.joblib │ ├── US500.joblib │ ├── US500_cla.joblib │ ├── US500_reg.joblib │ ├── USDCAD.joblib │ ├── USDCAD_cla.joblib │ ├── USDCAD_reg.joblib │ ├── XAUUSD.joblib │ ├── XAUUSD_cla.joblib │ └── XAUUSD_reg.joblib ├── SVC_app.ipynb └── SVR_app.ipynb ├── Chapter_12 ├── Backtest.py ├── Chapter_12_course.ipynb ├── MT5.py ├── Models │ ├── Alphabet_Inc_C_(GOOG.O).a_cla.joblib │ ├── Alphabet_Inc_C_(GOOG.O).a_reg.joblib │ ├── EURUSD_cla.joblib │ ├── EURUSD_reg.joblib │ ├── NAS100_cla.joblib │ ├── NAS100_reg.joblib │ ├── US2000_cla.joblib │ ├── US2000_reg.joblib │ ├── US500_cla.joblib │ ├── US500_reg.joblib │ ├── USDCAD_cla.joblib │ ├── USDCAD_reg.joblib │ ├── XAUUSD_cla.joblib │ └── XAUUSD_reg.joblib ├── Tree_cla_App.ipynb ├── Tree_reg_App.ipynb └── __pycache__ │ └── Backtest.cpython-39.pyc ├── Chapter_13 ├── ANN_reg_app.ipynb ├── Backtest.py ├── Chapter_13_courses.ipynb ├── MT5.py ├── Models │ ├── ANN_reg_AAPL.a.data-00000-of-00001 │ ├── ANN_reg_AAPL.a.index │ └── checkpoint └── checkpoint ├── Chapter_14 ├── Backtest.py ├── Chapter_14_course.ipynb ├── MT5.py ├── Models │ ├── RNN_reg_Netflix_Inc_(NFLX.O).data-00000-of-00001 │ ├── RNN_reg_Netflix_Inc_(NFLX.O).index │ └── checkpoint ├── RNN_reg_Netflix_Inc_(NFLX.O).data-00000-of-00001 ├── RNN_reg_Netflix_Inc_(NFLX.O).index ├── RNN_reg_app.ipynb └── checkpoint ├── Chapter_15_ bonus ├── Backtest.py └── Chapter_15_course.ipynb ├── Chapter_16 ├── Backtest.py ├── Full Project.ipynb ├── Models │ ├── Bitcoin_reg.joblib │ ├── EURUSD_reg.joblib │ ├── NAS100_reg.joblib │ └── US2000_reg.joblib ├── Voting_project_app.ipynb └── quantreo │ └── portfolio.py └── README.md /Chapter_01/Requierements.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "id": "11f0e0f1", 7 | "metadata": {}, 8 | "outputs": [], 9 | "source": [ 10 | "# If you have any issues, try to use Python 3.7 \n", 11 | "import sys\n", 12 | "\n", 13 | "!{sys.executable} -m pip install numpy==1.19.2 --user\n", 14 | "!{sys.executable} -m pip install pandas==1.3.3 --user\n", 15 | "!{sys.executable} -m pip install scipy==1.6.2 --user\n", 16 | "!{sys.executable} -m pip install tensorflow==2.4.0 --user\n", 17 | "!{sys.executable} -m pip install tensorflow-probability==0.11.0 --user\n", 18 | "!{sys.executable} -m pip install scikit-learn==0.24.1 --user\n", 19 | "!{sys.executable} -m pip install statsmodels==0.12.2 --user\n", 20 | "!{sys.executable} -m pip install ta --user\n", 21 | "!{sys.executable} -m pip install datetime --user\n", 22 | "!{sys.executable} -m pip install yfinance --user\n", 23 | "!{sys.executable} -m pip install MetaTrader5 --user\n", 24 | "!{sys.executable} -m pip install TA-Lib --user" 25 | ] 26 | } 27 | ], 28 | "metadata": { 29 | "kernelspec": { 30 | "display_name": "Python 3 (ipykernel)", 31 | "language": "python", 32 | "name": "python3" 33 | }, 34 | "language_info": { 35 | "codemirror_mode": { 36 | "name": "ipython", 37 | "version": 3 38 | }, 39 | "file_extension": ".py", 40 | "mimetype": "text/x-python", 41 | "name": "python", 42 | "nbconvert_exporter": "python", 43 | "pygments_lexer": "ipython3", 44 | "version": "3.9.12" 45 | } 46 | }, 47 | "nbformat": 4, 48 | "nbformat_minor": 5 49 | } 50 | -------------------------------------------------------------------------------- /Chapter_03/Backtest.py: -------------------------------------------------------------------------------- 1 | def backtest_static_portfolio(weights, database, ben="^GSPC", timeframe=252, CR=False): 2 | """ 3 | ----------------------------------------------------------------------------- 4 | | Output: Beta CAPM metric | 5 | ----------------------------------------------------------------------------- 6 | | Inputs: - weights (type 1d array numpy): weights of the portfolio | 7 | | - database (type dataframe pandas): Returns of the asset | 8 | | - ben (type string): Name of the benchmark | 9 | | - timeframe (type int): annualization factor | 10 | ----------------------------------------------------------------------------- 11 | """ 12 | import pandas as pd 13 | import yfinance as yf 14 | import numpy as np 15 | from scipy.optimize import minimize 16 | import matplotlib.pyplot as plt 17 | plt.style.use('seaborn') 18 | 19 | 20 | # Compute the portfolio 21 | portfolio = np.multiply(database,np.transpose(weights)) 22 | portfolio = portfolio.sum(axis=1) 23 | columns = database.columns 24 | columns = [col for col in columns] 25 | 26 | ######################### COMPUTE THE BETA ################################## 27 | # Importation of benchmark 28 | benchmark = yf.download(ben)["Adj Close"].pct_change(1).dropna() 29 | 30 | # Concat the asset and the benchmark 31 | join = pd.concat((portfolio, benchmark), axis=1).dropna() 32 | 33 | # Covariance between the asset and the benchmark 34 | cov = np.cov(join, rowvar=False)[0][1] 35 | 36 | # Compute the variance of the benchmark 37 | var = np.cov(join, rowvar=False)[1][1] 38 | 39 | beta = cov/var 40 | 41 | 42 | ######################### COMPUTE THE ALPHA ################################# 43 | # Mean of returns for the asset 44 | mean_stock_return = join.iloc[:,0].mean()*timeframe 45 | 46 | # Mean of returns for the market 47 | mean_market_return = join.iloc[:,1].mean()*timeframe 48 | 49 | # Alpha 50 | alpha = mean_stock_return - beta*mean_market_return 51 | 52 | 53 | ######################### COMPUTE THE SHARPE ################################ 54 | mean = portfolio.mean() * timeframe 55 | std = portfolio.std() * np.sqrt(timeframe) 56 | Sharpe = mean/std 57 | 58 | 59 | ######################### COMPUTE THE SORTINO ############################### 60 | downward = portfolio[portfolio<0] 61 | std_downward = downward.std() * np.sqrt(timeframe) 62 | Sortino = mean/std_downward 63 | 64 | 65 | ######################### COMPUTE THE DRAWDOWN ############################### 66 | # Compute the cumulative product returns 67 | cum_rets = (portfolio+1).cumprod() 68 | 69 | # Compute the running max 70 | running_max = np.maximum.accumulate(cum_rets.dropna()) 71 | running_max[running_max < 1] = 1 72 | 73 | # Compute the drawdown 74 | drawdown = ((cum_rets)/running_max - 1) 75 | min_drawdon = -drawdown.min() 76 | 77 | 78 | ######################### COMPUTE THE VaR ################################## 79 | theta = 0.01 80 | # Number of simulations 81 | n = 100000 82 | 83 | # Find the values for theta% error threshold 84 | t = int(n*theta) 85 | 86 | # Create a vector with n simulations of the normal law 87 | vec = pd.DataFrame(np.random.normal(mean, std, size=(n,)), 88 | columns = ["Simulations"]) 89 | 90 | # Orderer the values and find the theta% value 91 | VaR = -vec.sort_values(by="Simulations").iloc[t].values[0] 92 | 93 | 94 | ######################### COMPUTE THE cVaR ################################# 95 | cVaR = -vec.sort_values(by="Simulations").iloc[0:t,:].mean().values[0] 96 | 97 | ######################### COMPUTE THE RC ################################### 98 | if CR: 99 | # Find the number of the asset in the portfolio 100 | l = len(weights) 101 | 102 | # Compute the risk contribution of each asset 103 | crs = [] 104 | for i in range(l): 105 | # Importation of benchmark 106 | benchmark = yf.download(ben)["Adj Close"].pct_change(1).dropna() 107 | 108 | # Concat the asset and the benchmark 109 | join = pd.concat((database.iloc[:,i], benchmark), axis=1).dropna() 110 | 111 | # Covariance between the asset and the benchmark 112 | cov = np.cov(join, rowvar=False)[0][1] 113 | 114 | # Compute the variance of the benchmark 115 | var = np.cov(join, rowvar=False)[1][1] 116 | beta_s = cov/var 117 | cr = beta_s * weights[i] 118 | crs.append(cr) 119 | crs_ = crs/np.sum(crs) # Normalizing by the sum of the risk contribution 120 | 121 | ######################### PLOT THE RESULTS ################################# 122 | print(f""" 123 | ----------------------------------------------------------------------------- 124 | Portfolio: {columns} 125 | ----------------------------------------------------------------------------- 126 | Beta: {np.round(beta, 3)} \t Alpha: {np.round(alpha*100, 2)} %\t \ 127 | Sharpe: {np.round(Sharpe, 3)} \t Sortino: {np.round(Sortino, 3)} 128 | ----------------------------------------------------------------------------- 129 | VaR: {np.round(VaR*100, 2)} %\t cVaR: {np.round(cVaR*100, 2)} % \t \ 130 | VaR/cVaR: {np.round(cVaR/VaR, 3)} \t drawdown: {np.round(min_drawdon*100, 2)} % 131 | ----------------------------------------------------------------------------- 132 | """) 133 | 134 | plt.figure(figsize=(15,8)) 135 | plt.plot(join.iloc[:,0].cumsum()*100, color="#035593", linewidth=3) 136 | plt.plot(join.iloc[:,1].cumsum()*100, color="#068C72", linewidth=3) 137 | plt.title("CUMULTATIVE RETURN", size=15) 138 | plt.ylabel("Cumulative return %", size=15) 139 | plt.xticks(size=15,fontweight="bold") 140 | plt.yticks(size=15,fontweight="bold") 141 | plt.legend(["Strategy", "Benchmark"]) 142 | plt.show() 143 | 144 | plt.figure(figsize=(15,8)) 145 | plt.fill_between(drawdown.index, drawdown*100, 0, color="#CE5151") 146 | plt.plot(drawdown.index,drawdown*100, color="#930303", linewidth=1.5) 147 | plt.title("DRAWDOWN", size=15) 148 | plt.ylabel("Drawdown %", size=15) 149 | plt.xticks(size=15,fontweight="bold") 150 | plt.yticks(size=15,fontweight="bold") 151 | plt.show() 152 | 153 | 154 | 155 | if CR: 156 | plt.figure(figsize=(15,8)) 157 | plt.scatter(columns, crs_, linewidth=3, color = "#B96553") 158 | plt.axhline(0, color="#53A7B9") 159 | plt.grid(axis="x") 160 | plt.title("RISK CONTRIBUTION PORTFOLIO", size=15) 161 | plt.xlabel("Assets") 162 | plt.ylabel("Risk contribution") 163 | plt.xticks(size=15,fontweight="bold") 164 | plt.yticks(size=15,fontweight="bold") 165 | plt.show() 166 | plt.show() 167 | 168 | 169 | def backtest_dynamic_portfolio(portfolio, ben="^GSPC", timeframe=252): 170 | """ 171 | ----------------------------------------------------------------------------- 172 | | Output: Beta CAPM metric | 173 | ----------------------------------------------------------------------------- 174 | | Inputs: - weights (type 1d array numpy): weights of the portfolio | 175 | | - database (type dataframe pandas): Returns of the asset | 176 | | - ben (type string): Name of the benchmark | 177 | | - timeframe (type int): annualization factor | 178 | ----------------------------------------------------------------------------- 179 | """ 180 | import pandas as pd 181 | import yfinance as yf 182 | import numpy as np 183 | from scipy.optimize import minimize 184 | import matplotlib.pyplot as plt 185 | plt.style.use('seaborn') 186 | import matplotlib as mpl 187 | import matplotlib.pyplot as plt 188 | 189 | from matplotlib import cycler 190 | 191 | 192 | font = {'weight' : 'bold', "size":"300"} 193 | plt.rc('font', **font) 194 | 195 | 196 | 197 | ######################### COMPUTE THE BETA ################################## 198 | # Importation of benchmark 199 | benchmark = yf.download(ben)["Adj Close"].pct_change(1).dropna() 200 | 201 | # Concat the asset and the benchmark 202 | join = pd.concat((portfolio, benchmark), axis=1).dropna() 203 | 204 | # Covariance between the asset and the benchmark 205 | cov = np.cov(join, rowvar=False)[0][1] 206 | 207 | # Compute the variance of the benchmark 208 | var = np.cov(join, rowvar=False)[1][1] 209 | 210 | beta = cov/var 211 | 212 | 213 | ######################### COMPUTE THE ALPHA ################################# 214 | # Mean of returns for the asset 215 | mean_stock_return = join.iloc[:,0].mean()*timeframe 216 | 217 | # Mean of returns for the market 218 | mean_market_return = join.iloc[:,1].mean()*timeframe 219 | 220 | # Alpha 221 | alpha = mean_stock_return - beta*mean_market_return 222 | 223 | 224 | ######################### COMPUTE THE SHARPE ################################ 225 | mean = portfolio.mean() * timeframe 226 | std = portfolio.std() * np.sqrt(timeframe) 227 | Sharpe = mean/std 228 | 229 | 230 | ######################### COMPUTE THE SORTINO ############################### 231 | downward = portfolio[portfolio<0] 232 | std_downward = downward.std() * np.sqrt(timeframe) 233 | Sortino = mean/std_downward 234 | 235 | 236 | ######################### COMPUTE THE DRAWDOWN ############################### 237 | # Compute the cumulative product returns 238 | cum_rets = (portfolio+1).cumprod() 239 | 240 | # Compute the running max 241 | running_max = np.maximum.accumulate(cum_rets.dropna()) 242 | running_max[running_max < 1] = 1 243 | 244 | # Compute the drawdown 245 | drawdown = ((cum_rets)/running_max - 1) 246 | min_drawdon = -drawdown.min() 247 | 248 | 249 | ######################### COMPUTE THE VaR ################################## 250 | theta = 0.01 251 | # Number of simulations 252 | n = 100000 253 | 254 | # Find the values for theta% error threshold 255 | t = int(n*theta) 256 | 257 | # Create a vector with n simulations of the normal law 258 | vec = pd.DataFrame(np.random.normal(mean, std, size=(n,)),columns = ["Simulations"]) 259 | 260 | # Orderer the values and find the theta% value 261 | VaR = -vec.sort_values(by="Simulations").iloc[t].values[0] 262 | 263 | 264 | ######################### COMPUTE THE cVaR ################################# 265 | cVaR = -vec.sort_values(by="Simulations").iloc[0:t,:].mean().values[0] 266 | 267 | 268 | ######################### PLOT THE RESULTS ################################# 269 | print(f""" 270 | ----------------------------------------------------------------------------- 271 | Beta: {np.round(beta, 3)} \t Alpha: {np.round(alpha*100, 2)} %\t \ 272 | Sharpe: {np.round(Sharpe, 3)} \t Sortino: {np.round(Sortino, 3)} 273 | ----------------------------------------------------------------------------- 274 | VaR: {np.round(VaR*100, 2)} %\t cVaR: {np.round(cVaR*100, 2)} % \t \ 275 | VaR/cVaR: {np.round(cVaR/VaR, 3)} \t drawdown: {np.round(min_drawdon*100, 2)} % 276 | -----------------------------------------------------------------------------""") 277 | 278 | 279 | plt.figure(figsize=(15,8)) 280 | plt.plot(join.iloc[:,0].cumsum()*100, color="#035593", linewidth=3) 281 | plt.plot(join.iloc[:,1].cumsum()*100, color="#068C72", linewidth=3) 282 | plt.title("CUMULTATIVE RETURN", size=15) 283 | plt.ylabel("Cumulative return %", size=15) 284 | plt.xticks(size=15,fontweight="bold") 285 | plt.yticks(size=15,fontweight="bold") 286 | plt.legend(["Strategy", "Benchmark"]) 287 | plt.show() 288 | 289 | plt.figure(figsize=(15,8)) 290 | plt.fill_between(drawdown.index, drawdown*100, 0, color="#CE5151") 291 | plt.plot(drawdown.index,drawdown*100, color="#930303", linewidth=3) 292 | plt.title("DRAWDOWN", size=15) 293 | plt.ylabel("Drawdown %", size=15) 294 | plt.xticks(size=15,fontweight="bold") 295 | plt.yticks(size=15,fontweight="bold") 296 | plt.show() 297 | 298 | 299 | -------------------------------------------------------------------------------- /Chapter_04/Backtest.py: -------------------------------------------------------------------------------- 1 | def backtest_static_portfolio(weights, database, ben="^GSPC", timeframe=252, CR=False): 2 | """ 3 | ----------------------------------------------------------------------------- 4 | | Output: Beta CAPM metric | 5 | ----------------------------------------------------------------------------- 6 | | Inputs: - weights (type 1d array numpy): weights of the portfolio | 7 | | - database (type dataframe pandas): Returns of the asset | 8 | | - ben (type string): Name of the benchmark | 9 | | - timeframe (type int): annualization factor | 10 | ----------------------------------------------------------------------------- 11 | """ 12 | import pandas as pd 13 | import yfinance as yf 14 | import numpy as np 15 | from scipy.optimize import minimize 16 | import matplotlib.pyplot as plt 17 | plt.style.use('seaborn') 18 | 19 | 20 | # Compute the portfolio 21 | portfolio = np.multiply(database,np.transpose(weights)) 22 | portfolio = portfolio.sum(axis=1) 23 | columns = database.columns 24 | columns = [col for col in columns] 25 | 26 | ######################### COMPUTE THE BETA ################################## 27 | # Importation of benchmark 28 | benchmark = yf.download(ben)["Adj Close"].pct_change(1).dropna() 29 | 30 | # Concat the asset and the benchmark 31 | join = pd.concat((portfolio, benchmark), axis=1).dropna() 32 | 33 | # Covariance between the asset and the benchmark 34 | cov = np.cov(join, rowvar=False)[0][1] 35 | 36 | # Compute the variance of the benchmark 37 | var = np.cov(join, rowvar=False)[1][1] 38 | 39 | beta = cov/var 40 | 41 | 42 | ######################### COMPUTE THE ALPHA ################################# 43 | # Mean of returns for the asset 44 | mean_stock_return = join.iloc[:,0].mean()*timeframe 45 | 46 | # Mean of returns for the market 47 | mean_market_return = join.iloc[:,1].mean()*timeframe 48 | 49 | # Alpha 50 | alpha = mean_stock_return - beta*mean_market_return 51 | 52 | 53 | ######################### COMPUTE THE SHARPE ################################ 54 | mean = portfolio.mean() * timeframe 55 | std = portfolio.std() * np.sqrt(timeframe) 56 | Sharpe = mean/std 57 | 58 | 59 | ######################### COMPUTE THE SORTINO ############################### 60 | downward = portfolio[portfolio<0] 61 | std_downward = downward.std() * np.sqrt(timeframe) 62 | Sortino = mean/std_downward 63 | 64 | 65 | ######################### COMPUTE THE DRAWDOWN ############################### 66 | # Compute the cumulative product returns 67 | cum_rets = (portfolio+1).cumprod() 68 | 69 | # Compute the running max 70 | running_max = np.maximum.accumulate(cum_rets.dropna()) 71 | running_max[running_max < 1] = 1 72 | 73 | # Compute the drawdown 74 | drawdown = ((cum_rets)/running_max - 1) 75 | min_drawdon = -drawdown.min() 76 | 77 | 78 | ######################### COMPUTE THE VaR ################################## 79 | theta = 0.01 80 | # Number of simulations 81 | n = 100000 82 | 83 | # Find the values for theta% error threshold 84 | t = int(n*theta) 85 | 86 | # Create a vector with n simulations of the normal law 87 | vec = pd.DataFrame(np.random.normal(mean, std, size=(n,)), 88 | columns = ["Simulations"]) 89 | 90 | # Orderer the values and find the theta% value 91 | VaR = -vec.sort_values(by="Simulations").iloc[t].values[0] 92 | 93 | 94 | ######################### COMPUTE THE cVaR ################################# 95 | cVaR = -vec.sort_values(by="Simulations").iloc[0:t,:].mean().values[0] 96 | 97 | ######################### COMPUTE THE RC ################################### 98 | if CR: 99 | # Find the number of the asset in the portfolio 100 | l = len(weights) 101 | 102 | # Compute the risk contribution of each asset 103 | crs = [] 104 | for i in range(l): 105 | # Importation of benchmark 106 | benchmark = yf.download(ben)["Adj Close"].pct_change(1).dropna() 107 | 108 | # Concat the asset and the benchmark 109 | join = pd.concat((database.iloc[:,i], benchmark), axis=1).dropna() 110 | 111 | # Covariance between the asset and the benchmark 112 | cov = np.cov(join, rowvar=False)[0][1] 113 | 114 | # Compute the variance of the benchmark 115 | var = np.cov(join, rowvar=False)[1][1] 116 | beta_s = cov/var 117 | cr = beta_s * weights[i] 118 | crs.append(cr) 119 | crs_ = crs/np.sum(crs) # Normalizing by the sum of the risk contribution 120 | 121 | ######################### PLOT THE RESULTS ################################# 122 | print(f""" 123 | ----------------------------------------------------------------------------- 124 | Portfolio: {columns} 125 | ----------------------------------------------------------------------------- 126 | Beta: {np.round(beta, 3)} \t Alpha: {np.round(alpha*100, 2)} %\t \ 127 | Sharpe: {np.round(Sharpe, 3)} \t Sortino: {np.round(Sortino, 3)} 128 | ----------------------------------------------------------------------------- 129 | VaR: {np.round(VaR*100, 2)} %\t cVaR: {np.round(cVaR*100, 2)} % \t \ 130 | VaR/cVaR: {np.round(cVaR/VaR, 3)} \t drawdown: {np.round(min_drawdon*100, 2)} % 131 | ----------------------------------------------------------------------------- 132 | """) 133 | 134 | plt.figure(figsize=(15,8)) 135 | plt.plot(join.iloc[:,0].cumsum()*100, color="#035593", linewidth=3) 136 | plt.plot(join.iloc[:,1].cumsum()*100, color="#068C72", linewidth=3) 137 | plt.title("CUMULTATIVE RETURN", size=15) 138 | plt.ylabel("Cumulative return %", size=15) 139 | plt.xticks(size=15,fontweight="bold") 140 | plt.yticks(size=15,fontweight="bold") 141 | plt.legend(["Strategy", "Benchmark"]) 142 | plt.savefig(f'Cum.svg', format='svg', dpi=1200) 143 | plt.show() 144 | 145 | plt.figure(figsize=(15,8)) 146 | plt.fill_between(drawdown.index, drawdown*100, 0, color="#CE5151") 147 | plt.plot(drawdown.index,drawdown*100, color="#930303", linewidth=1.5) 148 | plt.title("DRAWDOWN", size=15) 149 | plt.ylabel("Drawdown %", size=15) 150 | plt.xticks(size=15,fontweight="bold") 151 | plt.yticks(size=15,fontweight="bold") 152 | plt.savefig(f'drawdown.svg', format='svg', dpi=1200) 153 | plt.show() 154 | 155 | 156 | 157 | if CR: 158 | plt.figure(figsize=(15,8)) 159 | plt.scatter(columns, crs_, linewidth=3, color = "#B96553") 160 | plt.axhline(0, color="#53A7B9") 161 | plt.grid(axis="x") 162 | plt.title("RISK CONTRIBUTION PORTFOLIO", size=15) 163 | plt.xlabel("Assets") 164 | plt.ylabel("Risk contribution") 165 | plt.xticks(size=15,fontweight="bold") 166 | plt.yticks(size=15,fontweight="bold") 167 | plt.savefig(f'CR.svg', format='svg', dpi=1200) 168 | plt.show() 169 | plt.show() 170 | 171 | 172 | def backtest_dynamic_portfolio(portfolio, ben="^GSPC", timeframe=252): 173 | """ 174 | ----------------------------------------------------------------------------- 175 | | Output: Beta CAPM metric | 176 | ----------------------------------------------------------------------------- 177 | | Inputs: - weights (type 1d array numpy): weights of the portfolio | 178 | | - database (type dataframe pandas): Returns of the asset | 179 | | - ben (type string): Name of the benchmark | 180 | | - timeframe (type int): annualization factor | 181 | ----------------------------------------------------------------------------- 182 | """ 183 | import pandas as pd 184 | import yfinance as yf 185 | import numpy as np 186 | from scipy.optimize import minimize 187 | import matplotlib.pyplot as plt 188 | plt.style.use('seaborn') 189 | import matplotlib as mpl 190 | import matplotlib.pyplot as plt 191 | 192 | from matplotlib import cycler 193 | 194 | 195 | font = {'weight' : 'bold', "size":"300"} 196 | plt.rc('font', **font) 197 | 198 | 199 | 200 | ######################### COMPUTE THE BETA ################################## 201 | # Importation of benchmark 202 | benchmark = yf.download(ben)["Adj Close"].pct_change(1).dropna() 203 | 204 | # Concat the asset and the benchmark 205 | join = pd.concat((portfolio, benchmark), axis=1).dropna() 206 | 207 | # Covariance between the asset and the benchmark 208 | cov = np.cov(join, rowvar=False)[0][1] 209 | 210 | # Compute the variance of the benchmark 211 | var = np.cov(join, rowvar=False)[1][1] 212 | 213 | beta = cov/var 214 | 215 | 216 | ######################### COMPUTE THE ALPHA ################################# 217 | # Mean of returns for the asset 218 | mean_stock_return = join.iloc[:,0].mean()*timeframe 219 | 220 | # Mean of returns for the market 221 | mean_market_return = join.iloc[:,1].mean()*timeframe 222 | 223 | # Alpha 224 | alpha = mean_stock_return - beta*mean_market_return 225 | 226 | 227 | ######################### COMPUTE THE SHARPE ################################ 228 | mean = portfolio.mean() * timeframe 229 | std = portfolio.std() * np.sqrt(timeframe) 230 | Sharpe = mean/std 231 | 232 | 233 | ######################### COMPUTE THE SORTINO ############################### 234 | downward = portfolio[portfolio<0] 235 | std_downward = downward.std() * np.sqrt(timeframe) 236 | Sortino = mean/std_downward 237 | 238 | 239 | ######################### COMPUTE THE DRAWDOWN ############################### 240 | # Compute the cumulative product returns 241 | cum_rets = (portfolio+1).cumprod() 242 | 243 | # Compute the running max 244 | running_max = np.maximum.accumulate(cum_rets.dropna()) 245 | running_max[running_max < 1] = 1 246 | 247 | # Compute the drawdown 248 | drawdown = ((cum_rets)/running_max - 1) 249 | min_drawdon = -drawdown.min() 250 | 251 | 252 | ######################### COMPUTE THE VaR ################################## 253 | theta = 0.01 254 | # Number of simulations 255 | n = 100000 256 | 257 | # Find the values for theta% error threshold 258 | t = int(n*theta) 259 | 260 | # Create a vector with n simulations of the normal law 261 | vec = pd.DataFrame(np.random.normal(mean, std, size=(n,)),columns = ["Simulations"]) 262 | 263 | # Orderer the values and find the theta% value 264 | VaR = -vec.sort_values(by="Simulations").iloc[t].values[0] 265 | 266 | 267 | ######################### COMPUTE THE cVaR ################################# 268 | cVaR = -vec.sort_values(by="Simulations").iloc[0:t,:].mean().values[0] 269 | 270 | 271 | ######################### PLOT THE RESULTS ################################# 272 | print(f""" 273 | ----------------------------------------------------------------------------- 274 | Beta: {np.round(beta, 3)} \t Alpha: {np.round(alpha*100, 2)} %\t \ 275 | Sharpe: {np.round(Sharpe, 3)} \t Sortino: {np.round(Sortino, 3)} 276 | ----------------------------------------------------------------------------- 277 | VaR: {np.round(VaR*100, 2)} %\t cVaR: {np.round(cVaR*100, 2)} % \t \ 278 | VaR/cVaR: {np.round(cVaR/VaR, 3)} \t drawdown: {np.round(min_drawdon*100, 2)} % 279 | -----------------------------------------------------------------------------""") 280 | 281 | 282 | plt.figure(figsize=(15,8)) 283 | plt.plot(join.iloc[:,0].cumsum()*100, color="#035593", linewidth=3) 284 | plt.plot(join.iloc[:,1].cumsum()*100, color="#068C72", linewidth=3) 285 | plt.title("CUMULTATIVE RETURN", size=15) 286 | plt.ylabel("Cumulative return %", size=15) 287 | plt.xticks(size=15,fontweight="bold") 288 | plt.yticks(size=15,fontweight="bold") 289 | plt.legend(["Strategy", "Benchmark"]) 290 | plt.show() 291 | 292 | plt.figure(figsize=(15,8)) 293 | plt.fill_between(drawdown.index, drawdown*100, 0, color="#CE5151") 294 | plt.plot(drawdown.index,drawdown*100, color="#930303", linewidth=3) 295 | plt.title("DRAWDOWN", size=15) 296 | plt.ylabel("Drawdown %", size=15) 297 | plt.xticks(size=15,fontweight="bold") 298 | plt.yticks(size=15,fontweight="bold") 299 | plt.show() 300 | 301 | 302 | -------------------------------------------------------------------------------- /Chapter_06/Backtest.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import yfinance as yf 3 | import numpy as np 4 | from scipy.optimize import minimize 5 | import matplotlib.pyplot as plt 6 | plt.style.use('seaborn') 7 | import matplotlib as mpl 8 | 9 | 10 | def backtest_static_portfolio(weights, database, ben="^GSPC", timeframe=252, CR=False): 11 | """ 12 | ----------------------------------------------------------------------------- 13 | | Output: Beta CAPM metric | 14 | ----------------------------------------------------------------------------- 15 | | Inputs: - weights (type 1d array numpy): weights of the portfolio | 16 | | - database (type dataframe pandas): Returns of the asset | 17 | | - ben (type string): Name of the benchmark | 18 | | - timeframe (type int): annualization factor | 19 | ----------------------------------------------------------------------------- 20 | """ 21 | import pandas as pd 22 | import yfinance as yf 23 | import numpy as np 24 | from scipy.optimize import minimize 25 | import matplotlib.pyplot as plt 26 | plt.style.use('seaborn') 27 | 28 | 29 | # Compute the portfolio 30 | portfolio = np.multiply(database,np.transpose(weights)) 31 | portfolio = portfolio.sum(axis=1) 32 | columns = database.columns 33 | columns = [col for col in columns] 34 | 35 | ######################### COMPUTE THE BETA ################################## 36 | # Importation of benchmark 37 | benchmark = yf.download(ben)["Adj Close"].pct_change(1).dropna() 38 | 39 | # Concat the asset and the benchmark 40 | join = pd.concat((portfolio, benchmark), axis=1).dropna() 41 | 42 | # Covariance between the asset and the benchmark 43 | cov = np.cov(join, rowvar=False)[0][1] 44 | 45 | # Compute the variance of the benchmark 46 | var = np.cov(join, rowvar=False)[1][1] 47 | 48 | beta = cov/var 49 | 50 | 51 | ######################### COMPUTE THE ALPHA ################################# 52 | # Mean of returns for the asset 53 | mean_stock_return = join.iloc[:,0].mean()*timeframe 54 | 55 | # Mean of returns for the market 56 | mean_market_return = join.iloc[:,1].mean()*timeframe 57 | 58 | # Alpha 59 | alpha = mean_stock_return - beta*mean_market_return 60 | 61 | 62 | ######################### COMPUTE THE SHARPE ################################ 63 | mean = portfolio.mean() * timeframe 64 | std = portfolio.std() * np.sqrt(timeframe) 65 | Sharpe = mean/std 66 | 67 | 68 | ######################### COMPUTE THE SORTINO ############################### 69 | downward = portfolio[portfolio<0] 70 | std_downward = downward.std() * np.sqrt(timeframe) 71 | Sortino = mean/std_downward 72 | 73 | 74 | ######################### COMPUTE THE DRAWDOWN ############################### 75 | # Compute the cumulative product returns 76 | cum_rets = (portfolio+1).cumprod() 77 | 78 | # Compute the running max 79 | running_max = np.maximum.accumulate(cum_rets.dropna()) 80 | running_max[running_max < 1] = 1 81 | 82 | # Compute the drawdown 83 | drawdown = ((cum_rets)/running_max - 1) 84 | min_drawdon = -drawdown.min() 85 | 86 | 87 | ######################### COMPUTE THE VaR ################################## 88 | theta = 0.01 89 | # Number of simulations 90 | n = 100000 91 | 92 | # Find the values for theta% error threshold 93 | t = int(n*theta) 94 | 95 | # Create a vector with n simulations of the normal law 96 | vec = pd.DataFrame(np.random.normal(mean, std, size=(n,)), 97 | columns = ["Simulations"]) 98 | 99 | # Orderer the values and find the theta% value 100 | VaR = -vec.sort_values(by="Simulations").iloc[t].values[0] 101 | 102 | 103 | ######################### COMPUTE THE cVaR ################################# 104 | cVaR = -vec.sort_values(by="Simulations").iloc[0:t,:].mean().values[0] 105 | 106 | ######################### COMPUTE THE RC ################################### 107 | if CR: 108 | # Find the number of the asset in the portfolio 109 | l = len(weights) 110 | 111 | # Compute the risk contribution of each asset 112 | crs = [] 113 | for i in range(l): 114 | # Importation of benchmark 115 | benchmark = yf.download(ben)["Adj Close"].pct_change(1).dropna() 116 | 117 | # Concat the asset and the benchmark 118 | join = pd.concat((database.iloc[:,i], benchmark), axis=1).dropna() 119 | 120 | # Covariance between the asset and the benchmark 121 | cov = np.cov(join, rowvar=False)[0][1] 122 | 123 | # Compute the variance of the benchmark 124 | var = np.cov(join, rowvar=False)[1][1] 125 | beta_s = cov/var 126 | cr = beta_s * weights[i] 127 | crs.append(cr) 128 | crs_ = crs/np.sum(crs) # Normalizing by the sum of the risk contribution 129 | 130 | ######################### PLOT THE RESULTS ################################# 131 | print(f""" 132 | ----------------------------------------------------------------------------- 133 | Portfolio: {columns} 134 | ----------------------------------------------------------------------------- 135 | Beta: {np.round(beta, 3)} \t Alpha: {np.round(alpha*100, 2)} %\t \ 136 | Sharpe: {np.round(Sharpe, 3)} \t Sortino: {np.round(Sortino, 3)} 137 | ----------------------------------------------------------------------------- 138 | VaR: {np.round(VaR*100, 2)} %\t cVaR: {np.round(cVaR*100, 2)} % \t \ 139 | VaR/cVaR: {np.round(cVaR/VaR, 3)} \t drawdown: {np.round(min_drawdon*100, 2)} % 140 | ----------------------------------------------------------------------------- 141 | """) 142 | 143 | plt.figure(figsize=(15,8)) 144 | plt.plot(join.iloc[:,0].cumsum()*100, color="#035593", linewidth=3) 145 | plt.plot(join.iloc[:,1].cumsum()*100, color="#068C72", linewidth=3) 146 | plt.title("CUMULTATIVE RETURN", size=15) 147 | plt.ylabel("Cumulative return %", size=15) 148 | plt.xticks(size=15,fontweight="bold") 149 | plt.yticks(size=15,fontweight="bold") 150 | plt.legend(["Strategy", "Benchmark"]) 151 | plt.savefig(f'Cum.svg', format='svg', dpi=1200) 152 | plt.show() 153 | 154 | plt.figure(figsize=(15,8)) 155 | plt.fill_between(drawdown.index, drawdown*100, 0, color="#CE5151") 156 | plt.plot(drawdown.index,drawdown*100, color="#930303", linewidth=1.5) 157 | plt.title("DRAWDOWN", size=15) 158 | plt.ylabel("Drawdown %", size=15) 159 | plt.xticks(size=15,fontweight="bold") 160 | plt.yticks(size=15,fontweight="bold") 161 | plt.savefig(f'drawdown.svg', format='svg', dpi=1200) 162 | plt.show() 163 | 164 | 165 | 166 | if CR: 167 | plt.figure(figsize=(15,8)) 168 | plt.scatter(columns, crs_, linewidth=3, color = "#B96553") 169 | plt.axhline(0, color="#53A7B9") 170 | plt.grid(axis="x") 171 | plt.title("RISK CONTRIBUTION PORTFOLIO", size=15) 172 | plt.xlabel("Assets") 173 | plt.ylabel("Risk contribution") 174 | plt.xticks(size=15,fontweight="bold") 175 | plt.yticks(size=15,fontweight="bold") 176 | plt.savefig(f'CR.svg', format='svg', dpi=1200) 177 | plt.show() 178 | plt.show() 179 | 180 | 181 | def backtest_dynamic_portfolio(dfc, ben="^GSPC", timeframe=252): 182 | """ 183 | ----------------------------------------------------------------------------- 184 | | Output: Beta CAPM metric | 185 | ----------------------------------------------------------------------------- 186 | | Inputs: - weights (type 1d array numpy): weights of the portfolio | 187 | | - database (type dataframe pandas): Returns of the asset | 188 | | - ben (type string): Name of the benchmark | 189 | | - timeframe (type int): annualization factor | 190 | ----------------------------------------------------------------------------- 191 | """ 192 | import pandas as pd 193 | import yfinance as yf 194 | import numpy as np 195 | from scipy.optimize import minimize 196 | import matplotlib.pyplot as plt 197 | plt.style.use('seaborn') 198 | import matplotlib as mpl 199 | import matplotlib.pyplot as plt 200 | 201 | from matplotlib import cycler 202 | 203 | 204 | font = {'weight' : 'bold', "size":"300"} 205 | plt.rc('font', **font) 206 | 207 | 208 | # CREATE DAILY RETURNS 209 | portfolio = dfc["returns"] 210 | if portfolio.index.name != "Time": 211 | portfolio.index.name = "Time" 212 | 213 | 214 | portfolio = portfolio.reset_index(drop=False) 215 | portfolio.groupby(pd.Grouper(key='Time',freq='d')).sum() 216 | portfolio = portfolio.set_index("Time") 217 | ######################### COMPUTE THE BETA ################################## 218 | # Importation of benchmark 219 | benchmark = yf.download(ben)["Adj Close"].pct_change(1).dropna() 220 | 221 | # Concat the asset and the benchmark 222 | join = pd.concat((portfolio, benchmark), axis=1).dropna() 223 | 224 | # Covariance between the asset and the benchmark 225 | cov = np.cov(join, rowvar=False)[0][1] 226 | 227 | # Compute the variance of the benchmark 228 | var = np.cov(join, rowvar=False)[1][1] 229 | 230 | beta = cov/var 231 | 232 | 233 | ######################### COMPUTE THE ALPHA ################################# 234 | # Mean of returns for the asset 235 | mean_stock_return = join.iloc[:,0].mean()*timeframe 236 | 237 | # Mean of returns for the market 238 | mean_market_return = join.iloc[:,1].mean()*timeframe 239 | 240 | # Alpha 241 | alpha = mean_stock_return - beta*mean_market_return 242 | 243 | 244 | ######################### COMPUTE THE SHARPE ################################ 245 | mean = portfolio.mean() * timeframe 246 | std = portfolio.std() * np.sqrt(timeframe) 247 | Sharpe = mean/std 248 | 249 | 250 | ######################### COMPUTE THE SORTINO ############################### 251 | downward = portfolio[portfolio<0] 252 | std_downward = downward.std() * np.sqrt(timeframe) 253 | Sortino = mean/std_downward 254 | 255 | 256 | ######################### COMPUTE THE DRAWDOWN ############################### 257 | # Compute the cumulative product returns 258 | cum_rets = (portfolio+1).cumprod() 259 | 260 | # Compute the running max 261 | running_max = np.maximum.accumulate(cum_rets.dropna()) 262 | running_max[running_max < 1] = 1 263 | 264 | # Compute the drawdown 265 | drawdown = ((cum_rets)/running_max - 1) 266 | min_drawdon = -drawdown.min() 267 | 268 | 269 | ######################### COMPUTE THE VaR ################################## 270 | theta = 0.01 271 | # Number of simulations 272 | n = 100000 273 | 274 | # Find the values for theta% error threshold 275 | t = int(n*theta) 276 | 277 | # Create a vector with n simulations of the normal law 278 | vec = pd.DataFrame(np.random.normal(mean, std, size=(n,)),columns = ["Simulations"]) 279 | 280 | # Orderer the values and find the theta% value 281 | VaR = -vec.sort_values(by="Simulations").iloc[t].values[0] 282 | 283 | 284 | ######################### COMPUTE THE cVaR ################################# 285 | cVaR = -vec.sort_values(by="Simulations").iloc[0:t,:].mean().values[0] 286 | 287 | ######################### TIME UNDERWATER ################################## 288 | tuw = len(drawdown[drawdown<0]) / len(drawdown) 289 | 290 | ######################### PLOT THE RESULTS ################################# 291 | print(f""" 292 | ----------------------------------------------------------------------------- 293 | Beta: {np.round(beta, 3)} \t Alpha: {np.round(alpha*100, 2)} %\t \ 294 | Sharpe: {np.round(Sharpe, 3)} \t Sortino: {np.round(Sortino, 3)} 295 | ----------------------------------------------------------------------------- 296 | VaR: {np.round(VaR*100, 2)} %\t cVaR: {np.round(cVaR*100, 2)} % \t \ 297 | VaR/cVaR: {np.round(cVaR/VaR, 3)} \t drawdown: {np.round(min_drawdon*100, 2)} % 298 | -----------------------------------------------------------------------------""") 299 | 300 | 301 | plt.figure(figsize=(15,8)) 302 | plt.plot(join.iloc[:,0].cumsum()*100, color="#035593", linewidth=3) 303 | plt.plot(join.iloc[:,1].cumsum()*100, color="#068C72", linewidth=3) 304 | plt.title("CUMULTATIVE RETURN", size=15) 305 | plt.ylabel("Cumulative return %", size=15) 306 | plt.xticks(size=15,fontweight="bold") 307 | plt.yticks(size=15,fontweight="bold") 308 | plt.legend(["Strategy", "Benchmark"]) 309 | plt.show() 310 | 311 | plt.figure(figsize=(15,8)) 312 | plt.fill_between(drawdown.index, drawdown*100, 0, color="#CE5151") 313 | plt.plot(drawdown.index,drawdown*100, color="#930303", linewidth=3) 314 | plt.title("DRAWDOWN", size=15) 315 | plt.ylabel("Drawdown %", size=15) 316 | plt.xticks(size=15,fontweight="bold") 317 | plt.yticks(size=15,fontweight="bold") 318 | plt.show() 319 | 320 | def backtest_tpsl_portfolio(dfc, ben="^GSPC", timeframe=252): 321 | 322 | """ 323 | ----------------------------------------------------------------------------- 324 | | Output: Backtest | 325 | ----------------------------------------------------------------------------- 326 | | Inputs: - database (type dataframe pandas): data of the asset | 327 | | - ben (type string): Name of the benchmark | 328 | | - timeframe (type int): annualization factor | 329 | ----------------------------------------------------------------------------- 330 | """ 331 | # COMPUTE TRADE LIFETIME 332 | sum_dates = dfc["duration"] 333 | seconds = np.round(np.mean(list(sum_dates.loc[sum_dates!=0])).total_seconds()) 334 | minutes = seconds//60 335 | minutes_left = int(minutes%60) 336 | hours = int(minutes//60) 337 | 338 | # CREATE DAILY RETURNS 339 | portfolio = dfc["returns"] 340 | if portfolio.index.name != "Time": 341 | portfolio.index.name = "Time" 342 | 343 | 344 | portfolio = portfolio.reset_index(drop=False) 345 | portfolio.groupby(pd.Grouper(key='Time',freq='d')).sum() 346 | portfolio = portfolio.set_index("Time") 347 | 348 | ######################### COMPUTE THE BETA ################################## 349 | # Importation of benchmark 350 | benchmark = yf.download(ben)["Adj Close"].pct_change(1).dropna() 351 | 352 | # Concat the asset and the benchmark 353 | join = pd.concat((portfolio[["returns"]], benchmark), axis=1).dropna() 354 | 355 | # Covariance between the asset and the benchmark 356 | cov = np.cov(join, rowvar=False)[0][1] 357 | 358 | # Compute the variance of the benchmark 359 | var = np.cov(join, rowvar=False)[1][1] 360 | 361 | beta = cov/var 362 | 363 | ######################### COMPUTE THE ALPHA ################################# 364 | # Mean of returns for the asset 365 | mean_stock_return = join.iloc[:,0].mean()*timeframe 366 | 367 | # Mean of returns for the market 368 | mean_market_return = join.iloc[:,1].mean()*timeframe 369 | 370 | # Alpha 371 | alpha = mean_stock_return - beta*mean_market_return 372 | 373 | ######################### COMPUTE THE SHARPE ################################ 374 | mean = portfolio.mean() * np.sqrt(timeframe) 375 | std = portfolio.std() 376 | Sharpe = (mean/std)[0] 377 | 378 | 379 | ######################### COMPUTE THE SORTINO ############################### 380 | downward = portfolio[portfolio<0]* np.sqrt(timeframe) 381 | std_downward = downward.std() 382 | Sortino = (mean/std_downward)[0] 383 | 384 | 385 | ######################### COMPUTE THE DRAWDOWN ############################### 386 | # Compute the cumulative product returns 387 | coef_rets = (portfolio+1).cumprod() 388 | cum_rets = coef_rets-1 389 | 390 | # Compute the running max 391 | running_max = np.maximum.accumulate(coef_rets.dropna()) 392 | #running_max[running_max < 1] = 1 393 | 394 | # Compute the drawdown 395 | drawdown = ((coef_rets/running_max) - 1) 396 | min_drawdon = (-drawdown.min())[0] 397 | 398 | ######################### COMPUTE THE VaR ################################## 399 | theta = 0.01 400 | # Number of simulations 401 | n = 100000 402 | 403 | # Find the values for theta% error threshold 404 | t = int(n*theta) 405 | 406 | # Create a vector with n simulations of the normal law 407 | vec = pd.DataFrame(np.random.normal(mean, std, size=(n,)),columns = ["Simulations"]) 408 | 409 | # Orderer the values and find the theta% value 410 | VaR = -vec.sort_values(by="Simulations").iloc[t].values[0] 411 | 412 | 413 | ######################### COMPUTE THE cVaR ################################# 414 | cVaR = -vec.sort_values(by="Simulations").iloc[0:t,:].mean().values[0] 415 | 416 | ######################### TIME UNDERWATER ################################## 417 | tuw = len(drawdown[drawdown["returns"]<0]) / len(drawdown) 418 | 419 | ######################### PLOT THE RESULTS ################################# 420 | print(f""" 421 | ----------------------------------------------------------------------------- 422 | Beta: {np.round(beta, 3)} \t Alpha: {np.round(alpha*100, 2)} %\t \ 423 | AVERAGE TRADE LIFETIME: {hours}H {minutes_left}min 424 | ----------------------------------------------------------------------------- 425 | VaR: {np.round(VaR*100, 2)} %\t cVaR: {np.round(cVaR*100, 2)} % \t \ 426 | TUW: {np.round(tuw*100,2)}% \t drawdown: {np.round(min_drawdon*100, 2)} % 427 | -----------------------------------------------------------------------------""") 428 | 429 | plt.figure(figsize=(15,8)) 430 | plt.plot(cum_rets*100, color="#035593", linewidth=3) 431 | plt.plot(join.iloc[:,1].cumsum()*100, color="#068C72", linewidth=3) 432 | plt.title("CUMULTATIVE RETURN", size=15) 433 | plt.ylabel("Cumulative return %", size=15) 434 | plt.xticks(size=15,fontweight="bold") 435 | plt.yticks(size=15,fontweight="bold") 436 | plt.legend(["Strategy", "Benchmark"]) 437 | plt.show() 438 | 439 | plt.figure(figsize=(15,8)) 440 | plt.fill_between(drawdown.index, drawdown.iloc[:,0]*100, 0, color="#CE5151") 441 | plt.plot(drawdown.index,drawdown.iloc[:,0]*100, color="#930303", linewidth=3) 442 | 443 | 444 | plt.title("DRAWDOWN", size=15) 445 | plt.ylabel("Drawdown %", size=15) 446 | plt.xticks(size=15,fontweight="bold") 447 | plt.yticks(size=15,fontweight="bold") 448 | plt.show() 449 | 450 | 451 | 452 | 453 | -------------------------------------------------------------------------------- /Chapter_06/Data_csv.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_06/Data_csv.zip -------------------------------------------------------------------------------- /Chapter_07/MT5.py: -------------------------------------------------------------------------------- 1 | import warnings 2 | from datetime import datetime 3 | import pandas as pd 4 | import MetaTrader5 as mt5 5 | warnings.filterwarnings("ignore") 6 | mt5.initialize() 7 | 8 | 9 | class MT5: 10 | 11 | def get_data(symbol, n, timeframe=mt5.TIMEFRAME_D1): 12 | """ Function to import the data of the chosen symbol""" 13 | 14 | # Initialize the connection if there is not 15 | mt5.initialize() 16 | 17 | # Current date extract 18 | utc_from = datetime.now() 19 | 20 | # Import the data into a tuple 21 | rates = mt5.copy_rates_from(symbol, timeframe, utc_from, n) 22 | 23 | # Tuple to dataframe 24 | rates_frame = pd.DataFrame(rates) 25 | 26 | # Convert time in seconds into the datetime format 27 | rates_frame['time'] = pd.to_datetime(rates_frame['time'], unit='s') 28 | 29 | # Convert the column "time" in the right format 30 | rates_frame['time'] = pd.to_datetime(rates_frame['time'], format='%Y-%m-%d') 31 | 32 | # Set column time as the index of the dataframe 33 | rates_frame = rates_frame.set_index('time') 34 | return rates_frame 35 | 36 | def orders(symbol, lot, buy=True, id_position=None): 37 | """ Send the orders """ 38 | 39 | # Initialize the connection if there is not 40 | if mt5.initialize() == False: 41 | mt5.initialize() 42 | 43 | # Get filling mode 44 | filling_mode = mt5.symbol_info(symbol).filling_mode - 1 45 | 46 | # Take ask price 47 | ask_price = mt5.symbol_info_tick(symbol).ask 48 | 49 | # Take bid price 50 | bid_price = mt5.symbol_info_tick(symbol).bid 51 | 52 | # Take the point of the asset 53 | point = mt5.symbol_info(symbol).point 54 | 55 | deviation = 20 # mt5.getSlippage(symbol) 56 | # **************************** Open a trade ***************************** 57 | if id_position == None: 58 | 59 | # Buy order Parameters 60 | if buy: 61 | type_trade = mt5.ORDER_TYPE_BUY 62 | sl = ask_price*(1-0.01) 63 | tp = ask_price*(1+0.01) 64 | price = ask_price 65 | 66 | # Sell order Parameters 67 | else: 68 | type_trade = mt5.ORDER_TYPE_SELL 69 | sl = bid_price*(1+0.01) 70 | tp = bid_price*(1-0.01) 71 | price = bid_price 72 | 73 | # Open the trade 74 | request = { 75 | "action": mt5.TRADE_ACTION_DEAL, 76 | "symbol": symbol, 77 | "volume": lot, 78 | "type": type_trade, 79 | "price": price, 80 | "deviation": deviation, 81 | "sl": sl, 82 | "tp": tp, 83 | "magic": 234000, 84 | "comment": "python script order", 85 | "type_time": mt5.ORDER_TIME_GTC, 86 | "type_filling": filling_mode, 87 | } 88 | # send a trading request 89 | result = mt5.order_send(request) 90 | result_comment = result.comment 91 | 92 | # **************************** Close a trade ***************************** 93 | else: 94 | # Buy order Parameters 95 | if buy: 96 | type_trade = mt5.ORDER_TYPE_SELL 97 | price = bid_price 98 | 99 | # Sell order Parameters 100 | else: 101 | type_trade = mt5.ORDER_TYPE_BUY 102 | price = ask_price 103 | 104 | # Close the trade 105 | request = { 106 | "action": mt5.TRADE_ACTION_DEAL, 107 | "symbol": symbol, 108 | "volume": lot, 109 | "type": type_trade, 110 | "position": id_position, 111 | "price": price, 112 | "deviation": deviation, 113 | "magic": 234000, 114 | "comment": "python script order", 115 | "type_time": mt5.ORDER_TIME_GTC, 116 | "type_filling": filling_mode, 117 | } 118 | 119 | # send a trading request 120 | result = mt5.order_send(request) 121 | result_comment = result.comment 122 | return result.comment 123 | 124 | def resume(): 125 | """ Return the current positions. Position=0 --> Buy """ 126 | # Initialize the connection if there is not 127 | mt5.initialize() 128 | 129 | # Define the name of the columns that we will create 130 | colonnes = ["ticket", "position", "symbol", "volume"] 131 | 132 | # Go take the current open trades 133 | current = mt5.positions_get() 134 | 135 | # Create a empty dataframe 136 | summary = pd.DataFrame() 137 | 138 | # Loop to add each row in dataframe 139 | # (Can be ameliorate using of list of list) 140 | for element in current: 141 | element_pandas = pd.DataFrame([element.ticket, 142 | element.type, 143 | element.symbol, 144 | element.volume], 145 | index=colonnes).transpose() 146 | summary = pd.concat((summary, element_pandas), axis=0) 147 | 148 | return summary 149 | 150 | 151 | def run(symbol, long, short, lot): 152 | 153 | # Initialize the connection if there is not 154 | if mt5.initialize() == False: 155 | mt5.initialize() 156 | 157 | # Choose your symbol 158 | print("------------------------------------------------------------------") 159 | print("Date: ", datetime.now().strftime("%Y-%m-%d %H:%M:%S")) 160 | print("SYMBOL:", symbol) 161 | 162 | # Initialize the device 163 | current_open_positions = MT5.resume() 164 | # Buy or sell 165 | print(f"BUY: {long} \t SHORT: {short}") 166 | 167 | """ Close trade eventually """ 168 | # Extraction type trade 169 | try: 170 | position = current_open_positions.loc[current_open_positions["symbol"]==symbol].values[0][1] 171 | 172 | identifier = current_open_positions.loc[current_open_positions["symbol"]==symbol].values[0][0] 173 | except: 174 | position= None 175 | identifier = None 176 | 177 | print(f"POSITION: {position} \t ID: {identifier}") 178 | 179 | # Close trades 180 | if long==True and position==0: 181 | long=False 182 | 183 | elif long==False and position==0: 184 | res = MT5.orders(symbol, lot, buy=True, id_position=identifier) 185 | print(f"CLOSE LONG TRADE: {res}") 186 | 187 | elif short==True and position ==1: 188 | short=False 189 | 190 | elif short == False and position == 1: 191 | res = MT5.orders(symbol, lot, buy=False, id_position=identifier) 192 | print(f"CLOSE SHORT TRADE: {res}") 193 | 194 | else: 195 | pass 196 | 197 | 198 | """ Buy or short """ 199 | if long==True: 200 | 201 | res = MT5.orders(symbol, lot, buy=True, id_position=None) 202 | print(f"OPEN LONG TRADE: {res}") 203 | 204 | if short==True: 205 | res = MT5.orders(symbol, lot, buy=False, id_position=None) 206 | print(f"OPEN SHORT TRADE: {res}") 207 | 208 | print("------------------------------------------------------------------") 209 | 210 | def close_all_night(): 211 | result = MT5.resume() 212 | for i in range(len(result)): 213 | before = mt5.account_info().balance 214 | row = result.iloc[0+i:1+i,:] 215 | if row["position"][0]==0: 216 | res = MT5.orders(row["symbol"][0], row["volume"][0], buy=True, id_position=row["ticket"][0]) 217 | 218 | else: 219 | res = MT5.orders(row["symbol"][0], row["volume"][0], buy=False, id_position=row["ticket"][0]) -------------------------------------------------------------------------------- /Chapter_07/Pairs_Trading_app.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 2, 6 | "id": "54a86315", 7 | "metadata": {}, 8 | "outputs": [ 9 | { 10 | "name": "stdout", 11 | "output_type": "stream", 12 | "text": [ 13 | "------------------------------------------------------------------\n", 14 | "Date: 2021-09-24 07:20:37\n", 15 | "Balance: 981.84 USD, \tEquity: 981.84 USD, \tProfit: 0.0 USD\n", 16 | "------------------------------------------------------------------\n", 17 | "------------------------------------------------------------------\n", 18 | "Date: 2021-09-24 07:20:37\n", 19 | "SYMBOL: EURUSD\n", 20 | "BUY: False \t SHORT: False\n", 21 | "POSITION: None \t ID: None\n", 22 | "------------------------------------------------------------------\n", 23 | "------------------------------------------------------------------\n", 24 | "Date: 2021-09-24 07:20:37\n", 25 | "SYMBOL: EURGBP\n", 26 | "BUY: False \t SHORT: False\n", 27 | "POSITION: None \t ID: None\n", 28 | "------------------------------------------------------------------\n" 29 | ] 30 | }, 31 | { 32 | "ename": "KeyboardInterrupt", 33 | "evalue": "", 34 | "output_type": "error", 35 | "traceback": [ 36 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", 37 | "\u001b[1;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", 38 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 126\u001b[0m \u001b[1;34mf\"Buy: {buy}\\t\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 127\u001b[0m f\"Sell: {sell}\")\n\u001b[1;32m--> 128\u001b[1;33m \u001b[0mtime\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msleep\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", 39 | "\u001b[1;31mKeyboardInterrupt\u001b[0m: " 40 | ] 41 | } 42 | ], 43 | "source": [ 44 | "import warnings\n", 45 | "warnings.filterwarnings(\"ignore\")\n", 46 | "from MT5 import *\n", 47 | "import numpy as np\n", 48 | "import time\n", 49 | "import MetaTrader5 as mt5\n", 50 | "\n", 51 | "def pair_trading(ts1_symbol, ts2_symbol, pair=1):\n", 52 | " mt5.initialize()\n", 53 | "\n", 54 | " #Import the data\n", 55 | " ts1_data = MT5.get_data(ts1_symbol, 3500)[\"close\"]\n", 56 | " ts2_data = MT5.get_data(ts2_symbol, 3500)[\"close\"]\n", 57 | " train_set = pd.concat((ts1_data, ts2_data), axis=1).dropna()\n", 58 | " train_set.columns = [ts1_symbol, ts2_symbol]\n", 59 | " \n", 60 | " train_set[\"spread\"] = train_set[ts1_symbol]-train_set[ts2_symbol]\n", 61 | "\n", 62 | " train_set[\"z-score\"] = (train_set[\"spread\"] - train_set[\"spread\"].mean()) / train_set[\"spread\"].std()\n", 63 | "\n", 64 | " mean = train_set[\"z-score\"].mean()\n", 65 | " std_high = train_set[\"z-score\"].std() + mean\n", 66 | " std_low = train_set[\"z-score\"].std() - mean\n", 67 | " \n", 68 | " # Yersteday\n", 69 | " yts1 = train_set[ts1_symbol].values[-2]\n", 70 | " yts2 = train_set[ts2_symbol].values[-2]\n", 71 | " \n", 72 | " #Today\n", 73 | " pts1 = train_set[ts1_symbol].values[-1]\n", 74 | " pts2 = train_set[ts2_symbol].values[-1]\n", 75 | " \n", 76 | " \n", 77 | " # Today data\n", 78 | " spread = pts1 - pts2\n", 79 | " zscore = (spread-train_set[\"spread\"].mean())/train_set[\"spread\"].std()\n", 80 | " \n", 81 | " # Yersteday\n", 82 | " yspread = yts1 - yts2\n", 83 | " yzscore = (yspread-train_set[\"spread\"].mean())/train_set[\"spread\"].std()\n", 84 | " \n", 85 | " \n", 86 | " # TS1\n", 87 | " short_ts1 = False\n", 88 | " long_ts1 = False\n", 89 | " \n", 90 | " if zscore < std_high and yzscore > std_high:\n", 91 | " short_ts1 = True\n", 92 | " long_ts1 = False\n", 93 | " \n", 94 | " \n", 95 | " elif zscore > std_low and yzscore < std_low:\n", 96 | " short_ts1 = False\n", 97 | " long_ts1 = True\n", 98 | " \n", 99 | " else:\n", 100 | " pass\n", 101 | " \n", 102 | " #TS2\n", 103 | " short_ts2 = False\n", 104 | " long_ts2 = False\n", 105 | " \n", 106 | " if zscore < std_high and yzscore > std_high:\n", 107 | " short_ts2 = False\n", 108 | " long_ts2 = True\n", 109 | " \n", 110 | " elif zscore > std_low and yzscore < std_low:\n", 111 | " short_ts2 = True\n", 112 | " long_ts2 = False\n", 113 | " \n", 114 | " else:\n", 115 | " pass\n", 116 | " \n", 117 | " # Positions\n", 118 | " if pair == 1:\n", 119 | " buy,sell = long_ts1, short_ts1\n", 120 | " \n", 121 | " else:\n", 122 | " buy,sell = long_ts2, short_ts2\n", 123 | " \n", 124 | " return buy,sell\n", 125 | " \n", 126 | "\n", 127 | "# True = Live Trading and False = screener \n", 128 | "live = True\n", 129 | "\n", 130 | "\n", 131 | "if live:\n", 132 | " current_account_info = mt5.account_info()\n", 133 | " print(\"------------------------------------------------------------------\")\n", 134 | " print(\"Date: \", datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\"))\n", 135 | " print(f\"Balance: {current_account_info.balance} USD, \\t\"\n", 136 | " f\"Equity: {current_account_info.equity} USD, \\t\"\n", 137 | " f\"Profit: {current_account_info.profit} USD\")\n", 138 | " print(\"------------------------------------------------------------------\")\n", 139 | "\n", 140 | "\n", 141 | "# Initialize the inputs\n", 142 | "symbols = [\"EURUSD\", \"EURGBP\"]\n", 143 | "lots = [0.01, 0.01]\n", 144 | "pairs = [1,2]\n", 145 | "\n", 146 | "\n", 147 | "start = datetime.now().strftime(\"%H:%M:%S\") #\"23:59:59\"\n", 148 | "while True:\n", 149 | " # Verfication for launch\n", 150 | " if datetime.now().weekday() not in (5,6):\n", 151 | " is_time = datetime.now().strftime(\"%H:%M:%S\") == start \n", 152 | " else:\n", 153 | " is_time = False\n", 154 | "\n", 155 | " # Launch the algorithm\n", 156 | " if is_time:\n", 157 | " for symbol, lot, pair in zip(symbols, lots, pairs):\n", 158 | "\n", 159 | " # Create the signals\n", 160 | " buy, sell = pair_trading(symbols[0], symbols[1], pair=pair)\n", 161 | "\n", 162 | " # Run the algorithm\n", 163 | " if live:\n", 164 | " MT5.run(symbol, buy, sell,lot)\n", 165 | "\n", 166 | " else:\n", 167 | " print(f\"Symbol: {symbol}\\t\"\n", 168 | " f\"Buy: {buy}\\t\"\n", 169 | " f\"Sell: {sell}\")\n", 170 | " time.sleep(1)" 171 | ] 172 | } 173 | ], 174 | "metadata": { 175 | "kernelspec": { 176 | "display_name": "Python 3", 177 | "language": "python", 178 | "name": "python3" 179 | }, 180 | "language_info": { 181 | "codemirror_mode": { 182 | "name": "ipython", 183 | "version": 3 184 | }, 185 | "file_extension": ".py", 186 | "mimetype": "text/x-python", 187 | "name": "python", 188 | "nbconvert_exporter": "python", 189 | "pygments_lexer": "ipython3", 190 | "version": "3.8.8" 191 | } 192 | }, 193 | "nbformat": 4, 194 | "nbformat_minor": 5 195 | } 196 | -------------------------------------------------------------------------------- /Chapter_08/ARIMA_app.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 2, 6 | "id": "02f6bb6a", 7 | "metadata": {}, 8 | "outputs": [ 9 | { 10 | "name": "stdout", 11 | "output_type": "stream", 12 | "text": [ 13 | "------------------------------------------------------------------\n", 14 | "Date: 2021-09-24 07:19:25\n", 15 | "Balance: 981.88 USD, \tEquity: 981.88 USD, \tProfit: 0.0 USD\n", 16 | "------------------------------------------------------------------\n", 17 | "------------------------------------------------------------------\n", 18 | "Date: 2021-09-24 07:19:26\n", 19 | "SYMBOL: EURUSD\n", 20 | "BUY: False \t SHORT: True\n", 21 | "POSITION: 1 \t ID: 35527124\n", 22 | "------------------------------------------------------------------\n" 23 | ] 24 | }, 25 | { 26 | "ename": "KeyboardInterrupt", 27 | "evalue": "", 28 | "output_type": "error", 29 | "traceback": [ 30 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", 31 | "\u001b[1;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", 32 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 85\u001b[0m \u001b[1;34mf\"Buy: {buy}\\t\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 86\u001b[0m f\"Sell: {sell}\")\n\u001b[1;32m---> 87\u001b[1;33m \u001b[0mtime\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msleep\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", 33 | "\u001b[1;31mKeyboardInterrupt\u001b[0m: " 34 | ] 35 | } 36 | ], 37 | "source": [ 38 | "import warnings\n", 39 | "warnings.filterwarnings(\"ignore\")\n", 40 | "from MT5 import *\n", 41 | "import numpy as np\n", 42 | "import numpy as np\n", 43 | "import pandas as pd\n", 44 | "import warnings\n", 45 | "warnings.filterwarnings(\"ignore\")\n", 46 | "from statsmodels.tsa.arima_model import ARIMA\n", 47 | "import time\n", 48 | "\n", 49 | "def sig_ARIMA_model(symbol):\n", 50 | " \"\"\" Function for predict the value of tommorow using ARIMA model\"\"\"\n", 51 | "\n", 52 | " train_set = MT5.get_data(symbol, 3500)[\"close\"]\n", 53 | " \n", 54 | " # Define model\n", 55 | " p = 1\n", 56 | " q = 1\n", 57 | " d = 1\n", 58 | " model = ARIMA(train_set, order=(p, d, q))\n", 59 | "\n", 60 | " # Fit the model\n", 61 | " model_fit = model.fit(disp=0)\n", 62 | "\n", 63 | " # Make forecast\n", 64 | " forecast = model_fit.forecast()\n", 65 | "\n", 66 | " value_forecasted = forecast[0][0]\n", 67 | " buy = train_set.iloc[-1] < value_forecasted\n", 68 | " sell = not buy\n", 69 | " return buy, sell\n", 70 | "\n", 71 | "\n", 72 | "\n", 73 | "# True = Live Trading and False = Screener\n", 74 | "live = True\n", 75 | "\n", 76 | "if live:\n", 77 | " current_account_info = mt5.account_info()\n", 78 | " print(\"------------------------------------------------------------------\")\n", 79 | " print(\"Date: \", datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\"))\n", 80 | " print(f\"Balance: {current_account_info.balance} USD, \\t\"\n", 81 | " f\"Equity: {current_account_info.equity} USD, \\t\"\n", 82 | " f\"Profit: {current_account_info.profit} USD\")\n", 83 | " print(\"------------------------------------------------------------------\")\n", 84 | "\n", 85 | "\n", 86 | "\n", 87 | "\n", 88 | "info_order = {\n", 89 | " \"Euro vs USdollar\": [\"EURUSD\", 0.01]\n", 90 | "}\n", 91 | "\n", 92 | "\n", 93 | "start = datetime.now().strftime(\"%H:%M:%S\")\n", 94 | "while True:\n", 95 | " # Verfication for launch\n", 96 | " if datetime.now().weekday() not in (5,6):\n", 97 | " is_time = datetime.now().strftime(\"%H:%M:%S\") == start #\"23:59:59\"\n", 98 | " else:\n", 99 | " is_time = False\n", 100 | "\n", 101 | " \n", 102 | " # Launch the algorithm\n", 103 | " if is_time:\n", 104 | "\n", 105 | " # Open the trades\n", 106 | " for asset in info_order.keys():\n", 107 | "\n", 108 | " # Initialize the inputs\n", 109 | " symbol = info_order[asset][0]\n", 110 | " lot = info_order[asset][1]\n", 111 | "\n", 112 | " # Create the signals\n", 113 | " buy, sell = sig_ARIMA_model(symbol)\n", 114 | "\n", 115 | " # Run the algorithm\n", 116 | " if live:\n", 117 | " MT5.run(symbol, buy, sell,lot)\n", 118 | "\n", 119 | " else:\n", 120 | " print(f\"Symbol: {symbol}\\t\"\n", 121 | " f\"Buy: {buy}\\t\"\n", 122 | " f\"Sell: {sell}\")\n", 123 | " time.sleep(1)" 124 | ] 125 | }, 126 | { 127 | "cell_type": "code", 128 | "execution_count": null, 129 | "id": "36b4b91f", 130 | "metadata": {}, 131 | "outputs": [], 132 | "source": [] 133 | } 134 | ], 135 | "metadata": { 136 | "kernelspec": { 137 | "display_name": "Python 3", 138 | "language": "python", 139 | "name": "python3" 140 | }, 141 | "language_info": { 142 | "codemirror_mode": { 143 | "name": "ipython", 144 | "version": 3 145 | }, 146 | "file_extension": ".py", 147 | "mimetype": "text/x-python", 148 | "name": "python", 149 | "nbconvert_exporter": "python", 150 | "pygments_lexer": "ipython3", 151 | "version": "3.8.8" 152 | } 153 | }, 154 | "nbformat": 4, 155 | "nbformat_minor": 5 156 | } 157 | -------------------------------------------------------------------------------- /Chapter_08/MT5.py: -------------------------------------------------------------------------------- 1 | import warnings 2 | from datetime import datetime 3 | import pandas as pd 4 | import MetaTrader5 as mt5 5 | warnings.filterwarnings("ignore") 6 | mt5.initialize() 7 | 8 | 9 | class MT5: 10 | 11 | def get_data(symbol, n, timeframe=mt5.TIMEFRAME_D1): 12 | """ Function to import the data of the chosen symbol""" 13 | 14 | # Initialize the connection if there is not 15 | mt5.initialize() 16 | 17 | # Current date extract 18 | utc_from = datetime.now() 19 | 20 | # Import the data into a tuple 21 | rates = mt5.copy_rates_from(symbol, timeframe, utc_from, n) 22 | 23 | # Tuple to dataframe 24 | rates_frame = pd.DataFrame(rates) 25 | 26 | # Convert time in seconds into the datetime format 27 | rates_frame['time'] = pd.to_datetime(rates_frame['time'], unit='s') 28 | 29 | # Convert the column "time" in the right format 30 | rates_frame['time'] = pd.to_datetime(rates_frame['time'], format='%Y-%m-%d') 31 | 32 | # Set column time as the index of the dataframe 33 | rates_frame = rates_frame.set_index('time') 34 | return rates_frame 35 | 36 | def orders(symbol, lot, buy=True, id_position=None): 37 | """ Send the orders """ 38 | 39 | # Initialize the connection if there is not 40 | if mt5.initialize() == False: 41 | mt5.initialize() 42 | 43 | # Get filling mode 44 | filling_mode = mt5.symbol_info(symbol).filling_mode - 1 45 | 46 | # Take ask price 47 | ask_price = mt5.symbol_info_tick(symbol).ask 48 | 49 | # Take bid price 50 | bid_price = mt5.symbol_info_tick(symbol).bid 51 | 52 | # Take the point of the asset 53 | point = mt5.symbol_info(symbol).point 54 | 55 | deviation = 20 # mt5.getSlippage(symbol) 56 | # **************************** Open a trade ***************************** 57 | if id_position == None: 58 | 59 | # Buy order Parameters 60 | if buy: 61 | type_trade = mt5.ORDER_TYPE_BUY 62 | sl = ask_price*(1-0.01) 63 | tp = ask_price*(1+0.01) 64 | price = ask_price 65 | 66 | # Sell order Parameters 67 | else: 68 | type_trade = mt5.ORDER_TYPE_SELL 69 | sl = bid_price*(1+0.01) 70 | tp = bid_price*(1-0.01) 71 | price = bid_price 72 | 73 | # Open the trade 74 | request = { 75 | "action": mt5.TRADE_ACTION_DEAL, 76 | "symbol": symbol, 77 | "volume": lot, 78 | "type": type_trade, 79 | "price": price, 80 | "deviation": deviation, 81 | "sl": sl, 82 | "tp": tp, 83 | "magic": 234000, 84 | "comment": "python script order", 85 | "type_time": mt5.ORDER_TIME_GTC, 86 | "type_filling": filling_mode, 87 | } 88 | # send a trading request 89 | result = mt5.order_send(request) 90 | result_comment = result.comment 91 | 92 | # **************************** Close a trade ***************************** 93 | else: 94 | # Buy order Parameters 95 | if buy: 96 | type_trade = mt5.ORDER_TYPE_SELL 97 | price = bid_price 98 | 99 | # Sell order Parameters 100 | else: 101 | type_trade = mt5.ORDER_TYPE_BUY 102 | price = ask_price 103 | 104 | # Close the trade 105 | request = { 106 | "action": mt5.TRADE_ACTION_DEAL, 107 | "symbol": symbol, 108 | "volume": lot, 109 | "type": type_trade, 110 | "position": id_position, 111 | "price": price, 112 | "deviation": deviation, 113 | "magic": 234000, 114 | "comment": "python script order", 115 | "type_time": mt5.ORDER_TIME_GTC, 116 | "type_filling": filling_mode, 117 | } 118 | 119 | # send a trading request 120 | result = mt5.order_send(request) 121 | result_comment = result.comment 122 | return result.comment 123 | 124 | def resume(): 125 | """ Return the current positions. Position=0 --> Buy """ 126 | # Initialize the connection if there is not 127 | mt5.initialize() 128 | 129 | # Define the name of the columns that we will create 130 | colonnes = ["ticket", "position", "symbol", "volume"] 131 | 132 | # Go take the current open trades 133 | current = mt5.positions_get() 134 | 135 | # Create a empty dataframe 136 | summary = pd.DataFrame() 137 | 138 | # Loop to add each row in dataframe 139 | # (Can be ameliorate using of list of list) 140 | for element in current: 141 | element_pandas = pd.DataFrame([element.ticket, 142 | element.type, 143 | element.symbol, 144 | element.volume], 145 | index=colonnes).transpose() 146 | summary = pd.concat((summary, element_pandas), axis=0) 147 | 148 | return summary 149 | 150 | 151 | def run(symbol, long, short, lot): 152 | 153 | # Initialize the connection if there is not 154 | if mt5.initialize() == False: 155 | mt5.initialize() 156 | 157 | # Choose your symbol 158 | print("------------------------------------------------------------------") 159 | print("Date: ", datetime.now().strftime("%Y-%m-%d %H:%M:%S")) 160 | print("SYMBOL:", symbol) 161 | 162 | # Initialize the device 163 | current_open_positions = MT5.resume() 164 | # Buy or sell 165 | print(f"BUY: {long} \t SHORT: {short}") 166 | 167 | """ Close trade eventually """ 168 | # Extraction type trade 169 | try: 170 | position = current_open_positions.loc[current_open_positions["symbol"]==symbol].values[0][1] 171 | 172 | identifier = current_open_positions.loc[current_open_positions["symbol"]==symbol].values[0][0] 173 | except: 174 | position= None 175 | identifier = None 176 | 177 | print(f"POSITION: {position} \t ID: {identifier}") 178 | 179 | # Close trades 180 | if long==True and position==0: 181 | long=False 182 | 183 | elif long==False and position==0: 184 | res = MT5.orders(symbol, lot, buy=True, id_position=identifier) 185 | print(f"CLOSE LONG TRADE: {res}") 186 | 187 | elif short==True and position ==1: 188 | short=False 189 | 190 | elif short == False and position == 1: 191 | res = MT5.orders(symbol, lot, buy=False, id_position=identifier) 192 | print(f"CLOSE SHORT TRADE: {res}") 193 | 194 | else: 195 | pass 196 | 197 | 198 | """ Buy or short """ 199 | if long==True: 200 | 201 | res = MT5.orders(symbol, lot, buy=True, id_position=None) 202 | print(f"OPEN LONG TRADE: {res}") 203 | 204 | if short==True: 205 | res = MT5.orders(symbol, lot, buy=False, id_position=None) 206 | print(f"OPEN SHORT TRADE: {res}") 207 | 208 | print("------------------------------------------------------------------") 209 | 210 | def close_all_night(): 211 | result = MT5.resume() 212 | for i in range(len(result)): 213 | before = mt5.account_info().balance 214 | row = result.iloc[0+i:1+i,:] 215 | if row["position"][0]==0: 216 | res = MT5.orders(row["symbol"][0], row["volume"][0], buy=True, id_position=row["ticket"][0]) 217 | 218 | else: 219 | res = MT5.orders(row["symbol"][0], row["volume"][0], buy=False, id_position=row["ticket"][0]) -------------------------------------------------------------------------------- /Chapter_09/Lin_Reg_App.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "id": "0b67e05f", 7 | "metadata": {}, 8 | "outputs": [ 9 | { 10 | "name": "stdout", 11 | "output_type": "stream", 12 | "text": [ 13 | "------------------------------------------------------------------\n", 14 | "Date: 2021-09-24 07:18:24\n", 15 | "Balance: 982.03 USD, \tEquity: 982.03 USD, \tProfit: 0.0 USD\n", 16 | "------------------------------------------------------------------\n", 17 | "------------------------------------------------------------------\n", 18 | "Date: 2021-09-24 07:18:24\n", 19 | "SYMBOL: EURUSD\n", 20 | "BUY: False \t SHORT: True\n", 21 | "POSITION: None \t ID: None\n", 22 | "OPEN SHORT TRADE: Request executed\n", 23 | "------------------------------------------------------------------\n" 24 | ] 25 | }, 26 | { 27 | "ename": "KeyboardInterrupt", 28 | "evalue": "", 29 | "output_type": "error", 30 | "traceback": [ 31 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", 32 | "\u001b[1;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", 33 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 127\u001b[0m \u001b[1;34mf\"Buy: {buy}\\t\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 128\u001b[0m f\"Sell: {sell}\")\n\u001b[1;32m--> 129\u001b[1;33m \u001b[0mtime\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msleep\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", 34 | "\u001b[1;31mKeyboardInterrupt\u001b[0m: " 35 | ] 36 | } 37 | ], 38 | "source": [ 39 | "from MT5 import *\n", 40 | "import numpy as np\n", 41 | "import pandas as pd\n", 42 | "import warnings\n", 43 | "warnings.filterwarnings(\"ignore\")\n", 44 | "from sklearn.linear_model import LinearRegression\n", 45 | "import time\n", 46 | "import pickle\n", 47 | "from joblib import dump, load\n", 48 | "import os\n", 49 | "\n", 50 | "path = \"\" # Ex: C:/Desktop/Python_for_finance_and_algorithmic_trading/ChapterN/Models\n", 51 | "\n", 52 | "\n", 53 | "def create_model_weights(symbol):\n", 54 | " \"\"\" Weights for Linear regression on the percentage change\"\"\"\n", 55 | " # Import the data\n", 56 | " data = MT5.get_data(symbol, 3500)[[\"close\"]].pct_change(1)\n", 57 | " \n", 58 | " # Create new variable\n", 59 | " data[\"close t-1\"] = data[[\"close\"]].shift(1)\n", 60 | " \n", 61 | " # Split the data\n", 62 | " data = data.dropna()\n", 63 | " split = int(0.80*len(data))\n", 64 | " \n", 65 | " # Train set creation\n", 66 | " X_train = data[[\"close t-1\"]].iloc[:split]\n", 67 | " y_train = data[[\"close\"]].iloc[:split]\n", 68 | "\n", 69 | " # Test set creation\n", 70 | " X_test = data[[\"close t-1\"]].iloc[split:]\n", 71 | " \n", 72 | " # Create the model\n", 73 | " alg = LinearRegression()\n", 74 | "\n", 75 | " # Fit the model\n", 76 | " alg.fit(X_train, y_train)\n", 77 | " \n", 78 | " # Save the model\n", 79 | " alg_var = pickle.dumps(alg)\n", 80 | " alg_pickel = pickle.loads(alg_var)\n", 81 | "\n", 82 | " dump(alg_pickel ,os.path.join(path,f\"Models/{symbol}.joblib\"))\n", 83 | " \n", 84 | " \n", 85 | " \n", 86 | "\n", 87 | "def lin_reg_sig(symbol):\n", 88 | " \"\"\" Function for predict the value of tommorow using ARIMA model\"\"\"\n", 89 | " \n", 90 | " # Create the weights if there is not in the folder\n", 91 | " try:\n", 92 | " alg = load(os.path.join(path,f\"Models/{symbol}.joblib\"))\n", 93 | " except:\n", 94 | " create_model_weights(symbol)\n", 95 | " alg = load(os.path.join(path,f\"Models/{symbol}.joblib\"))\n", 96 | " \n", 97 | " # Take the lastest percentage of change \n", 98 | " data = MT5.get_data(symbol, 3500)[[\"close\"]].pct_change(1)\n", 99 | " X = data[\"close\"].iloc[-1].reshape(-1,1)\n", 100 | " \n", 101 | " \n", 102 | " # Find the signal\n", 103 | " prediction = alg.predict(X)\n", 104 | " buy = prediction[0][0] > 0\n", 105 | " sell = not buy\n", 106 | " \n", 107 | " \n", 108 | " return buy, sell\n", 109 | "\n", 110 | "\n", 111 | "\n", 112 | "# True = Live Trading and False = Screener\n", 113 | "live = True\n", 114 | "\n", 115 | "if live:\n", 116 | " current_account_info = mt5.account_info()\n", 117 | " print(\"------------------------------------------------------------------\")\n", 118 | " print(\"Date: \", datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\"))\n", 119 | " print(f\"Balance: {current_account_info.balance} USD, \\t\"\n", 120 | " f\"Equity: {current_account_info.equity} USD, \\t\"\n", 121 | " f\"Profit: {current_account_info.profit} USD\")\n", 122 | " print(\"------------------------------------------------------------------\")\n", 123 | "\n", 124 | "\n", 125 | "\n", 126 | "\n", 127 | "info_order = {\n", 128 | " \"Euro vs USdollar\": [\"EURUSD\", 0.01]\n", 129 | "}\n", 130 | "\n", 131 | "\n", 132 | "start = datetime.now().strftime(\"%H:%M:%S\")\n", 133 | "while True:\n", 134 | " # Verfication for launch\n", 135 | " if datetime.now().weekday() not in (5,6):\n", 136 | " is_time = datetime.now().strftime(\"%H:%M:%S\") == start #\"23:59:59\"\n", 137 | " else:\n", 138 | " is_time = False\n", 139 | "\n", 140 | " \n", 141 | " # Launch the algorithm\n", 142 | " if is_time:\n", 143 | "\n", 144 | " # Open the trades\n", 145 | " for asset in info_order.keys():\n", 146 | "\n", 147 | " # Initialize the inputs\n", 148 | " symbol = info_order[asset][0]\n", 149 | " lot = info_order[asset][1]\n", 150 | "\n", 151 | " # Create the signals\n", 152 | " buy, sell = lin_reg_sig(symbol)\n", 153 | "\n", 154 | " # Run the algorithm\n", 155 | " if live:\n", 156 | " MT5.run(symbol, buy, sell,lot)\n", 157 | "\n", 158 | " else:\n", 159 | " print(f\"Symbol: {symbol}\\t\"\n", 160 | " f\"Buy: {buy}\\t\"\n", 161 | " f\"Sell: {sell}\")\n", 162 | " time.sleep(1)" 163 | ] 164 | }, 165 | { 166 | "cell_type": "code", 167 | "execution_count": null, 168 | "id": "182b5b90", 169 | "metadata": {}, 170 | "outputs": [], 171 | "source": [] 172 | } 173 | ], 174 | "metadata": { 175 | "kernelspec": { 176 | "display_name": "Python 3", 177 | "language": "python", 178 | "name": "python3" 179 | }, 180 | "language_info": { 181 | "codemirror_mode": { 182 | "name": "ipython", 183 | "version": 3 184 | }, 185 | "file_extension": ".py", 186 | "mimetype": "text/x-python", 187 | "name": "python", 188 | "nbconvert_exporter": "python", 189 | "pygments_lexer": "ipython3", 190 | "version": "3.8.8" 191 | } 192 | }, 193 | "nbformat": 4, 194 | "nbformat_minor": 5 195 | } 196 | -------------------------------------------------------------------------------- /Chapter_09/Log_Reg_App.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 2, 6 | "id": "0b67e05f", 7 | "metadata": {}, 8 | "outputs": [ 9 | { 10 | "name": "stdout", 11 | "output_type": "stream", 12 | "text": [ 13 | "------------------------------------------------------------------\n", 14 | "Date: 2021-09-24 07:17:27\n", 15 | "Balance: 982.13 USD, \tEquity: 982.13 USD, \tProfit: 0.0 USD\n", 16 | "------------------------------------------------------------------\n", 17 | "------------------------------------------------------------------\n", 18 | "Date: 2021-09-24 07:17:27\n", 19 | "SYMBOL: EURUSD\n", 20 | "BUY: True \t SHORT: False\n", 21 | "POSITION: None \t ID: None\n", 22 | "OPEN LONG TRADE: Request executed\n", 23 | "------------------------------------------------------------------\n" 24 | ] 25 | }, 26 | { 27 | "ename": "KeyboardInterrupt", 28 | "evalue": "", 29 | "output_type": "error", 30 | "traceback": [ 31 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", 32 | "\u001b[1;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", 33 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 127\u001b[0m \u001b[1;34mf\"Buy: {buy}\\t\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 128\u001b[0m f\"Sell: {sell}\")\n\u001b[1;32m--> 129\u001b[1;33m \u001b[0mtime\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msleep\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", 34 | "\u001b[1;31mKeyboardInterrupt\u001b[0m: " 35 | ] 36 | } 37 | ], 38 | "source": [ 39 | "from MT5 import *\n", 40 | "import numpy as np\n", 41 | "import pandas as pd\n", 42 | "import warnings\n", 43 | "warnings.filterwarnings(\"ignore\")\n", 44 | "from sklearn.linear_model import LogisticRegression\n", 45 | "import time\n", 46 | "import pickle\n", 47 | "from joblib import dump, load\n", 48 | "import os\n", 49 | "\n", 50 | "path = \"\" # Ex: C:/Desktop/Python_for_finance_and_algorithmic_trading/ChapterN/Models\n", 51 | "\n", 52 | "\n", 53 | "def create_model_weights(symbol):\n", 54 | " \"\"\" Weights for Linear regression on the percentage change\"\"\"\n", 55 | " # Import the data\n", 56 | " data = MT5.get_data(symbol, 3500)[[\"close\"]].pct_change(1)\n", 57 | " \n", 58 | " # Create new variable\n", 59 | " data[\"close t-1\"] = data[[\"close\"]].shift(1)\n", 60 | " \n", 61 | " # Split the data\n", 62 | " data = data.dropna()\n", 63 | " split = int(0.80*len(data))\n", 64 | " \n", 65 | " # Train set creation\n", 66 | " X_train = data[[\"close t-1\"]].iloc[:split]\n", 67 | " y_train = np.round(data[[\"close\"]].iloc[:split]+0.5)\n", 68 | "\n", 69 | " # Create the model\n", 70 | " alg = LogisticRegression()\n", 71 | "\n", 72 | " # Fit the model\n", 73 | " alg.fit(X_train, y_train)\n", 74 | " \n", 75 | " # Save the model\n", 76 | " alg_var = pickle.dumps(alg)\n", 77 | " alg_pickel = pickle.loads(alg_var)\n", 78 | "\n", 79 | " dump(alg_pickel ,os.path.join(path,f\"Models/{symbol}.joblib\"))\n", 80 | " \n", 81 | " \n", 82 | " \n", 83 | "\n", 84 | "def lin_reg_sig(symbol):\n", 85 | " \"\"\" Function for predict the value of tommorow using ARIMA model\"\"\"\n", 86 | " \n", 87 | " # Create the weights if there is not in the folder\n", 88 | " try:\n", 89 | " alg = load(os.path.join(path,f\"Models/{symbol}.joblib\"))\n", 90 | " except:\n", 91 | " create_model_weights(symbol)\n", 92 | " alg = load(os.path.join(path,f\"Models/{symbol}.joblib\"))\n", 93 | " \n", 94 | " # Take the lastest percentage of change \n", 95 | " data = MT5.get_data(symbol, 3500)[[\"close\"]].pct_change(1)\n", 96 | " X = data[\"close\"].iloc[-1].reshape(-1,1)\n", 97 | " \n", 98 | " \n", 99 | " # Find the signal\n", 100 | " prediction = alg.predict(X)\n", 101 | " prediction = np.where(prediction==0, -1, 1)\n", 102 | " buy = prediction[0][0] > 0\n", 103 | " sell = not buy\n", 104 | " \n", 105 | " \n", 106 | " return buy, sell\n", 107 | "\n", 108 | "\n", 109 | "\n", 110 | "# True = Live Trading and False = Screener\n", 111 | "live = True\n", 112 | "\n", 113 | "\n", 114 | "if live:\n", 115 | " current_account_info = mt5.account_info()\n", 116 | " print(\"------------------------------------------------------------------\")\n", 117 | " print(\"Date: \", datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\"))\n", 118 | " print(f\"Balance: {current_account_info.balance} USD, \\t\"\n", 119 | " f\"Equity: {current_account_info.equity} USD, \\t\"\n", 120 | " f\"Profit: {current_account_info.profit} USD\")\n", 121 | " print(\"------------------------------------------------------------------\")\n", 122 | "\n", 123 | "\n", 124 | "\n", 125 | "\n", 126 | "info_order = {\n", 127 | " \"Euro vs USdollar\": [\"EURUSD\", 0.01]\n", 128 | "}\n", 129 | "\n", 130 | "\n", 131 | "start = datetime.now().strftime(\"%H:%M:%S\")\n", 132 | "while True:\n", 133 | " # Verfication for launch\n", 134 | " if datetime.now().weekday() not in (5,6):\n", 135 | " is_time = datetime.now().strftime(\"%H:%M:%S\") == start #\"23:59:59\"\n", 136 | " else:\n", 137 | " is_time = False\n", 138 | "\n", 139 | " \n", 140 | " # Launch the algorithm\n", 141 | " if is_time:\n", 142 | "\n", 143 | " # Open the trades\n", 144 | " for asset in info_order.keys():\n", 145 | "\n", 146 | " # Initialize the inputs\n", 147 | " symbol = info_order[asset][0]\n", 148 | " lot = info_order[asset][1]\n", 149 | "\n", 150 | " # Create the signals\n", 151 | " buy, sell = lin_reg_sig(symbol)\n", 152 | "\n", 153 | " # Run the algorithm\n", 154 | " if live:\n", 155 | " MT5.run(symbol, buy, sell,lot)\n", 156 | "\n", 157 | " else:\n", 158 | " print(f\"Symbol: {symbol}\\t\"\n", 159 | " f\"Buy: {buy}\\t\"\n", 160 | " f\"Sell: {sell}\")\n", 161 | " time.sleep(1)" 162 | ] 163 | }, 164 | { 165 | "cell_type": "code", 166 | "execution_count": null, 167 | "id": "182b5b90", 168 | "metadata": {}, 169 | "outputs": [], 170 | "source": [] 171 | } 172 | ], 173 | "metadata": { 174 | "kernelspec": { 175 | "display_name": "Python 3", 176 | "language": "python", 177 | "name": "python3" 178 | }, 179 | "language_info": { 180 | "codemirror_mode": { 181 | "name": "ipython", 182 | "version": 3 183 | }, 184 | "file_extension": ".py", 185 | "mimetype": "text/x-python", 186 | "name": "python", 187 | "nbconvert_exporter": "python", 188 | "pygments_lexer": "ipython3", 189 | "version": "3.8.8" 190 | } 191 | }, 192 | "nbformat": 4, 193 | "nbformat_minor": 5 194 | } 195 | -------------------------------------------------------------------------------- /Chapter_09/MT5.py: -------------------------------------------------------------------------------- 1 | import warnings 2 | from datetime import datetime 3 | import pandas as pd 4 | import MetaTrader5 as mt5 5 | warnings.filterwarnings("ignore") 6 | mt5.initialize() 7 | 8 | 9 | class MT5: 10 | 11 | def get_data(symbol, n, timeframe=mt5.TIMEFRAME_D1): 12 | """ Function to import the data of the chosen symbol""" 13 | 14 | # Initialize the connection if there is not 15 | mt5.initialize() 16 | 17 | # Current date extract 18 | utc_from = datetime.now() 19 | 20 | # Import the data into a tuple 21 | rates = mt5.copy_rates_from(symbol, timeframe, utc_from, n) 22 | 23 | # Tuple to dataframe 24 | rates_frame = pd.DataFrame(rates) 25 | 26 | # Convert time in seconds into the datetime format 27 | rates_frame['time'] = pd.to_datetime(rates_frame['time'], unit='s') 28 | 29 | # Convert the column "time" in the right format 30 | rates_frame['time'] = pd.to_datetime(rates_frame['time'], format='%Y-%m-%d') 31 | 32 | # Set column time as the index of the dataframe 33 | rates_frame = rates_frame.set_index('time') 34 | return rates_frame 35 | 36 | def orders(symbol, lot, buy=True, id_position=None): 37 | """ Send the orders """ 38 | 39 | # Initialize the connection if there is not 40 | if mt5.initialize() == False: 41 | mt5.initialize() 42 | 43 | # Get filling mode 44 | filling_mode = mt5.symbol_info(symbol).filling_mode - 1 45 | 46 | # Take ask price 47 | ask_price = mt5.symbol_info_tick(symbol).ask 48 | 49 | # Take bid price 50 | bid_price = mt5.symbol_info_tick(symbol).bid 51 | 52 | # Take the point of the asset 53 | point = mt5.symbol_info(symbol).point 54 | 55 | deviation = 20 # mt5.getSlippage(symbol) 56 | # **************************** Open a trade ***************************** 57 | if id_position == None: 58 | 59 | # Buy order Parameters 60 | if buy: 61 | type_trade = mt5.ORDER_TYPE_BUY 62 | sl = ask_price*(1-0.01) 63 | tp = ask_price*(1+0.01) 64 | price = ask_price 65 | 66 | # Sell order Parameters 67 | else: 68 | type_trade = mt5.ORDER_TYPE_SELL 69 | sl = bid_price*(1+0.01) 70 | tp = bid_price*(1-0.01) 71 | price = bid_price 72 | 73 | # Open the trade 74 | request = { 75 | "action": mt5.TRADE_ACTION_DEAL, 76 | "symbol": symbol, 77 | "volume": lot, 78 | "type": type_trade, 79 | "price": price, 80 | "deviation": deviation, 81 | "sl": sl, 82 | "tp": tp, 83 | "magic": 234000, 84 | "comment": "python script order", 85 | "type_time": mt5.ORDER_TIME_GTC, 86 | "type_filling": filling_mode, 87 | } 88 | # send a trading request 89 | result = mt5.order_send(request) 90 | result_comment = result.comment 91 | 92 | # **************************** Close a trade ***************************** 93 | else: 94 | # Buy order Parameters 95 | if buy: 96 | type_trade = mt5.ORDER_TYPE_SELL 97 | price = bid_price 98 | 99 | # Sell order Parameters 100 | else: 101 | type_trade = mt5.ORDER_TYPE_BUY 102 | price = ask_price 103 | 104 | # Close the trade 105 | request = { 106 | "action": mt5.TRADE_ACTION_DEAL, 107 | "symbol": symbol, 108 | "volume": lot, 109 | "type": type_trade, 110 | "position": id_position, 111 | "price": price, 112 | "deviation": deviation, 113 | "magic": 234000, 114 | "comment": "python script order", 115 | "type_time": mt5.ORDER_TIME_GTC, 116 | "type_filling": filling_mode, 117 | } 118 | 119 | # send a trading request 120 | result = mt5.order_send(request) 121 | result_comment = result.comment 122 | return result.comment 123 | 124 | def resume(): 125 | """ Return the current positions. Position=0 --> Buy """ 126 | # Initialize the connection if there is not 127 | mt5.initialize() 128 | 129 | # Define the name of the columns that we will create 130 | colonnes = ["ticket", "position", "symbol", "volume"] 131 | 132 | # Go take the current open trades 133 | current = mt5.positions_get() 134 | 135 | # Create a empty dataframe 136 | summary = pd.DataFrame() 137 | 138 | # Loop to add each row in dataframe 139 | # (Can be ameliorate using of list of list) 140 | for element in current: 141 | element_pandas = pd.DataFrame([element.ticket, 142 | element.type, 143 | element.symbol, 144 | element.volume], 145 | index=colonnes).transpose() 146 | summary = pd.concat((summary, element_pandas), axis=0) 147 | 148 | return summary 149 | 150 | 151 | def run(symbol, long, short, lot): 152 | 153 | # Initialize the connection if there is not 154 | if mt5.initialize() == False: 155 | mt5.initialize() 156 | 157 | # Choose your symbol 158 | print("------------------------------------------------------------------") 159 | print("Date: ", datetime.now().strftime("%Y-%m-%d %H:%M:%S")) 160 | print("SYMBOL:", symbol) 161 | 162 | # Initialize the device 163 | current_open_positions = MT5.resume() 164 | # Buy or sell 165 | print(f"BUY: {long} \t SHORT: {short}") 166 | 167 | """ Close trade eventually """ 168 | # Extraction type trade 169 | try: 170 | position = current_open_positions.loc[current_open_positions["symbol"]==symbol].values[0][1] 171 | 172 | identifier = current_open_positions.loc[current_open_positions["symbol"]==symbol].values[0][0] 173 | except: 174 | position= None 175 | identifier = None 176 | 177 | print(f"POSITION: {position} \t ID: {identifier}") 178 | 179 | # Close trades 180 | if long==True and position==0: 181 | long=False 182 | 183 | elif long==False and position==0: 184 | res = MT5.orders(symbol, lot, buy=True, id_position=identifier) 185 | print(f"CLOSE LONG TRADE: {res}") 186 | 187 | elif short==True and position ==1: 188 | short=False 189 | 190 | elif short == False and position == 1: 191 | res = MT5.orders(symbol, lot, buy=False, id_position=identifier) 192 | print(f"CLOSE SHORT TRADE: {res}") 193 | 194 | else: 195 | pass 196 | 197 | 198 | """ Buy or short """ 199 | if long==True: 200 | 201 | res = MT5.orders(symbol, lot, buy=True, id_position=None) 202 | print(f"OPEN LONG TRADE: {res}") 203 | 204 | if short==True: 205 | res = MT5.orders(symbol, lot, buy=False, id_position=None) 206 | print(f"OPEN SHORT TRADE: {res}") 207 | 208 | print("------------------------------------------------------------------") 209 | 210 | def close_all_night(): 211 | result = MT5.resume() 212 | for i in range(len(result)): 213 | before = mt5.account_info().balance 214 | row = result.iloc[0+i:1+i,:] 215 | if row["position"][0]==0: 216 | res = MT5.orders(row["symbol"][0], row["volume"][0], buy=True, id_position=row["ticket"][0]) 217 | 218 | else: 219 | res = MT5.orders(row["symbol"][0], row["volume"][0], buy=False, id_position=row["ticket"][0]) -------------------------------------------------------------------------------- /Chapter_09/Models/EURUSD.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_09/Models/EURUSD.joblib -------------------------------------------------------------------------------- /Chapter_09/Models/NAS100.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_09/Models/NAS100.joblib -------------------------------------------------------------------------------- /Chapter_09/Models/US2000.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_09/Models/US2000.joblib -------------------------------------------------------------------------------- /Chapter_09/Models/US500.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_09/Models/US500.joblib -------------------------------------------------------------------------------- /Chapter_09/Models/USDCAD.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_09/Models/USDCAD.joblib -------------------------------------------------------------------------------- /Chapter_09/Models/XAUUSD.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_09/Models/XAUUSD.joblib -------------------------------------------------------------------------------- /Chapter_09/__pycache__/Backtest.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_09/__pycache__/Backtest.cpython-39.pyc -------------------------------------------------------------------------------- /Chapter_11/MT5.py: -------------------------------------------------------------------------------- 1 | import warnings 2 | from datetime import datetime 3 | import pandas as pd 4 | import MetaTrader5 as mt5 5 | warnings.filterwarnings("ignore") 6 | mt5.initialize() 7 | 8 | 9 | class MT5: 10 | 11 | def get_data(symbol, n, timeframe=mt5.TIMEFRAME_D1): 12 | """ Function to import the data of the chosen symbol""" 13 | 14 | # Initialize the connection if there is not 15 | mt5.initialize() 16 | 17 | # Current date extract 18 | utc_from = datetime.now() 19 | 20 | # Import the data into a tuple 21 | rates = mt5.copy_rates_from(symbol, timeframe, utc_from, n) 22 | 23 | # Tuple to dataframe 24 | rates_frame = pd.DataFrame(rates) 25 | 26 | # Convert time in seconds into the datetime format 27 | rates_frame['time'] = pd.to_datetime(rates_frame['time'], unit='s') 28 | 29 | # Convert the column "time" in the right format 30 | rates_frame['time'] = pd.to_datetime(rates_frame['time'], format='%Y-%m-%d') 31 | 32 | # Set column time as the index of the dataframe 33 | rates_frame = rates_frame.set_index('time') 34 | return rates_frame 35 | 36 | def orders(symbol, lot, buy=True, id_position=None): 37 | """ Send the orders """ 38 | 39 | # Initialize the connection if there is not 40 | if mt5.initialize() == False: 41 | mt5.initialize() 42 | 43 | # Get filling mode 44 | filling_mode = mt5.symbol_info(symbol).filling_mode - 1 45 | 46 | # Take ask price 47 | ask_price = mt5.symbol_info_tick(symbol).ask 48 | 49 | # Take bid price 50 | bid_price = mt5.symbol_info_tick(symbol).bid 51 | 52 | # Take the point of the asset 53 | point = mt5.symbol_info(symbol).point 54 | 55 | deviation = 20 # mt5.getSlippage(symbol) 56 | # **************************** Open a trade ***************************** 57 | if id_position == None: 58 | 59 | # Buy order Parameters 60 | if buy: 61 | type_trade = mt5.ORDER_TYPE_BUY 62 | sl = ask_price*(1-0.01) 63 | tp = ask_price*(1+0.01) 64 | price = ask_price 65 | 66 | # Sell order Parameters 67 | else: 68 | type_trade = mt5.ORDER_TYPE_SELL 69 | sl = bid_price*(1+0.01) 70 | tp = bid_price*(1-0.01) 71 | price = bid_price 72 | 73 | # Open the trade 74 | request = { 75 | "action": mt5.TRADE_ACTION_DEAL, 76 | "symbol": symbol, 77 | "volume": lot, 78 | "type": type_trade, 79 | "price": price, 80 | "deviation": deviation, 81 | "sl": sl, 82 | "tp": tp, 83 | "magic": 234000, 84 | "comment": "python script order", 85 | "type_time": mt5.ORDER_TIME_GTC, 86 | "type_filling": filling_mode, 87 | } 88 | # send a trading request 89 | result = mt5.order_send(request) 90 | result_comment = result.comment 91 | 92 | # **************************** Close a trade ***************************** 93 | else: 94 | # Buy order Parameters 95 | if buy: 96 | type_trade = mt5.ORDER_TYPE_SELL 97 | price = bid_price 98 | 99 | # Sell order Parameters 100 | else: 101 | type_trade = mt5.ORDER_TYPE_BUY 102 | price = ask_price 103 | 104 | # Close the trade 105 | request = { 106 | "action": mt5.TRADE_ACTION_DEAL, 107 | "symbol": symbol, 108 | "volume": lot, 109 | "type": type_trade, 110 | "position": id_position, 111 | "price": price, 112 | "deviation": deviation, 113 | "magic": 234000, 114 | "comment": "python script order", 115 | "type_time": mt5.ORDER_TIME_GTC, 116 | "type_filling": filling_mode, 117 | } 118 | 119 | # send a trading request 120 | result = mt5.order_send(request) 121 | result_comment = result.comment 122 | return result.comment 123 | 124 | def resume(): 125 | """ Return the current positions. Position=0 --> Buy """ 126 | # Initialize the connection if there is not 127 | mt5.initialize() 128 | 129 | # Define the name of the columns that we will create 130 | colonnes = ["ticket", "position", "symbol", "volume"] 131 | 132 | # Go take the current open trades 133 | current = mt5.positions_get() 134 | 135 | # Create a empty dataframe 136 | summary = pd.DataFrame() 137 | 138 | # Loop to add each row in dataframe 139 | # (Can be ameliorate using of list of list) 140 | for element in current: 141 | element_pandas = pd.DataFrame([element.ticket, 142 | element.type, 143 | element.symbol, 144 | element.volume], 145 | index=colonnes).transpose() 146 | summary = pd.concat((summary, element_pandas), axis=0) 147 | 148 | return summary 149 | 150 | 151 | def run(symbol, long, short, lot): 152 | 153 | # Initialize the connection if there is not 154 | if mt5.initialize() == False: 155 | mt5.initialize() 156 | 157 | # Choose your symbol 158 | print("------------------------------------------------------------------") 159 | print("Date: ", datetime.now().strftime("%Y-%m-%d %H:%M:%S")) 160 | print("SYMBOL:", symbol) 161 | 162 | # Initialize the device 163 | current_open_positions = MT5.resume() 164 | # Buy or sell 165 | print(f"BUY: {long} \t SHORT: {short}") 166 | 167 | """ Close trade eventually """ 168 | # Extraction type trade 169 | try: 170 | position = current_open_positions.loc[current_open_positions["symbol"]==symbol].values[0][1] 171 | 172 | identifier = current_open_positions.loc[current_open_positions["symbol"]==symbol].values[0][0] 173 | except: 174 | position= None 175 | identifier = None 176 | 177 | print(f"POSITION: {position} \t ID: {identifier}") 178 | 179 | # Close trades 180 | if long==True and position==0: 181 | long=False 182 | 183 | elif long==False and position==0: 184 | res = MT5.orders(symbol, lot, buy=True, id_position=identifier) 185 | print(f"CLOSE LONG TRADE: {res}") 186 | 187 | elif short==True and position ==1: 188 | short=False 189 | 190 | elif short == False and position == 1: 191 | res = MT5.orders(symbol, lot, buy=False, id_position=identifier) 192 | print(f"CLOSE SHORT TRADE: {res}") 193 | 194 | else: 195 | pass 196 | 197 | 198 | """ Buy or short """ 199 | if long==True: 200 | 201 | res = MT5.orders(symbol, lot, buy=True, id_position=None) 202 | print(f"OPEN LONG TRADE: {res}") 203 | 204 | if short==True: 205 | res = MT5.orders(symbol, lot, buy=False, id_position=None) 206 | print(f"OPEN SHORT TRADE: {res}") 207 | 208 | print("------------------------------------------------------------------") 209 | 210 | def close_all_night(): 211 | result = MT5.resume() 212 | for i in range(len(result)): 213 | before = mt5.account_info().balance 214 | row = result.iloc[0+i:1+i,:] 215 | if row["position"][0]==0: 216 | res = MT5.orders(row["symbol"][0], row["volume"][0], buy=True, id_position=row["ticket"][0]) 217 | 218 | else: 219 | res = MT5.orders(row["symbol"][0], row["volume"][0], buy=False, id_position=row["ticket"][0]) -------------------------------------------------------------------------------- /Chapter_11/Models/Alphabet_Inc_C_(GOOG.O).a_cla.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_11/Models/Alphabet_Inc_C_(GOOG.O).a_cla.joblib -------------------------------------------------------------------------------- /Chapter_11/Models/Alphabet_Inc_C_(GOOG.O).a_reg.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_11/Models/Alphabet_Inc_C_(GOOG.O).a_reg.joblib -------------------------------------------------------------------------------- /Chapter_11/Models/EURUSD.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_11/Models/EURUSD.joblib -------------------------------------------------------------------------------- /Chapter_11/Models/EURUSD_cla.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_11/Models/EURUSD_cla.joblib -------------------------------------------------------------------------------- /Chapter_11/Models/EURUSD_reg.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_11/Models/EURUSD_reg.joblib -------------------------------------------------------------------------------- /Chapter_11/Models/NAS100.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_11/Models/NAS100.joblib -------------------------------------------------------------------------------- /Chapter_11/Models/NAS100_cla.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_11/Models/NAS100_cla.joblib -------------------------------------------------------------------------------- /Chapter_11/Models/NAS100_reg.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_11/Models/NAS100_reg.joblib -------------------------------------------------------------------------------- /Chapter_11/Models/US2000.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_11/Models/US2000.joblib -------------------------------------------------------------------------------- /Chapter_11/Models/US2000_cla.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_11/Models/US2000_cla.joblib -------------------------------------------------------------------------------- /Chapter_11/Models/US2000_reg.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_11/Models/US2000_reg.joblib -------------------------------------------------------------------------------- /Chapter_11/Models/US500.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_11/Models/US500.joblib -------------------------------------------------------------------------------- /Chapter_11/Models/US500_cla.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_11/Models/US500_cla.joblib -------------------------------------------------------------------------------- /Chapter_11/Models/US500_reg.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_11/Models/US500_reg.joblib -------------------------------------------------------------------------------- /Chapter_11/Models/USDCAD.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_11/Models/USDCAD.joblib -------------------------------------------------------------------------------- /Chapter_11/Models/USDCAD_cla.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_11/Models/USDCAD_cla.joblib -------------------------------------------------------------------------------- /Chapter_11/Models/USDCAD_reg.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_11/Models/USDCAD_reg.joblib -------------------------------------------------------------------------------- /Chapter_11/Models/XAUUSD.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_11/Models/XAUUSD.joblib -------------------------------------------------------------------------------- /Chapter_11/Models/XAUUSD_cla.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_11/Models/XAUUSD_cla.joblib -------------------------------------------------------------------------------- /Chapter_11/Models/XAUUSD_reg.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_11/Models/XAUUSD_reg.joblib -------------------------------------------------------------------------------- /Chapter_11/SVC_app.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 2, 6 | "id": "868c87fd", 7 | "metadata": {}, 8 | "outputs": [ 9 | { 10 | "name": "stdout", 11 | "output_type": "stream", 12 | "text": [ 13 | "------------------------------------------------------------------\n", 14 | "Date: 2021-09-24 07:15:20\n", 15 | "Balance: 982.13 USD, \tEquity: 982.13 USD, \tProfit: 0.0 USD\n", 16 | "------------------------------------------------------------------\n", 17 | "------------------------------------------------------------------\n", 18 | "Date: 2021-09-24 07:15:20\n", 19 | "SYMBOL: Alphabet_Inc_C_(GOOG.O).a\n", 20 | "BUY: True \t SHORT: False\n", 21 | "POSITION: None \t ID: None\n", 22 | "OPEN LONG TRADE: Market closed\n", 23 | "------------------------------------------------------------------\n" 24 | ] 25 | }, 26 | { 27 | "ename": "KeyboardInterrupt", 28 | "evalue": "", 29 | "output_type": "error", 30 | "traceback": [ 31 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", 32 | "\u001b[1;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", 33 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 153\u001b[0m \u001b[1;34mf\"Buy: {buy}\\t\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 154\u001b[0m f\"Sell: {sell}\")\n\u001b[1;32m--> 155\u001b[1;33m \u001b[0mtime\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msleep\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", 34 | "\u001b[1;31mKeyboardInterrupt\u001b[0m: " 35 | ] 36 | } 37 | ], 38 | "source": [ 39 | "from MT5 import *\n", 40 | "import numpy as np\n", 41 | "import pandas as pd\n", 42 | "import warnings\n", 43 | "warnings.filterwarnings(\"ignore\")\n", 44 | "from sklearn.svm import SVC\n", 45 | "import time\n", 46 | "import pickle\n", 47 | "from joblib import dump, load\n", 48 | "import os\n", 49 | "from sklearn.preprocessing import StandardScaler\n", 50 | "\n", 51 | "path = \"\" # Ex: C:/Desktop/Python_for_finance_and_algorithmic_trading/ChapterN/Models\n", 52 | "\n", 53 | "\n", 54 | "def create_model_weights(symbol):\n", 55 | " \"\"\" Weights for Linear regression on the percentage change\"\"\"\n", 56 | " # Import the data\n", 57 | " data = MT5.get_data(symbol, 3500)[[\"close\"]].pct_change(1)\n", 58 | " \n", 59 | " # Create new variable\n", 60 | " data.columns = [\"returns\"]\n", 61 | "\n", 62 | " # Features engeeniring\n", 63 | " data[\"returns t-1\"] = data[[\"returns\"]].shift(1)\n", 64 | "\n", 65 | " # Mean of returns\n", 66 | " data[\"mean returns 15\"] = data[[\"returns\"]].rolling(15).mean().shift(1)\n", 67 | " data[\"mean returns 60\"] = data[[\"returns\"]].rolling(60).mean().shift(1)\n", 68 | "\n", 69 | " # Volatility of returns\n", 70 | " data[\"volatility returns 15\"] = data[[\"returns\"]].rolling(15).std().shift(1)\n", 71 | " data[\"volatility returns 60\"] = data[[\"returns\"]].rolling(60).std().shift(1)\n", 72 | " \n", 73 | " # Split the data\n", 74 | " data = data.dropna()\n", 75 | " split = int(0.80*len(data))\n", 76 | " \n", 77 | " # Train set creation\n", 78 | " X_train = data[[\"returns t-1\", \"mean returns 15\", \"mean returns 60\",\n", 79 | " \"volatility returns 15\",\n", 80 | " \"volatility returns 60\"]].iloc[:split]\n", 81 | " y_train = np.round(data[[\"returns\"]].iloc[:split]+0.5)\n", 82 | " \n", 83 | " # Create the model\n", 84 | " alg = SVC()\n", 85 | "\n", 86 | " # Fit the model\n", 87 | " alg.fit(X_train, y_train)\n", 88 | " \n", 89 | " # Save the model\n", 90 | " alg_var = pickle.dumps(alg)\n", 91 | " alg_pickel = pickle.loads(alg_var)\n", 92 | "\n", 93 | " dump(alg_pickel ,os.path.join(path,f\"Models/{symbol}_cla.joblib\"))\n", 94 | " \n", 95 | " \n", 96 | " \n", 97 | "\n", 98 | "def SVC_sig(symbol):\n", 99 | " \"\"\" Function for predict the value of tommorow using SVC model\"\"\"\n", 100 | " \n", 101 | " # Create the weights if there is not in the folder\n", 102 | " try:\n", 103 | " alg = load(os.path.join(path,f\"Models/{symbol}_cla.joblib\"))\n", 104 | " except:\n", 105 | " create_model_weights(symbol)\n", 106 | " alg = load(os.path.join(path,f\"Models/{symbol}_cla.joblib\"))\n", 107 | " \n", 108 | " # Take the lastest percentage of change \n", 109 | " data = MT5.get_data(symbol, 3500)[[\"close\"]].pct_change(1)\n", 110 | " # Create new variable\n", 111 | " data.columns = [\"returns\"]\n", 112 | "\n", 113 | " # Features engeeniring\n", 114 | "\n", 115 | " # Mean of returns\n", 116 | " data[\"mean returns 15\"] = data[[\"returns\"]].rolling(15).mean()\n", 117 | " data[\"mean returns 60\"] = data[[\"returns\"]].rolling(60).mean()\n", 118 | "\n", 119 | " # Volatility of returns\n", 120 | " data[\"volatility returns 15\"] = data[[\"returns\"]].rolling(15).std()\n", 121 | " data[\"volatility returns 60\"] = data[[\"returns\"]].rolling(60).std()\n", 122 | " \n", 123 | " X = data[[\"returns\", \"mean returns 15\", \"mean returns 60\",\n", 124 | " \"volatility returns 15\",\n", 125 | " \"volatility returns 60\"]].iloc[-1:,:].values\n", 126 | " \n", 127 | " # Find the signal\n", 128 | " prediction = alg.predict(X)\n", 129 | " prediction = np.where(prediction==0, -1, 1)\n", 130 | " buy = prediction[0] > 0\n", 131 | " sell = not buy\n", 132 | " \n", 133 | " \n", 134 | " return buy, sell\n", 135 | "\n", 136 | "\n", 137 | "\n", 138 | "# True = Live Trading and False = Screener\n", 139 | "live = True\n", 140 | "\n", 141 | "if live:\n", 142 | " current_account_info = mt5.account_info()\n", 143 | " print(\"------------------------------------------------------------------\")\n", 144 | " print(\"Date: \", datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\"))\n", 145 | " print(f\"Balance: {current_account_info.balance} USD, \\t\"\n", 146 | " f\"Equity: {current_account_info.equity} USD, \\t\"\n", 147 | " f\"Profit: {current_account_info.profit} USD\")\n", 148 | " print(\"------------------------------------------------------------------\")\n", 149 | "\n", 150 | "\n", 151 | "\n", 152 | "\n", 153 | "info_order = {\n", 154 | " \"Google\": [\"Alphabet_Inc_C_(GOOG.O).a\", 1.00]\n", 155 | "}\n", 156 | "\n", 157 | "\n", 158 | "start = datetime.now().strftime(\"%H:%M:%S\")\n", 159 | "while True:\n", 160 | " # Verfication for launch\n", 161 | " if datetime.now().weekday() not in (5,1):\n", 162 | " is_time = datetime.now().strftime(\"%H:%M:%S\") == start #\"23:59:59\"\n", 163 | " else:\n", 164 | " is_time = False\n", 165 | "\n", 166 | " \n", 167 | " # Launch the algorithm\n", 168 | " if is_time:\n", 169 | "\n", 170 | " # Open the trades\n", 171 | " for asset in info_order.keys():\n", 172 | "\n", 173 | " # Initialize the inputs\n", 174 | " symbol = info_order[asset][0]\n", 175 | " lot = info_order[asset][1]\n", 176 | "\n", 177 | " # Create the signals\n", 178 | " buy, sell = SVC_sig(symbol)\n", 179 | "\n", 180 | " # Run the algorithm\n", 181 | " if live:\n", 182 | " MT5.run(symbol, buy, sell,lot)\n", 183 | "\n", 184 | " else:\n", 185 | " print(f\"Symbol: {symbol}\\t\"\n", 186 | " f\"Buy: {buy}\\t\"\n", 187 | " f\"Sell: {sell}\")\n", 188 | " time.sleep(1)" 189 | ] 190 | }, 191 | { 192 | "cell_type": "code", 193 | "execution_count": null, 194 | "id": "cba8b625", 195 | "metadata": {}, 196 | "outputs": [], 197 | "source": [] 198 | } 199 | ], 200 | "metadata": { 201 | "kernelspec": { 202 | "display_name": "Python 3", 203 | "language": "python", 204 | "name": "python3" 205 | }, 206 | "language_info": { 207 | "codemirror_mode": { 208 | "name": "ipython", 209 | "version": 3 210 | }, 211 | "file_extension": ".py", 212 | "mimetype": "text/x-python", 213 | "name": "python", 214 | "nbconvert_exporter": "python", 215 | "pygments_lexer": "ipython3", 216 | "version": "3.8.8" 217 | } 218 | }, 219 | "nbformat": 4, 220 | "nbformat_minor": 5 221 | } 222 | -------------------------------------------------------------------------------- /Chapter_11/SVR_app.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "id": "2bd04fef", 7 | "metadata": {}, 8 | "outputs": [ 9 | { 10 | "name": "stdout", 11 | "output_type": "stream", 12 | "text": [ 13 | "------------------------------------------------------------------\n", 14 | "Date: 2021-09-24 07:16:18\n", 15 | "Balance: 982.13 USD, \tEquity: 982.13 USD, \tProfit: 0.0 USD\n", 16 | "------------------------------------------------------------------\n", 17 | "------------------------------------------------------------------\n", 18 | "Date: 2021-09-24 07:16:18\n", 19 | "SYMBOL: Alphabet_Inc_C_(GOOG.O).a\n", 20 | "BUY: False \t SHORT: True\n", 21 | "POSITION: None \t ID: None\n", 22 | "OPEN SHORT TRADE: Market closed\n", 23 | "------------------------------------------------------------------\n" 24 | ] 25 | }, 26 | { 27 | "ename": "KeyboardInterrupt", 28 | "evalue": "", 29 | "output_type": "error", 30 | "traceback": [ 31 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", 32 | "\u001b[1;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", 33 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 130\u001b[0m \u001b[1;31m# Verfication for launch\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 131\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mdatetime\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mnow\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mweekday\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[1;32min\u001b[0m \u001b[1;33m(\u001b[0m\u001b[1;36m5\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m3\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 132\u001b[1;33m \u001b[0mis_time\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mdatetime\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mnow\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mstrftime\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"%H:%M:%S\"\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m==\u001b[0m \u001b[0mstart\u001b[0m \u001b[1;31m#\"23:59:59\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 133\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 134\u001b[0m \u001b[0mis_time\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;32mFalse\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", 34 | "\u001b[1;31mKeyboardInterrupt\u001b[0m: " 35 | ] 36 | } 37 | ], 38 | "source": [ 39 | "from MT5 import *\n", 40 | "import numpy as np\n", 41 | "import pandas as pd\n", 42 | "import warnings\n", 43 | "warnings.filterwarnings(\"ignore\")\n", 44 | "from sklearn.svm import SVR\n", 45 | "import time\n", 46 | "import pickle\n", 47 | "from joblib import dump, load\n", 48 | "import os\n", 49 | "from sklearn.preprocessing import StandardScaler\n", 50 | "\n", 51 | "path = \"\" # Ex: C:/Desktop/Python_for_finance_and_algorithmic_trading/ChapterN/Models\n", 52 | "\n", 53 | "\n", 54 | "def create_model_weights(symbol):\n", 55 | " \"\"\" Weights for Linear regression on the percentage change\"\"\"\n", 56 | " # Import the data\n", 57 | " data = MT5.get_data(symbol, 3500)[[\"close\"]].pct_change(1)\n", 58 | " \n", 59 | " # Create new variable\n", 60 | " data.columns = [\"returns\"]\n", 61 | "\n", 62 | " # Features engeeniring\n", 63 | " data[\"returns t-1\"] = data[[\"returns\"]].shift(1)\n", 64 | "\n", 65 | " # Mean of returns\n", 66 | " data[\"mean returns 15\"] = data[[\"returns\"]].rolling(15).mean().shift(1)\n", 67 | " data[\"mean returns 60\"] = data[[\"returns\"]].rolling(60).mean().shift(1)\n", 68 | "\n", 69 | " # Volatility of returns\n", 70 | " data[\"volatility returns 15\"] = data[[\"returns\"]].rolling(15).std().shift(1)\n", 71 | " data[\"volatility returns 60\"] = data[[\"returns\"]].rolling(60).std().shift(1)\n", 72 | " \n", 73 | " # Split the data\n", 74 | " data = data.dropna()\n", 75 | " split = int(0.80*len(data))\n", 76 | " \n", 77 | " # Train set creation\n", 78 | " X_train = data[[\"returns t-1\", \"mean returns 15\", \"mean returns 60\",\n", 79 | " \"volatility returns 15\",\n", 80 | " \"volatility returns 60\"]].iloc[:split]\n", 81 | " y_train = data[[\"returns\"]].iloc[:split]\n", 82 | " \n", 83 | " sc = StandardScaler()\n", 84 | " X_train = sc.fit_transform(X_train)\n", 85 | " \n", 86 | " # Create the model\n", 87 | " alg = SVR(epsilon=1.5)\n", 88 | "\n", 89 | " # Fit the model\n", 90 | " alg.fit(X_train, y_train)\n", 91 | " \n", 92 | " # Save the model\n", 93 | " alg_var = pickle.dumps(alg)\n", 94 | " alg_pickel = pickle.loads(alg_var)\n", 95 | "\n", 96 | " dump(alg_pickel ,os.path.join(path,f\"Models/{symbol}_reg.joblib\"))\n", 97 | " \n", 98 | " \n", 99 | " \n", 100 | "\n", 101 | "def SVR_sig(symbol):\n", 102 | " \"\"\" Function for predict the value of tommorow using ARIMA model\"\"\"\n", 103 | " \n", 104 | " # Create the weights if there is not in the folder\n", 105 | " try:\n", 106 | " alg = load(os.path.join(path,f\"Models/{symbol}_reg.joblib\"))\n", 107 | " except:\n", 108 | " create_model_weights(symbol)\n", 109 | " alg = load(os.path.join(path,f\"Models/{symbol}_reg.joblib\"))\n", 110 | " \n", 111 | " # Take the lastest percentage of change \n", 112 | " data = MT5.get_data(symbol, 3500)[[\"close\"]].pct_change(1)\n", 113 | " \n", 114 | " # Create new variable\n", 115 | " data.columns = [\"returns\"]\n", 116 | "\n", 117 | " # Features engeeniring\n", 118 | "\n", 119 | " # Mean of returns\n", 120 | " data[\"mean returns 15\"] = data[[\"returns\"]].rolling(15).mean()\n", 121 | " data[\"mean returns 60\"] = data[[\"returns\"]].rolling(60).mean()\n", 122 | "\n", 123 | " # Volatility of returns\n", 124 | " data[\"volatility returns 15\"] = data[[\"returns\"]].rolling(15).std()\n", 125 | " data[\"volatility returns 60\"] = data[[\"returns\"]].rolling(60).std()\n", 126 | " \n", 127 | " X = data[[\"returns\", \"mean returns 15\", \"mean returns 60\",\n", 128 | " \"volatility returns 15\",\n", 129 | " \"volatility returns 60\"]].iloc[-1:,:].values\n", 130 | " \n", 131 | " # Find the signal\n", 132 | " prediction = alg.predict(X)\n", 133 | " buy = prediction[0] > 0\n", 134 | " sell = not buy\n", 135 | " \n", 136 | " \n", 137 | " return buy, sell\n", 138 | "\n", 139 | "\n", 140 | "\n", 141 | "# True = Live Trading and False = Screener\n", 142 | "live = True\n", 143 | "\n", 144 | "if live:\n", 145 | " current_account_info = mt5.account_info()\n", 146 | " print(\"------------------------------------------------------------------\")\n", 147 | " print(\"Date: \", datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\"))\n", 148 | " print(f\"Balance: {current_account_info.balance} USD, \\t\"\n", 149 | " f\"Equity: {current_account_info.equity} USD, \\t\"\n", 150 | " f\"Profit: {current_account_info.profit} USD\")\n", 151 | " print(\"------------------------------------------------------------------\")\n", 152 | "\n", 153 | "\n", 154 | "\n", 155 | "\n", 156 | "info_order = {\n", 157 | " \"Google\": [\"Alphabet_Inc_C_(GOOG.O).a\", 1.00]\n", 158 | "}\n", 159 | "\n", 160 | "\n", 161 | "start = datetime.now().strftime(\"%H:%M:%S\")\n", 162 | "while True:\n", 163 | " # Verfication for launch\n", 164 | " if datetime.now().weekday() not in (5,3):\n", 165 | " is_time = datetime.now().strftime(\"%H:%M:%S\") == start #\"23:59:59\"\n", 166 | " else:\n", 167 | " is_time = False\n", 168 | "\n", 169 | " \n", 170 | " # Launch the algorithm\n", 171 | " if is_time:\n", 172 | "\n", 173 | " # Open the trades\n", 174 | " for asset in info_order.keys():\n", 175 | "\n", 176 | " # Initialize the inputs\n", 177 | " symbol = info_order[asset][0]\n", 178 | " lot = info_order[asset][1]\n", 179 | "\n", 180 | " # Create the signals\n", 181 | " buy, sell = SVR_sig(symbol)\n", 182 | "\n", 183 | " # Run the algorithm\n", 184 | " if live:\n", 185 | " MT5.run(symbol, buy, sell,lot)\n", 186 | "\n", 187 | " else:\n", 188 | " print(f\"Symbol: {symbol}\\t\"\n", 189 | " f\"Buy: {buy}\\t\"\n", 190 | " f\"Sell: {sell}\")\n", 191 | " time.sleep(1)" 192 | ] 193 | }, 194 | { 195 | "cell_type": "code", 196 | "execution_count": null, 197 | "id": "6d746605", 198 | "metadata": {}, 199 | "outputs": [], 200 | "source": [] 201 | } 202 | ], 203 | "metadata": { 204 | "kernelspec": { 205 | "display_name": "Python 3", 206 | "language": "python", 207 | "name": "python3" 208 | }, 209 | "language_info": { 210 | "codemirror_mode": { 211 | "name": "ipython", 212 | "version": 3 213 | }, 214 | "file_extension": ".py", 215 | "mimetype": "text/x-python", 216 | "name": "python", 217 | "nbconvert_exporter": "python", 218 | "pygments_lexer": "ipython3", 219 | "version": "3.8.8" 220 | } 221 | }, 222 | "nbformat": 4, 223 | "nbformat_minor": 5 224 | } 225 | -------------------------------------------------------------------------------- /Chapter_12/MT5.py: -------------------------------------------------------------------------------- 1 | import warnings 2 | from datetime import datetime 3 | import pandas as pd 4 | import MetaTrader5 as mt5 5 | warnings.filterwarnings("ignore") 6 | mt5.initialize() 7 | 8 | 9 | class MT5: 10 | 11 | def get_data(symbol, n, timeframe=mt5.TIMEFRAME_D1): 12 | """ Function to import the data of the chosen symbol""" 13 | 14 | # Initialize the connection if there is not 15 | mt5.initialize() 16 | 17 | # Current date extract 18 | utc_from = datetime.now() 19 | 20 | # Import the data into a tuple 21 | rates = mt5.copy_rates_from(symbol, timeframe, utc_from, n) 22 | 23 | # Tuple to dataframe 24 | rates_frame = pd.DataFrame(rates) 25 | 26 | # Convert time in seconds into the datetime format 27 | rates_frame['time'] = pd.to_datetime(rates_frame['time'], unit='s') 28 | 29 | # Convert the column "time" in the right format 30 | rates_frame['time'] = pd.to_datetime(rates_frame['time'], format='%Y-%m-%d') 31 | 32 | # Set column time as the index of the dataframe 33 | rates_frame = rates_frame.set_index('time') 34 | return rates_frame 35 | 36 | def orders(symbol, lot, buy=True, id_position=None): 37 | """ Send the orders """ 38 | 39 | # Initialize the connection if there is not 40 | if mt5.initialize() == False: 41 | mt5.initialize() 42 | 43 | # Get filling mode 44 | filling_mode = mt5.symbol_info(symbol).filling_mode - 1 45 | 46 | # Take ask price 47 | ask_price = mt5.symbol_info_tick(symbol).ask 48 | 49 | # Take bid price 50 | bid_price = mt5.symbol_info_tick(symbol).bid 51 | 52 | # Take the point of the asset 53 | point = mt5.symbol_info(symbol).point 54 | 55 | deviation = 20 # mt5.getSlippage(symbol) 56 | # **************************** Open a trade ***************************** 57 | if id_position == None: 58 | 59 | # Buy order Parameters 60 | if buy: 61 | type_trade = mt5.ORDER_TYPE_BUY 62 | sl = ask_price*(1-0.01) 63 | tp = ask_price*(1+0.01) 64 | price = ask_price 65 | 66 | # Sell order Parameters 67 | else: 68 | type_trade = mt5.ORDER_TYPE_SELL 69 | sl = bid_price*(1+0.01) 70 | tp = bid_price*(1-0.01) 71 | price = bid_price 72 | 73 | # Open the trade 74 | request = { 75 | "action": mt5.TRADE_ACTION_DEAL, 76 | "symbol": symbol, 77 | "volume": lot, 78 | "type": type_trade, 79 | "price": price, 80 | "deviation": deviation, 81 | "sl": sl, 82 | "tp": tp, 83 | "magic": 234000, 84 | "comment": "python script order", 85 | "type_time": mt5.ORDER_TIME_GTC, 86 | "type_filling": filling_mode, 87 | } 88 | # send a trading request 89 | result = mt5.order_send(request) 90 | result_comment = result.comment 91 | 92 | # **************************** Close a trade ***************************** 93 | else: 94 | # Buy order Parameters 95 | if buy: 96 | type_trade = mt5.ORDER_TYPE_SELL 97 | price = bid_price 98 | 99 | # Sell order Parameters 100 | else: 101 | type_trade = mt5.ORDER_TYPE_BUY 102 | price = ask_price 103 | 104 | # Close the trade 105 | request = { 106 | "action": mt5.TRADE_ACTION_DEAL, 107 | "symbol": symbol, 108 | "volume": lot, 109 | "type": type_trade, 110 | "position": id_position, 111 | "price": price, 112 | "deviation": deviation, 113 | "magic": 234000, 114 | "comment": "python script order", 115 | "type_time": mt5.ORDER_TIME_GTC, 116 | "type_filling": filling_mode, 117 | } 118 | 119 | # send a trading request 120 | result = mt5.order_send(request) 121 | result_comment = result.comment 122 | return result.comment 123 | 124 | def resume(): 125 | """ Return the current positions. Position=0 --> Buy """ 126 | # Initialize the connection if there is not 127 | mt5.initialize() 128 | 129 | # Define the name of the columns that we will create 130 | colonnes = ["ticket", "position", "symbol", "volume"] 131 | 132 | # Go take the current open trades 133 | current = mt5.positions_get() 134 | 135 | # Create a empty dataframe 136 | summary = pd.DataFrame() 137 | 138 | # Loop to add each row in dataframe 139 | # (Can be ameliorate using of list of list) 140 | for element in current: 141 | element_pandas = pd.DataFrame([element.ticket, 142 | element.type, 143 | element.symbol, 144 | element.volume], 145 | index=colonnes).transpose() 146 | summary = pd.concat((summary, element_pandas), axis=0) 147 | 148 | return summary 149 | 150 | 151 | def run(symbol, long, short, lot): 152 | 153 | # Initialize the connection if there is not 154 | if mt5.initialize() == False: 155 | mt5.initialize() 156 | 157 | # Choose your symbol 158 | print("------------------------------------------------------------------") 159 | print("Date: ", datetime.now().strftime("%Y-%m-%d %H:%M:%S")) 160 | print("SYMBOL:", symbol) 161 | 162 | # Initialize the device 163 | current_open_positions = MT5.resume() 164 | # Buy or sell 165 | print(f"BUY: {long} \t SHORT: {short}") 166 | 167 | """ Close trade eventually """ 168 | # Extraction type trade 169 | try: 170 | position = current_open_positions.loc[current_open_positions["symbol"]==symbol].values[0][1] 171 | 172 | identifier = current_open_positions.loc[current_open_positions["symbol"]==symbol].values[0][0] 173 | except: 174 | position= None 175 | identifier = None 176 | 177 | print(f"POSITION: {position} \t ID: {identifier}") 178 | 179 | # Close trades 180 | if long==True and position==0: 181 | long=False 182 | 183 | elif long==False and position==0: 184 | res = MT5.orders(symbol, lot, buy=True, id_position=identifier) 185 | print(f"CLOSE LONG TRADE: {res}") 186 | 187 | elif short==True and position ==1: 188 | short=False 189 | 190 | elif short == False and position == 1: 191 | res = MT5.orders(symbol, lot, buy=False, id_position=identifier) 192 | print(f"CLOSE SHORT TRADE: {res}") 193 | 194 | else: 195 | pass 196 | 197 | 198 | """ Buy or short """ 199 | if long==True: 200 | 201 | res = MT5.orders(symbol, lot, buy=True, id_position=None) 202 | print(f"OPEN LONG TRADE: {res}") 203 | 204 | if short==True: 205 | res = MT5.orders(symbol, lot, buy=False, id_position=None) 206 | print(f"OPEN SHORT TRADE: {res}") 207 | 208 | print("------------------------------------------------------------------") 209 | 210 | def close_all_night(): 211 | result = MT5.resume() 212 | for i in range(len(result)): 213 | before = mt5.account_info().balance 214 | row = result.iloc[0+i:1+i,:] 215 | if row["position"][0]==0: 216 | res = MT5.orders(row["symbol"][0], row["volume"][0], buy=True, id_position=row["ticket"][0]) 217 | 218 | else: 219 | res = MT5.orders(row["symbol"][0], row["volume"][0], buy=False, id_position=row["ticket"][0]) -------------------------------------------------------------------------------- /Chapter_12/Models/Alphabet_Inc_C_(GOOG.O).a_cla.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_12/Models/Alphabet_Inc_C_(GOOG.O).a_cla.joblib -------------------------------------------------------------------------------- /Chapter_12/Models/Alphabet_Inc_C_(GOOG.O).a_reg.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_12/Models/Alphabet_Inc_C_(GOOG.O).a_reg.joblib -------------------------------------------------------------------------------- /Chapter_12/Models/EURUSD_cla.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_12/Models/EURUSD_cla.joblib -------------------------------------------------------------------------------- /Chapter_12/Models/EURUSD_reg.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_12/Models/EURUSD_reg.joblib -------------------------------------------------------------------------------- /Chapter_12/Models/NAS100_cla.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_12/Models/NAS100_cla.joblib -------------------------------------------------------------------------------- /Chapter_12/Models/NAS100_reg.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_12/Models/NAS100_reg.joblib -------------------------------------------------------------------------------- /Chapter_12/Models/US2000_cla.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_12/Models/US2000_cla.joblib -------------------------------------------------------------------------------- /Chapter_12/Models/US2000_reg.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_12/Models/US2000_reg.joblib -------------------------------------------------------------------------------- /Chapter_12/Models/US500_cla.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_12/Models/US500_cla.joblib -------------------------------------------------------------------------------- /Chapter_12/Models/US500_reg.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_12/Models/US500_reg.joblib -------------------------------------------------------------------------------- /Chapter_12/Models/USDCAD_cla.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_12/Models/USDCAD_cla.joblib -------------------------------------------------------------------------------- /Chapter_12/Models/USDCAD_reg.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_12/Models/USDCAD_reg.joblib -------------------------------------------------------------------------------- /Chapter_12/Models/XAUUSD_cla.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_12/Models/XAUUSD_cla.joblib -------------------------------------------------------------------------------- /Chapter_12/Models/XAUUSD_reg.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_12/Models/XAUUSD_reg.joblib -------------------------------------------------------------------------------- /Chapter_12/Tree_cla_App.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "id": "c1c506fd", 7 | "metadata": {}, 8 | "outputs": [ 9 | { 10 | "name": "stdout", 11 | "output_type": "stream", 12 | "text": [ 13 | "------------------------------------------------------------------\n", 14 | "Date: 2021-09-24 07:12:21\n", 15 | "Balance: 982.13 USD, \tEquity: 982.13 USD, \tProfit: 0.0 USD\n", 16 | "------------------------------------------------------------------\n", 17 | "------------------------------------------------------------------\n", 18 | "Date: 2021-09-24 07:12:21\n", 19 | "SYMBOL: Alphabet_Inc_C_(GOOG.O).a\n", 20 | "BUY: True \t SHORT: False\n", 21 | "POSITION: None \t ID: None\n", 22 | "OPEN LONG TRADE: Market closed\n", 23 | "------------------------------------------------------------------\n" 24 | ] 25 | }, 26 | { 27 | "ename": "KeyboardInterrupt", 28 | "evalue": "", 29 | "output_type": "error", 30 | "traceback": [ 31 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", 32 | "\u001b[1;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", 33 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 153\u001b[0m \u001b[1;34mf\"Buy: {buy}\\t\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 154\u001b[0m f\"Sell: {sell}\")\n\u001b[1;32m--> 155\u001b[1;33m \u001b[0mtime\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msleep\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", 34 | "\u001b[1;31mKeyboardInterrupt\u001b[0m: " 35 | ] 36 | } 37 | ], 38 | "source": [ 39 | "from MT5 import *\n", 40 | "import numpy as np\n", 41 | "import pandas as pd\n", 42 | "import warnings\n", 43 | "warnings.filterwarnings(\"ignore\")\n", 44 | "from sklearn.tree import DecisionTreeClassifier\n", 45 | "import time\n", 46 | "import pickle\n", 47 | "from joblib import dump, load\n", 48 | "import os\n", 49 | "from sklearn.preprocessing import StandardScaler\n", 50 | "\n", 51 | "path = \"\" # Ex: C:/Desktop/Python_for_finance_and_algorithmic_trading/ChapterN/Models\n", 52 | "\n", 53 | "\n", 54 | "def create_model_weights(symbol):\n", 55 | " \"\"\" Weights for Linear regression on the percentage change\"\"\"\n", 56 | " # Import the data\n", 57 | " data = MT5.get_data(symbol, 3500)[[\"close\"]].pct_change(1)\n", 58 | " \n", 59 | " # Create new variable\n", 60 | " data.columns = [\"returns\"]\n", 61 | "\n", 62 | " # Features engeeniring\n", 63 | " data[\"returns t-1\"] = data[[\"returns\"]].shift(1)\n", 64 | "\n", 65 | " # Mean of returns\n", 66 | " data[\"mean returns 15\"] = data[[\"returns\"]].rolling(15).mean().shift(1)\n", 67 | " data[\"mean returns 60\"] = data[[\"returns\"]].rolling(60).mean().shift(1)\n", 68 | "\n", 69 | " # Volatility of returns\n", 70 | " data[\"volatility returns 15\"] = data[[\"returns\"]].rolling(15).std().shift(1)\n", 71 | " data[\"volatility returns 60\"] = data[[\"returns\"]].rolling(60).std().shift(1)\n", 72 | " \n", 73 | " # Split the data\n", 74 | " data = data.dropna()\n", 75 | " split = int(0.80*len(data))\n", 76 | " \n", 77 | " # Train set creation\n", 78 | " X_train = data[[\"returns t-1\", \"mean returns 15\", \"mean returns 60\",\n", 79 | " \"volatility returns 15\",\n", 80 | " \"volatility returns 60\"]].iloc[:split]\n", 81 | " y_train = np.round(data[[\"returns\"]].iloc[:split]+0.5)\n", 82 | " \n", 83 | " # Create the model\n", 84 | " alg = DecisionTreeClassifier(max_depth=3)\n", 85 | "\n", 86 | " # Fit the model\n", 87 | " alg.fit(X_train, y_train)\n", 88 | " \n", 89 | " # Save the model\n", 90 | " alg_var = pickle.dumps(alg)\n", 91 | " alg_pickel = pickle.loads(alg_var)\n", 92 | "\n", 93 | " dump(alg_pickel ,os.path.join(path,f\"Models/{symbol}_cla.joblib\"))\n", 94 | " \n", 95 | " \n", 96 | " \n", 97 | "\n", 98 | "def tree_cla_sig(symbol):\n", 99 | " \"\"\" Function for predict the value of tommorow using ARIMA model\"\"\"\n", 100 | " \n", 101 | " # Create the weights if there is not in the folder\n", 102 | " try:\n", 103 | " alg = load(os.path.join(path,f\"Models/{symbol}_cla.joblib\"))\n", 104 | " except:\n", 105 | " create_model_weights(symbol)\n", 106 | " alg = load(os.path.join(path,f\"Models/{symbol}_cla.joblib\"))\n", 107 | " # Take the lastest percentage of change \n", 108 | " data = MT5.get_data(symbol, 3500)[[\"close\"]].pct_change(1)\n", 109 | " # Create new variable\n", 110 | " data.columns = [\"returns\"]\n", 111 | "\n", 112 | " # Features engeeniring\n", 113 | "\n", 114 | " # Mean of returns\n", 115 | " data[\"mean returns 15\"] = data[[\"returns\"]].rolling(15).mean()\n", 116 | " data[\"mean returns 60\"] = data[[\"returns\"]].rolling(60).mean()\n", 117 | "\n", 118 | " # Volatility of returns\n", 119 | " data[\"volatility returns 15\"] = data[[\"returns\"]].rolling(15).std()\n", 120 | " data[\"volatility returns 60\"] = data[[\"returns\"]].rolling(60).std()\n", 121 | " \n", 122 | " X = data[[\"returns\", \"mean returns 15\", \"mean returns 60\",\n", 123 | " \"volatility returns 15\",\n", 124 | " \"volatility returns 60\"]].iloc[-1:,:].values\n", 125 | " \n", 126 | " # Find the signal\n", 127 | " prediction = alg.predict(X)\n", 128 | " prediction = np.where(prediction==0, -1, 1)\n", 129 | " buy = prediction[0] > 0\n", 130 | " sell = not buy\n", 131 | " \n", 132 | " \n", 133 | " return buy, sell\n", 134 | "\n", 135 | "\n", 136 | "\n", 137 | "# True = Live Trading and False = Screener\n", 138 | "live = True\n", 139 | "\n", 140 | "if live:\n", 141 | " current_account_info = mt5.account_info()\n", 142 | " print(\"------------------------------------------------------------------\")\n", 143 | " print(\"Date: \", datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\"))\n", 144 | " print(f\"Balance: {current_account_info.balance} USD, \\t\"\n", 145 | " f\"Equity: {current_account_info.equity} USD, \\t\"\n", 146 | " f\"Profit: {current_account_info.profit} USD\")\n", 147 | " print(\"------------------------------------------------------------------\")\n", 148 | "\n", 149 | "\n", 150 | "\n", 151 | "\n", 152 | "\n", 153 | "info_order = {\n", 154 | " \"Google\": [\"Alphabet_Inc_C_(GOOG.O).a\", 1.00]\n", 155 | "}\n", 156 | "\n", 157 | "\n", 158 | "start = datetime.now().strftime(\"%H:%M:%S\")\n", 159 | "while True:\n", 160 | " # Verfication for launch\n", 161 | " if datetime.now().weekday() not in (5,1):\n", 162 | " is_time = datetime.now().strftime(\"%H:%M:%S\") == start #\"23:59:59\"\n", 163 | " else:\n", 164 | " is_time = False\n", 165 | "\n", 166 | " \n", 167 | " # Launch the algorithm\n", 168 | " if is_time:\n", 169 | "\n", 170 | " # Open the trades\n", 171 | " for asset in info_order.keys():\n", 172 | "\n", 173 | " # Initialize the inputs\n", 174 | " symbol = info_order[asset][0]\n", 175 | " lot = info_order[asset][1]\n", 176 | "\n", 177 | " # Create the signals\n", 178 | " buy, sell = tree_cla_sig(symbol)\n", 179 | "\n", 180 | " # Run the algorithm\n", 181 | " if live:\n", 182 | " MT5.run(symbol, buy, sell,lot)\n", 183 | "\n", 184 | " else:\n", 185 | " print(f\"Symbol: {symbol}\\t\"\n", 186 | " f\"Buy: {buy}\\t\"\n", 187 | " f\"Sell: {sell}\")\n", 188 | " time.sleep(1)" 189 | ] 190 | }, 191 | { 192 | "cell_type": "code", 193 | "execution_count": null, 194 | "id": "47e7e61e", 195 | "metadata": {}, 196 | "outputs": [], 197 | "source": [] 198 | } 199 | ], 200 | "metadata": { 201 | "kernelspec": { 202 | "display_name": "Python 3", 203 | "language": "python", 204 | "name": "python3" 205 | }, 206 | "language_info": { 207 | "codemirror_mode": { 208 | "name": "ipython", 209 | "version": 3 210 | }, 211 | "file_extension": ".py", 212 | "mimetype": "text/x-python", 213 | "name": "python", 214 | "nbconvert_exporter": "python", 215 | "pygments_lexer": "ipython3", 216 | "version": "3.8.8" 217 | } 218 | }, 219 | "nbformat": 4, 220 | "nbformat_minor": 5 221 | } 222 | -------------------------------------------------------------------------------- /Chapter_12/Tree_reg_App.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "id": "cb83c5b2", 7 | "metadata": {}, 8 | "outputs": [ 9 | { 10 | "name": "stdout", 11 | "output_type": "stream", 12 | "text": [ 13 | "------------------------------------------------------------------\n", 14 | "Date: 2021-09-24 07:13:20\n", 15 | "Balance: 982.13 USD, \tEquity: 982.13 USD, \tProfit: 0.0 USD\n", 16 | "------------------------------------------------------------------\n", 17 | "------------------------------------------------------------------\n", 18 | "Date: 2021-09-24 07:13:20\n", 19 | "SYMBOL: Alphabet_Inc_C_(GOOG.O).a\n", 20 | "BUY: True \t SHORT: False\n", 21 | "POSITION: None \t ID: None\n", 22 | "OPEN LONG TRADE: Market closed\n", 23 | "------------------------------------------------------------------\n" 24 | ] 25 | }, 26 | { 27 | "ename": "KeyboardInterrupt", 28 | "evalue": "", 29 | "output_type": "error", 30 | "traceback": [ 31 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", 32 | "\u001b[1;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", 33 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 130\u001b[0m \u001b[1;31m# Verfication for launch\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 131\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mdatetime\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mnow\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mweekday\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[1;32min\u001b[0m \u001b[1;33m(\u001b[0m\u001b[1;36m5\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m3\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 132\u001b[1;33m \u001b[0mis_time\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mdatetime\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mnow\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mstrftime\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"%H:%M:%S\"\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m==\u001b[0m \u001b[0mstart\u001b[0m \u001b[1;31m#\"23:59:59\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 133\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 134\u001b[0m \u001b[0mis_time\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;32mFalse\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", 34 | "\u001b[1;31mKeyboardInterrupt\u001b[0m: " 35 | ] 36 | } 37 | ], 38 | "source": [ 39 | "from MT5 import *\n", 40 | "import numpy as np\n", 41 | "import pandas as pd\n", 42 | "import warnings\n", 43 | "warnings.filterwarnings(\"ignore\")\n", 44 | "from sklearn.tree import DecisionTreeRegressor\n", 45 | "import time\n", 46 | "import pickle\n", 47 | "from joblib import dump, load\n", 48 | "import os\n", 49 | "from sklearn.preprocessing import StandardScaler\n", 50 | "\n", 51 | "path = \"\" # Ex: C:/Desktop/Python_for_finance_and_algorithmic_trading/ChapterN/Models\n", 52 | "\n", 53 | "\n", 54 | "def create_model_weights(symbol):\n", 55 | " \"\"\" Weights for Linear regression on the percentage change\"\"\"\n", 56 | " # Import the data\n", 57 | " data = MT5.get_data(symbol, 3500)[[\"close\"]].pct_change(1)\n", 58 | " \n", 59 | " # Create new variable\n", 60 | " data.columns = [\"returns\"]\n", 61 | "\n", 62 | " # Features engeeniring\n", 63 | " data[\"returns t-1\"] = data[[\"returns\"]].shift(1)\n", 64 | "\n", 65 | " # Mean of returns\n", 66 | " data[\"mean returns 15\"] = data[[\"returns\"]].rolling(15).mean().shift(1)\n", 67 | " data[\"mean returns 60\"] = data[[\"returns\"]].rolling(60).mean().shift(1)\n", 68 | "\n", 69 | " # Volatility of returns\n", 70 | " data[\"volatility returns 15\"] = data[[\"returns\"]].rolling(15).std().shift(1)\n", 71 | " data[\"volatility returns 60\"] = data[[\"returns\"]].rolling(60).std().shift(1)\n", 72 | " \n", 73 | " # Split the data\n", 74 | " data = data.dropna()\n", 75 | " split = int(0.80*len(data))\n", 76 | " \n", 77 | " # Train set creation\n", 78 | " X_train = data[[\"returns t-1\", \"mean returns 15\", \"mean returns 60\",\n", 79 | " \"volatility returns 15\",\n", 80 | " \"volatility returns 60\"]].iloc[:split]\n", 81 | " y_train = data[[\"returns\"]].iloc[:split]\n", 82 | " \n", 83 | " sc = StandardScaler()\n", 84 | " X_train = sc.fit_transform(X_train)\n", 85 | " \n", 86 | " # Create the model\n", 87 | " alg = DecisionTreeRegressor(max_depth=6)\n", 88 | "\n", 89 | " # Fit the model\n", 90 | " alg.fit(X_train, y_train)\n", 91 | " \n", 92 | " # Save the model\n", 93 | " alg_var = pickle.dumps(alg)\n", 94 | " alg_pickel = pickle.loads(alg_var)\n", 95 | "\n", 96 | " dump(alg_pickel ,os.path.join(path,f\"Models/{symbol}_reg.joblib\"))\n", 97 | " \n", 98 | " \n", 99 | " \n", 100 | "\n", 101 | "def tree_reg_sig(symbol):\n", 102 | " \"\"\" Function for predict the value of tommorow using ARIMA model\"\"\"\n", 103 | " \n", 104 | " # Create the weights if there is not in the folder\n", 105 | " try:\n", 106 | " alg = load(os.path.join(path,f\"Models/{symbol}_reg.joblib\"))\n", 107 | " except:\n", 108 | " create_model_weights(symbol)\n", 109 | " alg = load(os.path.join(path,f\"Models/{symbol}_reg.joblib\"))\n", 110 | " \n", 111 | " # Take the lastest percentage of change \n", 112 | " data = MT5.get_data(symbol, 3500)[[\"close\"]].pct_change(1)\n", 113 | " \n", 114 | " # Create new variable\n", 115 | " data.columns = [\"returns\"]\n", 116 | "\n", 117 | " # Features engeeniring\n", 118 | "\n", 119 | " # Mean of returns\n", 120 | " data[\"mean returns 15\"] = data[[\"returns\"]].rolling(15).mean()\n", 121 | " data[\"mean returns 60\"] = data[[\"returns\"]].rolling(60).mean()\n", 122 | "\n", 123 | " # Volatility of returns\n", 124 | " data[\"volatility returns 15\"] = data[[\"returns\"]].rolling(15).std()\n", 125 | " data[\"volatility returns 60\"] = data[[\"returns\"]].rolling(60).std()\n", 126 | " \n", 127 | " X = data[[\"returns\", \"mean returns 15\", \"mean returns 60\",\n", 128 | " \"volatility returns 15\",\n", 129 | " \"volatility returns 60\"]].iloc[-1:,:].values\n", 130 | " \n", 131 | " # Find the signal\n", 132 | " prediction = alg.predict(X)\n", 133 | " buy = prediction[0] > 0\n", 134 | " sell = not buy\n", 135 | " \n", 136 | " \n", 137 | " return buy, sell\n", 138 | "\n", 139 | "\n", 140 | "\n", 141 | "# True = Live Trading and False = Screener\n", 142 | "live = True\n", 143 | "\n", 144 | "if live:\n", 145 | " current_account_info = mt5.account_info()\n", 146 | " print(\"------------------------------------------------------------------\")\n", 147 | " print(\"Date: \", datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\"))\n", 148 | " print(f\"Balance: {current_account_info.balance} USD, \\t\"\n", 149 | " f\"Equity: {current_account_info.equity} USD, \\t\"\n", 150 | " f\"Profit: {current_account_info.profit} USD\")\n", 151 | " print(\"------------------------------------------------------------------\")\n", 152 | "\n", 153 | "\n", 154 | "\n", 155 | "\n", 156 | "info_order = {\n", 157 | " \"Google\": [\"Alphabet_Inc_C_(GOOG.O).a\", 1.00]\n", 158 | "}\n", 159 | "\n", 160 | "\n", 161 | "start = datetime.now().strftime(\"%H:%M:%S\")\n", 162 | "while True:\n", 163 | " # Verfication for launch\n", 164 | " if datetime.now().weekday() not in (5,3):\n", 165 | " is_time = datetime.now().strftime(\"%H:%M:%S\") == start #\"23:59:59\"\n", 166 | " else:\n", 167 | " is_time = False\n", 168 | "\n", 169 | " \n", 170 | " # Launch the algorithm\n", 171 | " if is_time:\n", 172 | "\n", 173 | " # Open the trades\n", 174 | " for asset in info_order.keys():\n", 175 | "\n", 176 | " # Initialize the inputs\n", 177 | " symbol = info_order[asset][0]\n", 178 | " lot = info_order[asset][1]\n", 179 | "\n", 180 | " # Create the signals\n", 181 | " buy, sell = tree_reg_sig(symbol)\n", 182 | "\n", 183 | " # Run the algorithm\n", 184 | " if live:\n", 185 | " MT5.run(symbol, buy, sell,lot)\n", 186 | "\n", 187 | " else:\n", 188 | " print(f\"Symbol: {symbol}\\t\"\n", 189 | " f\"Buy: {buy}\\t\"\n", 190 | " f\"Sell: {sell}\")\n", 191 | " time.sleep(1)" 192 | ] 193 | }, 194 | { 195 | "cell_type": "code", 196 | "execution_count": null, 197 | "id": "a6e49094", 198 | "metadata": {}, 199 | "outputs": [], 200 | "source": [] 201 | } 202 | ], 203 | "metadata": { 204 | "kernelspec": { 205 | "display_name": "Python 3", 206 | "language": "python", 207 | "name": "python3" 208 | }, 209 | "language_info": { 210 | "codemirror_mode": { 211 | "name": "ipython", 212 | "version": 3 213 | }, 214 | "file_extension": ".py", 215 | "mimetype": "text/x-python", 216 | "name": "python", 217 | "nbconvert_exporter": "python", 218 | "pygments_lexer": "ipython3", 219 | "version": "3.8.8" 220 | } 221 | }, 222 | "nbformat": 4, 223 | "nbformat_minor": 5 224 | } 225 | -------------------------------------------------------------------------------- /Chapter_12/__pycache__/Backtest.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_12/__pycache__/Backtest.cpython-39.pyc -------------------------------------------------------------------------------- /Chapter_13/ANN_reg_app.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "id": "a16ad7d8", 7 | "metadata": {}, 8 | "outputs": [ 9 | { 10 | "name": "stdout", 11 | "output_type": "stream", 12 | "text": [ 13 | "------------------------------------------------------------------\n", 14 | "Date: 2021-09-24 07:14:20\n", 15 | "Balance: 982.13 USD, \tEquity: 982.13 USD, \tProfit: 0.0 USD\n", 16 | "------------------------------------------------------------------\n", 17 | "------------------------------------------------------------------\n", 18 | "Date: 2021-09-24 07:14:20\n", 19 | "SYMBOL: AAPL.a\n", 20 | "BUY: True \t SHORT: False\n", 21 | "POSITION: None \t ID: None\n", 22 | "OPEN LONG TRADE: Market closed\n", 23 | "------------------------------------------------------------------\n" 24 | ] 25 | }, 26 | { 27 | "ename": "KeyboardInterrupt", 28 | "evalue": "", 29 | "output_type": "error", 30 | "traceback": [ 31 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", 32 | "\u001b[1;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", 33 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 178\u001b[0m \u001b[1;34mf\"Buy: {buy}\\t\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 179\u001b[0m f\"Sell: {sell}\")\n\u001b[1;32m--> 180\u001b[1;33m \u001b[0mtime\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msleep\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", 34 | "\u001b[1;31mKeyboardInterrupt\u001b[0m: " 35 | ] 36 | } 37 | ], 38 | "source": [ 39 | "from MT5 import *\n", 40 | "import numpy as np\n", 41 | "import pandas as pd\n", 42 | "import warnings\n", 43 | "warnings.filterwarnings(\"ignore\")\n", 44 | "import time\n", 45 | "import pickle\n", 46 | "from joblib import dump, load\n", 47 | "import os\n", 48 | "from sklearn.preprocessing import StandardScaler\n", 49 | "import tensorflow\n", 50 | "from tensorflow.keras.models import Sequential\n", 51 | "from tensorflow.keras.layers import Dense\n", 52 | "\n", 53 | "\n", 54 | "path = \"\" # Ex: C:/Desktop/Python_for_finance_and_algorithmic_trading/ChapterN/Models\n", 55 | "\n", 56 | "\n", 57 | "def ANN():\n", 58 | " # Create the model\n", 59 | " nb_hidden_layer = 1\n", 60 | "\n", 61 | "\n", 62 | " # INTIALIZATION SEQUENTIAL MODEL\n", 63 | " alg = Sequential()\n", 64 | "\n", 65 | " # ADD HIDDEN LAYER\n", 66 | " for _ in range(nb_hidden_layer):\n", 67 | " alg.add(Dense(75, input_shape = (5,), activation=\"relu\"))\n", 68 | "\n", 69 | "\n", 70 | " # OUTPUT LAYER DENSE\n", 71 | " alg.add(Dense(1, activation=\"linear\"))\n", 72 | "\n", 73 | " # COMPILE THE MODEL\n", 74 | " alg.compile(loss=\"mse\", optimizer=\"adam\")\n", 75 | " return alg\n", 76 | "\n", 77 | "def create_model_weights(symbol):\n", 78 | " \"\"\" Weights for Linear regression on the percentage change\"\"\"\n", 79 | " # Import the data\n", 80 | " data = MT5.get_data(symbol, 3500)[[\"close\"]].pct_change(1)\n", 81 | " \n", 82 | " # Create new variable\n", 83 | " data.columns = [\"returns\"]\n", 84 | "\n", 85 | " # Features engeeniring\n", 86 | " data[\"returns t-1\"] = data[[\"returns\"]].shift(1)\n", 87 | "\n", 88 | " # Mean of returns\n", 89 | " data[\"mean returns 15\"] = data[[\"returns\"]].rolling(15).mean().shift(1)\n", 90 | " data[\"mean returns 60\"] = data[[\"returns\"]].rolling(60).mean().shift(1)\n", 91 | "\n", 92 | " # Volatility of returns\n", 93 | " data[\"volatility returns 15\"] = data[[\"returns\"]].rolling(15).std().shift(1)\n", 94 | " data[\"volatility returns 60\"] = data[[\"returns\"]].rolling(60).std().shift(1)\n", 95 | " \n", 96 | " # Split the data\n", 97 | " data = data.dropna()\n", 98 | " split = int(0.80*len(data))\n", 99 | " \n", 100 | " # Train set creation\n", 101 | " X_train = data[[\"returns t-1\", \"mean returns 15\", \"mean returns 60\",\n", 102 | " \"volatility returns 15\",\n", 103 | " \"volatility returns 60\"]].iloc[:split]\n", 104 | " y_train = data[[\"returns\"]].iloc[:split]\n", 105 | " \n", 106 | " # Initialize the class\n", 107 | " sc = StandardScaler()\n", 108 | "\n", 109 | " # Standardize the data\n", 110 | " X_train = sc.fit_transform(X_train)\n", 111 | " \n", 112 | " alg = ANN()\n", 113 | "\n", 114 | " # TRAINING\n", 115 | " alg.fit(X_train, y_train, epochs=13, batch_size=32, verbose=1)\n", 116 | " \n", 117 | " # Save the model\n", 118 | " alg.save_weights(os.path.join(path,f\"Models/ANN_reg_{symbol}\"))\n", 119 | " \n", 120 | " \n", 121 | " \n", 122 | "def ANN_cla_sig(symbol):\n", 123 | " \"\"\" Function for predict the value of tommorow using ARIMA model\"\"\"\n", 124 | " \n", 125 | " # Create the weights if there is not in the folder\n", 126 | " try:\n", 127 | " alg = ANN()\n", 128 | " alg.load_weights(os.path.join(path,f\"Models/ANN_reg_{symbol}\"))\n", 129 | " except:\n", 130 | " create_model_weights(symbol)\n", 131 | " alg = ANN()\n", 132 | " alg.load_weights(os.path.join(path,f\"Models/ANN_reg_{symbol}\"))\n", 133 | " \n", 134 | " # Take the lastest percentage of change \n", 135 | " data = MT5.get_data(symbol, 3500)[[\"close\"]].pct_change(1)\n", 136 | " # Create new variable\n", 137 | " data.columns = [\"returns\"]\n", 138 | "\n", 139 | " # Features engeeniring\n", 140 | "\n", 141 | " # Mean of returns\n", 142 | " data[\"mean returns 15\"] = data[[\"returns\"]].rolling(15).mean()\n", 143 | " data[\"mean returns 60\"] = data[[\"returns\"]].rolling(60).mean()\n", 144 | "\n", 145 | " # Volatility of returns\n", 146 | " data[\"volatility returns 15\"] = data[[\"returns\"]].rolling(15).std()\n", 147 | " data[\"volatility returns 60\"] = data[[\"returns\"]].rolling(60).std()\n", 148 | " \n", 149 | " X = data[[\"returns\", \"mean returns 15\", \"mean returns 60\",\n", 150 | " \"volatility returns 15\",\n", 151 | " \"volatility returns 60\"]].iloc[-1:,:].values\n", 152 | " \n", 153 | " # Find the signal\n", 154 | " prediction = alg.predict(X)\n", 155 | " prediction = np.where(prediction==0, -1, 1)\n", 156 | " buy = prediction[0][0] > 0\n", 157 | " sell = not buy\n", 158 | " \n", 159 | " \n", 160 | " return buy, sell\n", 161 | "\n", 162 | "\n", 163 | "\n", 164 | "# True = Live Trading and False = Screener\n", 165 | "live = True\n", 166 | "\n", 167 | "if live:\n", 168 | " current_account_info = mt5.account_info()\n", 169 | " print(\"------------------------------------------------------------------\")\n", 170 | " print(\"Date: \", datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\"))\n", 171 | " print(f\"Balance: {current_account_info.balance} USD, \\t\"\n", 172 | " f\"Equity: {current_account_info.equity} USD, \\t\"\n", 173 | " f\"Profit: {current_account_info.profit} USD\")\n", 174 | " print(\"------------------------------------------------------------------\")\n", 175 | "\n", 176 | "\n", 177 | "\n", 178 | "info_order = {\n", 179 | " \"Apple\": [\"AAPL.a\", 1.00]\n", 180 | "}\n", 181 | "\n", 182 | "\n", 183 | "start = datetime.now().strftime(\"%H:%M:%S\")\n", 184 | "while True:\n", 185 | " # Verfication for launch\n", 186 | " if datetime.now().weekday() not in (5,1):\n", 187 | " is_time = datetime.now().strftime(\"%H:%M:%S\") == start #\"23:59:59\"\n", 188 | " else:\n", 189 | " is_time = False\n", 190 | "\n", 191 | " \n", 192 | " # Launch the algorithm\n", 193 | " if is_time:\n", 194 | "\n", 195 | " # Open the trades\n", 196 | " for asset in info_order.keys():\n", 197 | "\n", 198 | " # Initialize the inputs\n", 199 | " symbol = info_order[asset][0]\n", 200 | " lot = info_order[asset][1]\n", 201 | "\n", 202 | " # Create the signals\n", 203 | " buy, sell = ANN_cla_sig(symbol)\n", 204 | "\n", 205 | " # Run the algorithm\n", 206 | " if live:\n", 207 | " MT5.run(symbol, buy, sell,lot)\n", 208 | "\n", 209 | " else:\n", 210 | " print(f\"Symbol: {symbol}\\t\"\n", 211 | " f\"Buy: {buy}\\t\"\n", 212 | " f\"Sell: {sell}\")\n", 213 | " time.sleep(1)" 214 | ] 215 | }, 216 | { 217 | "cell_type": "code", 218 | "execution_count": null, 219 | "id": "ea4b28b6", 220 | "metadata": {}, 221 | "outputs": [], 222 | "source": [] 223 | } 224 | ], 225 | "metadata": { 226 | "kernelspec": { 227 | "display_name": "Python 3", 228 | "language": "python", 229 | "name": "python3" 230 | }, 231 | "language_info": { 232 | "codemirror_mode": { 233 | "name": "ipython", 234 | "version": 3 235 | }, 236 | "file_extension": ".py", 237 | "mimetype": "text/x-python", 238 | "name": "python", 239 | "nbconvert_exporter": "python", 240 | "pygments_lexer": "ipython3", 241 | "version": "3.8.8" 242 | } 243 | }, 244 | "nbformat": 4, 245 | "nbformat_minor": 5 246 | } 247 | -------------------------------------------------------------------------------- /Chapter_13/MT5.py: -------------------------------------------------------------------------------- 1 | import warnings 2 | from datetime import datetime 3 | import pandas as pd 4 | import MetaTrader5 as mt5 5 | warnings.filterwarnings("ignore") 6 | mt5.initialize() 7 | 8 | 9 | class MT5: 10 | 11 | def get_data(symbol, n, timeframe=mt5.TIMEFRAME_D1): 12 | """ Function to import the data of the chosen symbol""" 13 | 14 | # Initialize the connection if there is not 15 | mt5.initialize() 16 | 17 | # Current date extract 18 | utc_from = datetime.now() 19 | 20 | # Import the data into a tuple 21 | rates = mt5.copy_rates_from(symbol, timeframe, utc_from, n) 22 | 23 | # Tuple to dataframe 24 | rates_frame = pd.DataFrame(rates) 25 | 26 | # Convert time in seconds into the datetime format 27 | rates_frame['time'] = pd.to_datetime(rates_frame['time'], unit='s') 28 | 29 | # Convert the column "time" in the right format 30 | rates_frame['time'] = pd.to_datetime(rates_frame['time'], format='%Y-%m-%d') 31 | 32 | # Set column time as the index of the dataframe 33 | rates_frame = rates_frame.set_index('time') 34 | return rates_frame 35 | 36 | def orders(symbol, lot, buy=True, id_position=None): 37 | """ Send the orders """ 38 | 39 | # Initialize the connection if there is not 40 | if mt5.initialize() == False: 41 | mt5.initialize() 42 | 43 | # Get filling mode 44 | filling_mode = mt5.symbol_info(symbol).filling_mode - 1 45 | 46 | # Take ask price 47 | ask_price = mt5.symbol_info_tick(symbol).ask 48 | 49 | # Take bid price 50 | bid_price = mt5.symbol_info_tick(symbol).bid 51 | 52 | # Take the point of the asset 53 | point = mt5.symbol_info(symbol).point 54 | 55 | deviation = 20 # mt5.getSlippage(symbol) 56 | # **************************** Open a trade ***************************** 57 | if id_position == None: 58 | 59 | # Buy order Parameters 60 | if buy: 61 | type_trade = mt5.ORDER_TYPE_BUY 62 | sl = ask_price*(1-0.01) 63 | tp = ask_price*(1+0.01) 64 | price = ask_price 65 | 66 | # Sell order Parameters 67 | else: 68 | type_trade = mt5.ORDER_TYPE_SELL 69 | sl = bid_price*(1+0.01) 70 | tp = bid_price*(1-0.01) 71 | price = bid_price 72 | 73 | # Open the trade 74 | request = { 75 | "action": mt5.TRADE_ACTION_DEAL, 76 | "symbol": symbol, 77 | "volume": lot, 78 | "type": type_trade, 79 | "price": price, 80 | "deviation": deviation, 81 | "sl": sl, 82 | "tp": tp, 83 | "magic": 234000, 84 | "comment": "python script order", 85 | "type_time": mt5.ORDER_TIME_GTC, 86 | "type_filling": filling_mode, 87 | } 88 | # send a trading request 89 | result = mt5.order_send(request) 90 | result_comment = result.comment 91 | 92 | # **************************** Close a trade ***************************** 93 | else: 94 | # Buy order Parameters 95 | if buy: 96 | type_trade = mt5.ORDER_TYPE_SELL 97 | price = bid_price 98 | 99 | # Sell order Parameters 100 | else: 101 | type_trade = mt5.ORDER_TYPE_BUY 102 | price = ask_price 103 | 104 | # Close the trade 105 | request = { 106 | "action": mt5.TRADE_ACTION_DEAL, 107 | "symbol": symbol, 108 | "volume": lot, 109 | "type": type_trade, 110 | "position": id_position, 111 | "price": price, 112 | "deviation": deviation, 113 | "magic": 234000, 114 | "comment": "python script order", 115 | "type_time": mt5.ORDER_TIME_GTC, 116 | "type_filling": filling_mode, 117 | } 118 | 119 | # send a trading request 120 | result = mt5.order_send(request) 121 | result_comment = result.comment 122 | return result.comment 123 | 124 | def resume(): 125 | """ Return the current positions. Position=0 --> Buy """ 126 | # Initialize the connection if there is not 127 | mt5.initialize() 128 | 129 | # Define the name of the columns that we will create 130 | colonnes = ["ticket", "position", "symbol", "volume"] 131 | 132 | # Go take the current open trades 133 | current = mt5.positions_get() 134 | 135 | # Create a empty dataframe 136 | summary = pd.DataFrame() 137 | 138 | # Loop to add each row in dataframe 139 | # (Can be ameliorate using of list of list) 140 | for element in current: 141 | element_pandas = pd.DataFrame([element.ticket, 142 | element.type, 143 | element.symbol, 144 | element.volume], 145 | index=colonnes).transpose() 146 | summary = pd.concat((summary, element_pandas), axis=0) 147 | 148 | return summary 149 | 150 | 151 | def run(symbol, long, short, lot): 152 | 153 | # Initialize the connection if there is not 154 | if mt5.initialize() == False: 155 | mt5.initialize() 156 | 157 | # Choose your symbol 158 | print("------------------------------------------------------------------") 159 | print("Date: ", datetime.now().strftime("%Y-%m-%d %H:%M:%S")) 160 | print("SYMBOL:", symbol) 161 | 162 | # Initialize the device 163 | current_open_positions = MT5.resume() 164 | # Buy or sell 165 | print(f"BUY: {long} \t SHORT: {short}") 166 | 167 | """ Close trade eventually """ 168 | # Extraction type trade 169 | try: 170 | position = current_open_positions.loc[current_open_positions["symbol"]==symbol].values[0][1] 171 | 172 | identifier = current_open_positions.loc[current_open_positions["symbol"]==symbol].values[0][0] 173 | except: 174 | position= None 175 | identifier = None 176 | 177 | print(f"POSITION: {position} \t ID: {identifier}") 178 | 179 | # Close trades 180 | if long==True and position==0: 181 | long=False 182 | 183 | elif long==False and position==0: 184 | res = MT5.orders(symbol, lot, buy=True, id_position=identifier) 185 | print(f"CLOSE LONG TRADE: {res}") 186 | 187 | elif short==True and position ==1: 188 | short=False 189 | 190 | elif short == False and position == 1: 191 | res = MT5.orders(symbol, lot, buy=False, id_position=identifier) 192 | print(f"CLOSE SHORT TRADE: {res}") 193 | 194 | else: 195 | pass 196 | 197 | 198 | """ Buy or short """ 199 | if long==True: 200 | 201 | res = MT5.orders(symbol, lot, buy=True, id_position=None) 202 | print(f"OPEN LONG TRADE: {res}") 203 | 204 | if short==True: 205 | res = MT5.orders(symbol, lot, buy=False, id_position=None) 206 | print(f"OPEN SHORT TRADE: {res}") 207 | 208 | print("------------------------------------------------------------------") 209 | 210 | def close_all_night(): 211 | result = MT5.resume() 212 | for i in range(len(result)): 213 | before = mt5.account_info().balance 214 | row = result.iloc[0+i:1+i,:] 215 | if row["position"][0]==0: 216 | res = MT5.orders(row["symbol"][0], row["volume"][0], buy=True, id_position=row["ticket"][0]) 217 | 218 | else: 219 | res = MT5.orders(row["symbol"][0], row["volume"][0], buy=False, id_position=row["ticket"][0]) -------------------------------------------------------------------------------- /Chapter_13/Models/ANN_reg_AAPL.a.data-00000-of-00001: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_13/Models/ANN_reg_AAPL.a.data-00000-of-00001 -------------------------------------------------------------------------------- /Chapter_13/Models/ANN_reg_AAPL.a.index: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_13/Models/ANN_reg_AAPL.a.index -------------------------------------------------------------------------------- /Chapter_13/Models/checkpoint: -------------------------------------------------------------------------------- 1 | model_checkpoint_path: "ANN_reg_AAPL.a" 2 | all_model_checkpoint_paths: "ANN_reg_AAPL.a" 3 | -------------------------------------------------------------------------------- /Chapter_13/checkpoint: -------------------------------------------------------------------------------- 1 | model_checkpoint_path: "ANN_reg" 2 | all_model_checkpoint_paths: "ANN_reg" 3 | -------------------------------------------------------------------------------- /Chapter_14/MT5.py: -------------------------------------------------------------------------------- 1 | import warnings 2 | from datetime import datetime 3 | import pandas as pd 4 | import MetaTrader5 as mt5 5 | warnings.filterwarnings("ignore") 6 | mt5.initialize() 7 | 8 | 9 | class MT5: 10 | 11 | def get_data(symbol, n, timeframe=mt5.TIMEFRAME_D1): 12 | """ Function to import the data of the chosen symbol""" 13 | 14 | # Initialize the connection if there is not 15 | mt5.initialize() 16 | 17 | # Current date extract 18 | utc_from = datetime.now() 19 | 20 | # Import the data into a tuple 21 | rates = mt5.copy_rates_from(symbol, timeframe, utc_from, n) 22 | 23 | # Tuple to dataframe 24 | rates_frame = pd.DataFrame(rates) 25 | 26 | # Convert time in seconds into the datetime format 27 | rates_frame['time'] = pd.to_datetime(rates_frame['time'], unit='s') 28 | 29 | # Convert the column "time" in the right format 30 | rates_frame['time'] = pd.to_datetime(rates_frame['time'], format='%Y-%m-%d') 31 | 32 | # Set column time as the index of the dataframe 33 | rates_frame = rates_frame.set_index('time') 34 | return rates_frame 35 | 36 | def orders(symbol, lot, buy=True, id_position=None): 37 | """ Send the orders """ 38 | 39 | # Initialize the connection if there is not 40 | if mt5.initialize() == False: 41 | mt5.initialize() 42 | 43 | # Get filling mode 44 | filling_mode = mt5.symbol_info(symbol).filling_mode - 1 45 | 46 | # Take ask price 47 | ask_price = mt5.symbol_info_tick(symbol).ask 48 | 49 | # Take bid price 50 | bid_price = mt5.symbol_info_tick(symbol).bid 51 | 52 | # Take the point of the asset 53 | point = mt5.symbol_info(symbol).point 54 | 55 | deviation = 20 # mt5.getSlippage(symbol) 56 | # **************************** Open a trade ***************************** 57 | if id_position == None: 58 | 59 | # Buy order Parameters 60 | if buy: 61 | type_trade = mt5.ORDER_TYPE_BUY 62 | sl = ask_price*(1-0.01) 63 | tp = ask_price*(1+0.01) 64 | price = ask_price 65 | 66 | # Sell order Parameters 67 | else: 68 | type_trade = mt5.ORDER_TYPE_SELL 69 | sl = bid_price*(1+0.01) 70 | tp = bid_price*(1-0.01) 71 | price = bid_price 72 | 73 | # Open the trade 74 | request = { 75 | "action": mt5.TRADE_ACTION_DEAL, 76 | "symbol": symbol, 77 | "volume": lot, 78 | "type": type_trade, 79 | "price": price, 80 | "deviation": deviation, 81 | "sl": sl, 82 | "tp": tp, 83 | "magic": 234000, 84 | "comment": "python script order", 85 | "type_time": mt5.ORDER_TIME_GTC, 86 | "type_filling": filling_mode, 87 | } 88 | # send a trading request 89 | result = mt5.order_send(request) 90 | result_comment = result.comment 91 | 92 | # **************************** Close a trade ***************************** 93 | else: 94 | # Buy order Parameters 95 | if buy: 96 | type_trade = mt5.ORDER_TYPE_SELL 97 | price = bid_price 98 | 99 | # Sell order Parameters 100 | else: 101 | type_trade = mt5.ORDER_TYPE_BUY 102 | price = ask_price 103 | 104 | # Close the trade 105 | request = { 106 | "action": mt5.TRADE_ACTION_DEAL, 107 | "symbol": symbol, 108 | "volume": lot, 109 | "type": type_trade, 110 | "position": id_position, 111 | "price": price, 112 | "deviation": deviation, 113 | "magic": 234000, 114 | "comment": "python script order", 115 | "type_time": mt5.ORDER_TIME_GTC, 116 | "type_filling": filling_mode, 117 | } 118 | 119 | # send a trading request 120 | result = mt5.order_send(request) 121 | result_comment = result.comment 122 | return result.comment 123 | 124 | def resume(): 125 | """ Return the current positions. Position=0 --> Buy """ 126 | # Initialize the connection if there is not 127 | mt5.initialize() 128 | 129 | # Define the name of the columns that we will create 130 | colonnes = ["ticket", "position", "symbol", "volume"] 131 | 132 | # Go take the current open trades 133 | current = mt5.positions_get() 134 | 135 | # Create a empty dataframe 136 | summary = pd.DataFrame() 137 | 138 | # Loop to add each row in dataframe 139 | # (Can be ameliorate using of list of list) 140 | for element in current: 141 | element_pandas = pd.DataFrame([element.ticket, 142 | element.type, 143 | element.symbol, 144 | element.volume], 145 | index=colonnes).transpose() 146 | summary = pd.concat((summary, element_pandas), axis=0) 147 | 148 | return summary 149 | 150 | 151 | def run(symbol, long, short, lot): 152 | 153 | # Initialize the connection if there is not 154 | if mt5.initialize() == False: 155 | mt5.initialize() 156 | 157 | # Choose your symbol 158 | print("------------------------------------------------------------------") 159 | print("Date: ", datetime.now().strftime("%Y-%m-%d %H:%M:%S")) 160 | print("SYMBOL:", symbol) 161 | 162 | # Initialize the device 163 | current_open_positions = MT5.resume() 164 | # Buy or sell 165 | print(f"BUY: {long} \t SHORT: {short}") 166 | 167 | """ Close trade eventually """ 168 | # Extraction type trade 169 | try: 170 | position = current_open_positions.loc[current_open_positions["symbol"]==symbol].values[0][1] 171 | 172 | identifier = current_open_positions.loc[current_open_positions["symbol"]==symbol].values[0][0] 173 | except: 174 | position= None 175 | identifier = None 176 | 177 | print(f"POSITION: {position} \t ID: {identifier}") 178 | 179 | # Close trades 180 | if long==True and position==0: 181 | long=False 182 | 183 | elif long==False and position==0: 184 | res = MT5.orders(symbol, lot, buy=True, id_position=identifier) 185 | print(f"CLOSE LONG TRADE: {res}") 186 | 187 | elif short==True and position ==1: 188 | short=False 189 | 190 | elif short == False and position == 1: 191 | res = MT5.orders(symbol, lot, buy=False, id_position=identifier) 192 | print(f"CLOSE SHORT TRADE: {res}") 193 | 194 | else: 195 | pass 196 | 197 | 198 | """ Buy or short """ 199 | if long==True: 200 | 201 | res = MT5.orders(symbol, lot, buy=True, id_position=None) 202 | print(f"OPEN LONG TRADE: {res}") 203 | 204 | if short==True: 205 | res = MT5.orders(symbol, lot, buy=False, id_position=None) 206 | print(f"OPEN SHORT TRADE: {res}") 207 | 208 | print("------------------------------------------------------------------") 209 | 210 | def close_all_night(): 211 | result = MT5.resume() 212 | for i in range(len(result)): 213 | before = mt5.account_info().balance 214 | row = result.iloc[0+i:1+i,:] 215 | if row["position"][0]==0: 216 | res = MT5.orders(row["symbol"][0], row["volume"][0], buy=True, id_position=row["ticket"][0]) 217 | 218 | else: 219 | res = MT5.orders(row["symbol"][0], row["volume"][0], buy=False, id_position=row["ticket"][0]) -------------------------------------------------------------------------------- /Chapter_14/Models/RNN_reg_Netflix_Inc_(NFLX.O).data-00000-of-00001: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_14/Models/RNN_reg_Netflix_Inc_(NFLX.O).data-00000-of-00001 -------------------------------------------------------------------------------- /Chapter_14/Models/RNN_reg_Netflix_Inc_(NFLX.O).index: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_14/Models/RNN_reg_Netflix_Inc_(NFLX.O).index -------------------------------------------------------------------------------- /Chapter_14/Models/checkpoint: -------------------------------------------------------------------------------- 1 | model_checkpoint_path: "RNN_reg_Netflix_Inc_(NFLX.O)" 2 | all_model_checkpoint_paths: "RNN_reg_Netflix_Inc_(NFLX.O)" 3 | -------------------------------------------------------------------------------- /Chapter_14/RNN_reg_Netflix_Inc_(NFLX.O).data-00000-of-00001: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_14/RNN_reg_Netflix_Inc_(NFLX.O).data-00000-of-00001 -------------------------------------------------------------------------------- /Chapter_14/RNN_reg_Netflix_Inc_(NFLX.O).index: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_14/RNN_reg_Netflix_Inc_(NFLX.O).index -------------------------------------------------------------------------------- /Chapter_14/RNN_reg_app.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 2, 6 | "id": "3895ae4b", 7 | "metadata": {}, 8 | "outputs": [ 9 | { 10 | "name": "stdout", 11 | "output_type": "stream", 12 | "text": [ 13 | "------------------------------------------------------------------\n", 14 | "Date: 2021-09-24 07:09:38\n", 15 | "Balance: 996.75 USD, \tEquity: 996.75 USD, \tProfit: 0.0 USD\n", 16 | "------------------------------------------------------------------\n", 17 | "WARNING:tensorflow:Unresolved object in checkpoint: (root).optimizer.iter\n", 18 | "WARNING:tensorflow:Unresolved object in checkpoint: (root).optimizer.beta_1\n", 19 | "WARNING:tensorflow:Unresolved object in checkpoint: (root).optimizer.beta_2\n", 20 | "WARNING:tensorflow:Unresolved object in checkpoint: (root).optimizer.decay\n", 21 | "WARNING:tensorflow:Unresolved object in checkpoint: (root).optimizer.learning_rate\n", 22 | "WARNING:tensorflow:A checkpoint was restored (e.g. tf.train.Checkpoint.restore or tf.keras.Model.load_weights) but not all checkpointed values were used. See above for specific issues. Use expect_partial() on the load status object, e.g. tf.train.Checkpoint.restore(...).expect_partial(), to silence these warnings, or use assert_consumed() to make the check explicit. See https://www.tensorflow.org/guide/checkpoint#loading_mechanics for details.\n", 23 | "------------------------------------------------------------------\n", 24 | "Date: 2021-09-24 07:09:46\n", 25 | "SYMBOL: Netflix_Inc_(NFLX.O)\n", 26 | "BUY: True \t SHORT: False\n", 27 | "POSITION: None \t ID: None\n", 28 | "OPEN LONG TRADE: Market closed\n", 29 | "------------------------------------------------------------------\n" 30 | ] 31 | }, 32 | { 33 | "ename": "KeyboardInterrupt", 34 | "evalue": "", 35 | "output_type": "error", 36 | "traceback": [ 37 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", 38 | "\u001b[1;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", 39 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 238\u001b[0m \u001b[1;34mf\"Buy: {buy}\\t\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 239\u001b[0m f\"Sell: {sell}\")\n\u001b[1;32m--> 240\u001b[1;33m \u001b[0mtime\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msleep\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", 40 | "\u001b[1;31mKeyboardInterrupt\u001b[0m: " 41 | ] 42 | } 43 | ], 44 | "source": [ 45 | "from MT5 import *\n", 46 | "import numpy as np\n", 47 | "import pandas as pd\n", 48 | "import warnings\n", 49 | "warnings.filterwarnings(\"ignore\")\n", 50 | "import time\n", 51 | "import pickle\n", 52 | "from joblib import dump, load\n", 53 | "import os\n", 54 | "from sklearn.preprocessing import StandardScaler\n", 55 | "from tensorflow.keras.models import Sequential\n", 56 | "from tensorflow.keras.layers import Dense, LSTM, Dropout\n", 57 | "\n", 58 | "\n", 59 | "path = \"\" # Ex: C:/Desktop/Python_for_finance_and_algorithmic_trading/ChapterN/Models\n", 60 | "\n", 61 | "def X_3d_RNN(X_s, y_s, lag):\n", 62 | "\n", 63 | " # Simple verification\n", 64 | " if len(X_s) != len(y_s):\n", 65 | " print(\"Warnings\")\n", 66 | "\n", 67 | " # Create the X_train\n", 68 | " X_train = []\n", 69 | " for variable in range(0, X_s.shape[1]):\n", 70 | " X = []\n", 71 | " for i in range(lag, X_s.shape[0]):\n", 72 | " X.append(X_s[i-lag:i, variable])\n", 73 | " X_train.append(X)\n", 74 | " X_train, np.array(X_train)\n", 75 | " X_train = np.swapaxes(np.swapaxes(X_train, 0, 1), 1, 2)\n", 76 | "\n", 77 | " # Create the y_train\n", 78 | " y_train = []\n", 79 | " for i in range(lag, y_s.shape[0]):\n", 80 | " y_train.append(y_s[i, :].reshape(-1,1).transpose())\n", 81 | " y_train = np.concatenate(y_train, axis=0)\n", 82 | " return X_train, y_train\n", 83 | "\n", 84 | "\n", 85 | "\n", 86 | "def RNN():\n", 87 | " # Create the model\n", 88 | " number_hidden_layer = 15\n", 89 | " number_neurons = 10\n", 90 | " loss=\"mse\"\n", 91 | " metrics=[\"mae\"]\n", 92 | " activation=\"linear\"\n", 93 | " optimizer=\"adam\"\n", 94 | " pct_dropout=0.5\n", 95 | " \n", 96 | " # INITIALIZATION OF THE DATA\n", 97 | " model = Sequential()\n", 98 | "\n", 99 | " # ADD LSTM LAYER\n", 100 | " model.add(LSTM(units = number_neurons, return_sequences = True, input_shape = (15,5,)))\n", 101 | "\n", 102 | " # ADD DROPOUT LAYER\n", 103 | " model.add(Dropout(pct_dropout))\n", 104 | "\n", 105 | " # LOOP WHICH ADD LSTM AND DROPPOUT LAYER\n", 106 | " for _ in range(number_hidden_layer):\n", 107 | " model.add(LSTM(units = number_neurons, return_sequences = True))\n", 108 | " model.add(Dropout(pct_dropout))\n", 109 | "\n", 110 | " # LAST LSTM LAYER BUT WITH return_sequences = False\n", 111 | " model.add(LSTM(units = number_neurons, return_sequences = False))\n", 112 | "\n", 113 | " # ADD DROPOUT LAYER\n", 114 | " model.add(Dropout(pct_dropout))\n", 115 | "\n", 116 | " # OUTPUT DENSE LAYER\n", 117 | " model.add(Dense(1, activation=activation))\n", 118 | "\n", 119 | " # COMPILE THE MODEL\n", 120 | " model.compile(loss=loss, optimizer=optimizer, metrics=metrics)\n", 121 | " return model\n", 122 | "\n", 123 | "def create_model_weights(symbol):\n", 124 | " \"\"\" Weights for Linear regression on the percentage change\"\"\"\n", 125 | " # Import the data\n", 126 | " data = MT5.get_data(symbol, 3500)[[\"close\"]].pct_change(1)\n", 127 | " \n", 128 | " # Create new variable\n", 129 | " data.columns = [\"returns\"]\n", 130 | "\n", 131 | " # Features engeeniring\n", 132 | " data[\"returns t-1\"] = data[[\"returns\"]].shift(1)\n", 133 | "\n", 134 | " # Mean of returns\n", 135 | " data[\"mean returns 15\"] = data[[\"returns\"]].rolling(15).mean().shift(1)\n", 136 | " data[\"mean returns 60\"] = data[[\"returns\"]].rolling(60).mean().shift(1)\n", 137 | "\n", 138 | " # Volatility of returns\n", 139 | " data[\"volatility returns 15\"] = data[[\"returns\"]].rolling(15).std().shift(1)\n", 140 | " data[\"volatility returns 60\"] = data[[\"returns\"]].rolling(60).std().shift(1)\n", 141 | " \n", 142 | " # Split the data\n", 143 | " data = data.dropna()\n", 144 | " split = int(0.80*len(data))\n", 145 | " \n", 146 | " # Train set creation\n", 147 | " X_train = data[[\"returns t-1\", \"mean returns 15\", \"mean returns 60\",\n", 148 | " \"volatility returns 15\",\n", 149 | " \"volatility returns 60\"]].iloc[:split]\n", 150 | " y_train = np.round(data[[\"returns\"]].iloc[:split]+0.5)\n", 151 | " \n", 152 | " \n", 153 | " \n", 154 | " # Initialize the class\n", 155 | " sc = StandardScaler()\n", 156 | "\n", 157 | " # Standardize the data\n", 158 | " X_train = sc.fit_transform(X_train)\n", 159 | " \n", 160 | " lag = 15\n", 161 | " X_train, y_train = X_3d_RNN(X_train, y_train.values, 15)\n", 162 | " \n", 163 | " alg = RNN()\n", 164 | "\n", 165 | " # TRAINING\n", 166 | " alg.fit(X_train, y_train, epochs=1, batch_size=32, verbose=1)\n", 167 | " \n", 168 | " # Save the model\n", 169 | " print(\"Train the model because there are no existed weights\")\n", 170 | " alg.save_weights(os.path.join(path,f\"Models/RNN_reg_{symbol}\"))\n", 171 | " \n", 172 | " \n", 173 | " \n", 174 | "def RNN_reg_sig(symbol):\n", 175 | " \"\"\" Function for predict the value of tommorow using ARIMA model\"\"\"\n", 176 | " \n", 177 | " # Create the weights if there is not in the folder\n", 178 | " try:\n", 179 | " alg = RNN()\n", 180 | " alg.load_weights(os.path.join(path,f\"Models/RNN_reg_{symbol}\"))\n", 181 | " except:\n", 182 | " create_model_weights(symbol)\n", 183 | " alg = RNN()\n", 184 | " alg.load_weights(os.path.join(path,f\"Models/RNN_reg_{symbol}\"))\n", 185 | " \n", 186 | " # Take the lastest percentage of change \n", 187 | " data = MT5.get_data(symbol, 3500)[[\"close\"]].pct_change(1)\n", 188 | " # Create new variable\n", 189 | " data.columns = [\"returns\"]\n", 190 | "\n", 191 | " # Features engeeniring\n", 192 | "\n", 193 | " # Mean of returns\n", 194 | " data[\"mean returns 15\"] = data[[\"returns\"]].rolling(15).mean()\n", 195 | " data[\"mean returns 60\"] = data[[\"returns\"]].rolling(60).mean()\n", 196 | "\n", 197 | " # Volatility of returns\n", 198 | " data[\"volatility returns 15\"] = data[[\"returns\"]].rolling(15).std()\n", 199 | " data[\"volatility returns 60\"] = data[[\"returns\"]].rolling(60).std()\n", 200 | " \n", 201 | " \n", 202 | " X = data[[\"returns\", \"mean returns 15\", \"mean returns 60\",\n", 203 | " \"volatility returns 15\",\n", 204 | " \"volatility returns 60\"]]\n", 205 | " \n", 206 | " # Initialize the class\n", 207 | " sc = StandardScaler()\n", 208 | "\n", 209 | " # Standardize the data\n", 210 | " X = sc.fit_transform(X)\n", 211 | " \n", 212 | " y = data[[\"returns t-1\"]]\n", 213 | "\n", 214 | " X, _ = X_3d_RNN(X, y.values, 15)\n", 215 | "\n", 216 | " X = X[-1:,:,:]\n", 217 | "\n", 218 | " # Find the signal\n", 219 | " prediction = alg.predict(X)\n", 220 | " buy = prediction[0][0] > 0\n", 221 | " sell = not buy\n", 222 | " \n", 223 | " \n", 224 | " return buy, sell\n", 225 | "\n", 226 | "\n", 227 | "\n", 228 | "# True = Live Trading and Flse = Screener\n", 229 | "live = True\n", 230 | "\n", 231 | "\n", 232 | "if live:\n", 233 | " current_account_info = mt5.account_info()\n", 234 | " print(\"------------------------------------------------------------------\")\n", 235 | " print(\"Date: \", datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\"))\n", 236 | " print(f\"Balance: {current_account_info.balance} USD, \\t\"\n", 237 | " f\"Equity: {current_account_info.equity} USD, \\t\"\n", 238 | " f\"Profit: {current_account_info.profit} USD\")\n", 239 | " print(\"------------------------------------------------------------------\")\n", 240 | "\n", 241 | "\n", 242 | "\n", 243 | "\n", 244 | "info_order = {\n", 245 | " \"Netflix\": [\"Netflix_Inc_(NFLX.O)\", 1.00]\n", 246 | "}\n", 247 | "\n", 248 | "\n", 249 | "start = datetime.now().strftime(\"%H:%M:%S\")\n", 250 | "while True:\n", 251 | " # Verfication for launch\n", 252 | " if datetime.now().weekday() not in (5,1):\n", 253 | " is_time = datetime.now().strftime(\"%H:%M:%S\") == start #\"23:59:59\"\n", 254 | " else:\n", 255 | " is_time = False\n", 256 | "\n", 257 | " \n", 258 | " # Launch the algorithm\n", 259 | " if is_time:\n", 260 | "\n", 261 | " # Open the trades\n", 262 | " for asset in info_order.keys():\n", 263 | "\n", 264 | " # Initialize the inputs\n", 265 | " symbol = info_order[asset][0]\n", 266 | " lot = info_order[asset][1]\n", 267 | "\n", 268 | " # Create the signals\n", 269 | " buy, sell = RNN_reg_sig(symbol)\n", 270 | "\n", 271 | " # Run the algorithm\n", 272 | " if live:\n", 273 | " MT5.run(symbol, buy, sell,lot)\n", 274 | "\n", 275 | " else:\n", 276 | " print(f\"Symbol: {symbol}\\t\"\n", 277 | " f\"Buy: {buy}\\t\"\n", 278 | " f\"Sell: {sell}\")\n", 279 | " time.sleep(1)" 280 | ] 281 | }, 282 | { 283 | "cell_type": "code", 284 | "execution_count": null, 285 | "id": "7414e47b", 286 | "metadata": {}, 287 | "outputs": [], 288 | "source": [] 289 | } 290 | ], 291 | "metadata": { 292 | "kernelspec": { 293 | "display_name": "Python 3", 294 | "language": "python", 295 | "name": "python3" 296 | }, 297 | "language_info": { 298 | "codemirror_mode": { 299 | "name": "ipython", 300 | "version": 3 301 | }, 302 | "file_extension": ".py", 303 | "mimetype": "text/x-python", 304 | "name": "python", 305 | "nbconvert_exporter": "python", 306 | "pygments_lexer": "ipython3", 307 | "version": "3.8.8" 308 | } 309 | }, 310 | "nbformat": 4, 311 | "nbformat_minor": 5 312 | } 313 | -------------------------------------------------------------------------------- /Chapter_14/checkpoint: -------------------------------------------------------------------------------- 1 | model_checkpoint_path: "RNN_reg_Netflix_Inc_(NFLX.O)" 2 | all_model_checkpoint_paths: "RNN_reg_Netflix_Inc_(NFLX.O)" 3 | -------------------------------------------------------------------------------- /Chapter_16/Models/Bitcoin_reg.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_16/Models/Bitcoin_reg.joblib -------------------------------------------------------------------------------- /Chapter_16/Models/EURUSD_reg.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_16/Models/EURUSD_reg.joblib -------------------------------------------------------------------------------- /Chapter_16/Models/NAS100_reg.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_16/Models/NAS100_reg.joblib -------------------------------------------------------------------------------- /Chapter_16/Models/US2000_reg.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quantreo/2nd-edition-BOOK-AMAZON-Python-for-Finance-and-Algorithmic-Trading/04b1430c5058b5ec4efa517829232f525463b611/Chapter_16/Models/US2000_reg.joblib -------------------------------------------------------------------------------- /Chapter_16/Voting_project_app.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "id": "7d0ca1c9", 7 | "metadata": {}, 8 | "outputs": [ 9 | { 10 | "name": "stdout", 11 | "output_type": "stream", 12 | "text": [ 13 | "------------------------------------------------------------------\n", 14 | "Date: 2021-09-24 07:11:13\n", 15 | "Balance: 987.03 USD, \tEquity: 987.03 USD, \tProfit: 0.0 USD\n", 16 | "------------------------------------------------------------------\n", 17 | "------------------------------------------------------------------\n", 18 | "Date: 2021-09-24 07:11:13\n", 19 | "SYMBOL: US2000\n", 20 | "BUY: True \t SHORT: False\n", 21 | "POSITION: None \t ID: None\n", 22 | "OPEN LONG TRADE: Request executed\n", 23 | "------------------------------------------------------------------\n", 24 | "------------------------------------------------------------------\n", 25 | "Date: 2021-09-24 07:11:13\n", 26 | "SYMBOL: Bitcoin\n", 27 | "BUY: True \t SHORT: False\n", 28 | "POSITION: None \t ID: None\n", 29 | "OPEN LONG TRADE: Request executed\n", 30 | "------------------------------------------------------------------\n", 31 | "------------------------------------------------------------------\n", 32 | "Date: 2021-09-24 07:11:13\n", 33 | "SYMBOL: NAS100\n", 34 | "BUY: True \t SHORT: False\n", 35 | "POSITION: None \t ID: None\n", 36 | "OPEN LONG TRADE: Request executed\n", 37 | "------------------------------------------------------------------\n" 38 | ] 39 | }, 40 | { 41 | "ename": "KeyboardInterrupt", 42 | "evalue": "", 43 | "output_type": "error", 44 | "traceback": [ 45 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", 46 | "\u001b[1;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", 47 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 138\u001b[0m \u001b[1;31m# Verfication for launch\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 139\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mdatetime\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mnow\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mweekday\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[1;32min\u001b[0m \u001b[1;33m(\u001b[0m\u001b[1;36m5\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m3\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 140\u001b[1;33m \u001b[0mis_time\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mdatetime\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mnow\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mstrftime\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"%H:%M:%S\"\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m==\u001b[0m \u001b[0mstart\u001b[0m \u001b[1;31m#\"23:59:59\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 141\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 142\u001b[0m \u001b[0mis_time\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;32mFalse\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", 48 | "\u001b[1;31mKeyboardInterrupt\u001b[0m: " 49 | ] 50 | } 51 | ], 52 | "source": [ 53 | "from MT5 import *\n", 54 | "import numpy as np\n", 55 | "import pandas as pd\n", 56 | "import warnings\n", 57 | "warnings.filterwarnings(\"ignore\")\n", 58 | "from sklearn.svm import SVC\n", 59 | "from sklearn.tree import DecisionTreeClassifier\n", 60 | "from sklearn.linear_model import LogisticRegression\n", 61 | "import time\n", 62 | "from sklearn.ensemble import VotingClassifier\n", 63 | "import pickle\n", 64 | "from joblib import dump, load\n", 65 | "import os\n", 66 | "from sklearn.preprocessing import StandardScaler\n", 67 | "\n", 68 | "path = \"\" # Ex: C:/Desktop/Python_for_finance_and_algorithmic_trading/ChapterN/\n", 69 | "\n", 70 | "\n", 71 | "def create_model_weights(symbol):\n", 72 | " \"\"\" Weights for Linear regression on the percentage change\"\"\"\n", 73 | " # Import the data\n", 74 | " data = MT5.get_data(symbol, 3500)[[\"close\"]].pct_change(1)\n", 75 | " \n", 76 | " # Create new variable\n", 77 | " data.columns = [\"returns\"]\n", 78 | "\n", 79 | " # Features engeeniring\n", 80 | " data[\"returns t-1\"] = data[[\"returns\"]].shift(1)\n", 81 | "\n", 82 | " # Mean of returns\n", 83 | " data[\"mean returns 15\"] = data[[\"returns\"]].rolling(15).mean().shift(1)\n", 84 | " data[\"mean returns 60\"] = data[[\"returns\"]].rolling(60).mean().shift(1)\n", 85 | "\n", 86 | " # Volatility of returns\n", 87 | " data[\"volatility returns 15\"] = data[[\"returns\"]].rolling(15).std().shift(1)\n", 88 | " data[\"volatility returns 60\"] = data[[\"returns\"]].rolling(60).std().shift(1)\n", 89 | " \n", 90 | " # Split the data\n", 91 | " data = data.dropna()\n", 92 | " split = int(0.80*len(data))\n", 93 | " \n", 94 | " # Train set creation\n", 95 | " X_train = data[[\"returns t-1\", \"mean returns 15\", \"mean returns 60\",\n", 96 | " \"volatility returns 15\",\n", 97 | " \"volatility returns 60\"]].iloc[:split]\n", 98 | " y_train = np.round(data[[\"returns\"]].iloc[:split]+0.5)\n", 99 | " \n", 100 | " sc = StandardScaler()\n", 101 | " X_train = sc.fit_transform(X_train)\n", 102 | " \n", 103 | " # Create the model\n", 104 | " tree = DecisionTreeClassifier(max_depth=6)\n", 105 | " svr = SVC()\n", 106 | " lin = LogisticRegression()\n", 107 | "\n", 108 | " alg = VotingClassifier(estimators=[\n", 109 | " ('lr', lin), (\"tree\", tree), (\"svr\", svr)])\n", 110 | "\n", 111 | " # Fit the model\n", 112 | " alg.fit(X_train, y_train)\n", 113 | " \n", 114 | " # Save the model\n", 115 | " alg_var = pickle.dumps(alg)\n", 116 | " alg_pickel = pickle.loads(alg_var)\n", 117 | "\n", 118 | " dump(alg_pickel ,os.path.join(path,f\"Models/{symbol}_reg.joblib\"))\n", 119 | " \n", 120 | " \n", 121 | " \n", 122 | "\n", 123 | "def vot_cla_sig(symbol):\n", 124 | " \"\"\" Function for predict the value of tommorow using ARIMA model\"\"\"\n", 125 | " \n", 126 | " # Create the weights if there is not in the folder\n", 127 | " try:\n", 128 | " alg = load(os.path.join(path,f\"Models/{symbol}_reg.joblib\"))\n", 129 | " except:\n", 130 | " create_model_weights(symbol)\n", 131 | " alg = load(os.path.join(path,f\"Models/{symbol}_reg.joblib\"))\n", 132 | " \n", 133 | " # Take the lastest percentage of change \n", 134 | " data = MT5.get_data(symbol, 3500)[[\"close\"]].pct_change(1)\n", 135 | " \n", 136 | " # Create new variable\n", 137 | " data.columns = [\"returns\"]\n", 138 | "\n", 139 | " # Features engeeniring\n", 140 | "\n", 141 | " # Mean of returns\n", 142 | " data[\"mean returns 15\"] = data[[\"returns\"]].rolling(15).mean()\n", 143 | " data[\"mean returns 60\"] = data[[\"returns\"]].rolling(60).mean()\n", 144 | "\n", 145 | " # Volatility of returns\n", 146 | " data[\"volatility returns 15\"] = data[[\"returns\"]].rolling(15).std()\n", 147 | " data[\"volatility returns 60\"] = data[[\"returns\"]].rolling(60).std()\n", 148 | " \n", 149 | " X = data[[\"returns\", \"mean returns 15\", \"mean returns 60\",\n", 150 | " \"volatility returns 15\",\n", 151 | " \"volatility returns 60\"]].iloc[-1:,:].values\n", 152 | " \n", 153 | " # Find the signal\n", 154 | " prediction = alg.predict(X)\n", 155 | " prediction = np.where(prediction==0, -1, 1)\n", 156 | " buy = prediction[0] > 0\n", 157 | " sell = not buy\n", 158 | " \n", 159 | " \n", 160 | " return buy, sell\n", 161 | "\n", 162 | "\n", 163 | "# True = Live Trading and False = Screener\n", 164 | "live = True\n", 165 | "\n", 166 | "if live:\n", 167 | " current_account_info = mt5.account_info()\n", 168 | " print(\"------------------------------------------------------------------\")\n", 169 | " print(\"Date: \", datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\"))\n", 170 | " print(f\"Balance: {current_account_info.balance} USD, \\t\"\n", 171 | " f\"Equity: {current_account_info.equity} USD, \\t\"\n", 172 | " f\"Profit: {current_account_info.profit} USD\")\n", 173 | " print(\"------------------------------------------------------------------\")\n", 174 | "\n", 175 | "\n", 176 | "info_order = {\n", 177 | " \"RUSSEL 2000\": [\"US2000\", 1.1],\n", 178 | " \"Bitcoin\": [\"Bitcoin\", 0.1],\n", 179 | " \"Nasdaq 100\": [\"NAS100\", 0.3]\n", 180 | "}\n", 181 | "\n", 182 | "\n", 183 | "start = datetime.now().strftime(\"%H:%M:%S\")\n", 184 | "while True:\n", 185 | " # Verfication for launch\n", 186 | " if datetime.now().weekday() not in (5,3):\n", 187 | " is_time = datetime.now().strftime(\"%H:%M:%S\") == start #\"23:59:59\"\n", 188 | " else:\n", 189 | " is_time = False\n", 190 | "\n", 191 | " \n", 192 | " # Launch the algorithm\n", 193 | " if is_time:\n", 194 | "\n", 195 | " # Open the trades\n", 196 | " for asset in info_order.keys():\n", 197 | "\n", 198 | " # Initialize the inputs\n", 199 | " symbol = info_order[asset][0]\n", 200 | " lot = info_order[asset][1]\n", 201 | "\n", 202 | " # Create the signals\n", 203 | " buy, sell = vot_cla_sig(symbol)\n", 204 | "\n", 205 | " # Run the algorithm\n", 206 | " if live:\n", 207 | " MT5.run(symbol, buy, sell,lot)\n", 208 | "\n", 209 | " else:\n", 210 | " print(f\"Symbol: {symbol}\\t\"\n", 211 | " f\"Buy: {buy}\\t\"\n", 212 | " f\"Sell: {sell}\")\n", 213 | " time.sleep(1)" 214 | ] 215 | }, 216 | { 217 | "cell_type": "code", 218 | "execution_count": null, 219 | "id": "ca127ff4", 220 | "metadata": {}, 221 | "outputs": [], 222 | "source": [] 223 | } 224 | ], 225 | "metadata": { 226 | "kernelspec": { 227 | "display_name": "Python 3", 228 | "language": "python", 229 | "name": "python3" 230 | }, 231 | "language_info": { 232 | "codemirror_mode": { 233 | "name": "ipython", 234 | "version": 3 235 | }, 236 | "file_extension": ".py", 237 | "mimetype": "text/x-python", 238 | "name": "python", 239 | "nbconvert_exporter": "python", 240 | "pygments_lexer": "ipython3", 241 | "version": "3.8.8" 242 | } 243 | }, 244 | "nbformat": 4, 245 | "nbformat_minor": 5 246 | } 247 | -------------------------------------------------------------------------------- /Chapter_16/quantreo/portfolio.py: -------------------------------------------------------------------------------- 1 | from scipy.optimize import minimize 2 | import numpy as np 3 | import pandas as pds 4 | 5 | 6 | 7 | def SOR_criterion(weight, data): 8 | """ 9 | ----------------------------------------------------------------------------- 10 | | Output: Opposite Sortino ratio to do a m imization | 11 | ----------------------------------------------------------------------------- 12 | | Inputs: -Weight (type ndarray numpy): Wheight for portfolio | 13 | | -data (type dataframe pandas): Returns of stocks | 14 | ----------------------------------------------------------------------------- 15 | """ 16 | # Compute portfolio returns 17 | portfolio_return = np.multiply(data, np.transpose(weight)) 18 | portfolio_return = portfolio_return.sum(axis=1) 19 | 20 | # Compute mean, volatility of the portfolio 21 | mean = np.mean(portfolio_return, axis=0) 22 | std = np.std(portfolio_return[portfolio_return < 0], axis=0) 23 | 24 | # Compute the opposite of the Sharpe ratio 25 | Sortino = mean / std 26 | Sortino = -Sortino 27 | return Sortino 28 | 29 | 30 | def MV_criterion(weights, data): 31 | """ 32 | ----------------------------------------------------------------------------- 33 | | Output: optimization porfolio criterion | 34 | ----------------------------------------------------------------------------- 35 | | Inputs: -weight (type ndarray numpy): Wheight for portfolio | 36 | | -data (type ndarray numpy): Returns of stocks | 37 | ----------------------------------------------------------------------------- 38 | """ 39 | 40 | # Parameters 41 | Lambda = 3 42 | W = 1 43 | Wbar = 1 + 0.25 / 100 44 | 45 | # Compute portfolio returns 46 | portfolio_return = np.multiply(data, np.transpose(weights)) 47 | portfolio_return = portfolio_return.sum(axis=1) 48 | 49 | # Compute mean and volatility of the portfolio 50 | mean = np.mean(portfolio_return, axis=0) 51 | std = np.std(portfolio_return, axis=0) 52 | 53 | # Compute the criterion 54 | criterion = Wbar ** (1 - Lambda) / (1 + Lambda) + Wbar ** (-Lambda) \ 55 | * W * mean - Lambda / 2 * Wbar ** (-1 - Lambda) * W ** 2 * std ** 2 56 | criterion = -criterion 57 | return criterion 58 | 59 | def SK_criterion(weights, data): 60 | """ 61 | ----------------------------------------------------------------------------- 62 | | Output: optimization porfolio criterion | 63 | ----------------------------------------------------------------------------- 64 | | Inputs: -weight (type ndarray numpy): Wheight for portfolio | 65 | | -data (type ndarray numpy): Returns of stocks | 66 | ----------------------------------------------------------------------------- 67 | """ 68 | from scipy.stats import skew, kurtosis 69 | # Parameters 70 | Lambda = 3 71 | W = 1 72 | Wbar = 1 + 0.25 / 100 73 | 74 | # Compute portfolio returns 75 | portfolio_return = np.multiply(data, np.transpose(weights)) 76 | portfolio_return = portfolio_return.sum(axis=1) 77 | 78 | # Compute mean, volatility, skew, kurtosis of the portfolio 79 | mean = np.mean(portfolio_return, axis=0) 80 | std = np.std(portfolio_return, axis=0) 81 | skewness = skew(portfolio_return, 0) 82 | kurt = kurtosis(portfolio_return, 0) 83 | 84 | # Compute the criterion 85 | criterion = Wbar ** (1 - Lambda) / (1 + Lambda) + Wbar ** (-Lambda) \ 86 | * W * mean - Lambda / 2 * Wbar ** (-1 - Lambda) * W ** 2 * std ** 2 \ 87 | + Lambda * (Lambda + 1) / (6) * Wbar ** (-2 - Lambda) * W ** 3 * skewness \ 88 | - Lambda * (Lambda + 1) * (Lambda + 2) / (24) * Wbar ** (-3 - Lambda) *\ 89 | W ** 4 * kurt 90 | 91 | criterion = -criterion 92 | return criterion 93 | 94 | 95 | def optimization_portfolio(criterion, data): 96 | 97 | # Find the number of asset 98 | n=data.shape[1] 99 | 100 | # Initialisation weight value 101 | x0 = np.ones(n) 102 | 103 | # Optimization constraints problem 104 | cons=({'type':'eq', 'fun': lambda x:sum(abs(x))-1}) 105 | 106 | # Set the bounds 107 | Bounds= [(0 , 1) for i in range(0,n)] 108 | 109 | 110 | # Optimization problem solving 111 | res_SK = minimize(criterion, x0, method="SLSQP", 112 | args=(data),bounds=Bounds, 113 | constraints=cons,options={'disp': True}) 114 | 115 | # Result for computations 116 | X = res_SK.x 117 | return X 118 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Python for finance and algorithmic trading (2nd edition) 2 | 📚Find the book:https://www.amazon.com/gp/product/B0BB5DDB1Q 3 | 4 | This second version has allowed us to tweak some points of the existing chapters but especially to add **3 new chapters** based on your feedbacks of the first version. So I am proud to offer you 3 new chapters: **"Advanced backtest methods"**, **”Features and target engineering"** and **”From nothing to a live trading bot"**. **The book presents the benefits of portfolio management, statistics and machine learning applied to live trading with MetaTrader™ 5**. 5 | 6 | Capture d’écran 2022-08-25 à 09 51 47 7 | 8 | 9 | 10 | * Learn portfolio management technics and how to implement your optimization criterion 11 | * How to backtest a strategy using the most valuable metrics in trading 12 | * Import data from your broker to be as close as possible to the market 13 | * Learn statistical arbitrage through pairs trading strategy 14 | * Generate market predictions using machine learning, deep learning, and time series analysis 15 | * Learn how to find the best take profit, stop loss, and leverage for your strategies 16 | * Combine trading strategies using portfolio management to increase the robustness of the strategies 17 | * Connect your Python algorithm to your MetaTrader 5 and run it with a demo or live trading account 18 | * All codes in the book can be used for live trading or screener if you prefer manual trading 19 | 20 | 21 | **MetaTrader configuration explanation**: https://www.youtube.com/watch?v=ZXrjwTds4vU&list=PLGaqkGqYH255Vt9EOhhLqFTDFo1Opnya2 22 | 23 | 24 | 25 | 26 | 27 | 28 | **Disclaimer**: I am not authorized by any financial authority to give investment advice. This book is for educational purposes only. I disclaim all responsibility for any loss of capital on your part. Moreover, 78.18% of private investors lose money trading CFD. Use of the information and instructions contained in this work is at your own risk. If any code samples or other technologies, this work contains or describes is subject to open-source licenses or the intellectual property rights of others, it is your responsibility to ensure that your use thereof complies with such licenses and/or rights. This book is not intended as financial advice. Please consult a qualified professional if you require financial advice. Past performance is no indication of future performance. 29 | --------------------------------------------------------------------------------