public void Build_InputContractsInLinearTrend_ResultsLinear()
        {
            // Parameters of linear trend
            const double intercept  = 45.7;
            const double dailySlope = 0.8;

            double dailyPrice  = intercept;
            Day    contractDay = new Day(2019, 5, 11);
            var    contracts   = new List <Contract <Hour> >();

            for (int i = 0; i < 14; i++)
            {
                contracts.Add(Contract <Hour> .Create(contractDay, dailyPrice));
                contractDay++;
                dailyPrice += dailySlope;
            }

            var curve = new MaxSmoothnessSplineCurveBuilder <Hour>()
                        .AddContracts(contracts)
                        .BuildCurve();

            double hourlySlope = dailySlope / 24;

            foreach (var pricePair in curve.Data.Zip(curve.Data.Skip(1),
                                                     (priceHour1, priceHour2) => new { priceHour1, priceHour2 }))
            {
                double hourlyChange = pricePair.priceHour2 - pricePair.priceHour1;
                Assert.AreEqual(hourlySlope, hourlyChange, 1E-12);
            }
        }
        public void Build_WithOverlappingContracts_ThrowArgumentException()
        {
            var builder = new MaxSmoothnessSplineCurveBuilder <Month>()
                          .AddContract(Month.CreateJanuary(2019), Month.CreateMarch(2019), 19.8)
                          .AddContract(Month.CreateMarch(2019), 15.2)
                          .AddContract(Month.CreateApril(2019), 10.02);

            Assert.Throws(Is.TypeOf <ArgumentException>().And.Message.EqualTo(
                              "contracts are overlapping"),
                          () => builder.BuildCurve());
        }
        public void Build_WithMonthTypeParameter_CurveConsistentWithInputs(List <Contract <Month> > contracts)
        {
            var results = new MaxSmoothnessSplineCurveBuilder <Month>()
                          .AddContracts(contracts)
                          .WithMultiplySeasonalAdjustment(MonthlySeasonalAdjust)
                                                         // TODO add additive seasonal adjustment
                          .WithFrontFirstDerivative(0.8) // TODO pass in as parameter?
                          .WithBackFirstDerivative(-1.5) // TODO pass in as parameter?
                          .BuildCurve();

            TestHelper.AssertCurveConsistentWithInputs(contracts, period => period.End.Subtract(period.Start).Days, results, Tolerance);
        }
        public void Build_InputContractsAllEqualAndNoSeasonalAdjustments_ResultsInFlatCurve()
        {
            const double flatPrice = 84.54;
            var          curve     = new MaxSmoothnessSplineCurveBuilder <Day>()
                                     .AddContract(Month.CreateJanuary(2019), flatPrice)
                                     .AddContract(Month.CreateFebruary(2019), flatPrice)
                                     .AddContract(Month.CreateMarch(2019), flatPrice)
                                     .AddContract(Quarter.CreateQuarter2(2019), flatPrice)
                                     .AddContract(Quarter.CreateQuarter3(2019), flatPrice)
                                     .AddContract(Season.CreateWinter(2019), flatPrice)
                                     .BuildCurve();

            foreach (double price in curve.Data)
            {
                Assert.AreEqual(flatPrice, price, 1E-12);
            }
        }
예제 #5
0
파일: Program.cs 프로젝트: seanahmad/curves
        static void Main(string[] args)
        {
            // The following code shows how to use the spline to derive a smooth daily curve from
            // monthly and quarterly granularity input contract prices. Also demonstrated is the
            // optional seasonal adjustment factor, in this case used to apply day-of-week seasonality.

            var dayOfWeekAdjustment = new Dictionary <DayOfWeek, double>
            {
                [DayOfWeek.Monday]    = 0.95,
                [DayOfWeek.Tuesday]   = 0.99,
                [DayOfWeek.Wednesday] = 1.05,
                [DayOfWeek.Thursday]  = 1.01,
                [DayOfWeek.Friday]    = 0.98,
                [DayOfWeek.Saturday]  = 0.92,
                [DayOfWeek.Sunday]    = 0.91
            };

            DoubleCurve <Day> curve = new MaxSmoothnessSplineCurveBuilder <Day>()
                                      .AddContract(Month.CreateJuly(2019), 77.98)
                                      .AddContract(Month.CreateAugust(2019), 76.01)
                                      .AddContract(Month.CreateSeptember(2019), 78.74)
                                      .AddContract(Quarter.CreateQuarter4(2019), 85.58)
                                      .AddContract(Quarter.CreateQuarter1(2020), 87.01)
                                      .WithMultiplySeasonalAdjustment(day => dayOfWeekAdjustment[day.DayOfWeek])
                                      .BuildCurve();

            Console.WriteLine(curve.FormatData("F5"));

            Console.WriteLine();
            Console.WriteLine();

            //===============================================================================================
            // APPLYING AN ALTERNATIVE WEIGHTING SCHEME

            // By default, the spline calculations assume averages are weighted by the number of minutes in a contract period.
            // This assumption is fine for instruments where the commodity is delivered at a constant rate, e.g. natural gas forwards.
            // An alternative weighting scheme can be added by calling WithAverageWeighting and supplying a weighting scheme as a function.
            // The below example makes use of the Weighting helper class to provide the weighting function as the count of business days.
            // An example of when such a weighting scheme should be used is for oil swaps, based on an index which is only published on a business day
            // to create a monthly curve from quarterly granularity inputs.

            var holidays = new List <Day>()
            {
                new Day(2020, 1, 1)
            };
            Func <Month, double> busDayWeight = Weighting.BusinessDayCount <Month>(holidays);

            var contracts = new List <Contract <Month> >()
            {
                Contract <Month> .Create(Quarter.CreateQuarter4(2019), 76.58),
                Contract <Month> .Create(Quarter.CreateQuarter1(2020), 77.20),
                Contract <Month> .Create(Quarter.CreateQuarter2(2020), 76.01),
                Contract <Month> .Create(Quarter.CreateQuarter3(2020), 74.95),
                Contract <Month> .Create(Quarter.CreateQuarter4(2020), 74.92),
            };

            DoubleCurve <Month> curveBusDayWeight = new MaxSmoothnessSplineCurveBuilder <Month>()
                                                    .AddContracts(contracts)
                                                    .WithWeighting(busDayWeight)
                                                    .BuildCurve();

            Console.WriteLine("Derived smooth curve with business day weighting:");
            Console.WriteLine(curveBusDayWeight.FormatData("F5", -1));

            Console.ReadKey();
        }