<jupyter_start><jupyter_text>1. Get SP500 data<jupyter_code># !pip install yfinance
import yfinance as yf
# !pip install pandas_datareader
import pandas_datareader.data as web
import datetime
start = datetime.datetime(2000, 1, 1)
end = datetime.date.today()

sp500 = web.DataReader(['sp500'], 'fred', start, end)
sp500.shape
sp500.tail()
sp500.head()
df = yf.download(["spy"], start, end)
df.shape
df.tail()
sp500["change"] = np.log(sp500["sp500"]).diff()
sp500.isna().sum()
sp500 = sp500.dropna()
# Plot data
fig, ax = plt.subplots(figsize=(14,4))
sp500.plot(y="change", label="SP 500", ax=ax);<jupyter_output><empty_output><jupyter_text>Model<jupyter_code>def make_sv_model(data):
    with pm.Model(coords={"time": data.index.values}) as model:
        step_size = pm.Exponential("step_size", 10)
        volatility = pm.GaussianRandomWalk("volatility", sigma=step_size, dims="time")
        nu = pm.Exponential("nu", 0.1)
        returns = pm.StudentT("returns", nu=nu, lam=np.exp(-2*volatility), observed=data["change"])
    return model
model = make_sv_model(sp500)
pm.model_to_graphviz(model)
with model:
    trace = az.from_pymc3(prior=pm.sample_prior_predictive(1000))
prior_predictive = trace.prior_predictive.stack(pooled_chain=("chain", "draw"))
prior_predictive
fig, ax = plt.subplots(figsize=(14, 4))
sp500["change"].plot(ax=ax, lw=1, color="black")
ax.plot(
    prior_predictive["returns"].isel(pooled_chain=slice(4, 6, None)),
    "g",
    alpha=0.5,
    lw=1,
    zorder=-10,
)

max_observed, max_simulated = np.max(np.abs(returns["change"])), np.max(
    np.abs(prior_predictive["returns"].values)
)
ax.set_title(f"Maximum observed: {max_observed:.2g}\nMaximum simulated: {max_simulated:.2g}(!)");<jupyter_output><empty_output><jupyter_text>Fit Model<jupyter_code>with model:
    trace = pm.sample(2000, tune=2000, return_inferencedata=True)
ppc = trace.posterior.stack(pooled_chain=("chain", "draw"))
ppc["exp_volatility"] = np.exp(ppc["volatility"])
trace
az.plot_trace(trace, var_names=["step_size", "nu"]);<jupyter_output><empty_output><jupyter_text>Posterior predictive check<jupyter_code>fig, ax = plt.subplots(figsize=(12,4))
y_vals = ppc["exp_volatility"].isel(pooled_chain=slice(None, None, 5))
x_vals = pd.to_datetime(sp500.index)

plt.plot(x_vals, y_vals, "k", alpha=0.002);
fig, ax = plt.subplots(figsize=(14, 4))

y_vals = ppc["exp_volatility"].isel(pooled_chain=slice(None, None, 5))
x_vals = pd.to_datetime(sp500.index)#y_vals.time.astype(np.datetime64)

plt.plot(x_vals, y_vals, "k", alpha=0.002)
ax.set_xlim(x_vals.min(), x_vals.max())
ax.set_ylim(bottom=0)
ax.set(title="Estimated volatility over time", xlabel="Date", ylabel="Volatility");
ppc
fig, axes = plt.subplots(nrows=2, figsize=(14, 7), sharex=True)
sp500["change"].plot(ax=axes[0], color="black")

axes[1].plot(x_vals, ppc["exp_volatility"].isel(pooled_chain=slice(None, None, 100)), "r", alpha=0.5)
# axes[0].plot(
#     x_vals,
#     ppc["returns"].isel(pooled_chain=slice(None, None, 100)),
#     "g",
#     alpha=0.5,
#     zorder=-10,
# )
axes[0].set_title("True log returns (black) and posterior predictive log returns (green)")
axes[1].set_title("Posterior volatility");<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1811367895065584, 'fraction_numerical': 0.043098063710181135, 'mean_word_length': 6.608076009501188, 'pattern_counts': {'":': 1, '<': 17, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '4', 'dir': 'jupyter-structured-clean-dedup', 'id': '401944', 'license': 'Apache-2.0', 'n_tokens_mistral': 1380, 'n_tokens_neox': 1247, 'n_words': 200, 'path': 'pymc_examples/stochastic_volatility_model.ipynb', 'repo_name': 'danhphan/bayesian_inferences', 'size': '3202'}