|
From: U.Mutlu <um...@mu...> - 2023-09-10 13:01:01
|
Ioannis Rigopoulos wrote on 09/10/23 13:06: > new GeometricBrownianMotionProcess(S, mu - 0.5*sigma^2*t, sigma) Thank you for your analysis. I guess you mean "mu * t - 0.5 * sigma * sigma * t", though in our example with t=1 it doesn't make any difference. It gives for timeSteps=1 this result: $ ./Testing_GBM_of_QuantLib.exe 1 timeSteps=1 nRuns=1000000 seed=1694350548 S=100.000000 mu=0.000000 sigma=0.300000 t=1.000000 : nGenAll=1000000 USE_ITO=1 : -1SD=70.822035 +1SD=129.046162 cHit=663067/1000000(66.307%) This is far from the expected value of 68.2689% for timeStep=1. So, there must be a bug somewhere. IMO it's our suspect friend Ito :-) Cf. also the following showing similar results for GBM, which then was compared to the standard lognormal calculation: https://www.elitetrader.com/et/threads/simulating-stock-prices-using-gbm.375533/page-3#post-5849548 And, honestly, I've never seen that Sx@-1SD and Sx@+1SD get computed with Ito's lemma applied. Ioannis Rigopoulos wrote on 09/10/23 13:06: > Thank you for testing the BoxMullerGaussianRng code, which - as I wrote - does > not seem to be used in other areas of the standard part of QuantLib. > > Your numerical results below ... > > indicate that the simulated values for ln(S(t)) produced with timeSteps = 1 > are very likely normally distributed with mean (I use your notation) ln(S(0)) > + mu*t and standard deviation sigma * sqrt(t) > > This result _*is consistent*_ with: > > a) the SDE: dS(t) = S(t)*mu*dt + S(t)*sigma*dw > > _*and*_ > > b) the fact that in QuantLib the PathGenerator.next().value returns the result > of the SDE expression _*without *_applying the ITO correction associated with > the fact that dt is not infinitesimal. > > The b) is also responsible for the lack of convergence in your output towards > the theoretical target of 68.27% > > You would get the correct convergence if you modified your code by using the > expressions below: > > const double m1SD = S * exp(mu * t - 0.5*sigma^2*t + sigma * sqrt(t) * > -1.0); // Sx at -1SD > const double p1SD = S * exp(mu * t - 0.5*sigma^2*t + sigma * sqrt(t) * > 1.0); // Sx at +1SD > > new GeometricBrownianMotionProcess(S, mu - 0.5*sigma^2*t, sigma) (as > Peter also pointed out) > > Again, due to b) one can produce the correct simulated values of a GBM > diffused quantity (such as a stock price in the GBM model) by using N time > steps, with N very large. Using N = 1 (like in your example), the simulated > values will still be lognormally distributed (whence your good result with N = > 1), but will be centered at a wrong mean and thus will _*fail *_to represent > the correct values expected by the GBM SDE. > > Ioannis > > On 9/10/2023 11:29 AM, U.Mutlu wrote: >> As said in other posting here, after fixing the test program >> by skipping the first item (the initial price) in the >> generated sample path, BoxMullerGaussianRng now passes the said test. >> >> The bugfixed test code and the new test results can be found here: >> https://www.elitetrader.com/et/threads/simulating-stock-prices-using-gbm.375533/page-4#post-5861666 >> >> >> That important fact that the generated sample path contains >> not timeSteps elements but 1 + timeSteps elements needs >> to be documented in the library doc. >> For example on this API doc page one normally would expect >> to find such an important information, but it's missing: >> https://www.quantlib.org/reference/class_quant_lib_1_1_path_generator.html >> >> If you or someone else can change/extend the test program by using >> the suggested alternative(s) to BoxMullerGaussianRng, I would be happy >> to hear about it. Thx. >> >> >> Ioannis Rigopoulos wrote on 09/09/23 16:28: >>> If you search within the QuantLib code for BoxMullerGaussianRng, you will see >>> it is used only in the experimental folder. It is therefore not surprising if >>> it doesn't produce the expected results. >>> >>> I use myself the MultiPathGenerator with PseudoRandom::rsg_type, which is used >>> extensively in other areas of QuantLib. >>> >>> This type expands to InverseCumulativeRsg< RandomSequenceGenerator< >>> MersenneTwisterUniformRng > , InverseCumulativeNormal > and gives me good >>> results. >>> >>> Ioannis Rigopoulos, founder of deriscope.com |