public void Calculate_CurrentPeriodEqualToStorageEndStorageMustBeEmptyAtEnd_ResultWithEmptyDecisionProfile() { var currentPeriod = new Day(2019, 9, 30); IntrinsicStorageValuationResults <Day> valuationResults = GenerateValuationResults(0.0, TimeSeries <Day, double> .Empty, currentPeriod); Assert.True(valuationResults.StorageProfile.IsEmpty); }
public void Calculate_CurrentPeriodEqualToStorageEndStorageMustBeEmptyAtEnd_ResultWithZeroNetPresentValue() { var currentPeriod = new Day(2019, 9, 30); IntrinsicStorageValuationResults <Day> valuationResults = GenerateValuationResults(0.0, TimeSeries <Day, double> .Empty, currentPeriod); Assert.Equal(0.0, valuationResults.NetPresentValue); }
public void Calculate_CurrentPeriodEqualToStorageEndStorageInventoryHasTerminalValue_ResultWithEmptyDecisionProfile() { const double terminalInventory = 120.1; const double forwardPriceForEndDate = 45.67; IntrinsicStorageValuationResults <Day> valuationResults = GenerateValuationResults_CurrentPeriodEqualToStorageEndStorageInventoryHasTerminalValue(terminalInventory, forwardPriceForEndDate); Assert.True(valuationResults.StorageProfile.IsEmpty); }
public void Calculate_ZeroInventoryCurveBackwardated_ResultWithZeroNetPresentValue() { var currentPeriod = new Day(2019, 9, 15); var forwardCurve = GenerateBackwardatedCurve(new Day(2019, 9, 1), new Day(2019, 9, 30)); IntrinsicStorageValuationResults <Day> valuationResults = GenerateValuationResults(0.0, forwardCurve, currentPeriod); Assert.Equal(0.0, valuationResults.NetPresentValue); }
public void Calculate_CurrentPeriodEqualToStorageEndStorageInventoryHasTerminalValue_ResultWithNetPresentValueEqualToTerminalValue() { const double terminalInventory = 120.1; const double forwardPriceForEndDate = 45.67; IntrinsicStorageValuationResults <Day> valuationResults = GenerateValuationResults_CurrentPeriodEqualToStorageEndStorageInventoryHasTerminalValue(terminalInventory, forwardPriceForEndDate); double expectedNpv = terminalInventory * forwardPriceForEndDate - 999.0; // Arbitrary terminal function defined for storage Assert.Equal(expectedNpv, valuationResults.NetPresentValue); }
public void Calculate_ZeroInventoryCurveBackwardated_ResultWithZerosDecisionProfile() { var currentPeriod = new Day(2019, 9, 15); var forwardCurve = GenerateBackwardatedCurve(new Day(2019, 9, 1), new Day(2019, 9, 30)); IntrinsicStorageValuationResults <Day> valuationResults = GenerateValuationResults(0.0, forwardCurve, currentPeriod); AssertDecisionProfileAllZeros(valuationResults.StorageProfile, new Day(2019, 9, 15), new Day(2019, 9, 30)); }
private static IntrinsicStorageValuationResults <T> IntrinsicStorageVal <T>( DateTime valuationDateTime, DateTime storageStartDateTime, DateTime storageEndDateTime, object injectWithdrawConstraints, string injectWithdrawInterpolation, double injectionCostRate, double cmdtyConsumedOnInjection, double withdrawalCostRate, double cmdtyConsumedOnWithdrawal, double currentInventory, object forwardCurveIn, 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, injectWithdrawConstraints, injectWithdrawInterpolation, injectionCostRate, cmdtyConsumedOnInjection, withdrawalCostRate, cmdtyConsumedOnWithdrawal, numericalTolerance); T currentPeriod = TimePeriodFactory.FromDateTime <T>(valuationDateTime); TimeSeries <T, double> forwardCurve = StorageExcelHelper.CreateDoubleTimeSeries <T>(forwardCurveIn, "Forward_curve"); // TODO input settlement dates and use interest rates int numGridPoints = StorageExcelHelper.DefaultIfExcelEmptyOrMissing <int>(numGlobalGridPointsIn, 100, "Num_global_grid_points"); IntrinsicStorageValuationResults <T> valuationResults = IntrinsicStorageValuation <T> .ForStorage(storage) .WithStartingInventory(currentInventory) .ForCurrentPeriod(currentPeriod) .WithForwardCurve(forwardCurve) .WithCmdtySettlementRule(period => period.First <Day>()) // TODO get rid if this .WithDiscountFactorFunc((currentDate, cashFlowDate) => 1.0) // TODO add proper discounting .WithFixedNumberOfPointsOnGlobalInventoryRange(numGridPoints) .WithLinearInventorySpaceInterpolation() .WithNumericalTolerance(numericalTolerance) .Calculate(); return(valuationResults); }
GenerateValuationResults_CurrentPeriodEqualToStorageEndStorageInventoryHasTerminalValue(double startingInventory, double forwardPrice) { var storageStart = new Day(2019, 9, 1); var storageEnd = new Day(2019, 9, 30); TimeSeries <Month, Day> settlementDates = new TimeSeries <Month, Day> .Builder { { new Month(2019, 9), new Day(2019, 10, 5) } }.Build(); CmdtyStorage <Day> storage = CmdtyStorage <Day> .Builder .WithActiveTimePeriod(storageStart, storageEnd) .WithConstantInjectWithdrawRange(-45.5, 56.6) .WithConstantMinInventory(0.0) .WithConstantMaxInventory(1000.0) .WithPerUnitInjectionCost(0.8, injectionDate => injectionDate) .WithNoCmdtyConsumedOnInject() .WithPerUnitWithdrawalCost(1.2, withdrawalDate => withdrawalDate) .WithNoCmdtyConsumedOnWithdraw() .WithNoCmdtyInventoryLoss() .WithNoInventoryCost() .WithTerminalInventoryNpv((cmdtyPrice, terminalInventory) => cmdtyPrice * terminalInventory - 999.0) .Build(); var forwardCurve = new TimeSeries <Day, double> .Builder(1) { { storageEnd, forwardPrice } } .Build(); IntrinsicStorageValuationResults <Day> valuationResults = IntrinsicStorageValuation <Day> .ForStorage(storage) .WithStartingInventory(startingInventory) .ForCurrentPeriod(storageEnd) .WithForwardCurve(forwardCurve) .WithMonthlySettlement(settlementDates) .WithDiscountFactorFunc((valuationDate, cashFlowDate) => 1.0) // No discounting .WithFixedGridSpacing(10.0) .WithLinearInventorySpaceInterpolation() .WithNumericalTolerance(1E-10) .Calculate(); return(valuationResults); }
private static IntrinsicStorageValuationResults <Day> IntrinsicValuationZeroInventoryForwardCurveWithSpread(double forwardSpread) { var currentPeriod = new Day(2019, 9, 15); const double lowerForwardPrice = 56.6; double higherForwardPrice = lowerForwardPrice + forwardSpread; var forwardCurveBuilder = new TimeSeries <Day, double> .Builder(); foreach (var day in new Day(2019, 9, 15).EnumerateTo(new Day(2019, 9, 22))) { forwardCurveBuilder.Add(day, lowerForwardPrice); } foreach (var day in new Day(2019, 9, 23).EnumerateTo(new Day(2019, 9, 30))) { forwardCurveBuilder.Add(day, higherForwardPrice); } IntrinsicStorageValuationResults <Day> valuationResults = GenerateValuationResults(0.0, forwardCurveBuilder.Build(), currentPeriod); return(valuationResults); }
public static object StorageIntrinsicDecisionProfile( DateTime valuationDate, DateTime storageStart, DateTime storageEnd, object injectWithdrawConstraints, [ExcelArgument(Name = ExcelArg.RatchetInterpolation.Name, Description = ExcelArg.RatchetInterpolation.Description)] string injectWithdrawInterpolation, double injectionCostRate, double cmdtyConsumedOnInjection, double withdrawalCostRate, double cmdtyConsumedOnWithdrawal, double currentInventory, object forwardCurve, object interestRateCurve, object numGlobalGridPoints, // TODO excel argument says default is 100 object numericalTolerance, [ExcelArgument(Name = "Granularity")] object granularity) { return(StorageExcelHelper.ExecuteExcelFunction(() => { IntrinsicStorageValuationResults <Day> valuationResults = IntrinsicStorageVal <Day>(valuationDate, storageStart, storageEnd, injectWithdrawConstraints, injectWithdrawInterpolation, injectionCostRate, cmdtyConsumedOnInjection, withdrawalCostRate, cmdtyConsumedOnWithdrawal, currentInventory, forwardCurve, interestRateCurve, numGlobalGridPoints, numericalTolerance); var resultArray = new object[valuationResults.StorageProfile.Count, 3]; for (int i = 0; i < resultArray.GetLength(0); i++) { resultArray[i, 0] = valuationResults.StorageProfile.Indices[i].Start; resultArray[i, 1] = valuationResults.StorageProfile[i].InjectWithdrawVolume; resultArray[i, 2] = valuationResults.StorageProfile[i].CmdtyConsumed; } return resultArray; })); }
static void Main(string[] args) { const double constantMaxInjectRate = 5.26; const double constantMaxWithdrawRate = 14.74; const double constantMaxInventory = 1100.74; const double constantMinInventory = 0.0; const double constantInjectionCost = 0.48; const double constantWithdrawalCost = 0.74; CmdtyStorage <Day> storage = CmdtyStorage <Day> .Builder .WithActiveTimePeriod(new Day(2019, 9, 1), new Day(2019, 10, 1)) .WithConstantInjectWithdrawRange(-constantMaxWithdrawRate, constantMaxInjectRate) .WithConstantMinInventory(constantMinInventory) .WithConstantMaxInventory(constantMaxInventory) .WithPerUnitInjectionCost(constantInjectionCost, injectionDate => injectionDate) .WithNoCmdtyConsumedOnInject() .WithPerUnitWithdrawalCost(constantWithdrawalCost, withdrawalDate => withdrawalDate) .WithNoCmdtyConsumedOnWithdraw() .WithNoCmdtyInventoryLoss() .WithNoCmdtyInventoryCost() .MustBeEmptyAtEnd() .Build(); var currentPeriod = new Day(2019, 9, 15); const double lowerForwardPrice = 56.6; const double forwardSpread = 87.81; double higherForwardPrice = lowerForwardPrice + forwardSpread; var forwardCurveBuilder = new TimeSeries <Day, double> .Builder(); foreach (var day in new Day(2019, 9, 15).EnumerateTo(new Day(2019, 9, 22))) { forwardCurveBuilder.Add(day, lowerForwardPrice); } foreach (var day in new Day(2019, 9, 23).EnumerateTo(new Day(2019, 10, 1))) { forwardCurveBuilder.Add(day, higherForwardPrice); } const double startingInventory = 50.0; IntrinsicStorageValuationResults <Day> valuationResults = IntrinsicStorageValuation <Day> .ForStorage(storage) .WithStartingInventory(startingInventory) .ForCurrentPeriod(currentPeriod) .WithForwardCurve(forwardCurveBuilder.Build()) .WithCmdtySettlementRule(day => day.First <Month>().Offset(1).First <Day>().Offset(5)) // Commodity is settled on the 5th day of the next month .WithDiscountFactorFunc(day => 1.0) // Assumes to discounting .WithFixedGridSpacing(10.0) .WithLinearInventorySpaceInterpolation() .WithNumericalTolerance(1E-12) .Calculate(); Console.WriteLine("Calculated intrinsic storage NPV: " + valuationResults.NetPresentValue.ToString("F2")); Console.WriteLine(); Console.WriteLine("Decision profile:"); Console.WriteLine(valuationResults.DecisionProfile.FormatData("F2", -1)); Console.WriteLine("Press any key to exit"); Console.ReadKey(); }