A typical characteristic of energy commodities such as electricity and natural gas is that delivery takes place over a period in time, not on a single date. Listed futures contracts cover standardized periods, such as “Week”, “Month”, “Quarter”, “Season” or “Year”. The forward curve is an essential tool for pricing non-standard OTC contracts having any settlement period.
An example of such standard energy market contracts can be found in the package data set powfutures130513
.
powfutures130513#> Include Contract Start End Closing
#> 1 TRUE W21-13 2013-05-20 2013-05-26 33.65
#> 2 TRUE W22-13 2013-05-27 2013-06-02 35.77
#> 3 TRUE W23-13 2013-06-03 2013-06-09 36.58
#> 4 TRUE W24-13 2013-06-10 2013-06-16 35.93
#> 5 TRUE W25-13 2013-06-17 2013-06-23 33.14
#> 6 TRUE W26-13 2013-06-24 2013-06-30 34.16
#> 7 FALSE MJUN-13 2013-06-01 2013-06-30 35.35
#> 8 TRUE MJUL-13 2013-07-01 2013-07-31 33.14
#> 9 TRUE MAUG-13 2013-08-01 2013-08-31 35.72
#> 10 TRUE MSEP-13 2013-09-01 2013-09-30 38.41
#> 11 TRUE MOCT-13 2013-10-01 2013-10-31 38.81
#> 12 TRUE MNOV-13 2013-11-01 2013-11-30 40.94
#> 13 FALSE Q3-13 2013-07-01 2013-09-30 35.72
#> 14 TRUE Q4-13 2013-10-01 2013-12-31 40.53
#> 15 TRUE Q1-14 2014-01-01 2014-03-31 42.40
#> 16 TRUE Q2-14 2014-04-01 2014-06-30 33.39
#> 17 TRUE Q3-14 2014-07-01 2014-09-30 31.78
#> 18 TRUE Q4-14 2014-10-01 2014-12-31 38.25
#> 19 TRUE Q1-15 2015-01-01 2015-03-31 40.73
#> 20 TRUE Q2-15 2015-04-01 2015-06-30 32.64
#> 21 TRUE Q3-15 2015-07-01 2015-09-30 30.87
#> 22 TRUE Q4-15 2015-10-01 2015-12-31 37.22
#> 23 FALSE CAL-14 2014-01-01 2014-12-31 36.43
#> 24 FALSE CAL-15 2015-01-01 2015-12-31 35.12
#> 25 TRUE CAL-16 2016-01-01 2016-12-31 34.10
#> 26 FALSE CAL-17 2017-01-01 2017-12-31 35.22
#> 27 FALSE CAL-18 2018-01-01 2018-12-31 36.36
#> 28 FALSE CAL-19 2019-01-01 2019-12-31 37.44
#> 29 FALSE CAL-20 2020-01-01 2020-12-31 38.58
#> 30 FALSE CAL-21 2021-01-01 2021-12-31 39.73
#> 31 FALSE CAL-22 2022-01-01 2022-12-31 40.93
#> 32 FALSE CAL-23 2023-01-01 2023-12-31 42.15
The data set contains closing prices for a set of synthetic futures contracts on the trading date 2013-05-13. It can be used to create an instance of the MSFC class with:
<- msfc(tdate = as.Date("2013-05-13"),
fwd_npri include = powfutures130513$Include,
contract = powfutures130513$Contract,
sdate = powfutures130513$Start,
edate = powfutures130513$End,
f = powfutures130513$Closing)
In addition to the arguments from the list of contracts, the user may also provide a prior function to the calculation. This is relevant for markets with strong seasonality, such as power markets. The default value for the msfc()
function is prior = 0
, but the user can provide any vector expressing a belief regarding the market to be combined with the observed prices. We create a new MSFC
instance, this time including a simple seasonal prior collected from the package data set powpriors130513
:
<- msfc(tdate = as.Date("2013-05-13"),
fwd_wpri include = powfutures130513$Include,
contract = powfutures130513$Contract,
sdate = powfutures130513$Start,
edate = powfutures130513$End,
f = powfutures130513$Closing,
prior = powpriors130513$mod.prior)
Available methods for the objects fwd_npri
and fwd_wpri
are plot()
, summary()
and show()
. The effect from the prior curve can be visually inspected by comparing the two plots:
plot(fwd_npri, title = "Forward curve without prior")
plot(fwd_wpri, title = "Forward curve with prior")
As shown in the plots, the shorter contracts close in time to the trading date clearly reflect a seasonal pattern. This is typical in power markets, where weather and calendar effects have strong influence on transacted volume and price formation. On a longer horizon however, this information is not observable in market prices, as the quoted contracts cover longer time spans. This is where price data may be supplemented with prior knowledge in order to create a representation of the market consistent with both the underlying fundamentals and the listed contracts.
In etrm
, the forward curve is calculated with the function \(f(t) = \lambda(t) + \epsilon(t)\) where \(\lambda(t)\) is the prior supplied by the user and \(\epsilon(t)\) is an adjustment function taking the observed prices into account. The msfc()
function finds the smoothest possible adjustment function \(\epsilon(t)\) by minimizing the mean squared value of a spline function, while ensuring that the average value of the curve \(f(t)\) is equal to contract prices used in the calculation for the respective time intervals. The number of polynomials used in the spline along with head(prior)
and computed prices based on the curve are available with the summary()
method:
summary(fwd_npri)
#> $Description
#> [1] "MSFC of length 1329 built with 41 polynomials at trade date 2013-05-13"
#>
#> $PriorFunc
#> [1] 0 0 0 0 0 0
#>
#> $BenchSheet
#> Include Contract From To Price Comp
#> 1 TRUE W21-13 2013-05-20 2013-05-26 33.65 33.65
#> 2 TRUE W22-13 2013-05-27 2013-06-02 35.77 35.77
#> 3 TRUE W23-13 2013-06-03 2013-06-09 36.58 36.58
#> 4 TRUE W24-13 2013-06-10 2013-06-16 35.93 35.93
#> 5 TRUE W25-13 2013-06-17 2013-06-23 33.14 33.14
#> 6 TRUE W26-13 2013-06-24 2013-06-30 34.16 34.16
#> 8 TRUE MJUL-13 2013-07-01 2013-07-31 33.14 33.14
#> 9 TRUE MAUG-13 2013-08-01 2013-08-31 35.72 35.72
#> 10 TRUE MSEP-13 2013-09-01 2013-09-30 38.41 38.41
#> 11 TRUE MOCT-13 2013-10-01 2013-10-31 38.81 38.81
#> 12 TRUE MNOV-13 2013-11-01 2013-11-30 40.94 40.94
#> 14 TRUE Q4-13 2013-10-01 2013-12-31 40.53 40.53
#> 15 TRUE Q1-14 2014-01-01 2014-03-31 42.40 42.40
#> 16 TRUE Q2-14 2014-04-01 2014-06-30 33.39 33.39
#> 17 TRUE Q3-14 2014-07-01 2014-09-30 31.78 31.78
#> 18 TRUE Q4-14 2014-10-01 2014-12-31 38.25 38.25
#> 19 TRUE Q1-15 2015-01-01 2015-03-31 40.73 40.73
#> 20 TRUE Q2-15 2015-04-01 2015-06-30 32.64 32.64
#> 21 TRUE Q3-15 2015-07-01 2015-09-30 30.87 30.87
#> 22 TRUE Q4-15 2015-10-01 2015-12-31 37.22 37.22
#> 25 TRUE CAL-16 2016-01-01 2016-12-31 34.10 34.10
For comparison, the calculation including prior:
summary(fwd_wpri)
#> $Description
#> [1] "MSFC of length 1329 built with 41 polynomials at trade date 2013-05-13"
#>
#> $PriorFunc
#> [1] 30.10842 30.16396 30.19572 30.16144 29.06268 28.93272
#>
#> $BenchSheet
#> Include Contract From To Price Comp
#> 1 TRUE W21-13 2013-05-20 2013-05-26 33.65 33.65
#> 2 TRUE W22-13 2013-05-27 2013-06-02 35.77 35.77
#> 3 TRUE W23-13 2013-06-03 2013-06-09 36.58 36.58
#> 4 TRUE W24-13 2013-06-10 2013-06-16 35.93 35.93
#> 5 TRUE W25-13 2013-06-17 2013-06-23 33.14 33.14
#> 6 TRUE W26-13 2013-06-24 2013-06-30 34.16 34.16
#> 8 TRUE MJUL-13 2013-07-01 2013-07-31 33.14 33.14
#> 9 TRUE MAUG-13 2013-08-01 2013-08-31 35.72 35.72
#> 10 TRUE MSEP-13 2013-09-01 2013-09-30 38.41 38.41
#> 11 TRUE MOCT-13 2013-10-01 2013-10-31 38.81 38.81
#> 12 TRUE MNOV-13 2013-11-01 2013-11-30 40.94 40.94
#> 14 TRUE Q4-13 2013-10-01 2013-12-31 40.53 40.53
#> 15 TRUE Q1-14 2014-01-01 2014-03-31 42.40 42.40
#> 16 TRUE Q2-14 2014-04-01 2014-06-30 33.39 33.39
#> 17 TRUE Q3-14 2014-07-01 2014-09-30 31.78 31.78
#> 18 TRUE Q4-14 2014-10-01 2014-12-31 38.25 38.25
#> 19 TRUE Q1-15 2015-01-01 2015-03-31 40.73 40.73
#> 20 TRUE Q2-15 2015-04-01 2015-06-30 32.64 32.64
#> 21 TRUE Q3-15 2015-07-01 2015-09-30 30.87 30.87
#> 22 TRUE Q4-15 2015-10-01 2015-12-31 37.22 37.22
#> 25 TRUE CAL-16 2016-01-01 2016-12-31 34.10 34.10
The forward curve values can be extracted along with daily prices for the contracts used in the calculation with the show()
method:
head(show(fwd_npri), 15)[1:8]
#> Date MSFC W21-13 W22-13 W23-13 W24-13 W25-13 W26-13
#> 1 2013-05-13 29.54905 NA NA NA NA NA NA
#> 2 2013-05-14 29.96485 NA NA NA NA NA NA
#> 3 2013-05-15 30.38054 NA NA NA NA NA NA
#> 4 2013-05-16 30.79674 NA NA NA NA NA NA
#> 5 2013-05-17 31.21359 NA NA NA NA NA NA
#> 6 2013-05-18 31.63077 NA NA NA NA NA NA
#> 7 2013-05-19 32.04745 NA NA NA NA NA NA
#> 8 2013-05-20 32.46234 33.65 NA NA NA NA NA
#> 9 2013-05-21 32.87354 33.65 NA NA NA NA NA
#> 10 2013-05-22 33.27815 33.65 NA NA NA NA NA
#> 11 2013-05-23 33.67247 33.65 NA NA NA NA NA
#> 12 2013-05-24 34.05208 33.65 NA NA NA NA NA
#> 13 2013-05-25 34.41187 33.65 NA NA NA NA NA
#> 14 2013-05-26 34.74600 33.65 NA NA NA NA NA
#> 15 2013-05-27 35.05074 NA 35.77 NA NA NA NA
We have excluded columns from the data frame for the sake of presentation. Further details regarding the calculation such as spline coefficients and knot points can be found in the slots:
slotNames(fwd_npri)
#> [1] "Name" "TradeDate" "BenchSheet" "Polynomials" "PriorFunc"
#> [6] "Results" "SplineCoef" "KnotPoints" "CalcDat"