예제 #1
0
        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);
        }
예제 #2
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);
        }
예제 #3
0
        public static TimeSeries <TIndex, TData> CreateTimeSeries <TIndex, TData>(object excelValues, string excelArgumentName,
                                                                                  TryCreateData <TData> tryCreateData)
            where TIndex : ITimePeriod <TIndex>
        {
            if (excelValues is ExcelMissing || excelValues is ExcelEmpty)
            {
                throw new ArgumentException(excelArgumentName + " hasn't been specified.");
            }

            if (!(excelValues is object[,] excelValuesArray))
            {
                throw new ArgumentException(excelArgumentName + " has been incorrectly entered. Argument value should be of a range with 2 columns, the first containing dates, the second containing numbers.");
            }

            if (excelValuesArray.GetLength(1) != 2)
            {
                throw new ArgumentException(excelArgumentName + " has been incorrectly entered. Argument value should be a range with 2 columns.");
            }

            var builder = new TimeSeries <TIndex, TData> .Builder();

            for (int i = 0; i < excelValuesArray.GetLength(0); i++)
            {
                if (excelValuesArray[i, 0] is ExcelEmpty || excelValuesArray[i, 0] is ExcelError)
                {
                    break;
                }

                object dataValueIn = excelValuesArray[i, 1];
                if (!tryCreateData(dataValueIn, out TData dataValue))
                {
                    throw new ArgumentException($"Value in the second column of row {i} for argument {excelArgumentName} cannot be converted to type {typeof(TData).Name}.");
                }

                DateTime curvePointDateTime = ObjectToDateTime(excelValuesArray[i, 0], $"Cannot create DateTime from value in first row of argument {excelArgumentName}.");
                TIndex   curvePointPeriod   = TimePeriodFactory.FromDateTime <TIndex>(curvePointDateTime);

                builder.Add(curvePointPeriod, dataValue);
            }

            return(builder.Build());
        }
예제 #4
0
        public static DoubleTimeSeries <T> CreateDoubleTimeSeries <T>(object excelValues, string excelArgumentName)
            where T : ITimePeriod <T>
        {
            if (excelValues is ExcelMissing || excelValues is ExcelEmpty)
            {
                throw new ArgumentException(excelArgumentName + " hasn't been specified.");
            }

            if (!(excelValues is object[,] excelValuesArray))
            {
                throw new ArgumentException(excelArgumentName + " has been incorrectly entered. Argument value should be of a range with 2 columns, the first containing dates, the second containing numbers.");
            }

            if (excelValuesArray.GetLength(1) != 2)
            {
                throw new ArgumentException(excelArgumentName + " has been incorrectly entered. Argument value should be a range with 2 columns.");
            }

            var builder = new DoubleTimeSeries <T> .Builder();

            for (int i = 0; i < excelValuesArray.GetLength(0); i++)
            {
                if (excelValuesArray[i, 0] is ExcelEmpty || excelValuesArray[i, 0] is ExcelError)
                {
                    break;
                }

                if (!(excelValuesArray[i, 1] is double doubleValue))
                {
                    throw new ArgumentException($"Value in the second column of row {i} for argument {excelArgumentName} is not a number.");
                }

                DateTime curvePointDateTime = ObjectToDateTime(excelValuesArray[i, 0], $"Cannot create DateTime from value in first row of argument {excelArgumentName}.");
                T        curvePointPeriod   = TimePeriodFactory.FromDateTime <T>(curvePointDateTime);

                builder.Add(curvePointPeriod, doubleValue);
            }

            return(builder.Build());
        }
