sim — Price Process Simulation
Stochastic process simulation for commodity price modelling and Monte Carlo. Process selection is driven by the cluster type of the commodity being modelled.
Process selection by cluster:
Key Functions
ou(theta, mu, sigma, n, dt=1/252, x0=None, nSims=1)Ornstein-Uhlenbeck mean-reverting process. Primary model for Cluster A.
gbm(mu, sigma, nSteps, nSims, s0=100, dt=1/252)Geometric Brownian Motion. Standard for energy-linked clusters.
levyOu(theta, mu, sigma, jumpIntensity, jumpMean, jumpStd, n, dt=1/252)Lévy OU — OU process with superimposed compound Poisson jumps.
compoundPoisson(lam, jumpMean, jumpStd, n, dt=1/252, seed=None)Compound Poisson process for event-triggered demand (Cluster B: road salt; Cluster T: floral events).
markovSwitching(states, transitionMatrix, stateMeans, stateSigmas, n, seed=None)Hidden Markov regime-switching process. Use for markets with regulatory regimes (Cluster R) or weather state transitions (Cluster B).
garch(omega, alpha, beta, n, mu=0.0, seed=None)GARCH(1,1) conditional volatility. Calibrate with
fit.fitGarch().heston(S0, v0, kappa, theta, xi, rho, r, T, nSteps, nSims, seed=None)Heston stochastic volatility model. For markets with vol-of-vol dynamics.
arma(ar, ma, n, sigma=1.0, mu=0.0, seed=None)ARMA(p,q) process for serially correlated price drivers.
poisson(lam, n, seed=None)Homogeneous Poisson process for event counting.
simulate(model, params, n, nSims=1, seed=None)General dispatcher: pass model name as string and params dict.
import sipQuant as sq
import numpy as np
# Cluster A — OU process for Alberta Hay (calibrated from fit.fitOu)
paths = sq.sim.ou(
theta=0.85, # mean reversion speed (weekly)
mu=187.50, # long-run mean price
sigma=8.20, # volatility $/tonne per week
n=52, # 1 year of weekly steps
dt=1/52,
x0=185.0,
nSims=1000,
)
# paths shape: (1000, 52)
# Cluster B — Compound Poisson for weather-event demand
jumps = sq.sim.compoundPoisson(
lam=2.5, # 2.5 demand events per year
jumpMean=35.0, # avg price spike $/tonne
jumpStd=12.0,
n=52,
dt=1/52,
seed=42,
)
# Cluster R — Markov switching for regulatory regime
transition = np.array([[0.95, 0.05], # stable → disrupted: 5%/period
[0.20, 0.80]]) # disrupted → stable: 20%/period
regime_paths = sq.sim.markovSwitching(
states=2,
transitionMatrix=transition,
stateMeans=np.array([185.0, 320.0]), # stable vs disrupted price
stateSigmas=np.array([8.0, 45.0]),
n=52,
seed=42,
)