Fix the GBM model and the price simulation - #5
Open
shehio wants to merge 1 commit into
Open
Conversation
calculate_price() returned NaN: run() invokes the estimator with a single argument while geometric_brownian expects (estimators, time, random), so estimators.mean and estimators.std were undefined. The price, estimators and horizon are now closed over by the estimator passed to run(). The model itself had two further errors: * The shock was sigma * random * time instead of sigma * sqrt(time) * random, so variance grew with the square of the horizon rather than linearly. * The drift was missing the Ito correction, and the generator was Math.random, uniform on [0, 1), where a standard normal is required. With a non-negative shock the simulated price could only ever move up. standard_normal (Box-Muller) supplies the normal draws, and the log return over dt is now (mu - sigma^2 / 2)dt + sigma * sqrt(dt) * Z, so that E[S_T] = S_0 * exp(mu * T). Measured with S_0 = 100, mu = 0.08, sigma = 0.25, T = 2 over 400k paths: the analytical mean is 117.3511; the old model gave 152.2503 (+29.7%, with 0 of 400000 shocks negative), the corrected one gives 117.2575.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
StockHelper.calculate_price()returnedNaN, and the geometric Brownian motion behind it was wrong in three independent ways. All four defects sat in a module no test reached.What Was Broken
1. Arity mismatch —
calculate_price()returnedNaN.run(sample_number, probability_distribution, estimator_function)callsestimator_function(probability_distribution()), i.e. with one argument, whilegeometric_brownian(estimators, time, random)takes three. Soestimatorswas bound to the random draw,estimators.meanandestimators.stdwereundefined, and every term wasNaN.Reproduced on
develop:2. The shock did not scale with √Δt. It was
sigma * random * time, so the variance of the log return grew astime²instead of linearly intime.3. No Itô correction. The drift was
mu * time, not(mu - sigma²/2) * time, soE[S_T]overshotS_0·e^{μT}byexp(σ²T/2).4.
Math.random()was used where a standard normal is required. It is uniform on[0, 1)and therefore never negative — the simulated price could only ever be pushed up. Over 400,000 draws, 0 shocks were negative and the minimum shock was exactly0.0000.The Fix
calculate_price(price, estimators, time, sample_size?)closes over the price, estimators and horizon, so the single-argument estimatorrun()expects receives only the random draw. It now returnsS_0 · E[exp(log return)].standard_normal()(Box-Muller) supplies the normal draws.Δtis now(μ − σ²/2)Δt + σ√(Δt)·Z, soE[S_T] = S_0·e^{μT}.console.loginsidegeometric_brownian; it printed one line per Monte Carlo path.Measured Before and After
S_0 = 100,μ = 0.08,σ = 0.25,T = 2, 400,000 paths. AnalyticalE[S_T] = S_0·e^{μT} = 117.3511.E[S_T]The resulting distribution is lognormal, as it should be — the log returns are normal:
(μ − σ²/2)Tσ²TTests
finance/test/models.test.tsis new and is the first test to reachfinance/models.tsat all. It covers the standard normal's moments, that it actually produces negative draws, the Itô correction, the √Δt scaling, and the convergence ofE[S_T]toS_0·e^{μT}.Suite: 34 tests / 10 suites before → 40 tests / 11 suites after, all passing.
🤖 Generated with Claude Code
https://claude.ai/code/session_01THEv7BFJd31NjvBRehbZPL