Guest User

Devenir rentier / effet de levier et stress-test

a guest
Jul 9th, 2020
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.76 KB | None | 0 0
  1. import numpy as np
  2. import random
  3. import matplotlib.pyplot as plt
  4. from progress.bar import Bar
  5. import time as tm
  6.  
  7. N = 9*int(365*5/7) ##Market open monday-friday
  8. Nbins = 200
  9. def historical_return(markets):
  10. #Generate a list of daily returns
  11.     import yfinance as yf
  12.     r=[]
  13.     for market in markets :
  14.         df = yf.download(market,period='max',interval='1d')
  15.         close = df['Close']
  16.         for i in range(1,len(close)) : r.append(100*((close[i]-close[i-1])/close[i-1]))
  17.     return r
  18.    
  19. def gaus(x,a,x0,sigma):
  20.     return a*np.exp(-(x-x0)**2/(2*sigma**2))
  21.    
  22. def generate_random(on,N):
  23.     H = np.histogram(on,bins=Nbins,density=True)
  24.     y = np.array(H[0])
  25.     x = np.linspace(H[1][0],H[1][-1],len(y))
  26.     R = []
  27.     for i in range(N): ##Méthode de rejet
  28.         search=True
  29.         while search:
  30.             j = random.randint(0,len(x)-1)
  31.             Y=x[j]
  32.             U=random.random()
  33.             if U<=y[j] :
  34.                 search=False
  35.                 R.append(Y)
  36.     return R
  37.  
  38. def cumulative(array):
  39.     S = np.sum(array)
  40.     C = [array[0]/S]
  41.     for i in range(1,len(array)):
  42.         C.append(C[-1]+array[i]/S)
  43.     return C
  44.    
  45. def gaussian_fit(R,array):
  46.     import pylab as plb
  47.     from scipy.optimize import curve_fit
  48. #    N = 200
  49.     H = plt.hist(array,bins=Nbins,label='real data',density=True)
  50.  
  51. #    Compute gaussian fit
  52. #    x = np.linspace(min(array),max(array),N)
  53.     y = np.array(H[0])
  54.     x = np.linspace(H[1][0],H[1][-1],len(y))
  55.     popt,pcov = curve_fit(gaus,x,y,p0=[1,np.mean(y),np.std(y)])
  56. #    Shell = gaussian_shell(x,popt)
  57.  
  58. #    Plot setup
  59.     xtick = np.arange(-30,30,step=5)
  60.     xticklabel = []
  61.     for xt in xtick:
  62.         xticklabel.append(str(xt)+' %')
  63.     plt.xticks(xtick)
  64.     plt.xticks(xtick,xticklabel)
  65.     plt.plot(x,gaus(x,*popt),'--',label='gaussian fit')
  66.     plt.yscale('log')
  67.     plt.ylim([0.0001,1])
  68.     plt.xlim([min(x),max(x)])
  69.     plt.xlabel('Daily return')
  70.     plt.ylabel('Normalized')
  71.     plt.hist(R,bins=100,alpha=0.5,label='simulated data',density=True,color='r')
  72.     plt.grid()
  73.     plt.legend()
  74.     plt.title('Comparing gaussian fit to reality')
  75.     plt.show()
  76.  
  77. def generate_single_scenario(multipliers,R,N):
  78.     daily_returns={}
  79.     daily_cumulated={}
  80.     for m in multipliers :
  81.         daily_returns[m]=[]
  82.         daily_cumulated[m]=[1]
  83.     for i in range(N):
  84.         rtrn=random.choice(R)
  85.         for m in multipliers :
  86.             daily_returns[m].append(1+m*rtrn/100)
  87.             daily_cumulated[m].append(daily_cumulated[m][-1]*daily_returns[m][-1])
  88.     return daily_returns,daily_cumulated
  89.  
  90. def computeTRI(initialInvest,monthlyInvest,finalValue,nYears) :
  91.     search = True
  92.     order = 1
  93.     new_rate = 1
  94.     old_rate = 1
  95.     old_VAN = np.nan
  96.     new_VAN = np.nan
  97.    
  98.     while search :
  99.         CF = [-initialInvest]
  100.         for i in range(nYears*12) :
  101.             CF.append(-monthlyInvest*(1+new_rate/100)**(-(i+1)/12))
  102.         CF.append(finalValue*(1+new_rate/100)**(-(nYears+1/12)))
  103.         old_VAN = new_VAN
  104.         new_VAN = np.sum(CF)
  105.         old_rate = new_rate
  106.         if(new_VAN*old_VAN<0) :
  107.             if order == 0.001 : search = False
  108.             order/=10
  109.             if abs(old_VAN) < abs(new_VAN) : new_rate = old_rate
  110.         elif new_VAN<0 : new_rate-=order
  111.         elif new_VAN>0 : new_rate+=order
  112.     return new_rate
  113.  
  114. def payTaxes(finalValue,initialValue,m):
  115.     tax = 0
  116.     PEA_tax = .172
  117.     CTO_tax = .3
  118.     if m==1 : #PEA
  119.         if finalValue>initialValue : tax = (finalValue-initialValue)*PEA_tax
  120.     else : ##CTO
  121.         if finalValue>initialValue : tax = (finalValue-initialValue)*CTO_tax
  122.  
  123.     finalValue -= tax
  124.     return finalValue
  125.  
  126. def compareToRegular(R) :
  127.     oneShot = []
  128.     mulShot = []
  129.     n = 2000
  130.     bar = Bar('Single shot vs. Multiple shot', max=n)
  131.     for i in range(n):
  132.         bar.next()
  133.         df,dc = generate_single_scenario([1],R,N)
  134.         df = df[1]
  135.         initialInvest = 10000
  136.         regularInvest = 500
  137.         totalInvest = initialInvest
  138.         old_portfolio = [df[0]]
  139.         new_portfolio = [df[0]*initialInvest]
  140.         for i in range(1,len(df)):
  141.             old_portfolio.append(old_portfolio[-1]*df[i])
  142.             new_portfolio.append(new_portfolio[-1]*df[i])
  143.             if i>0 and i%22==0 :
  144.                 new_portfolio[-1]+=regularInvest
  145.                 totalInvest+=regularInvest
  146.        
  147.         old_portfolio[-1] = payTaxes(old_portfolio[-1],1,1)
  148.         new_portfolio[-1] = payTaxes(new_portfolio[-1],totalInvest,1)
  149.         oneShot_tri = 100*(old_portfolio[-1]**(1/9)-1)
  150.         regular_tri = computeTRI(initialInvest,regularInvest,new_portfolio[-1],9)
  151.         oneShot.append(oneShot_tri)
  152.         mulShot.append(regular_tri)
  153.     bar.finish()
  154.  
  155.     K = 30
  156.     H,xH,yH = np.histogram2d(oneShot,mulShot,bins=K)
  157.     plt.contourf(np.linspace(xH[0],xH[-1],K),np.linspace(yH[0],yH[-1],K),H,levels=100)
  158.     plt.xlabel('One Shot')
  159.     plt.ylabel('Multiple Shot')
  160.     x=np.linspace(min(oneShot),max(oneShot),100)
  161.     print(min(oneShot),max(oneShot))
  162.     print(min(mulShot),max(mulShot))
  163.     plt.plot(x,x,'r--')
  164.     plt.colorbar()
  165.     plt.show()
  166.    
  167. def simulate_portfolio(R) :
  168.     multipliers = [1,2,3,4]
  169.     brokerMarginRequest = 0.3
  170.     def generate_multiple_scenario(multipliers,R,N):
  171.         V={}
  172.         for m in multipliers : V[m]=[]
  173.         nHisto=1500
  174.         bar = Bar('Generating histograms', max=nHisto)
  175.         for j in range(nHisto):
  176.             if j>0 and j%1000==0 : tm.sleep(10) ##Short break for CPU
  177.             bar.next()
  178.             df,dc=generate_single_scenario(multipliers,R,N)
  179.             lowestReferenceValue = min(dc[1])
  180.  
  181.             for m,returns in df.items():
  182.                 maxLoss = m*(1-lowestReferenceValue)
  183.                 if maxLoss > 1-brokerMarginRequest and m>1 : finalValue = 1e-7
  184.                 else : finalValue = np.product(returns)
  185.                
  186.                 finalValue = payTaxes(finalValue,1,m)
  187.                 V[m].append(finalValue)
  188.         bar.finish()
  189.         return V
  190.    
  191.     V = generate_multiple_scenario(multipliers,R,N)
  192.    
  193.     #Plot histograms and cumulative function
  194.     fig,ax = plt.subplots(len(multipliers),2,sharex=True)
  195.     pos=0
  196.     for m in multipliers :
  197.         #Histogram
  198.         Values = V[m]
  199.         hist, bins = np.histogram(Values, bins=Nbins)
  200.         logbins = np.logspace(np.log10(bins[0]),np.log10(bins[-1]),len(bins))
  201.         ax[pos][0].hist(Values,bins=logbins,label=str(m)+"-multiplier")
  202.         ax[pos][0].grid(True)
  203.         ax[pos][0].legend()
  204.         ax[pos][0].set_xscale('log')
  205.        
  206.         #cumulative
  207.         C=cumulative(hist)
  208.         logx = np.logspace(np.log10(bins[0]),np.log10(bins[-1]),len(C))
  209.         H,B = np.histogram(Values, bins=logbins)
  210.         C = cumulative(H)
  211.         ax[pos][1].plot(logx,C)
  212.         ax[pos][1].grid(True)
  213.         ax[pos][1].set_ylim([0,1])
  214.         ax[pos][1].set_xscale('log')
  215.         pos+=1
  216.        
  217.         print(np.mean(Values),np.std(Values))
  218.  
  219.     plt.show()
  220.  
  221. def conditional_probability(on):
  222.     def bin2label(bin,new_size):
  223.         return np.linspace(bin[0],bin[-1],new_size)
  224.        
  225.     matrix,xbins,ybins = np.histogram2d(on[:-1],on[1:],bins=50)
  226.     xbins = bin2label(xbins,matrix.shape[0])
  227.     ybins = bin2label(ybins,matrix.shape[1])
  228.     for i in range(len(ybins)):
  229.         S = np.sum(matrix[:,i])
  230.         if S>0 : matrix[:,i]/=S
  231.     plt.contourf(ybins,xbins,matrix,levels=100)
  232.     plt.xlabel('Yesterday daily-return')
  233.     plt.ylabel('Today daily-return')
  234.     plt.colorbar()
  235.     plt.show()
  236.    
  237. on = historical_return(['^GSPC'])
  238. R = generate_random(on,30000)
  239. #compareToRegular(R)
  240. #gaussian_fit(R,on)
  241. #simulate_portfolio(R)
  242. conditional_probability(on) #on is "real" data, replace by R for simulated data
  243. #conditional_probability(R)
Add Comment
Please, Sign In to add comment