Code: const double t_D = t; const double left_BSM = BSM_C - BSM_P; // const double right_BSM = S - D - K * exp(-r * t); // WRONG, but wikipedia says so // const double right_BSM = S - D * exp(-r * t_D) - K * exp(-r * t); // WRONG, but some research papers say so, fe. "Extracting Implied Dividends from Options Prices", p2 // const double right_BSM = S - D * exp(-q * t_D) - K * exp(-r * t); // WRONG const double right_BSM = S * exp(-q * t_D) - K * exp(-r * t); // this is used in the BSM formula, it fits, but is it also correct? it's not intuitive
The FPM algorithm and the FPM P/C parity: Code: FPM(S=100, K=100, t=1, s=30%, r=0%, q=0%): Internal info: S=100.000000 K=100.000000 t=1.000000000000 s=0.300000 r=0.000000 q=0.000000 Sx=100.000000 C_ITMX=0.000000000000 P_ITMX=0.000000000000 st=0.300000000000 rt=0.000000000000 qt=0.000000000000 u=0.000000000000 ut=0.000000000000 exp_mrt=1.000000000000 exp_mqt=1.000000000000 exp_mut=1.000000000000 z2=-0.300000000000 z0=0.000000000000 z1=0.300000000000 p2=0.382088577811 p0=0.500000000000 p1=0.617911422189 d_p=0.235822844378 K_d_p=23.582284437791 p_S2K=p0=0.500000000000 p_S2K_rest=0.500000000000 FPM: CALL=11.791142218895 PUT=11.791142218895 FPM P/C parity: (K * d_p * p_S2K = C0 (100.000000 * 0.235823 * 0.500000 = 11.791142 (C0 + C_ITMX * p_S2K) * exp(-r * t) = C (11.791142 + 0.000000 * 0.500000) * 1.000000 = 11.791142218895 ((K * d_p - C0) + P_ITMX * p_S2K_rest) * exp(-r * t) = P ((100.000000 * 0.235823 - 11.791142) + 0.000000 * 0.500000) * 1.000000 = 11.791142218895
Hahahahaha.... you found the criminal conspiracy but only realized about put call parity despite there being several posts about it in your various threads. but don’t fret. I only taunt so as to slow you down. I don’t want you to figure out what I have. It’s worth hundreds of millions. I made that 28mm on 2,000.
Now with the FPM algorithm published (s.a.), people should be able to confirm my finding that the BSM algorithm is wrong as written here: https://www.elitetrader.com/et/threads/the-fairput-initiative.349291/page-11#post-5191774
The FPM algorithm is conceptually different from the BSM algorithm (due to the wanted "same payoff for CALL and PUT at same z distance" requirement; this affects primarily the PUT side). But since BSM has a bug, I'll now try to fix it by keeping its other features/behaviors as is... Soon in this theater...
To recapitulate: there are two issues with BSM: 1) Wrong pricing for both CALL and PUT 2) PUT payoff is less than it should be I guess @newwurldmn has somehow found a way for profiting from these issues... If I think deeper and longer, I think I too could figure it out, but unfortunately I lack the motivation for profiting by using such an IMHO unethical way...
Minor typo fixes (superfluous braces) in the FPM P/C parity in https://www.elitetrader.com/et/threads/the-fairput-initiative.349291/page-13#post-5193079 : Code: FPM P/C parity: K * d_p * p_S2K = C0 100.000000 * 0.235823 * 0.500000 = 11.791142218895 (C0 + C_ITMX * p_S2K) * exp(-r * t) = C (11.791142 + 0.000000 * 0.500000) * 1.000000 = 11.791142218895 (K * d_p - C0 + P_ITMX * p_S2K_rest) * exp(-r * t) = P (100.000000 * 0.235823 - 11.791142 + 0.000000 * 0.500000) * 1.000000 = 11.791142218895
The key here is of course: d_p = p1 - p2 That's: p2=cdf(z2)=0.382088577811 p0=cdf(z0)=0.500000000000 p1=cdf(z1)=1.0-p2=0.617911422189 d_p=p1-p2=0.235822844378 K_d_p=K*d_p=23.582284437791 p_S2K=p0=0.500000000000 p_S2K_rest=1.0-p_S2K=0.500000000000 Of course one can slightly optimize by making p1 = 1.0 - p2 p1 and p2 are similar to d1 and d2 in BSM, but (of course) have differing probability values due to differing underlying z values.
...continued: z0 is calculated exactly the same like in BSM. But z1 and z2 differ: BSM takes half of sigma off of z0, we take whole sigma, as it stochastically should be, IMO. Code: // calculate lognormal z // formula "St = S * exp(z * s * sqrt(t) + u * t)" solved for z // ATTN: for BSM: fForward=false must be used double calc_z(const double St, const double S, const double st, const double ut, const bool fForward) { return (log(St / S) + (fForward ? -ut : ut)) / st; } BSM (w/o any "Ito's lemma" stuff, that substitute too is my invention :-)): const double st = s * sqrt(t); const double u = r - q; const double ut = u * t; const double z0 = calc_z(S, K, st, ut, false); // last param must be "false" const double z1 = z0 + st / 2.0; const double z2 = z0 - st / 2.0; const double p0 = normal_cdf(z0); // also interesting, but not used in BSM const double p1 = normal_cdf(z1); const double p2 = normal_cdf(z2); ... FPM: const double st = s * sqrt(t); const double u = r - q; const double ut = u * t; const double z0 = calc_z(S, K, st, ut, false); // last param must be "false" const double z1 = z0 + st; const double z2 = z0 - st; const double p0 = normal_cdf(z0); // also interesting & required in FPM const double p1 = normal_cdf(z1); const double p2 = normal_cdf(z2); ... As can be seen, the difference is in z1 and z2, and that p0 is mandatory in FPM.