Pages

mardi 26 mars 2013

Improved PricingParameters class

I improved a bit the code of the PricingParameters class.

I moved the preparediv and preparerate methods into class method for this class.
When we init pricing parameters, the class takes the vector of forward rates and calculate the equivalent spot rate by calculating the product of discount factors from 0 to expiration.
It also calculate the present value and forward value of dividends using proper rates.
It introduces a discretization of time but I fixed it to delta T= 1 day which should be perfectly acceptable.

The methods are still useable withing the pricing functions as before.
Obviously the pricer code should be updated (we remove the preparediv and preparerates static methods in the binomialpricer class and in the pricing function we need to call them via PricinParameters.preparedivs() instead...)

The following code replaces the previous class definition.

  1. class PricingParameters:  
  2.     _div = [[], []]  
  3.     _r = 0  
  4.     _T = 0  
  5.     _S0 = 0  
  6.     _r2 = [[], []]  
  7.       
  8.     _pvdividends = 0  
  9.     _fvdividends = 0  
  10.       
  11.     @staticmethod  
  12.     def preparedivs(divi, T, dt):  
  13.         dividends = [[], []]   
  14.         #2 columns vector, one for amount one for time.  
  15.         #we make sure we don't take into account dividend happening after expiration  
  16.      
  17.         if (np.size(divi)>0 and divi[0][0]<T) :  
  18.             lastdiv = np.nonzero(np.array(divi[0][:])<= T)[0][-1]  
  19.             dividends[0] = divi[0][:lastdiv+1]          
  20.             dividends[1] = divi[1][:lastdiv+1]   
  21.       
  22.         #Transform the dividend date into a step  
  23.         if np.size(dividends)>0:  
  24.             dividendsStep = np.floor(np.multiply(dividends[0], 1/dt))  
  25.         else:  
  26.             dividendsStep = []   
  27.         return dividends, dividendsStep  
  28.   
  29.     @staticmethod  
  30.     def preparerates(r2, T, dt, NTS):  
  31.         r = [[], []]  
  32.           
  33.         #similar structure for rates  
  34.         # rates with date d1 is use until date d1 so we need the first date post maturity.     
  35.         if np.size(r2)>0 :  
  36.             lastrate = np.nonzero(np.array(r2[0][:])>= T)[0]+1  
  37.             #i take the one just after expiration  
  38.             r[0] = r2[0][:lastrate]          
  39.             r[1] = r2[1][:lastrate]         
  40.         if np.size(r)>0:  
  41.             rateChangeStep = np.floor(np.multiply(r[0], 1/dt))  
  42.         else:  
  43.             rateChangeStep = []        
  44.           
  45.         #prepare the array for rates used for the PDE  
  46.         rArray = np.zeros((NTS+2, 1), float)     
  47.         DFArray = np.zeros((NTS+2, 1), float)  
  48.       
  49.         #get the steps where the rate changes  
  50.         prevstep = 0  
  51.           
  52.         for step in range(len(rateChangeStep)):  
  53.               
  54.             DFArray[prevstep:min(rateChangeStep[step], NTS+2)] = np.exp(-r[1][step]*dt)  
  55.             rArray[prevstep:min(rateChangeStep[step], NTS+2)] = r[1][step]  
  56.             prevstep = rateChangeStep[step]  
  57.   
  58.         return r, rArray, rateChangeStep, DFArray  
  59.           
  60.     def __init__(self, S0, T, r2 = "", divi = ""):  
  61.         self._S0 = float(S0)  
  62.         self._T = float(T)  
  63.         self._r2 = r2  
  64.         self._pvdividends=0  
  65.         self._fvdividends=0  
  66.           
  67.         #we don't store dividends past T  
  68.         if (np.size(divi)>0 and divi[0][0]<T) :  
  69.             lastdiv = np.nonzero(np.array(divi[0][:])<= T)[0][-1]  
  70.             self._div[0] = divi[0][:lastdiv+1]          
  71.             self._div[1] = divi[1][:lastdiv+1]  
  72.           
  73.         dividends, dividendsStep = PricingParameters.preparedivs(divi, T, 1/365.0)  
  74.         r, rArray, rateChangeStep, DFArray = PricingParameters.preparerates(r2,T, 1/365.0,int(T*365))  
  75.         #calculate equivalent constant rate for r:  
  76.         df=np.prod(DFArray[0:int(T*365)])  
  77.         self._r=-np.log(df)/T  
  78.    
  79.         #for the two dividend handling methods we need present and forward value of the dividend      
  80.         if np.size(self._div)>0:  
  81.             for index, dv in enumerate(list(self._div[1])):  
  82.                 self._pvdividends = self._pvdividends+dv*np.prod(DFArray[:np.int_(dividendsStep[index])])  
  83.                 self._fvdividends = self._fvdividends+dv*np.prod(1.0/DFArray[np.int_(dividendsStep[index]):int(T*365)])  
  84.      
  85.     def printSelf(self):       
  86.         print "S0\tstock price at time 0:",  self._S0  
  87.         print "r\tcontinuously compounded risk-free rate:",  self._r  
  88.         print "T\ttime to maturity in trading years:",  self._T  
  89.         print "D\tDividends:", self._div   
  90.         print "FV of the dividends:", self._fvdividends   
  91.         print "PV of the dividends:", self._pvdividends   


Aucun commentaire:

Enregistrer un commentaire