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));
        }
示例#7
0
        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);
        }
示例#10
0
        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;
            }));
        }
示例#11
0
        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();
        }