MATLAB Examples

# Natural Gas Storage Valuation: 2. Intrinsic & Spread-Option Valuation

This is the second script of 4 in the Natural Gas Storage Valuation case study. This script prices a natural gas storage contract using the Intrinsic & Spread Option valuation methods. Please see the Readme document for more information on each valuation method and script1_DataPrep for more information on how the data was prepared for this analysis.

## Define Storage Facility, Contract & Valuation Parameters

These are parameters that define the storage facility, its constraints and costs. These are defined in "defineStorageParameters.m"

```type defineStorageParameters defineStorageParameters; % Add path to helper functions addpath Utilities ```
```%% Define Storage Facility, Contract & Valuation Parameters % These are parameters that define the storage facility, its constraints % and costs. % Copyright 2014 The MathWorks, Inc. %% Facility Parameters facility.vMax = 1e6; % MMBtu (Maximum gas volume for facility) facility.vMin = 0; % MMBtu (Minimum gas volume for facility) facility.cI = .01; % \$/MMBtu (cost of injection) facility.cW = .01; % \$/MMBtu (cost of withdrawal) % Ratchet Constraints facility.iMax = [ 0 8197; facility.vMax*.8 8197; facility.vMax*.9 6000; facility.vMax 0]; % MMBtu/day (max injection rate) facility.wMax = [ 0 6000; facility.vMax*.2 14000; facility.vMax*.4 16393; facility.vMax 16393]; % MMBtu/day (max withdrawal rate) %% Contract parameters contract.startDate = '1 Jun 2014'; contract.endDate = '1 Jun 2015'; contract.startVolume = 0; % Contract initial volume contract.endVolume = 0; % Contract terminal volume %% Valuation Parameters valuation.valDate = datenum('15 May 2014');% Valuation date valuation.discRate = .03; % Valuation discount rate valuation.liquiditySpread = .02; % Liquidity spread (Bid - Ask) valuation.minLotSize = 1; valuation.nTrials = 100; % Number of Monte Carlo trials % Add initial forward Curve to valuation parameters load Data\FwdCurveHistory ind1 = datenum(valuation.valDate) == obsDate; ind2 = expDate >= datenum(contract.startDate) & ... expDate < datenum(contract.endDate); valuation.startCurve = fwdPrice(ind1, ind2); valuation.expDates = expDate(ind2); % Expiration dates clear ind1 ind2 expDate obsDate fwdPrice ```

## Visualize Forward Curve

The forward curve on the valuation date determines the intrinsic value of storage

```plot(valuation.expDates, valuation.startCurve, 'o-'); grid on; ylabel('Forward price (\$/MMBtu)'); datetick; title(sprintf('Forward curve on %s', datestr(valuation.valDate))); ```

## Compute Ratchet Parameters

The daily injection and withdrawal limits are functions of the working gas volume. Since the storage optimization is done with monthly contracts, the monthly injection and withdrawal limit function needs to be calculated. In addition we compute a piece-wise linear approximation of the function for the optimization solver.

```[facility.injMax, facility.witMax, facility.injCoef, facility.witCoef] = ... generateIWLimitArrays(facility,'linear',6,1000); plotIWLimits(facility); ```

## Perform Intrinsic Valuation

Run a linear program to select optimal injection (long) and withdrawal (short) positions in forwards that maximize storage value and meet physical constraints.

```bid = valuation.startCurve' - valuation.liquiditySpread/2; ask = valuation.startCurve' + valuation.liquiditySpread/2; [intrPos, intrValue] = optimizeStorageIntr(facility, bid, ask, contract, valuation); figure(1); clf plotResults(intrPos(:,1), intrPos(:,2), valuation.expDates, facility,... contract, 30*ones(size(bid))); fprintf('Intrinsic Storage Value: \$%0.2fk\n\n', intrValue/1e3); ```
```Optimization terminated. Storage Schedule ------------------------------------------------------------ Month Inj With Vol InjLim WitLim _______ ______ ______ ______ ______ ______ 'Jun14' 0 0 0 245.91 0 'Jul14' 0 0 0 245.91 0 'Aug14' 245.91 0 245.91 245.91 0 'Sep14' 245.59 0 491.5 245.91 245.91 'Oct14' 245.26 0 736.76 245.91 420.88 'Nov14' 201.8 0 938.56 203.16 484.15 'Dec14' 0 111.8 826.76 51.84 491.79 'Jan15' 0 488.97 337.78 142.95 490.64 'Feb15' 0 337.78 0.001 245.91 337.74 'Mar15' 0 0 0.001 245.91 0.001 'Apr15' 0 0 0.001 245.91 0.001 'May15' 0 0 0.001 245.91 0.001 Intrinsic Storage Value: \$96.59k ```

