Calibration of Ornstein-Uhlenbeck Mean Reverting Process Description The model is used for calibrating an Ornstein-Uhlenbeck (OU) process with mean reverting drift. The process can be considered to be a modification of the random walk in continuous time, or Wiener process, in which the properties of the process have been changed so that there is a tendency of the walk to move back towards a central location, with a greater attraction when the process is further away from the centre. Algorithm Details The OU process can also be considered as the continuous-time analogue of the discrete-time AR(1) process. Also, an OU model is a special case of a Hull-White-Vasicek model with constant volatility. The mean reversion nature of the process makes it suitable to describe the evolution of price of commodities such as natural gas where the long term mean is determined by physical/economical forces (e.g. supply-demand) but the price of the commodity can deviate from that long term mean significantly due to short term disturbances on the market. Figure 1 shows the spot price of natural gas with daily resolution at Henry Hub. Figure 1. Natural gas spot price, daily, dollars per million Btu, at Henry Hub 1
In the simplest case the long-term mean can be a constant but it can also follow a deterministic (e.g. seasonality) or even a stochastic process. The current implementation of the model only supports constant mean. Seasonal or other deterministic or stochastic components must be subtracted from data prior to feeding them into the model. Stochastic processes are heavily used for risk analysis and pricing derivatives. In order to avoid negative prices, the evolution of the log series is usually modeled and the result is exponentiated. In an OU process, the evolution of the quantity S t, satisfies the following stochastic differential equation (SDE): ds # = λ μ S # dt + σdw # where l > 0 is the mean reversion rate, µ is the long term mean, s 0 is the volatility or noise and W t is the Wiener process. The exact solution of the above SDE is S -./ = S - e 123 + μ 1 e 123 + σ 1 e1523 N 2λ 8,/ Where δ is the time step and N 0,1 is a Gaussian random variable with 0 mean and 1 standard deviation. The relationship between the consecutive steps S i, S i+1 is linear hence we can find the model parameters using linear regression. Figure 2. shows scenarios of a simulated OU process calibrated on the Henry Hub data. 2
Figure 2. Simulated paths of an Ornstein-Uhlenbeck process, model is calibrated on natural gas spot price at Henry Hub Input Details The input of the model has two main components stored in JSON format. {"data": data, "config": config data[dictionary] : features of data to calibrate model. series [list] : stores time series to calibrate model. It is a 1D data and stores only realizations (y), no time information is stored. time_step [float scalar] time step of data. In case of daily series use time_step = 1/253 to produce annualized parameter values (e.g. volatility). 1/253 accounts for 253 observations (i.e. business days) in a typical year. config [dictionary] : empty, kept for further usage. Example of input { "config": [], "data": { "series": [1.34,2.56,3.456,2.1,5.6], "time_step": 0.003, Output Details mean_level [float scalar] estimated value of long term mean mean_reversion_rate [float scalar] estimated value of mean reversion rate volatility : [float scalar] estimated value of volatility (or noise) of the process Example output { "result": { "mean_level": 1.37, "mean_reversion_rate": 1.11, "volatility": 0.709 Usage Example 3
We read spot price of the natural gas at Henry Hub then calibrate our model on the data. # python snippet to run model from future import division import pandas as pd from numpy import log from os import getcwd from os.path import join from analytics.data_science_functions import calibrate_mean_reversion #---------- # Read data # Henry hub daily natural gas spot prices csvfile = join(getcwd(), 'experiments', 'HenryHub_NGPrice.csv') ng_data = pd.read_csv(csvfile) # --------------- # Calibrate mean reverting model series_to_fit = log(ng_data.ngprice) dt = 1/253 # daily spot price data = {'series':series_to_fit,'time_step':dt config = [] result = calibrate_mean_reversion(data=data,config=config) print 'Mean level (mu): %4.2f' % result['mean_level'] print 'Mean reversion rate (lamda): %4.2f' % result['mean_reversion_rate'] print 'Volatility (sigma): %4.2f' % result['volatility'] >>> Mean level (mu): 1.37 >>> Mean reversion rate (lamda): 1.12 >>> Volatility (sigma): 0.71 References [1] Ornstein-Uhlenbeck Process, Wikipedia https://en.wikipedia.org/wiki/ornstein%e2%80%93uhlenbeck_process [2] Wiener process, Wolfram, http://mathworld.wolfram.com/wienerprocess.html [3] Historical natural gas price, EIA, http://www.eia.gov/dnav/ng/hist/rngwhhdd.htm 4
2016 General Electric Company All rights reserved. GE, the GE Monogram and Predix are trademarks of General Electric Company. No part of this document may be distributed, reproduced or posted without the express written permission of General Electric Company. THIS DOCUMENT AND ITS CONTENTS ARE PROVIDED AS IS, WITH NO REPRESENTATION OR WARRANTIES OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF DESIGN, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. ALL OTHER LIABILITY ARISING FROM RELIANCE UPON ANY INFORMATION CONTAINED HEREIN IS EXPRESSLY DISCLAIMED. 5