예제 #5
0
        public static CmdtyStorage <T> CreateCmdtyStorageFromExcelInputs <T>(DateTime storageStartDateTime,
                                                                             DateTime storageEndDateTime,
                                                                             object injectWithdrawConstraintsIn,
                                                                             string injectWithdrawInterpolationIn,
                                                                             double injectionCostRate,
                                                                             double cmdtyConsumedOnInjection,
                                                                             double withdrawalCostRate,
                                                                             double cmdtyConsumedOnWithdrawal,
                                                                             double newtonRaphsonAccuracy)
            where T : ITimePeriod <T>
        {
            T storageStart = TimePeriodFactory.FromDateTime <T>(storageStartDateTime);
            T storageEnd   = TimePeriodFactory.FromDateTime <T>(storageEndDateTime);

            if (injectWithdrawConstraintsIn is ExcelMissing || injectWithdrawConstraintsIn is ExcelEmpty)
            {
                throw new ArgumentException("Inject/withdraw constraints haven't been specified.");
            }

            if (!(injectWithdrawConstraintsIn is object[,] injectWithdrawArray))
            {
                throw new ArgumentException("Inject/withdraw constraints have been incorrectly entered. Argument value should be of a range with 4 columns, the first containing dates, the rest containing numbers.");
            }

            if (injectWithdrawArray.GetLength(1) != 4)
            {
                throw new ArgumentException("Inject/withdraw constraints have been incorrectly entered. Argument value should be a range 4 columns.");
            }

            var injectWithdrawGrouped = TakeWhileNotEmptyOrError(injectWithdrawArray).Select((row, i) => new
            {
                period       = ObjectToDateTime(row[0], $"Row {i + 1} of inject/withdraw/inventory constrains contains invalid date time in 1st column."),
                inventory    = ObjectToDouble(row[1], $"Row {i + 1} of inject/withdraw/inventory constraints contains invalid inventory in 2nd column as is not a number."),
                injectRate   = ObjectToDouble(row[2], $"Row {i + 1} of inject/withdraw/inventory constraints contains invalid injection rate in 3rd column as is not a number."),
                withdrawRate = ObjectToDouble(row[3], $"Row {i + 1} of inject/withdraw/inventory constraints contains invalid withdrawal in 4th column as is not a number.")
            }).GroupBy(arg => arg.period);

            var injectWithdrawConstraints = new List <InjectWithdrawRangeByInventoryAndPeriod <T> >();

            foreach (var injectWithdrawGroup in injectWithdrawGrouped)
            {
                T period = TimePeriodFactory.FromDateTime <T>(injectWithdrawGroup.Key);
                IEnumerable <InjectWithdrawRangeByInventory> injectWithdrawByInventory = injectWithdrawGroup.Select(arg =>
                                                                                                                    new InjectWithdrawRangeByInventory(arg.inventory, new InjectWithdrawRange(-arg.withdrawRate, arg.injectRate)));
                injectWithdrawConstraints.Add(new InjectWithdrawRangeByInventoryAndPeriod <T>(period, injectWithdrawByInventory));
            }

            InterpolationType interpolationType;

            if (injectWithdrawInterpolationIn == "PiecewiseLinear")
            {
                interpolationType = InterpolationType.PiecewiseLinear;
            }
            else if (injectWithdrawInterpolationIn == "Polynomial")
            {
                interpolationType = InterpolationType.PolynomialWithParams(newtonRaphsonAccuracy);
            }
            else
            {
                throw new ArgumentException($"Value of Inject_withdraw_interpolation '{injectWithdrawInterpolationIn}' not recognised. Must be either 'PiecewiseLinear' or 'Polynomial'.");
            }

            CmdtyStorage <T> storage = CmdtyStorage <T> .Builder
                                       .WithActiveTimePeriod(storageStart, storageEnd)
                                       .WithTimeAndInventoryVaryingInjectWithdrawRates(injectWithdrawConstraints, interpolationType)
                                       .WithPerUnitInjectionCost(injectionCostRate)
                                       .WithFixedPercentCmdtyConsumedOnInject(cmdtyConsumedOnInjection)
                                       .WithPerUnitWithdrawalCost(withdrawalCostRate)
                                       .WithFixedPercentCmdtyConsumedOnWithdraw(cmdtyConsumedOnWithdrawal)
                                       .WithNoCmdtyInventoryLoss()
                                       .WithNoInventoryCost()
                                       .MustBeEmptyAtEnd()
                                       .Build();

            return(storage);
        }
        public void FromDateTime_MonthTypeParameter_EqualsExpected(DateTime dateTime, Month expectedMonth)
        {
            var month = TimePeriodFactory.FromDateTime <Month>(dateTime);

            Assert.AreEqual(expectedMonth, month);
        }