private void AssertStandDevEqualsVolSquRootTimeToMaturity(MultiFactorSpotSimResults <Day> simResults)
 {
     for (int i = 0; i < simResults.NumSteps; i++)
     {
         ReadOnlyMemory <double> simulatedSpotPrices =
             simResults.SpotPricesForStepIndex(i);
         Day    period              = simResults.SimulatedPeriods[i];
         double factorVolForPeriod  = _singleNonMeanRevertingFactorParams.Factors.Single().Volatility[period];
         double timeToMaturity      = TimeFunctions.Act365(_currentDate, period.Start);
         double expectedLogStanDev  = factorVolForPeriod * Math.Sqrt(timeToMaturity);
         double simulatedLogStanDev = LogStandardDeviation(simulatedSpotPrices.Span);
         double percentageError     = Math.Abs((simulatedLogStanDev - expectedLogStanDev) / expectedLogStanDev);
         Assert.LessOrEqual(percentageError, 0.001);
     }
 }
        public void Simulate_ZeroVolatility_PricesEqualForwardCurve()
        {
            MultiFactorSpotSimResults <Day> simResults = SimulateForZeroVolatility();

            IReadOnlyList <Day> simulatedPeriods = simResults.SimulatedPeriods;

            for (int periodIndex = 0; periodIndex < simulatedPeriods.Count; periodIndex++)
            {
                double forwardPrice = _dailyForwardCurve[simulatedPeriods[periodIndex]];
                ReadOnlyMemory <double> simulatedSpotPrices = simResults.SpotPricesForStepIndex(periodIndex);
                for (int simIndex = 0; simIndex < simulatedSpotPrices.Length; simIndex++)
                {
                    Assert.AreEqual(forwardPrice, simulatedSpotPrices.Span[simIndex]);
                }
            }
        }
        private static void MeanRevertingFactorsAverageWithin3StanDevsOfZero(MultiFactorSpotSimResults <Day> simResults)
        {
            AssertWithin3StanDevsOfExpectedValueValue(
                simResults.MarkovFactorsForStepIndex(0, 1).Span, 0.0);
            AssertWithin3StanDevsOfExpectedValueValue(
                simResults.MarkovFactorsForStepIndex(0, 2).Span, 0.0);

            AssertWithin3StanDevsOfExpectedValueValue(
                simResults.MarkovFactorsForStepIndex(1, 1).Span, 0.0);
            AssertWithin3StanDevsOfExpectedValueValue(
                simResults.MarkovFactorsForStepIndex(1, 2).Span, 0.0);

            AssertWithin3StanDevsOfExpectedValueValue(
                simResults.MarkovFactorsForPeriod(new Day(2021, 07, 30), 1).Span, 0.0);
            AssertWithin3StanDevsOfExpectedValueValue(
                simResults.MarkovFactorsForPeriod(new Day(2021, 07, 30), 2).Span, 0.0);
        }
        public MultiFactorSpotPriceSimulatorTest()
        {
            _seed        = 12;
            _currentDate = new DateTime(2020, 07, 27);

            _dailyForwardCurve = new Dictionary <Day, double>
            {
                { new Day(2020, 08, 01), 56.85 },
                { new Day(2021, 01, 15), 59.08 },
                { new Day(2021, 07, 30), 62.453 }
            };

            _meanAndNonMeanRevertingFactorsResultsAntithetic    = SimulateForMeanAndNonMeanRevertingFactors(true);
            _meanAndNonMeanRevertingFactorsResultsNotAntithetic = SimulateForMeanAndNonMeanRevertingFactors(false);
            _twoNonMeanRevertingFactorsResultsAntithetic        = SimulateForTwoNonMeanRevertingFactors(true);
            _twoNonMeanRevertingFactorsResultsNotAntithetic     = SimulateForTwoNonMeanRevertingFactors(false);
            _singleNonMeanRevertingFactorResultsAntithetic      = SimulateForSingleNonMeanRevertingFactor(true);
            _singleNonMeanRevertingFactorResultsNotAntithetic   = SimulateForSingleNonMeanRevertingFactor(false);
        }
        private static void AssertAverageSimSpotPricesWithin3StanDevsOfForwardPrice <T>(MultiFactorSpotSimResults <T> simResults, Dictionary <T, double> forwardCurve)
            where T : ITimePeriod <T>
        {
            IReadOnlyList <T> simulatedPeriods = simResults.SimulatedPeriods;

            for (int periodIndex = 0; periodIndex < simulatedPeriods.Count; periodIndex++)
            {
                double forwardPrice = forwardCurve[simulatedPeriods[periodIndex]];
                ReadOnlyMemory <double> simulatedSpotPrices = simResults.SpotPricesForStepIndex(periodIndex);

                AssertWithin3StanDevsOfExpectedValueValue(simulatedSpotPrices.Span, forwardPrice);
            }
        }