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.
- class PricingParameters:
- _div = [[], []]
- _r = 0
- _T = 0
- _S0 = 0
- _r2 = [[], []]
- _pvdividends = 0
- _fvdividends = 0
- @staticmethod
- def preparedivs(divi, T, dt):
- dividends = [[], []]
- #2 columns vector, one for amount one for time.
- #we make sure we don't take into account dividend happening after expiration
- if (np.size(divi)>0 and divi[0][0]<T) :
- lastdiv = np.nonzero(np.array(divi[0][:])<= T)[0][-1]
- dividends[0] = divi[0][:lastdiv+1]
- dividends[1] = divi[1][:lastdiv+1]
- #Transform the dividend date into a step
- if np.size(dividends)>0:
- dividendsStep = np.floor(np.multiply(dividends[0], 1/dt))
- else:
- dividendsStep = []
- return dividends, dividendsStep
- @staticmethod
- def preparerates(r2, T, dt, NTS):
- r = [[], []]
- #similar structure for rates
- # rates with date d1 is use until date d1 so we need the first date post maturity.
- if np.size(r2)>0 :
- lastrate = np.nonzero(np.array(r2[0][:])>= T)[0]+1
- #i take the one just after expiration
- r[0] = r2[0][:lastrate]
- r[1] = r2[1][:lastrate]
- if np.size(r)>0:
- rateChangeStep = np.floor(np.multiply(r[0], 1/dt))
- else:
- rateChangeStep = []
- #prepare the array for rates used for the PDE
- rArray = np.zeros((NTS+2, 1), float)
- DFArray = np.zeros((NTS+2, 1), float)
- #get the steps where the rate changes
- prevstep = 0
- for step in range(len(rateChangeStep)):
- DFArray[prevstep:min(rateChangeStep[step], NTS+2)] = np.exp(-r[1][step]*dt)
- rArray[prevstep:min(rateChangeStep[step], NTS+2)] = r[1][step]
- prevstep = rateChangeStep[step]
- return r, rArray, rateChangeStep, DFArray
- def __init__(self, S0, T, r2 = "", divi = ""):
- self._S0 = float(S0)
- self._T = float(T)
- self._r2 = r2
- self._pvdividends=0
- self._fvdividends=0
- #we don't store dividends past T
- if (np.size(divi)>0 and divi[0][0]<T) :
- lastdiv = np.nonzero(np.array(divi[0][:])<= T)[0][-1]
- self._div[0] = divi[0][:lastdiv+1]
- self._div[1] = divi[1][:lastdiv+1]
- dividends, dividendsStep = PricingParameters.preparedivs(divi, T, 1/365.0)
- r, rArray, rateChangeStep, DFArray = PricingParameters.preparerates(r2,T, 1/365.0,int(T*365))
- #calculate equivalent constant rate for r:
- df=np.prod(DFArray[0:int(T*365)])
- self._r=-np.log(df)/T
- #for the two dividend handling methods we need present and forward value of the dividend
- if np.size(self._div)>0:
- for index, dv in enumerate(list(self._div[1])):
- self._pvdividends = self._pvdividends+dv*np.prod(DFArray[:np.int_(dividendsStep[index])])
- self._fvdividends = self._fvdividends+dv*np.prod(1.0/DFArray[np.int_(dividendsStep[index]):int(T*365)])
- def printSelf(self):
- print "S0\tstock price at time 0:", self._S0
- print "r\tcontinuously compounded risk-free rate:", self._r
- print "T\ttime to maturity in trading years:", self._T
- print "D\tDividends:", self._div
- print "FV of the dividends:", self._fvdividends
- print "PV of the dividends:", self._pvdividends
Aucun commentaire:
Enregistrer un commentaire