algo_trading_book/PythonCodesAndData/monteCarloOptimLeverage.py
2025-06-05 08:48:33 +02:00

100 lines
3.7 KiB
Python

# Box 8.1
import numpy as np
import pandas as pd
#from scipy.stats import describe
from scipy.stats import pearson3
#import matplotlib.pyplot as plt
#import statsmodels.formula.api as sm
#import statsmodels.tsa.stattools as ts
#import statsmodels.tsa.vector_ar.vecm as vm
from scipy.optimize import minimize
df=pd.read_csv('AUDCAD_unequal_ret.csv')
skew_, loc_, scale_=pearson3.fit(df)
print('skew=%f loc=%f scale=%f' % (skew_, loc_, scale_))
mean,var,skew,kurt=pearson3.stats(skew_, loc_, scale_, moments='mvks')
print('mean=%f var=%f skew=%f kurt=%f' % (mean, var, skew, kurt))
ret_sim=pearson3.rvs(skew_, loc_, scale_, size=100000, random_state=0)
def g(f, R):
return np.sum(np.log(1+f*R), axis=0)/R.shape[0]
myf=range(1, 24)
myg=np.full(24, np.NaN)
for f in myf:
myg[f]=g(f, ret_sim)
myg=myg[1:]
myg=pd.DataFrame(myg)
myg.plot()
minusG = lambda f : -g(f, df)
minusGsim = lambda f : -g(f, ret_sim)
#optimal leverage based on simulated returns
res = minimize(minusGsim, 0, method='Nelder-Mead')
optimalF=res.x
print('Optimal leverage=%f optimal growth rate=%f' % (optimalF, -res.fun))
#Optimal leverage=25.512625 optimal growth rate=0.005767
minR=np.min(ret_sim)
print('minR=%f' % (minR))
#minR=-0.018201
# max drawdown with optimal leverage
from calculateMaxDD import calculateMaxDD
maxDD, maxDDD, i=calculateMaxDD((np.cumproduct(1+optimalF*ret_sim)-1))
print('Max DD=%f with optimal leverage=%f' % (maxDD, optimalF))
#Max DD=-0.996312 with optimal leverage=25.512625
#max drawdown with half of optimal leverage
maxDD, maxDDD, i=calculateMaxDD((np.cumproduct(1+optimalF/2*ret_sim)-1))
print('Max DD=%f with half optimal leverage=%f' % (maxDD, optimalF/2))
#Max DD=-0.900276 with half optimal leverage=12.756313
# max drawdown with 1/7 of optimal leverage
maxDD, maxDDD, i=calculateMaxDD((np.cumproduct(1+optimalF/7*ret_sim)-1))
print('Max DD=%f with half optimal leverage=%f' % (maxDD, optimalF/7))
#Max DD=-0.429629 with half optimal leverage=3.644661
#max drawdown with 1/1.4 of optimal leverage for historical returns
maxDD, maxDDD, i=calculateMaxDD((np.cumproduct(1+optimalF/1.4*df.values)-1))
print('Max DD=%f with historical returns=%f' % (maxDD, optimalF/1.4))
#Max DD=-0.625894 with historical returns=18.223304
D=0.5
print('Growth rate on simulated returns using D=%3.1f of optimal leverage on full account=%f' % (D, -minusGsim(optimalF*D)))
#Growth rate on simulated returns using D=0.5 of optimal leverage on full account=0.004317
maxDD, maxDDD, i=calculateMaxDD((np.cumproduct(1+optimalF*D*ret_sim)-1))
print('MaxDD on simulated returns using D of optimal leverage on full account=%f' % (maxDD))
#MaxDD on simulated returns using D of optimal leverage on full account=-0.900276
# CPPI
g_cppi=0
drawdown=0
for t in range(ret_sim.shape[0]):
g_cppi+=np.log(1+ret_sim[t]*D*optimalF*(1+drawdown))
drawdown=min([0, (1+drawdown)*(1+ret_sim[t])-1])
g_cppi=g_cppi/len(ret_sim)
print('Growth rate on simulated returns using CPPI=%f' % g_cppi)
#Growth rate on simulated returns using CPPI=0.004264
print('Growth rate on historical returns using D of optimal leverage on full account=%f' % (-minusG(optimalF*D)))
#Growth rate on historical returns using D of optimal leverage on full account=0.004053
maxDD, maxDDD, i=calculateMaxDD((np.cumproduct(1+optimalF*D*df.values)-1))
print('MaxDD on historical returns using D of optimal leverage on full account=%f' % (maxDD))
#MaxDD on historical returns using D of optimal leverage on full account=-0.303448
# CPPI
g_cppi=0
drawdown=0
for t in range(df.shape[0]):
g_cppi+=np.log(1+df.iloc[t,]*D*optimalF*(1+drawdown))
drawdown=np.min([0, (1+drawdown)*(1+df.iloc[t,])-1])
g_cppi=g_cppi/len(df)
print('Growth rate on historical returns CPPI=%f' % (g_cppi))