private static TreeStorageValuationResults <T> TrinomialStorageValuation <T>( DateTime valuationDateTime, DateTime storageStartDateTime, DateTime storageEndDateTime, object ratchets, string injectWithdrawInterpolation, double injectionCostRate, double cmdtyConsumedOnInjection, double withdrawalCostRate, double cmdtyConsumedOnWithdrawal, double currentInventory, object forwardCurveIn, object spotVolatilityCurveIn, double meanReversion, object interestRateCurve, object numGlobalGridPointsIn, object numericalToleranceIn) where T : ITimePeriod <T> { double numericalTolerance = StorageExcelHelper.DefaultIfExcelEmptyOrMissing(numericalToleranceIn, 1E-10, "Numerical_tolerance"); var storage = StorageExcelHelper.CreateCmdtyStorageFromExcelInputs <T>(storageStartDateTime, storageEndDateTime, ratchets, injectWithdrawInterpolation, injectionCostRate, cmdtyConsumedOnInjection, withdrawalCostRate, cmdtyConsumedOnWithdrawal, numericalTolerance); T currentPeriod = TimePeriodFactory.FromDateTime <T>(valuationDateTime); TimeSeries <T, double> forwardCurve = StorageExcelHelper.CreateDoubleTimeSeries <T>(forwardCurveIn, "Forward_curve"); TimeSeries <T, double> spotVolatilityCurve = StorageExcelHelper.CreateDoubleTimeSeries <T>(spotVolatilityCurveIn, "Spot_volatility_curve"); // TODO input settlement dates int numGridPoints = StorageExcelHelper.DefaultIfExcelEmptyOrMissing <int>(numGlobalGridPointsIn, 100, "Num_global_grid_points"); double timeDelta = 1.0 / 365.0; // TODO remove this hard coding Func <Day, double> interpolatedInterestRates = StorageExcelHelper.CreateLinearInterpolatedInterestRateFunc(interestRateCurve, ExcelArg.InterestRateCurve.Name); TreeStorageValuationResults <T> valuationResults = TreeStorageValuation <T> .ForStorage(storage) .WithStartingInventory(currentInventory) .ForCurrentPeriod(currentPeriod) .WithForwardCurve(forwardCurve) .WithOneFactorTrinomialTree(spotVolatilityCurve, meanReversion, timeDelta) .WithCmdtySettlementRule(period => period.First <Day>()) // TODO get rid if this .WithAct365ContinuouslyCompoundedInterestRate(interpolatedInterestRates) .WithFixedNumberOfPointsOnGlobalInventoryRange(numGridPoints) .WithLinearInventorySpaceInterpolation() .WithNumericalTolerance(numericalTolerance) .Calculate(); return(valuationResults); }
public void Calculate_StorageLooksLikeCallOptions_NpvEqualsBlack76() { const double percentTolerance = 0.005; // 0.5% tolerance var currentDate = new Day(2019, 8, 29); (DoubleTimeSeries <Day> forwardCurve, DoubleTimeSeries <Day> spotVolCurve) = TestHelper.CreateDailyTestForwardAndSpotVolCurves(currentDate, new Day(2020, 4, 1)); const double meanReversion = 16.5; const double timeDelta = 1.0 / 365.0; const double interestRate = 0.09; TestHelper.CallOptionLikeTestData testData = TestHelper.CreateThreeCallsLikeStorageTestData(forwardCurve); TreeStorageValuationResults <Day> valuationResults = TreeStorageValuation <Day> .ForStorage(testData.Storage) .WithStartingInventory(testData.Inventory) .ForCurrentPeriod(currentDate) .WithForwardCurve(forwardCurve) .WithOneFactorTrinomialTree(spotVolCurve, meanReversion, timeDelta) .WithMonthlySettlement(testData.SettleDates) .WithAct365ContinuouslyCompoundedInterestRate(day => interestRate) // Constant interest rate .WithFixedNumberOfPointsOnGlobalInventoryRange(100) .WithLinearInventorySpaceInterpolation() .WithNumericalTolerance(1E-10) .Calculate(); // Calculate value of equivalent call options double expectStorageValue = 0.0; foreach (TestHelper.CallOption option in testData.CallOptions) { double impliedVol = TestHelper.OneFactorImpliedVol(currentDate, option.ExpiryDate, spotVolCurve, meanReversion); double forwardPrice = forwardCurve[option.ExpiryDate]; double black76Value = TestHelper.Black76CallOptionValue(currentDate, forwardPrice, impliedVol, interestRate, option.StrikePrice, option.ExpiryDate, option.SettleDate) * option.NotionalVolume; expectStorageValue += black76Value; } double percentError = (valuationResults.NetPresentValue - expectStorageValue) / expectStorageValue; Assert.InRange(percentError, -percentTolerance, percentTolerance); }
internal DecisionSimulator(TreeStorageValuationResults <T> valuationResults, TreeStorageValuation <T> storageValuation) { ValuationResults = valuationResults; _storageValuation = storageValuation; }