## Intrinsic Valuation with Minimum Lot Sizes

Perform the same intrinsic valuation with lot sizes that are a multiple of 10000. This turns the problem into an integer-linear program. As expected, notice that the optimal solution produces a slightly lower value than the intrinsic valuation.

```val = valuation; val.minLotSize = 10000; [intrLPos, istorageValue] = optimizeStorageIntr(facility, bid, ask, contract, val); figure(2) plotResults(intrLPos(:,1), intrLPos(:,2), valuation.expDates, facility,... contract, 30*ones(size(bid))); fprintf('Intrinsic Storage Value with Lot Sizes: \$%0.4fk\n\n', istorageValue/1e3); ```
```LP: Optimal objective value is -9.585680. Heuristics: Found 1 solution using rss. Upper bound is -9.479961. Relative gap is 1.00%. Branch and Bound: nodes total num int integer relative explored time (s) solution fval gap (%) 19 0.02 2 -9.513454e+00 1.402418e-01 36 0.02 2 -9.513454e+00 0.000000e+00 Optimal solution found. Intlinprog stopped because the objective value is within a gap tolerance of the optimal value; options.TolGapAbs = 0 (the default value). The intcon variables are integer within tolerance, options.TolInteger = 1e-05 (the default value). Storage Schedule ------------------------------------------------------------ Month Inj With Vol InjLim WitLim _______ ___ ____ ___ ______ ______ 'Jun14' 0 0 0 245.91 0 'Jul14' 20 0 20 245.91 0 'Aug14' 240 0 260 245.91 20 'Sep14' 240 0 500 245.91 260 'Oct14' 240 0 740 245.91 424.67 'Nov14' 200 0 940 201.37 484.49 'Dec14' 0 130 810 50.625 491.79 'Jan15' 0 480 330 155.45 489.86 'Feb15' 0 330 0 245.91 330 'Mar15' 0 0 0 245.91 0 'Apr15' 0 0 0 245.91 0 'May15' 0 0 0 245.91 0 Intrinsic Storage Value with Lot Sizes: \$95.1345k ```

```optVol = load('Data\OptionVol'); % opt ivTerm stats = load('Data\CurveStats'); % m sigma vol cor valOpt = mergestruct(valuation, optVol, stats); [optPos, optValue, SO] = optimizeStorageSO(facility, contract, valOpt, 'gross'); figure(3); plotSpreadResults(optPos, valuation.expDates, facility, contract, 30*ones(size(bid))); fprintf('Spread Option Storage Value: \$%0.2fk\n', optValue/1e3); fprintf(' Discounted Intrinsic Value: \$%0.2fk\n\n', SO.intrValue/1e3); ```
```Storage Schedule ------------------------------------------------------------ Month Inj With Vol InjLim WitLim _______ ______ ______ ______ ______ ______ 'Jun14' 245.91 0 245.91 245.91 0 'Jul14' 245.59 0 491.5 245.91 245.91 'Aug14' 0 0.646 490.85 245.91 420.88 'Sep14' 91.382 0 582.23 245.91 420.58 'Oct14' 245.15 0 827.38 245.14 455.7 'Nov14' 141.65 0 969.03 142.48 490.66 'Dec14' 0 80.495 888.53 26.132 491.79 'Jan15' 0 397.46 491.07 93.941 491.79 'Feb15' 0 153.29 337.78 245.91 420.68 'Mar15' 0 92.316 245.47 245.91 337.74 'Apr15' 0.121 0 245.59 245.91 245.47 'May15' 0 245.59 0 245.91 245.59 Spread Option Storage Value: \$280.27k Discounted Intrinsic Value: \$142.68k ```
```figure(4); spreadOptCashFlows(optPos, bid', ask', valuation, facility, SO, 1); figure(5); subplot(2,1,1); bar(SO.sens(:,1)); xlabel('Forward'); ylabel('\$/MMBtu'); legend('Delta'); title('Sensitivity of Storage Value to Forwards'); set(gca,'YGrid', 'on'); subplot(2,2,3); bar(SO.sens(:,2)); xlabel('Forward'); ylabel('\$/MMBtu'); legend('Gamma'); set(gca,'YGrid', 'on'); subplot(2,2,4); bar(SO.sens(:,3)); xlabel('Forward'); ylabel('\$/MMBtu'); legend('Vega'); set(gca,'YGrid', 'on'); ```