Fitting Gaussian Random Walk to stock prices

I am trying to find the underlying ‘hidden’ price of a stock by modelling it as a Gaussian Random walk for the past 100 days. This is the model that I have:

n_samples = 500
with pm.Model() as model:
    σ = pm.Exponential('σ', 1/np.abs(np.diff(y,axis=0)).mean())
    f = pm.GaussianRandomWalk('f', sd=σ, shape=len(y))
    
    sd = pm.Bound(pm.Normal, lower=0.0, upper=0.1)('sd', mu=0.0, sd=1.0, testval=1.0)
    likelihood = pm.Normal('y', mu=f, sd=sd, observed=y)
    
    trace = pm.sample(n_samples, njobs=4)

However ‘f’ simply ends up being zero. I bounded sd because it was an attempt to make it ‘stick’ to the observed prices a bit better. Having it unbounded didn’t improve or worsen the model. Any thoughts on how I could improve this model? The full code is here, (see cell 27/28).

Your model is unidentifiable as it is. Think of it this way: the variance in each observation in y comes from 2 places: from the GaussianRandomWalk controlled by σ (also the covariance with the previous time point) and the Normal distribution controlled by sd. With uniform prior, y could be generated completely from a GaussianRandomWalk with σ=var(diff(y)), or a Normal distribution with sd=var(y).

You can put more informative prior on the σ for the random walk (currently you use Exponential which put too much weight on the small value, thus pushing the variance of y all loaded onto the Normal), but I like to instead model the total variance and distribute them onto σ and sd:

with pm.Model() as model:
    smth_parm = pm.Uniform("alpha", lower=0, upper=1)
    mu2 = pm.Normal("mu", sd=100)
    tau2 = pm.Exponential("tau", 1.0/100)
    z2 = pm.GaussianRandomWalk("f",
                           mu=mu2,
                           tau=tau2 / (1.0 - smth_parm), 
                           shape=y.shape)
    obs = pm.Normal("obs", 
                    mu=z2, 
                    tau=tau2 / smth_parm, 
                    observed=y)
    trace = pm.sample(1000, njobs=4, tune=1000)

Which variance contributed more is controlled by alpha, you can interpreted it as a smoothing parameter.

You can find more explanations here:

2 Likes