Timeline for Why is my Risk Neutral Density recovery failing?
Current License: CC BY-SA 4.0
14 events
when toggle format | what | by | license | comment | |
---|---|---|---|---|---|
Mar 7 at 20:54 | comment | added | v.y. |
Unfortunately, I don't have the reputation to create a chatroom. What I meant by "coincidence" is that the 2nd derivative and densityR coincide ONLY when (numElements = 10000 AND returns = np.linspace(0, 2, numElements) ... densityS = densityR / (2*(currentPrice)) ) - increasing OR decreasing either numElements or the upper bound of returns causes the 2nd derivative and densityR to drift apart - I'm trying to understand this behavior.
|
|
Mar 5 at 12:05 | comment | added | Achrbot |
Great that you found a solution! The reason you get the almost correct (i.e. up to a scaling factor) for your old calculation is because of the scaling behavior of the uniform distribution. More precisely, the vector np.ones(N)/N is the pdf of a $U(0,N)$ variable, evaluated at $1,\ldots, N$, or equivalently the probability that a U(0,1) variable lies in the interval $(0,\frac{1}{N}),\ldots,(\frac{N-1}{N},1)$. So changing $N$ (or the upper bound in linspace) changes the scale factor you are off by. Hope this helps, else you can create a chatroom for continouing the conversation.
|
|
Mar 4 at 22:00 | comment | added | v.y. |
I do think that the OLD calculation (densityS = densityR / (2*(currentPrice)) ) giving us the density of ST across the StrikePrices range wasn't correct. If I use it with returns = np.linspace(0, 10, numElements) ...densityS = densityR / (10*(currentPrice)) instead of np.linspace(0, 2, numElements) ... densityS = densityR / (2*(currentPrice)) , the second derivative diverges from densityR: imgur.com/a/i565z1x. Actually, if we just increase numElements to 50000, there is a divergence too: imgur.com/a/Nn62kk6. Could ((OLD) densityS ≈ d2ydx2) have simply been a coincidence?
|
|
Mar 4 at 21:37 | vote | accept | v.y. | ||
Mar 4 at 22:01 | |||||
Mar 4 at 21:37 | comment | added | v.y. |
I wrote densityS = scipy.stats.uniform(loc=0, scale=2*currentPrice) , and use it as pdf_values=densityS.pdf(StrikePrices) ... probability_of_lying_in_each_interval=np.insert(pdf_values[1:]*np.diff(StrikePrices),0,0) ... optionPrices[i] = np.sum(allPayoffsForCurrentStrike * probability_of_lying_in_each_interval) * np.exp(-r * tau) . When I do this, np.sum(probability_of_lying_in_each_interval)=1 , and I do manage to recover the original PDF (imgur.com/a/1ty0MLm), and also the probability_of_lying_in_each_interval. Thanks.
|
|
Mar 4 at 16:13 | comment | added | Achrbot |
To specify densityS directly, you can write densityS = np.ones(numElements)/(2*currentPrice) , or densityS = scipy.stats.uniform(StrikePrices, 0, 2*currentPrice) .
|
|
Mar 1 at 20:03 | comment | added | v.y. |
Also, how would I specify densityS directly? Even if I do StrikePrices = np.linspace(0, currentPrice*2, numElements) and densityS = np.ones(numElements) * (1 / numElements) , I still get the same issue as before (imgur.com/a/jPpMvfA).
|
|
Mar 1 at 20:00 | comment | added | v.y. |
I understand that densityS = densityR / (2*(currentPrice)) follows from the change of variables in probability. However, you said "densityR does not denote the density of R at each point, but rather the probability that R lies in each partition interval" - if that is so, how could we apply the change of variables rules, and produce a "discrete sample of the density function" - when densityR is apparently not a density?
|
|
Mar 1 at 12:05 | comment | added | Achrbot |
In general, if $X$ has density $f_X$, then $Y = aX$ has density $f_Y(y) = \frac{1}{a}f_X(\frac{y}{a})$. However, in your case, may I ask why you don't just specify \densityS directly?
|
|
Mar 1 at 11:50 | comment | added | Achrbot | This is because you have chosen the uniform distribution, and does not hold in general. IIUC, you define $R$ as being $\sim U(0,2)$, so its density $f_R(x) = \frac{1}{2}$ for $x \in [0,2]$. This means that $S_T = RS_0$ is $\sim U(0,2S_0)$, so its density $f_{S_T}(x) = \frac{1}{2S_0}$ for $x \in [0,2S_0]$. | |
Feb 29 at 20:24 | comment | added | v.y. |
I don't understand why densityS = densityR / (2*(currentPrice)) gives us the density of ST across the StrikePrices range. How do you derive that from "the probability that R lies in each partition interval = densityR"?
|
|
Feb 29 at 8:54 | comment | added | Achrbot |
densityS represents the density of ST across the range defined in StrikePrices . We don't expect densityS to sum to 1, because the size/length of its domain ( StrikePrices ) is not 1. Instead, we would expect densityS to integrate to 1, over all possible strike-prices. You can check that this is the case, by running np.sum(densityS[:-1]*np.diff(StrikePrices)) . I think you are conflating "probabilities must sum to 1" with "the discrete sample of my density function must sum to 1" (which is incorrect).
|
|
Feb 28 at 21:33 | comment | added | v.y. |
Thank you, simply doing densityS = densityR / (2*(currentPrice)) , and then using it instead of densityR in my original option price calculation ensures that (the second derivative of optionPrices with respect to StrikePrices) ≈ densityR. However, densityS sums to ~0.01, not 1. I've never done these sort of discretization problems before, so I might be missing something obvious. Can you tell me, and/or link me to further reading material, regarding why this rescaling is justified and necessary?
|
|
Feb 27 at 11:34 | history | answered | Achrbot | CC BY-SA 4.0 |