PageRenderTime 28ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/BDDS_dnaCompleteExome_optimized/pymodules/python2.7/lib/python/statsmodels-0.5.0-py2.7-linux-x86_64.egg/statsmodels/sandbox/tsa/diffusion2.py

https://gitlab.com/pooja043/Globus_Docker
Python | 505 lines | 461 code | 0 blank | 44 comment | 0 complexity | b16bd7126aff5edd524d227a8beaed92 MD5 | raw file
  1. """ Diffusion 2: jump diffusion, stochastic volatility, stochastic time
  2. Created on Tue Dec 08 15:03:49 2009
  3. Author: josef-pktd following Meucci
  4. License: BSD
  5. contains:
  6. CIRSubordinatedBrownian
  7. Heston
  8. IG
  9. JumpDiffusionKou
  10. JumpDiffusionMerton
  11. NIG
  12. VG
  13. References
  14. ----------
  15. Attilio Meucci, Review of Discrete and Continuous Processes in Finance: Theory and Applications
  16. Bloomberg Portfolio Research Paper No. 2009-02-CLASSROOM July 1, 2009
  17. http://papers.ssrn.com/sol3/papers.cfm?abstract_id=1373102
  18. this is currently mostly a translation from matlab of
  19. http://www.mathworks.com/matlabcentral/fileexchange/23554-review-of-discrete-and-continuous-processes-in-finance
  20. license BSD:
  21. Copyright (c) 2008, Attilio Meucci
  22. All rights reserved.
  23. Redistribution and use in source and binary forms, with or without
  24. modification, are permitted provided that the following conditions are
  25. met:
  26. * Redistributions of source code must retain the above copyright
  27. notice, this list of conditions and the following disclaimer.
  28. * Redistributions in binary form must reproduce the above copyright
  29. notice, this list of conditions and the following disclaimer in
  30. the documentation and/or other materials provided with the distribution
  31. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  32. AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  33. IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  34. ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  35. LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  36. CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  37. SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  38. INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  39. CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  40. ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  41. POSSIBILITY OF SUCH DAMAGE.
  42. TODO:
  43. * vectorize where possible
  44. * which processes are exactly simulated by finite differences ?
  45. * include or exclude (now) the initial observation ?
  46. * convert to and merge with diffusion.py (part 1 of diffusions)
  47. * which processes can be easily estimated ?
  48. loglike or characteristic function ?
  49. * tests ? check for possible index errors (random indices), graphs look ok
  50. * adjust notation, variable names, more consistent, more pythonic
  51. * delete a few unused lines, cleanup
  52. * docstrings
  53. random bug (showed up only once, need fuzz-testing to replicate)
  54. File "...\diffusion2.py", line 375, in <module>
  55. x = jd.simulate(mu,sigma,lambd,a,D,ts,nrepl)
  56. File "...\diffusion2.py", line 129, in simulate
  57. jumps_ts[n] = CumS[Events]
  58. IndexError: index out of bounds
  59. CumS is empty array, Events == -1
  60. """
  61. import numpy as np
  62. #from scipy import stats # currently only uses np.random
  63. import matplotlib.pyplot as plt
  64. class JumpDiffusionMerton(object):
  65. '''
  66. Example
  67. -------
  68. mu=.00 # deterministic drift
  69. sig=.20 # Gaussian component
  70. l=3.45 # Poisson process arrival rate
  71. a=0 # drift of log-jump
  72. D=.2 # st.dev of log-jump
  73. X = JumpDiffusionMerton().simulate(mu,sig,lambd,a,D,ts,nrepl)
  74. plt.figure()
  75. plt.plot(X.T)
  76. plt.title('Merton jump-diffusion')
  77. '''
  78. def __init__(self):
  79. pass
  80. def simulate(self, m,s,lambd,a,D,ts,nrepl):
  81. T = ts[-1] # time points
  82. # simulate number of jumps
  83. n_jumps = np.random.poisson(lambd*T, size=(nrepl, 1))
  84. jumps=[]
  85. nobs=len(ts)
  86. jumps=np.zeros((nrepl,nobs))
  87. for j in range(nrepl):
  88. # simulate jump arrival time
  89. t = T*np.random.rand(n_jumps[j])#,1) #uniform
  90. t = np.sort(t,0)
  91. # simulate jump size
  92. S = a + D*np.random.randn(n_jumps[j],1)
  93. # put things together
  94. CumS = np.cumsum(S)
  95. jumps_ts = np.zeros(nobs)
  96. for n in range(nobs):
  97. Events = np.sum(t<=ts[n])-1
  98. #print n, Events, CumS.shape, jumps_ts.shape
  99. jumps_ts[n]=0
  100. if Events > 0:
  101. jumps_ts[n] = CumS[Events] #TODO: out of bounds see top
  102. #jumps = np.column_stack((jumps, jumps_ts)) #maybe wrong transl
  103. jumps[j,:] = jumps_ts
  104. D_Diff = np.zeros((nrepl,nobs))
  105. for k in range(nobs):
  106. Dt=ts[k]
  107. if k>1:
  108. Dt=ts[k]-ts[k-1]
  109. D_Diff[:,k]=m*Dt + s*np.sqrt(Dt)*np.random.randn(nrepl)
  110. x = np.hstack((np.zeros((nrepl,1)),np.cumsum(D_Diff,1)+jumps))
  111. return x
  112. class JumpDiffusionKou(object):
  113. def __init__(self):
  114. pass
  115. def simulate(self, m,s,lambd,p,e1,e2,ts,nrepl):
  116. T=ts[-1]
  117. # simulate number of jumps
  118. N = np.random.poisson(lambd*T,size =(nrepl,1))
  119. jumps=[]
  120. nobs=len(ts)
  121. jumps=np.zeros((nrepl,nobs))
  122. for j in range(nrepl):
  123. # simulate jump arrival time
  124. t=T*np.random.rand(N[j])
  125. t=np.sort(t)
  126. # simulate jump size
  127. ww = np.random.binomial(1, p, size=(N[j]))
  128. S = ww * np.random.exponential(e1, size=(N[j])) - \
  129. (1-ww) * np.random.exponential(e2, N[j])
  130. # put things together
  131. CumS = np.cumsum(S)
  132. jumps_ts = np.zeros(nobs)
  133. for n in range(nobs):
  134. Events = sum(t<=ts[n])-1
  135. jumps_ts[n]=0
  136. if Events:
  137. jumps_ts[n]=CumS[Events]
  138. jumps[j,:] = jumps_ts
  139. D_Diff = np.zeros((nrepl,nobs))
  140. for k in range(nobs):
  141. Dt=ts[k]
  142. if k>1:
  143. Dt=ts[k]-ts[k-1]
  144. D_Diff[:,k]=m*Dt + s*np.sqrt(Dt)*np.random.normal(size=nrepl)
  145. x = np.hstack((np.zeros((nrepl,1)),np.cumsum(D_Diff,1)+jumps))
  146. return x
  147. class VG(object):
  148. '''variance gamma process
  149. '''
  150. def __init__(self):
  151. pass
  152. def simulate(self, m,s,kappa,ts,nrepl):
  153. T=len(ts)
  154. dXs = np.zeros((nrepl,T))
  155. for t in range(T):
  156. dt=ts[1]-0
  157. if t>1:
  158. dt = ts[t]-ts[t-1]
  159. #print dt/kappa
  160. #TODO: check parameterization of gamrnd, checked looks same as np
  161. d_tau = kappa * np.random.gamma(dt/kappa,1.,size=(nrepl))
  162. #print s*np.sqrt(d_tau)
  163. # this raises exception:
  164. #dX = stats.norm.rvs(m*d_tau,(s*np.sqrt(d_tau)))
  165. # np.random.normal requires scale >0
  166. dX = np.random.normal(loc=m*d_tau, scale=1e-6+s*np.sqrt(d_tau))
  167. dXs[:,t] = dX
  168. x = np.cumsum(dXs,1)
  169. return x
  170. class IG(object):
  171. '''inverse-Gaussian ??? used by NIG
  172. '''
  173. def __init__(self):
  174. pass
  175. def simulate(self, l,m,nrepl):
  176. N = np.random.randn(nrepl,1)
  177. Y = N**2
  178. X = m + (.5*m*m/l)*Y - (.5*m/l)*np.sqrt(4*m*l*Y+m*m*(Y**2))
  179. U = np.random.rand(nrepl,1)
  180. ind = U>m/(X+m)
  181. X[ind] = m*m/X[ind]
  182. return X.ravel()
  183. class NIG(object):
  184. '''normal-inverse-Gaussian
  185. '''
  186. def __init__(self):
  187. pass
  188. def simulate(self, th,k,s,ts,nrepl):
  189. T = len(ts)
  190. DXs = np.zeros((nrepl,T))
  191. for t in range(T):
  192. Dt=ts[1]-0
  193. if t>1:
  194. Dt=ts[t]-ts[t-1]
  195. l = 1/k*(Dt**2)
  196. m = Dt
  197. DS = IG().simulate(l,m,nrepl)
  198. N = np.random.randn(nrepl)
  199. DX = s*N*np.sqrt(DS) + th*DS
  200. #print DS.shape, DX.shape, DXs.shape
  201. DXs[:,t] = DX
  202. x = np.cumsum(DXs,1)
  203. return x
  204. class Heston(object):
  205. '''Heston Stochastic Volatility
  206. '''
  207. def __init__(self):
  208. pass
  209. def simulate(self, m, kappa, eta,lambd,r, ts, nrepl,tratio=1.):
  210. T = ts[-1]
  211. nobs = len(ts)
  212. dt = np.zeros(nobs) #/tratio
  213. dt[0] = ts[0]-0
  214. dt[1:] = np.diff(ts)
  215. DXs = np.zeros((nrepl,nobs))
  216. dB_1 = np.sqrt(dt) * np.random.randn(nrepl,nobs)
  217. dB_2u = np.sqrt(dt) * np.random.randn(nrepl,nobs)
  218. dB_2 = r*dB_1 + np.sqrt(1-r**2)*dB_2u
  219. vt = eta*np.ones(nrepl)
  220. v=[]
  221. dXs = np.zeros((nrepl,nobs))
  222. vts = np.zeros((nrepl,nobs))
  223. for t in range(nobs):
  224. dv = kappa*(eta-vt)*dt[t]+ lambd*np.sqrt(vt)*dB_2[:,t]
  225. dX = m*dt[t] + np.sqrt(vt*dt[t]) * dB_1[:,t]
  226. vt = vt + dv
  227. vts[:,t] = vt
  228. dXs[:,t] = dX
  229. x = np.cumsum(dXs,1)
  230. return x, vts
  231. class CIRSubordinatedBrownian(object):
  232. '''CIR subordinated Brownian Motion
  233. '''
  234. def __init__(self):
  235. pass
  236. def simulate(self, m, kappa, T_dot,lambd,sigma, ts, nrepl):
  237. T = ts[-1]
  238. nobs = len(ts)
  239. dtarr = np.zeros(nobs) #/tratio
  240. dtarr[0] = ts[0]-0
  241. dtarr[1:] = np.diff(ts)
  242. DXs = np.zeros((nrepl,nobs))
  243. dB = np.sqrt(dtarr) * np.random.randn(nrepl,nobs)
  244. yt = 1.
  245. dXs = np.zeros((nrepl,nobs))
  246. dtaus = np.zeros((nrepl,nobs))
  247. y = np.zeros((nrepl,nobs))
  248. for t in range(nobs):
  249. dt = dtarr[t]
  250. dy = kappa*(T_dot-yt)*dt + lambd*np.sqrt(yt)*dB[:,t]
  251. yt = np.maximum(yt+dy,1e-10) # keep away from zero ?
  252. dtau = np.maximum(yt*dt, 1e-6)
  253. dX = np.random.normal(loc=m*dtau, scale=sigma*np.sqrt(dtau))
  254. y[:,t] = yt
  255. dtaus[:,t] = dtau
  256. dXs[:,t] = dX
  257. tau = np.cumsum(dtaus,1)
  258. x = np.cumsum(dXs,1)
  259. return x, tau, y
  260. def schout2contank(a,b,d):
  261. th = d*b/np.sqrt(a**2-b**2)
  262. k = 1/(d*np.sqrt(a**2-b**2))
  263. s = np.sqrt(d/np.sqrt(a**2-b**2))
  264. return th,k,s
  265. if __name__ == '__main__':
  266. #Merton Jump Diffusion
  267. #^^^^^^^^^^^^^^^^^^^^^
  268. # grid of time values at which the process is evaluated
  269. #("0" will be added, too)
  270. nobs = 252.#1000 #252.
  271. ts = np.linspace(1./nobs, 1., nobs)
  272. nrepl=5 # number of simulations
  273. mu=.010 # deterministic drift
  274. sigma = .020 # Gaussian component
  275. lambd = 3.45 *10 # Poisson process arrival rate
  276. a=0 # drift of log-jump
  277. D=.2 # st.dev of log-jump
  278. jd = JumpDiffusionMerton()
  279. x = jd.simulate(mu,sigma,lambd,a,D,ts,nrepl)
  280. plt.figure()
  281. plt.plot(x.T) #Todo
  282. plt.title('Merton jump-diffusion')
  283. sigma = 0.2
  284. lambd = 3.45
  285. x = jd.simulate(mu,sigma,lambd,a,D,ts,nrepl)
  286. plt.figure()
  287. plt.plot(x.T) #Todo
  288. plt.title('Merton jump-diffusion')
  289. #Kou jump diffusion
  290. #^^^^^^^^^^^^^^^^^^
  291. mu=.0 # deterministic drift
  292. lambd=4.25 # Poisson process arrival rate
  293. p=.5 # prob. of up-jump
  294. e1=.2 # parameter of up-jump
  295. e2=.3 # parameter of down-jump
  296. sig=.2 # Gaussian component
  297. x = JumpDiffusionKou().simulate(mu,sig,lambd,p,e1,e2,ts,nrepl)
  298. plt.figure()
  299. plt.plot(x.T) #Todo
  300. plt.title('double exponential (Kou jump diffusion)')
  301. #variance-gamma
  302. #^^^^^^^^^^^^^^
  303. mu = .1 # deterministic drift in subordinated Brownian motion
  304. kappa = 1. #10. #1 # inverse for gamma shape parameter
  305. sig = 0.5 #.2 # s.dev in subordinated Brownian motion
  306. x = VG().simulate(mu,sig,kappa,ts,nrepl)
  307. plt.figure()
  308. plt.plot(x.T) #Todo
  309. plt.title('variance gamma')
  310. #normal-inverse-Gaussian
  311. #^^^^^^^^^^^^^^^^^^^^^^^
  312. # (Schoutens notation)
  313. al = 2.1
  314. be = 0
  315. de = 1
  316. # convert parameters to Cont-Tankov notation
  317. th,k,s = schout2contank(al,be,de)
  318. x = NIG().simulate(th,k,s,ts,nrepl)
  319. plt.figure()
  320. plt.plot(x.T) #Todo x-axis
  321. plt.title('normal-inverse-Gaussian')
  322. #Heston Stochastic Volatility
  323. #^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  324. m=.0
  325. kappa = .6 # 2*Kappa*Eta>Lambda^2
  326. eta = .3**2
  327. lambd =.25
  328. r = -.7
  329. T = 20.
  330. nobs = 252.*T#1000 #252.
  331. tsh = np.linspace(T/nobs, T, nobs)
  332. x, vts = Heston().simulate(m,kappa, eta,lambd,r, tsh, nrepl, tratio=20.)
  333. plt.figure()
  334. plt.plot(x.T)
  335. plt.title('Heston Stochastic Volatility')
  336. plt.figure()
  337. plt.plot(np.sqrt(vts).T)
  338. plt.title('Heston Stochastic Volatility - CIR Vol.')
  339. plt.figure()
  340. plt.subplot(2,1,1)
  341. plt.plot(x[0])
  342. plt.title('Heston Stochastic Volatility process')
  343. plt.subplot(2,1,2)
  344. plt.plot(np.sqrt(vts[0]))
  345. plt.title('CIR Volatility')
  346. #CIR subordinated Brownian
  347. #^^^^^^^^^^^^^^^^^^^^^^^^^
  348. m=.1
  349. sigma=.4
  350. kappa=.6 # 2*Kappa*T_dot>Lambda^2
  351. T_dot=1
  352. lambd=1
  353. #T=252*10
  354. #dt=1/252
  355. #nrepl=2
  356. T = 10.
  357. nobs = 252.*T#1000 #252.
  358. tsh = np.linspace(T/nobs, T, nobs)
  359. x, tau, y = CIRSubordinatedBrownian().simulate(m, kappa, T_dot,lambd,sigma, tsh, nrepl)
  360. plt.figure()
  361. plt.plot(tsh, x.T)
  362. plt.title('CIRSubordinatedBrownian process')
  363. plt.figure()
  364. plt.plot(tsh, y.T)
  365. plt.title('CIRSubordinatedBrownian - CIR')
  366. plt.figure()
  367. plt.plot(tsh, tau.T)
  368. plt.title('CIRSubordinatedBrownian - stochastic time ')
  369. plt.figure()
  370. plt.subplot(2,1,1)
  371. plt.plot(tsh, x[0])
  372. plt.title('CIRSubordinatedBrownian process')
  373. plt.subplot(2,1,2)
  374. plt.plot(tsh, y[0], label='CIR')
  375. plt.plot(tsh, tau[0], label='stoch. time')
  376. plt.legend(loc='upper left')
  377. plt.title('CIRSubordinatedBrownian')
  378. #plt.show()