public void TestExtrapolate2()
        {
            IStock              stockASXParent = LoadStock("AGK");
            IStock              stockASXChild  = LoadStock("ANZ");
            IStock              stockSDParent  = LoadStock("BHP");
            IVolatilitySurface  child          = CreateNullVolSurface();
            ExtrapolationHelper extrapHelper   = new ExtrapolationHelper();
            double              factor         = 0.314843 / 0.290393;
            double              parentVol1     = 0.394634;
            double              scal           = extrapHelper.CalcExtrapFactor(stockASXParent, stockASXChild, new DateTime(2009, 9, 30));

            Assert.AreEqual(scal, factor, 0.001);
            double parentVol2 = 0.38754555;
            double parentVol3 = 0.71063645;

            if (stockASXParent.VolatilitySurface.Expiries[0].Strikes[0].InterpModel.GetType() == typeof(WingInterp))
            {
                extrapHelper.DoExtrap(stockASXParent,
                                      stockASXChild,
                                      stockSDParent,
                                      child);
                //moneyness = 0.3;
                Assert.AreEqual(Convert.ToDouble(child.NodalExpiries[2].Strikes[0].Volatility.Value), factor * parentVol3, 0.001);
                //moneyness = 1.0;
                Assert.AreEqual(Convert.ToDouble(child.NodalExpiries[2].Strikes[1].Volatility.Value), factor * parentVol1, 0.001);
                //moneyness = 1.2;
                Assert.AreEqual(Convert.ToDouble(child.NodalExpiries[2].Strikes[2].Volatility.Value), factor * parentVol2, 0.001);
            }
        }
        /// <summary>
        /// Gets the vol.
        /// </summary>
        /// <param name="volCurve">The vol curve.</param>
        /// <param name="expiry">The expiry.</param>
        /// <param name="strike">The strike.</param>
        /// <returns></returns>
        public double GetVolatility(IVolatilitySurface volCurve, Double expiry,
                                    Double strike)
        {
            IPoint point = new Point2D(expiry, strike);
            var    vol   = volCurve.Value(point);

            return(vol);
        }
 ///// <param name="isCall">The isCall flag. If [true] then the the option is a call.</param>
 ///// <param name="rate">The rate.</param>
 ///// <param name="timeToExpiry">The time To Expiry.</param>
 /// <summary>
 /// Initiates a new model.
 /// </summary>
 /// <param name="valuationDate">The valuation date.</param>
 /// <param name="timeToIndex">The timeToIndex. Not necessarily the time to expiry. This is used for surface interpolation..</param>
 /// <param name="strike">The strike.</param>
 /// <param name="reportingCurrencyFxCurve">THe fx curve. It must already be normalised.</param>
 /// <param name="indexVolSurface">THe volatility surface to use. </param>
 ///// <param name="discountCurve">The rate curve to use for discounting.</param>
 public SimpleIRSwaptionInstrumentAnalytic(DateTime valuationDate,                                                //DateTime paymentDate, bool isCall,
                                           decimal timeToIndex, decimal strike,
                                                                                                                  //decimal timeToExpiry, decimal rate,
                                           IFxCurve reportingCurrencyFxCurve, IVolatilitySurface indexVolSurface) //IRateCurve discountCurve, /// <param name="paymentDate">The payment date of the cash flow.</param>
 {
     ToReportingCurrencyRate = EvaluateReportingCurrencyFxRate(valuationDate, reportingCurrencyFxCurve);
     TimeToIndex             = timeToIndex;
     Strike     = strike;
     Volatility = (decimal)indexVolSurface.GetValue((double)timeToIndex, (double)strike);
 }
        public void TestExtrapolate3()
        {
            IStock              stockASXParent = LoadStock("AGK");
            IStock              stockASXChild  = LoadStock("ANZ");
            IStock              stockSDParent  = LoadStock("BHP");
            IVolatilitySurface  child          = CreateOnePointChild();
            ExtrapolationHelper extrapHelper   = new ExtrapolationHelper();
            double              scal           = extrapHelper.CalcExtrapFactor(stockASXParent, stockASXChild, new DateTime(2009, 9, 10));

            Assert.AreEqual(scal, 1.05239899198348, 0.001);                                                             //OLD 0.314301/0.298668 //1.06102304848855
            extrapHelper.DoExtrap(stockASXParent, stockASXChild, stockSDParent, child);
            Assert.AreEqual(Convert.ToDouble(child.Expiries[0].Strikes[0].Volatility.Value), 0.997545918986369, 0.001); //0.930043543995147
        }
        /// <summary>
        /// Gets the vols.
        /// </summary>
        /// <param name="volCurve">The vol curve.</param>
        /// <param name="timesToExpiry">The times To Expiry.</param>
        /// <param name="strikes">The strikes.</param>
        /// <returns></returns>
        public List <double> GetVolatilties(IVolatilitySurface volCurve, List <double> timesToExpiry,
                                            List <double> strikes)
        {
            var vol = new List <double>();

            if (timesToExpiry.Count == strikes.Count)
            {
                var index = 0;
                foreach (var time in timesToExpiry)
                {
                    vol.Add(GetVolatility(volCurve, time, strikes[index]));
                    index++;
                }
            }
            return(vol);
        }
        public void TestExtrapolate1()
        {
            IStock              stockASXParent = LoadStock("AGK");
            IStock              stockASXChild  = LoadStock("ANZ");
            IStock              stockSDParent  = LoadStock("AGK");
            IVolatilitySurface  child          = CreateTestVolSurface();
            ExtrapolationHelper extrapHelper   = new ExtrapolationHelper();

            if (stockASXParent.VolatilitySurface.Expiries[0].Strikes[0].InterpModel.GetType() == typeof(WingInterp))
            {
                extrapHelper.DoExtrap(stockASXParent,
                                      stockASXChild,
                                      stockSDParent,
                                      child);
                Assert.AreEqual(Convert.ToDouble(child.NodalExpiries[0].Strikes[0].Volatility.Value), 0.295126142, 0.0001);
            }
        }
        public void TestHistoricalExtrapolate()
        {
            IStock             stockASXParent = LoadStock("AGK");
            IVolatilitySurface stockASXChild  = CreateNullVolSurface();
            IVolatilitySurface targetChild    = CreateNullVolSurface();
            IStock             stockSDParent  = LoadStock("AGK");

            stockASXParent.Valuations.Add(new Valuation(new DateTime(2008, 8, 28), 1208));
            stockASXParent.Valuations.Add(new Valuation(new DateTime(2008, 8, 29), 1221));
            stockASXParent.Valuations.Add(new Valuation(new DateTime(2008, 8, 30), 1218));
            stockASXParent.Valuations.Add(new Valuation(new DateTime(2008, 8, 31), 1207));
            stockASXParent.Valuations.Add(new Valuation(new DateTime(2008, 9, 1), 1250));
            RateCurve       rateCurve    = CreateRateCurve();
            List <Dividend> divCurve     = CreateDividends();
            IStock          nullASXChild = new Stock(new DateTime(2009, 9, 9), 200.0M, "ZZZ", "ZZZ", rateCurve, divCurve);

            nullASXChild.VolatilitySurface = stockASXChild;
            nullASXChild.Valuations.Add(new Valuation(new DateTime(2008, 12, 12), 208));
            nullASXChild.Valuations.Add(new Valuation(new DateTime(2008, 12, 13), 221));
            nullASXChild.Valuations.Add(new Valuation(new DateTime(2008, 12, 14), 218));
            nullASXChild.Valuations.Add(new Valuation(new DateTime(2008, 12, 15), 207));
            nullASXChild.Valuations.Add(new Valuation(new DateTime(2008, 12, 16), 201));
            ExtrapolationHelper extrap   = new ExtrapolationHelper();
            decimal             histvol1 = extrap.DoHistVolCalc(stockASXParent);
            decimal             histvol2 = extrap.DoHistVolCalc(nullASXChild);

            Assert.AreEqual(0.375846, Convert.ToDouble(histvol1), 0.0001);
            Assert.AreEqual(0.770018, Convert.ToDouble(histvol2), 0.0001);
            extrap.PopulateHistoricalVols(stockASXParent, nullASXChild, targetChild);
            double scalFactor = Convert.ToDouble(extrap.GetHistoricalScalFactor(stockASXParent, nullASXChild));

            Assert.AreEqual(scalFactor, 2.0487573, 0.0001);
            //Spreadsheet fit SD parent to (5d, 1.000 * F) point, flatline endpoints.
            decimal SDParentVol0 = 0.296175M;
            // Spreadsheet fit SD parent to (7d,0.867 * F) point
            decimal SDParentVol1 = 0.320240M;
            // Spreadsheet fit SD parent to (21d,1.00 * F) point
            decimal SDParentVol2    = 0.287656M;
            double  childExtrapVol0 = scalFactor * Convert.ToDouble(SDParentVol0);
            double  childExtrapVol1 = scalFactor * Convert.ToDouble(SDParentVol1);
            double  childExtrapVol2 = scalFactor * Convert.ToDouble(SDParentVol2);

            Assert.AreEqual(Convert.ToDouble(SDParentVol0 * histvol2 / histvol1), childExtrapVol0, 0.001);
            Assert.AreEqual(Convert.ToDouble(SDParentVol1 * histvol2 / histvol1), childExtrapVol1, 0.001);
            Assert.AreEqual(Convert.ToDouble(SDParentVol2 * histvol2 / histvol1), childExtrapVol2, 0.001);
        }
 /// <summary>
 /// This assumes that the rest dates are consistent with the curve.
 /// </summary>
 /// <param name="valuationDate"></param>
 /// <param name="paymentDate"></param>
 /// <param name="indexCurve"></param>
 /// <param name="expiryTime">The expiry time. </param>
 /// <param name="timeToIndex">The time to reset or expiry. </param>
 /// <param name="strike">The strike. </param>
 /// <param name="indexVolatilitySurface">The index volatility surface. </param>
 /// <param name="fxOptionType">The option type. </param>
 public FxOptionLegAnalytic(DateTime valuationDate, DateTime paymentDate, IFxCurve indexCurve, decimal strike, decimal expiryTime, decimal timeToIndex
                            , IVolatilitySurface indexVolatilitySurface, FxOptionType fxOptionType)
 {
     //ToReportingCurrencyRate = EvaluateReportingCurrencyFxRate(valuationDate, reportingCurrencyFxCurve);
     ForwardFxRate = (decimal)indexCurve.GetForward(valuationDate, paymentDate);
     OptionType    = fxOptionType;
     Strikes       = new List <decimal> {
         strike
     };
     ExpiryTimes = new List <decimal> {
         expiryTime
     };
     TimeToIndices = new List <decimal> {
         timeToIndex
     };
     Volatilities = new List <decimal> {
         (decimal)indexVolatilitySurface.GetValue((double)timeToIndex, (double)strike)
     };
 }
 /// <summary>
 /// Does the extrap.
 /// </summary>
 /// <param name="asxParent">The ASX parent.</param>
 /// <param name="asxChild">The ASX child.</param>
 /// <param name="sdParent">The SD parent.</param>
 /// <param name="child">The child.</param>
 public void DoExtrap(IStock asxParent, IStock asxChild, IStock sdParent, IVolatilitySurface child)
 {
     //foreach expiry in child, interpolate ratio at ASX parent, child and interpolate SD Parent and apply to SD Parent.
     foreach (ForwardExpiry exp in child.NodalExpiries)
     {
         foreach (Strike str in exp.Strikes)
         {
             if (!str.VolatilityHasBeenSet)
             {
                 double           moneyness     = str.StrikePrice / Convert.ToDouble(exp.FwdPrice);
                 double           parentVol     = GetVolAt(sdParent, exp.ExpiryDate, moneyness);
                 double           scalingFactor = CalcExtrapFactor(asxParent, asxChild, exp.ExpiryDate);
                 IVolatilityPoint vp            = new VolatilityPoint();
                 vp.SetVolatility(Convert.ToDecimal(parentVol * scalingFactor), VolatilityState.Default());
                 str.SetVolatility(vp);
             }
         }
     }
 }
        /// <summary>
        /// Populates the historical vols.
        /// </summary>
        /// <param name="leadStock">The lead stock.</param>
        /// <param name="childStock">The child stock.</param>
        /// <param name="child">The child.</param>
        public void PopulateHistoricalVols(IStock leadStock, IStock childStock, IVolatilitySurface child)
        {
            decimal scalingFactor = GetHistoricalScalFactor(leadStock, childStock);

            foreach (ForwardExpiry exp in child.NodalExpiries)
            {
                foreach (Strike str in exp.Strikes)
                {
                    if (!str.VolatilityHasBeenSet)
                    {
                        double           moneyness = str.StrikePrice / Convert.ToDouble(exp.FwdPrice);
                        double           parentVol = GetVolAt(leadStock, exp.ExpiryDate, moneyness);
                        IVolatilityPoint vp        = new VolatilityPoint();
                        vp.SetVolatility(Convert.ToDecimal(parentVol) * scalingFactor, VolatilityState.Default());
                        str.SetVolatility(vp);
                    }
                }
            }
        }
Example #11
0
 /// <summary>
 /// This assumes that the rest dates are consistent with the curve.
 /// </summary>
 /// <param name="valuationDate">The valuation date.</param>
 /// <param name="paymentDate">The payment date. The same rest period is assumed as with the spot date.</param>
 /// <param name="indexCurve">The index curve should be already in the correct form for the fx.</param>
 /// <param name="currency2">Normaly the foreign rate curve.</param>
 /// <param name="currency2PerCurrency1">The currency2PerCurrency1 flag. </param>
 /// <param name="currency1">Normally the domestic rate curve. </param>
 /// <param name="expiryTime">The expiry time. </param>
 /// <param name="timeToIndex">The time to reset or expiry. </param>
 /// <param name="indexVolSurface">The index volatility surface.</param>
 /// <param name="currency1Settlement">Is the currency1 the settlement currency? </param>
 /// <param name="strike">The strike. </param>
 /// <param name="reportingCurrencyFxCurve">The reporting current fx curve from settlement currency to reporting currency. It must already be normalised.</param>
 /// <param name="fxOptionType">The option type. </param>
 public FxOptionAnalytic(DateTime valuationDate, DateTime paymentDate, IFxCurve indexCurve, IRateCurve currency1, IRateCurve currency2,
                         bool currency2PerCurrency1, bool currency1Settlement, decimal strike, decimal expiryTime, decimal timeToIndex,
                         IVolatilitySurface indexVolSurface, FxOptionType fxOptionType, IFxCurve reportingCurrencyFxCurve)
     : base(valuationDate, paymentDate, indexCurve, currency1, currency2, currency2PerCurrency1, currency1Settlement, reportingCurrencyFxCurve)
 {
     OptionType = fxOptionType;
     Strikes    = new List <decimal> {
         strike
     };
     ExpiryTimes = new List <decimal> {
         expiryTime
     };
     TimeToIndices = new List <decimal> {
         timeToIndex
     };
     Volatilities = new List <decimal> {
         (decimal)indexVolSurface.GetValue((double)timeToIndex, (double)strike)
     };
 }
Example #12
0
        /// <summary>
        /// Calculates the specified model data.
        /// </summary>
        /// <param name="modelData">The model data.</param>
        /// <returns></returns>
        public override AssetValuation Calculate(IInstrumentControllerData modelData)
        {
            ModelData = modelData;
            AnalyticModelParameters = null;
            AnalyticsModel          = new RateOptionCouponAnalytic();
            RequiresReset           = modelData.ValuationDate > ResetDate;
            IsRealised   = HasBeenRealised(ModelData.ValuationDate);
            TimeToExpiry = GetPaymentYearFraction(ModelData.ValuationDate, AdjustedFixingDate);
            var                volatilityCurveNodeTime = GetPaymentYearFraction(ModelData.ValuationDate, AccrualStartDate);
            IFxCurve           fxCurve         = null;
            IRateCurve         discountCurve   = null;
            IRateCurve         forecastCurve   = null;
            IVolatilitySurface indexVolSurface = null;
            //Add the extra metrics required
            var quotes = ModelData.AssetValuation.quote.ToList();

            if (AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.BreakEvenRate.ToString()) == null)
            {
                var quote = QuotationHelper.Create(0.0m, InstrumentMetrics.BreakEvenRate.ToString(), "DecimalValue");
                quotes.Add(quote);
            }
            if (AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.AccrualFactor.ToString()) == null)
            {
                var quote = QuotationHelper.Create(0.0m, InstrumentMetrics.AccrualFactor.ToString(), "DecimalValue");
                quotes.Add(quote);
            }
            if (AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.FloatingNPV.ToString()) == null)
            {
                var quote = QuotationHelper.Create(0.0m, InstrumentMetrics.FloatingNPV.ToString(), "DecimalValue");
                quotes.Add(quote);
            }
            if (AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.NPV.ToString()) == null)
            {
                var quote = QuotationHelper.Create(0.0m, InstrumentMetrics.NPV.ToString(), "DecimalValue");
                quotes.Add(quote);
            }
            if (AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.LocalCurrencyNPV.ToString()) == null)
            {
                var quote = QuotationHelper.Create(0.0m, InstrumentMetrics.LocalCurrencyNPV.ToString(), "DecimalValue");
                quotes.Add(quote);
            }
            if (AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.LocalCurrencyExpectedValue.ToString()) == null)
            {
                var quote = QuotationHelper.Create(0.0m, InstrumentMetrics.LocalCurrencyExpectedValue.ToString(), "DecimalValue");
                quotes.Add(quote);
            }
            //Check if risk calc are required.
            bool delta1PDH = AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.LocalCurrencyDelta1PDH.ToString()) != null ||
                             AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.Delta1PDH.ToString()) != null;
            //Check if risk calc are required.
            bool delta0PDH = AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.LocalCurrencyDelta0PDH.ToString()) != null ||
                             AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.Delta0PDH.ToString()) != null;

            ModelData.AssetValuation.quote = quotes.ToArray();
            var metrics = ResolveModelMetrics(AnalyticsModel.Metrics);

            //// Determine if DFAM has been requested - if so that is all we evaluate - every other metric is ignored
            //if (metrics.Contains(InstrumentMetrics.DiscountFactorAtMaturity))
            //{
            //    metrics.RemoveAll(metricItem => metricItem != InstrumentMetrics.DiscountFactorAtMaturity);
            //}
            //Set the forecast rate dates. The ForecastRateInterpolation should have been set.
            ForwardStartDate = AccrualStartDate;
            ForwardEndDate   = ForecastRateInterpolation ? AccrualEndDate : AdjustedDateHelper.ToAdjustedDate(FixingCalendar, ForecastRateIndex.indexTenor.Add(ForwardStartDate), AccrualBusinessDayAdjustments);
            //Set the strike
            var strike1  = 0.0m;
            var strike2  = 0.0m;
            var isCollar = false;

            if (PriceableCouponType == CouponType.Cap)
            {
                if (CapStrike != null)
                {
                    strike1 = (decimal)CapStrike;
                }
            }
            if (PriceableCouponType == CouponType.Floor)
            {
                if (FloorStrike != null)
                {
                    strike1 = (decimal)FloorStrike;
                }
            }
            if (PriceableCouponType == CouponType.Collar)//TODO Need to add the Floor calculation which will require a new model or extension of the current model.
            {
                if (CapStrike != null)
                {
                    strike1 = (decimal)CapStrike;
                }
                if (FloorStrike != null)
                {
                    strike2 = (decimal)FloorStrike;
                }
                isCollar = true;
            }
            //var metricsToEvaluate = metrics.ToArray();
            if (metrics.Count > 0)
            {
                YearFractionToCashFlowPayment = GetPaymentYearFraction(ModelData.ValuationDate, PaymentDate);
                var reportingCurrency = ModelData.ReportingCurrency == null
                                            ? PaymentCurrency.Value
                                            : ModelData.ReportingCurrency.Value;
                IRateCouponParameters analyticModelParameters = new RateCouponParameters {
                    Multiplier         = Multiplier,
                    ValuationDate      = modelData.ValuationDate,
                    PaymentDate        = PaymentDate,
                    Currency           = PaymentCurrency.Value,
                    ReportingCurrency  = reportingCurrency,
                    DiscountType       = DiscountType,
                    IsRealised         = IsRealised,
                    HasReset           = RequiresReset,
                    NotionalAmount     = NotionalAmount.amount,
                    Spread             = Margin,
                    YearFraction       = CouponYearFraction,
                    CurveYearFraction  = YearFractionToCashFlowPayment,
                    ExpiryYearFraction = TimeToExpiry,
                    IsCall             = IsCall
                };
                // Curve Related
                if (modelData.MarketEnvironment is ISwapLegEnvironment environment)
                {
                    var streamMarket = environment;
                    discountCurve = streamMarket.GetDiscountRateCurve();
                    discountCurve.PricingStructureEvolutionType = PricingStructureEvolutionType;
                    forecastCurve = streamMarket.GetForecastRateCurve();
                    forecastCurve.PricingStructureEvolutionType = PricingStructureEvolutionType;
                    indexVolSurface = streamMarket.GetVolatilitySurface();
                    indexVolSurface.PricingStructureEvolutionType = PricingStructureEvolutionType;
                    DiscountCurveName     = discountCurve.GetPricingStructureId().UniqueIdentifier;
                    ForecastCurveName     = forecastCurve.GetPricingStructureId().UniqueIdentifier;
                    VolatilitySurfaceName = indexVolSurface.GetPricingStructureId().UniqueIdentifier;
                    // Bucketed Delta
                    if (BucketedDates.Length > 1)
                    {
                        analyticModelParameters.PeriodAsTimesPerYear = GetPaymentYearFraction(BucketedDates[0],
                                                                                              BucketedDates[1]);
                        analyticModelParameters.BucketedDiscountFactors = GetBucketedDiscountFactors(discountCurve,
                                                                                                     ModelData.
                                                                                                     ValuationDate,
                                                                                                     BucketedDates);
                    }
                    //Check for currency.
                    if (ModelData.ReportingCurrency != null)
                    {
                        if (ModelData.ReportingCurrency.Value != PaymentCurrency.Value)
                        {
                            fxCurve = streamMarket.GetReportingCurrencyFxCurve();
                            fxCurve.PricingStructureEvolutionType = PricingStructureEvolutionType;
                        }
                    }
                }
                else if (modelData.MarketEnvironment.GetType() == typeof(MarketEnvironment))
                {
                    var market = (MarketEnvironment)modelData.MarketEnvironment;
                    discountCurve = (IRateCurve)market.SearchForPricingStructureType(DiscountCurveName);
                    discountCurve.PricingStructureEvolutionType = PricingStructureEvolutionType;
                    forecastCurve = (IRateCurve)market.SearchForPricingStructureType(ForecastCurveName);
                    forecastCurve.PricingStructureEvolutionType = PricingStructureEvolutionType;
                    indexVolSurface = (IVolatilitySurface)market.SearchForPricingStructureType(VolatilitySurfaceName);
                    indexVolSurface.PricingStructureEvolutionType = PricingStructureEvolutionType;
                    if (!UseObservedRate)
                    {
                        Rate = GetRate(ForwardStartDate, ForwardEndDate, forecastCurve, ModelData.ValuationDate);
                    }
                    //the rate params
                    analyticModelParameters.Rate = GetRate(ForwardStartDate, ForwardEndDate, forecastCurve, ModelData.ValuationDate);
                    // Bucketed Delta
                    if (BucketedDates.Length > 1)
                    {
                        analyticModelParameters.PeriodAsTimesPerYear = GetPaymentYearFraction(BucketedDates[0],
                                                                                              BucketedDates[1]);
                        analyticModelParameters.BucketedDiscountFactors = GetBucketedDiscountFactors(discountCurve,
                                                                                                     ModelData.
                                                                                                     ValuationDate,
                                                                                                     BucketedDates);
                    }
                    if (delta1PDH)
                    {
                        var riskMarket = market.SearchForPerturbedPricingStructures(DiscountCurveName, "delta1PDH");
                        analyticModelParameters.Delta1PDHCurves       = riskMarket;
                        analyticModelParameters.Delta1PDHPerturbation = 10;
                    }
                    if (delta0PDH)
                    {
                        var riskMarket = market.SearchForPerturbedPricingStructures(ForecastCurveName, "delta0PDH");
                        analyticModelParameters.Delta0PDHCurves       = riskMarket;
                        analyticModelParameters.Delta0PDHPerturbation = 10;
                    }
                    //Check for currency.
                    if (ModelData.ReportingCurrency != null)
                    {
                        if (ModelData.ReportingCurrency.Value != PaymentCurrency.Value)
                        {
                            string curveName = MarketEnvironmentHelper.ResolveFxCurveNames(PaymentCurrency.Value, modelData.ReportingCurrency.Value);
                            fxCurve = (IFxCurve)market.SearchForPricingStructureType(curveName);
                            fxCurve.PricingStructureEvolutionType = PricingStructureEvolutionType;
                        }
                    }
                }
                analyticModelParameters.DiscountCurve            = discountCurve;
                analyticModelParameters.ForecastCurve            = forecastCurve;
                analyticModelParameters.VolatilitySurface        = indexVolSurface;
                analyticModelParameters.ReportingCurrencyFxCurve = fxCurve;
                AnalyticModelParameters = analyticModelParameters;
                //Set the base rate. Default is zero
                if (AnalyticModelParameters != null)
                {
                    AnalyticModelParameters.BaseRate = BaseRate;
                }
                if (UseObservedRate)
                {
                    AnalyticsModel = new FixedRateCouponAnalytic(ModelData.ValuationDate, AccrualStartDate, AccrualEndDate, PaymentDate, Rate,
                                                                 analyticModelParameters.YearFraction, DiscountType, fxCurve, discountCurve, forecastCurve);
                    if (Rate != null)
                    {
                        analyticModelParameters.Rate = (decimal)Rate;
                    }
                }
                if (!isCollar)
                {
                    AnalyticsModel = new RateOptionCouponAnalytic(ModelData.ValuationDate, AccrualStartDate, AccrualEndDate, PaymentDate, volatilityCurveNodeTime,
                                                                  strike1, fxCurve, discountCurve, forecastCurve, indexVolSurface);
                }
                else
                {
                    AnalyticsModel = new RateOptionCouponAnalytic(ModelData.ValuationDate, AccrualStartDate, AccrualEndDate, PaymentDate, volatilityCurveNodeTime,
                                                                  strike1, strike2, fxCurve, discountCurve, forecastCurve, indexVolSurface);
                }
                CalculationResults            = AnalyticsModel.Calculate <IRateInstrumentResults, RateInstrumentResults>(AnalyticModelParameters, metrics.ToArray());
                CalculationPerformedIndicator = true;
                PaymentDiscountFactor         = ((FixedRateCouponAnalytic)AnalyticsModel).PaymentDiscountFactor;
                if (!UseObservedRate)
                {
                    Rate = CalculationResults.BreakEvenRate;
                }
                ForecastAmount = MoneyHelper.GetAmount(CalculationResults.LocalCurrencyExpectedValue, PaymentAmount.currency);
                NPV            = MoneyHelper.GetAmount(CalculationResults.LocalCurrencyNPV, PaymentAmount.currency);
            }
            AssetValuation valuation = GetValue(CalculationResults, modelData.ValuationDate);

            valuation.id = Id;
            return(valuation);
        }
Example #13
0
        /// <summary>
        /// This routine finds the average of the index and the volatility between PaymentStart and PaymentEnd.
        /// AveFrequency determines the daily averaging frequency
        /// e.g.AveFrequency =  1 finds average of daily values;
        /// AveFrequency =  7 finds average of weekly values etc.
        /// PaymentEnd is not included in the averaging calculation.
        /// It is assumed that PaymentStart and PaymentEnd have already been adjusted to be business days
        /// Each AverageDate is calculated by adding on the correct number of business days
        /// PaymentRateSet is the sum of the rates that have already been fixed in the period.
        /// This is added onto the sum of the forward rates and the average calculated by dividing
        /// the total sum by the number of averaging points in the period
        /// Holidays:	Index Start is appropriate working day for the Average Date
        ///             Index Set is two working days prior to this Index Start
        ///             Index End is the appropriate working day following addition of the tenor
        /// </summary>
        /// <param name="valueDate"></param>
        /// <param name="discountCurve"></param>
        /// <param name="indexCurve"></param>
        /// <param name="paymentStart"></param>
        /// <param name="paymentEnd"></param>
        /// <param name="indexDaycount"></param>
        /// <param name="indexTenor"></param>
        /// <param name="indexCoupon"></param>
        /// <param name="paymentRateSet"></param>
        /// <param name="indexRateSet"></param>
        /// <param name="averagingFrequency"></param>
        /// <param name="averagePreset"></param>
        /// <param name="indexCity"></param>
        /// <param name="convention"></param>
        /// <param name="volatilityMargin"></param>
        /// <param name="indexVolatility"></param>
        /// <returns></returns>
        public static Double? GetAverageRate(DateTime valueDate, IRateCurve discountCurve,
            IRateCurve indexCurve, DateTime paymentStart, DateTime paymentEnd, int indexDaycount, int indexTenor, int indexCoupon,
            double paymentRateSet, double indexRateSet, int averagingFrequency,
            int averagePreset, long indexCity, int convention, double volatilityMargin,
            IVolatilitySurface indexVolatility)
        {
            long indexSet, indexStart, indexEnd;
            double sumRate = 0.0;
            double sumVol = 0.0;
            double firstVol = 0.0;
            var averageDate = paymentStart;
            int numAvePoints = 0;
            if (indexCurve is null)
                return null;
            //Do simple approximation i.e. divide the sum of the start and end values by two 
            if (averagingFrequency <= 0)
            {

                DateTime Ave_Index_Start, Ave_Index_End;
                //Calculate the fixing date for the start date of the period
                long firstSet = AddWorkDays(PaymentStart, Ave_Preset, Index_City, CHoliday::PRECEEDING);
                //Calculate the fixing date for the end date of the period
                long lastSet = AddWorkDays(PaymentEnd, Ave_Preset, Index_City, CHoliday::PRECEEDING);
                if (valueDate >= lastSet)
                {
                    IndexVolatility = 0.0;
                    return Payment_Rateset / 2.0; //Both the start and the end rates have been fixed
                }

                double firstRate;
                if (valueDate < firstSet)
                {
                    Index_Start = PaymentStart;
                    Date Ave_Index_Start = Index_Start;
                    Date Ave_Index_End = Ave_Index_Start.AddMonths(ConvertToMonths(Index_Tenor));
                    Index_End = GoodDay(Ave_Index_End.GetJulian(), Index_City, Convention);
                    long Index_Tenor_Days = (long) (Index_End - Index_Start);
                    long IndexExpiry = (long) (firstSet - Value_Date);

                    firstRate = _GetIndex(Value_Date, firstSet, Index_Start, Index_End, Index_Tenor,
                        Index_Daycount, Index_Coupon, Index_Coupon, *pIndexCurve, Index_Rateset);
                    // SAJ 25/9/96  Added Volatility margin to volatility to allow for bumping
                    firstVol = GetVolatility(CapsVolName, SwaptVolName, IndexExpiry, Index_Tenor_Days, 0.0) +
                               VolatilityMargin;
                    // SAJ 25/9/96	Added following lines for convexity effect
                    double Weight, AdjForward;
                    GetModifiedForward(Value_Date, PaymentEnd, firstSet, Index_Start, Index_End,
                        Index_Tenor, Index_Coupon, Index_Daycount,
                        *pIndexCurve, firstRate, firstVol, Weight, AdjForward);
                    firstRate = Weight * firstRate + (1 - Weight) * AdjForward;
                    // SAJ 25/9/96 End
                }
                else
                {
                    firstRate = Payment_Rateset;
                    firstVol = 0.0;
                }

                Index_Start = PaymentEnd;
                Ave_Index_Start = Index_Start;
                Ave_Index_End = Ave_Index_Start.AddMonths(ConvertToMonths(Index_Tenor));
                Index_End = GoodDay(Ave_Index_End.GetJulian(), Index_City, Convention);
                long Index_Tenor_Days = (long) (Index_End - Index_Start);
                long IndexExpiry = (long) (lastSet - Value_Date);
                double lastRate = _GetIndex(Value_Date, lastSet, Index_Start, Index_End, Index_Tenor,
                    Index_Daycount, Index_Coupon, Index_Coupon, *pIndexCurve, Index_Rateset);
                // SAJ 25/9/96  Added Volatility margin to volatility to allow for bumping
                double LastVol = GetVolatility(CapsVolName, SwaptVolName, IndexExpiry, Index_Tenor_Days, 0.0) +
                                 VolatilityMargin;
                // SAJ 25/9/96	Added following lines for convexity effect
                double Weight, AdjForward;
                GetModifiedForward(Value_Date, PaymentEnd, lastSet, Index_Start, Index_End,
                    Index_Tenor, Index_Coupon, Index_Daycount,
                    *pIndexCurve, lastRate, LastVol, Weight, AdjForward);
                lastRate = Weight * lastRate + (1 - Weight) * AdjForward;
                // SAJ 25/9/96 End
                IndexVolatility = (firstVol + LastVol) / 2.0 + VolatilityMargin;
                return (firstRate + lastRate) / 2.0;
            }

            //Check if already into the averaging loop or the period is historical
            if (valueDate > PaymentStart)
            {
                sumRate = Payment_Rateset;
                sumVol = 0.0;
            }

            //Begin the averaging loop
            while (averageDate < PaymentEnd)
            {
                //Calculate the index setting date
                Index_Set = AddWorkDays(AverageDate, Ave_Preset, Index_City, CHoliday::PRECEEDING);
                if (Value_Date < Index_Set)
                {
                    Date Ave_Index_Start = AverageDate;
                    Date Ave_Index_End = Ave_Index_Start.AddMonths(ConvertToMonths(Index_Tenor));
                    Index_End = GoodDay(Ave_Index_End.GetJulian(), Index_City, Convention);
                    long Index_Tenor_Days = (long) (Index_End - AverageDate);
                    long IndexExpiry = (long) (Index_Set - Value_Date);
                    double NewRate = _GetIndex(Value_Date, Index_Set, AverageDate, Index_End, Index_Tenor,
                        Index_Daycount, Index_Coupon, Index_Coupon, *pIndexCurve, Index_Rateset);

                    // SAJ 25/9/96  Added Volatility margin to volatility to allow for bumping
                    double newVol = GetVolatility(CapsVolName, SwaptVolName, IndexExpiry, Index_Tenor_Days, 0.0) +
                                    VolatilityMargin;

                    // SAJ 25/9/96	Added following lines for convexity effect
                    double weight, adjForward;
                    GetModifiedForward(Value_Date, PaymentEnd, Index_Set, AverageDate, Index_End,
                        Index_Tenor, Index_Coupon, Index_Daycount,
                        *pIndexCurve, NewRate, newVol, weight, adjForward);
                    NewRate = weight * NewRate + (1 - weight) * adjForward;
                    // SAJ 25/9/96 End
                    sumRate += NewRate;
                    sumVol += (newVol * newVol);
                }

                numAvePoints++;
                // Increment average date by the averaging frequency
                // Here should make the convention Following otherwise will not get out of the end of the month
                // SAJ 25/9/96 Changed the following line to add AveFrequency days and then check good days
                //	    AverageDate = AddWorkDays(AverageDate, AveFrequency, Index_City, CHoliday::FOLLOWING);
                averageDate += AveFrequency;
                averageDate =
                    GoodDay(AverageDate, Index_City, CHoliday::FOLLOWING); // Use following to prevent chattering
                // SAJ 25/9/96 End
            }

            IndexVolatility = Math.Sqrt(sumVol / numAvePoints) + volatilityMargin;
            return sumRate / numAvePoints;
        }
 /// <summary>
 /// Initiates a new model.
 /// </summary>
 /// <param name="valuationDate">The valuation date.</param>
 /// <param name="startDate">The start date of the coupon.</param>
 /// <param name="endDate">The end date of the coupon.</param>
 /// <param name="paymentDate">The payment date of the cash flow.</param>
 /// <param name="timeToIndex">The timeToIndex. Not necessarily the time to expiry. This is used for surface interpolation..</param>
 /// <param name="capStrike">The cap strike.</param>
 /// <param name="floorStrike">The floor strike.</param>
 /// <param name="reportingCurrencyFxCurve">THe fx curve. It must already be normalised.</param>
 /// <param name="discountCurve">The rate curve to use for discounting.</param>
 /// <param name="forecastCurve">The forecast curve.</param>
 /// <param name="indexVolSurface">The index volatility surface.</param>
 public RateOptionCouponAnalytic(DateTime valuationDate, DateTime startDate, DateTime endDate, DateTime paymentDate,
                                 decimal timeToIndex, decimal capStrike, decimal floorStrike, IFxCurve reportingCurrencyFxCurve, IRateCurve discountCurve, IRateCurve forecastCurve, IVolatilitySurface indexVolSurface)
     : this(valuationDate, startDate, endDate, paymentDate, timeToIndex, capStrike, reportingCurrencyFxCurve, discountCurve, forecastCurve, indexVolSurface)
 {
     IsCollar              = true;
     CollarFloorStrike     = floorStrike;
     CollarFloorVolatility = (decimal)indexVolSurface.GetValue((double)timeToIndex, (double)floorStrike);
 }
        /// <summary>
        /// This assumes that the rest dates are consistent with the curve.
        /// </summary>
        /// <param name="valuationDate"></param>
        /// <param name="paymentDate">The payment date. The same rest period is assumed as with the spot date.</param>
        /// <param name="indexCurve">The index curve should be already in the correct form for the fx.</param>
        /// <param name="currency2">Normally the foreign rate curve.</param>
        /// <param name="currency2PerCurrency1">The currency2PerCurrency1 flag. </param>
        /// <param name="currency1">Normally the domestic rate curve. </param>
        /// <param name="indexVolatilitySurface">The index volatility surface. </param>
        /// <param name="expiryTime">The expiry time. </param>
        /// <param name="timeToIndex">The time to reset or expiry. </param>
        /// <param name="strike">The strike. </param>
        /// <param name="fxOptionType">The option type. </param>
        public FxOptionLegAnalytic(DateTime valuationDate, DateTime paymentDate, IFxCurve indexCurve, IRateCurve currency1, IRateCurve currency2,
                                   bool currency2PerCurrency1, decimal strike, decimal expiryTime, decimal timeToIndex, IVolatilitySurface indexVolatilitySurface, FxOptionType fxOptionType)
        {
            //ToReportingCurrencyRate = EvaluateReportingCurrencyFxRate(valuationDate, reportingCurrencyFxCurve);
            var todayRate = indexCurve.GetForward(valuationDate, valuationDate); //TODO The spot rate may not be the same due to the carry effect, but the evolution works.
            var df1       = currency1.GetDiscountFactor(valuationDate, paymentDate);
            var df2       = currency2.GetDiscountFactor(valuationDate, paymentDate);
            var forward   = df1 / df2;

            if (!currency2PerCurrency1)
            {
                forward = df2 / df1;
            }
            ForwardFxRate = (decimal)(todayRate * forward);
            OptionType    = fxOptionType;
            Strikes       = new List <decimal> {
                strike
            };
            ExpiryTimes = new List <decimal> {
                expiryTime
            };
            TimeToIndices = new List <decimal> {
                timeToIndex
            };
            Volatilities = new List <decimal> {
                (decimal)indexVolatilitySurface.GetValue((double)timeToIndex, (double)strike)
            };
        }
        /// <summary>
        /// Creates a stream environment.
        /// </summary>
        /// <param name="baseDate"></param>
        /// <param name="discountCurve"></param>
        /// <param name="forecastCurve"></param>
        /// <param name="fxCurve"></param>
        /// <param name="volSurface"></param>
        /// <returns></returns>
        public static ISwapLegEnvironment CreateInterestRateStreamEnvironment(DateTime baseDate, IRateCurve discountCurve, IRateCurve forecastCurve, IFxCurve fxCurve, IVolatilitySurface volSurface)
        {
            var market = new SwapLegEnvironment();

            market.AddPricingStructure(InterestRateStreamPSTypes.DiscountCurve.ToString(), discountCurve);
            market.AddPricingStructure(InterestRateStreamPSTypes.ForecastCurve.ToString(), forecastCurve);
            market.AddPricingStructure(InterestRateStreamPSTypes.ReportingCurrencyFxCurve.ToString(), fxCurve);
            market.AddPricingStructure(InterestRateStreamPSTypes.ForecastIndexVolatilitySurface.ToString(), volSurface);
            return(market);
        }
 /// <summary>
 /// Initiates a new model.
 /// </summary>
 /// <param name="valuationDate">The valuation date.</param>
 /// <param name="startDate">The start date of the coupon.</param>
 /// <param name="endDate">The end date of the coupon.</param>
 /// <param name="paymentDate">The payment date of the cash flow.</param>
 /// <param name="timeToIndex">The timeToIndex. Not necessarily the time to expiry. This is used for surface interpolation..</param>
 /// <param name="strike">The strike.</param>
 /// <param name="reportingCurrencyFxCurve">THe fx curve. It must already be normalised.</param>
 /// <param name="discountCurve">The rate curve to use for discounting.</param>
 /// <param name="forecastCurve">The forecast curve.</param>
 /// <param name="indexVolSurface">The index volatility surface.</param>
 public RateOptionCouponAnalytic(DateTime valuationDate, DateTime startDate, DateTime endDate, DateTime paymentDate,
                                 decimal timeToIndex, decimal strike, IFxCurve reportingCurrencyFxCurve, IRateCurve discountCurve, IRateCurve forecastCurve, IVolatilitySurface indexVolSurface)
     : base(valuationDate, startDate, endDate, paymentDate, reportingCurrencyFxCurve, discountCurve, forecastCurve)
 {
     Strike      = strike;
     TimeToIndex = timeToIndex;
     Volatility  = (decimal)indexVolSurface.GetValue((double)timeToIndex, (double)strike);
 }
Example #18
0
        /// <summary>
        /// Calculates the specified model data.
        /// </summary>
        /// <param name="valuationDate">The valuation date.</param>
        /// <param name="discountCurve">The discount curve.</param>
        /// <param name="forecastCurve">The forward curve.</param>
        /// <param name="volCurve">The volatility surface.
        /// and discount curves when called with ForecastRateCurve.</param>
        /// <param name="curveToPerturb">The curve to perturb: the discount curve, the forecast curve or both.</param>
        /// <returns></returns>
        public IDictionary <string, double> CalculateRatePDH(DateTime valuationDate,
                                                             IRateCurve discountCurve, IRateCurve forecastCurve, IVolatilitySurface volCurve, CurvePerturbation curveToPerturb)
        {
            var result = new Dictionary <string, double>();

            AnalyticResults = new RateOptionAssetResults();
            switch (ModelIdentifier)
            {
            case "CapAsset":
                AnalyticsModel = new RateOptionAssetAnalytic();
                break;

            case "DiscountCapAsset":
                AnalyticsModel = new RateOptionAssetAnalytic();
                break;
            }
            ForecastCurveName   = forecastCurve.GetPricingStructureId().UniqueIdentifier;
            DiscountCurveName   = discountCurve.GetPricingStructureId().UniqueIdentifier;
            VolatilityCurveName = volCurve.GetPricingStructureId().UniqueIdentifier;
            var analyticModelParameters = new RateOptionAssetParameters {
                IsPut = !IsCap, Notionals = Notionals
            };

            //and the rest rates
            if (ResetRates != null)
            {
                analyticModelParameters.ForwardRates = ResetRates;
            }
            //2. Get the discount factors
            analyticModelParameters.ForecastDiscountFactors =
                GetDiscountFactors(forecastCurve, AdjustedPeriodDates.ToArray(), valuationDate);
            analyticModelParameters.PaymentDiscountFactors =
                GetDiscountFactors(discountCurve, AdjustedPeriodDates.ToArray(), valuationDate);
            //3. Get the respective year fractions
            analyticModelParameters.YearFractions = YearFractions;
            //4. set the expiry times.
            TimesToExpiry =
                GetTimesToExpiry(ExpiryDates, valuationDate);
            analyticModelParameters.TimesToExpiry = TimesToExpiry;
            //5. Get the vols
            analyticModelParameters.Volatilities =
                GetVolatilties(volCurve, TimesToExpiry, Strikes);
            //8. Get the Strikes
            analyticModelParameters.Strikes = Strikes;
            //9. Set the analytic input parameters and Calculate the respective metrics
            var analyticResults =
                AnalyticsModel.Calculate <IRateOptionAssetResults, RateOptionAssetResults>(analyticModelParameters,
                                                                                           new[] { RateOptionMetrics.NPV });

            AnalyticResults = analyticResults;
            var baseNPV = SumDoubleList(AnalyticResults.NPV, 0);

            //Now loop through the risk curves.
            if (curveToPerturb == CurvePerturbation.DiscountCurve)
            {
                var riskCurves = discountCurve.CreateCurveRiskSet(1);
                foreach (var curve in riskCurves)
                {
                    var perturbedAsset = curve.GetPricingStructureId().Properties.GetValue <string>("PerturbedAsset");
                    analyticResults = RiskCalculationHelper((IRateCurve)curve, analyticModelParameters);
                    result.Add("DiscountCurve:" + perturbedAsset, baseNPV - SumDoubleList(analyticResults.NPV, 0));
                }
            }
            if (curveToPerturb == CurvePerturbation.ForecastCurve)
            {
                var riskCurves = forecastCurve.CreateCurveRiskSet(1);
                foreach (var curve in riskCurves)
                {
                    var perturbedAsset = curve.GetPricingStructureId().Properties.GetValue <string>("PerturbedAsset");
                    analyticResults = ForecastRiskCalculationHelper((IRateCurve)curve, analyticModelParameters);
                    result.Add("ForecastCurve:" + perturbedAsset, baseNPV - SumDoubleList(analyticResults.NPV, 0));
                }
            }
            if (curveToPerturb == CurvePerturbation.Both)
            {
                var riskCurves1 = discountCurve.CreateCurveRiskSet(1);
                foreach (var curve in riskCurves1)
                {
                    var perturbedAsset = curve.GetPricingStructureId().Properties.GetValue <string>("PerturbedAsset");
                    analyticResults = RiskCalculationHelper((IRateCurve)curve, analyticModelParameters);
                    result.Add("DiscountCurve:" + perturbedAsset, baseNPV - SumDoubleList(analyticResults.NPV, 0));
                }
                var riskCurves2 = forecastCurve.CreateCurveRiskSet(1);
                foreach (var curve in riskCurves2)
                {
                    var perturbedAsset = curve.GetPricingStructureId().Properties.GetValue <string>("PerturbedAsset");
                    analyticResults = ForecastRiskCalculationHelper((IRateCurve)curve, analyticModelParameters);
                    result.Add("ForecastCurve:" + perturbedAsset, baseNPV - SumDoubleList(analyticResults.NPV, 0));
                }
            }
            return(result);
        }
Example #19
0
        /// <summary>
        /// Calculates the specified model data.
        /// </summary>
        /// <param name="modelData">The model data.</param>
        /// <returns></returns>
        public override BasicAssetValuation Calculate(IAssetControllerData modelData)
        {
            ModelData = modelData;
            switch (ModelIdentifier)
            {
            case "CapAsset":
                AnalyticsModel = new RateOptionAssetAnalytic();
                break;

            case "DiscountCapAsset":
                AnalyticsModel = new RateOptionAssetAnalytic();
                break;
            }
            var metrics                 = MetricsHelper.GetMetricsToEvaluate(Metrics, AnalyticsModel.Metrics);
            var metricsToEvaluate       = metrics.ToArray();
            var analyticModelParameters = new RateOptionAssetParameters();

            AnalyticResults = new RateOptionAssetResults();
            var                marketEnvironment = modelData.MarketEnvironment;
            IRateCurve         rateCurve         = null;
            IRateCurve         discountCurve     = null;
            IVolatilitySurface volCurve          = null;

            //1. instantiate curve
            if (marketEnvironment.GetType() == typeof(SwapLegEnvironment))
            {
                rateCurve           = ((ISwapLegEnvironment)marketEnvironment).GetForecastRateCurve();
                ForecastCurveName   = rateCurve.GetPricingStructureId().UniqueIdentifier;
                discountCurve       = ((ISwapLegEnvironment)marketEnvironment).GetDiscountRateCurve();
                DiscountCurveName   = discountCurve.GetPricingStructureId().UniqueIdentifier;
                volCurve            = ((ISwapLegEnvironment)marketEnvironment).GetVolatilitySurface();
                VolatilityCurveName = volCurve.GetPricingStructureId().UniqueIdentifier;
            }
            //Cap logic.
            analyticModelParameters.IsPut = !IsCap;
            //1. Notionals
            analyticModelParameters.Notionals = Notionals;
            //and the rest rates
            if (ResetRates != null)
            {
                analyticModelParameters.ForwardRates = ResetRates;
            }
            //2. Get the discount factors
            analyticModelParameters.ForecastDiscountFactors =
                GetDiscountFactors(rateCurve, AdjustedPeriodDates.ToArray(), modelData.ValuationDate);
            analyticModelParameters.PaymentDiscountFactors =
                GetDiscountFactors(discountCurve, AdjustedPeriodDates.ToArray(), modelData.ValuationDate);
            //3. Get the respective year fractions
            analyticModelParameters.YearFractions = YearFractions;
            //4. set the expiry times.
            TimesToExpiry =
                GetTimesToExpiry(ExpiryDates, modelData.ValuationDate);
            analyticModelParameters.TimesToExpiry = TimesToExpiry;
            //5. Get the vols
            analyticModelParameters.Volatilities =
                GetVolatilties(volCurve, TimesToExpiry, Strikes);
            //8. Get the Strikes
            analyticModelParameters.Strikes = Strikes;
            ParRate = CalculateImpliedParRate(modelData.ValuationDate);
            analyticModelParameters.Rate = (double)ParRate;
            //9. Set the analytic input parameters and Calculate the respective metrics
            AnalyticResults =
                AnalyticsModel.Calculate <IRateOptionAssetResults, RateOptionAssetResults>(analyticModelParameters,
                                                                                           metricsToEvaluate);
            //TODO change this method and return a table report of all greeks.
            return(GetValue(AnalyticResults));
        }
        public static Decimal CalculateStrikeDelta(bool isCall, decimal swapBreakEvenRate, decimal strike, double timeToExpiry, double timeToIndex, IVolatilitySurface indexVolSurface)
        {
            var volatility = (decimal)indexVolSurface.GetValue(timeToIndex, (double)strike);
            var result     = OptionAnalytics.OptWithGreeks(isCall, (double)swapBreakEvenRate, (double)strike, (double)volatility, timeToExpiry)[6];

            return((decimal)result);
        }
        /// <summary>
        /// Calculates the specified model data.
        /// </summary>
        /// <param name="modelData">The model data.</param>
        /// <returns></returns>
        public override AssetValuation Calculate(IInstrumentControllerData modelData)
        {
            ModelData = modelData;
            AnalyticModelParameters = null;
            CalculationResults      = null;
            UpdateBucketingInterval(ModelData.ValuationDate, PeriodHelper.Parse(CDefaultBucketingInterval));
            // 1. First derive the analytics to be evaluated via the stream controller model
            // NOTE: These take precendence of the child model metrics
            if (AnalyticsModel == null)
            {
                AnalyticsModel = new SimpleIRSwaptionInstrumentAnalytic();
            }
            var swaptionControllerMetrics = ResolveModelMetrics(AnalyticsModel.Metrics);
            var quotes = ModelData.AssetValuation.quote.ToList();

            if (AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.BreakEvenRate.ToString()) == null)
            {
                var quote = QuotationHelper.Create(0.0m, InstrumentMetrics.BreakEvenRate.ToString(), "DecimalValue");
                quotes.Add(quote);
            }
            if (AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.NPV.ToString()) == null)
            {
                var quote = QuotationHelper.Create(0.0m, InstrumentMetrics.NPV.ToString(), "DecimalValue");
                quotes.Add(quote);
            }
            ModelData.AssetValuation.quote = quotes.ToArray();
            AssetValuation swaptionValuation;

            //Sets the evolution type for calculations.
            Swap.PricingStructureEvolutionType = PricingStructureEvolutionType;
            Swap.BucketedDates = BucketedDates;
            if (PremiumPayments != null)
            {
                foreach (var payment in PremiumPayments)
                {
                    payment.PricingStructureEvolutionType = PricingStructureEvolutionType;
                    payment.BucketedDates = BucketedDates;
                }
            }
            //The assetValuation list.
            var childValuations = new List <AssetValuation>();

            // 2. Now evaluate only the child specific metrics (if any)
            if (PremiumPayments != null)
            {
                var paymentControllers = new List <InstrumentControllerBase>(PremiumPayments);
                childValuations.AddRange(paymentControllers.Select(payment => payment.Calculate(modelData)));
            }
            var swapMetrics = Swap.Calculate(modelData);
            //We assume the fixed leg is always the first leg!
            var fixedLeg      = Swap.GetLegs()[0].Calculate(modelData);
            var breakEvenRate = AssetValuationHelper.GetQuotationByMeasureType(swapMetrics, InstrumentMetrics.BreakEvenRate.ToString()).value;
            var timeToIndex   = (Swap.EffectiveDate - ModelData.ValuationDate).Days / 365.0;
            //This is European only.
            var expiryTime = (ExerciseDates[0] - ModelData.ValuationDate).Days / 365.0;
            IVolatilitySurface indexVolSurface = null;

            if (modelData.MarketEnvironment is ISwapLegEnvironment streamMarket1)
            {
                indexVolSurface = streamMarket1.GetVolatilitySurface();
                indexVolSurface.PricingStructureEvolutionType = PricingStructureEvolutionType;
                VolatilitySurfaceName = indexVolSurface.GetPricingStructureId().UniqueIdentifier;
            }
            else
            {
                if (!string.IsNullOrEmpty(VolatilitySurfaceName))
                {
                    indexVolSurface = (IVolatilitySurface)modelData.MarketEnvironment.GetPricingStructure(VolatilitySurfaceName);
                }
            }
            //Calculate the delta
            var delta = SimpleIRSwaptionInstrumentAnalytic.CalculateOptionDelta(IsCall, breakEvenRate, StrikeRate, expiryTime, timeToIndex, indexVolSurface);

            //Set the multiplier using the delta of the option.
            //Multiplier = delta;?
            Swap.Multiplier = System.Math.Abs(delta);
            //New function that converts the metrics by multiplying be the delta.
            var swapCalculations = Swap.Calculate(modelData);
            //childValuations.Add(swapCalculations);
            var childControllerValuations = AssetValuationHelper.AggregateMetrics(childValuations, new List <string>(Metrics), PaymentCurrencies); // modelData.ValuationDate);
            var streamAccrualFactor       = AssetValuationHelper.GetQuotationByMeasureType(fixedLeg, InstrumentMetrics.AccrualFactor.ToString());  //TODO This is not correct!
            var npv = AssetValuationHelper.GetQuotationByMeasureType(childControllerValuations, InstrumentMetrics.NPV.ToString());

            childValuations.Add(swapCalculations);
            // Child metrics have now been calculated so we can now evaluate the stream model metrics
            if (swaptionControllerMetrics.Count > 0)
            {
                //Get the market data.
                IFxCurve fxCurve = null;
                ISwaptionInstrumentParameters analyticModelParameters = new SwaptionInstrumentParameters
                {
                    IsBought          = IsBasePartyBuyer,
                    IsCall            = IsCall,
                    SwapAccrualFactor = System.Math.Abs(streamAccrualFactor.value),
                    Strike            = StrikeRate,
                    OtherNPV          = npv.value,
                    TimeToExpiry      = (decimal)expiryTime,
                    SwapBreakEvenRate = breakEvenRate,
                    //OtherNPV =
                };
                // Curve Related
                if (modelData.MarketEnvironment is ISwapLegEnvironment streamMarket)
                {
                    analyticModelParameters.VolatilitySurface = indexVolSurface;
                    //Check for currency.
                    if (ModelData.ReportingCurrency != null)
                    {
                        if (ModelData.ReportingCurrency.Value != PaymentCurrencies[0])//This is an interest rate swap and so only has one currency.
                        {
                            fxCurve = streamMarket.GetReportingCurrencyFxCurve();
                            fxCurve.PricingStructureEvolutionType = PricingStructureEvolutionType;
                        }
                    }
                }
                var analyticsModel = new SimpleIRSwaptionInstrumentAnalytic(ModelData.ValuationDate, (decimal)timeToIndex,
                                                                            StrikeRate, fxCurve, indexVolSurface);
                AnalyticsModel          = analyticsModel;
                Volatility              = analyticsModel.Volatility;
                AnalyticModelParameters = analyticModelParameters;
                CalculationResults      = AnalyticsModel.Calculate <ISwaptionInstrumentResults, SwaptionInstrumentResults>(analyticModelParameters, swaptionControllerMetrics.ToArray());
                // Now merge back into the overall stream valuation
                var swapControllerValuation = GetValue(CalculationResults, modelData.ValuationDate);
                //childValuations.Add(swapControllerValuation);
                childControllerValuations = AssetValuationHelper.AggregateMetrics(childValuations, new List <string>(Metrics), PaymentCurrencies);// modelData.ValuationDate);
                swaptionValuation         = AssetValuationHelper.UpdateValuation(swapControllerValuation,
                                                                                 childControllerValuations, ConvertMetrics(swaptionControllerMetrics), new List <string>(Metrics));
                //swaptionValuation = AssetValuationHelper.AggregateMetrics(childValuations, new List<string>(Metrics), modelData.ValuationDate);
            }
            else
            {
                swaptionValuation = childControllerValuations;
            }
            CalculationPerfomedIndicator = true;
            swaptionValuation.id         = Id;
            return(swaptionValuation);
        }
Example #22
0
        /// <summary>
        /// Calculates the specified model data.
        /// </summary>
        /// <param name="modelData">The model data.</param>
        /// <returns></returns>
        public override AssetValuation Calculate(IInstrumentControllerData modelData)
        {
            ModelData = modelData;
            AnalyticModelParameters       = null;
            AnalyticsModel                = new FxOptionAnalytic();
            CalculationResults            = null;
            YearFractionToCashFlowPayment = Convert.ToDecimal(CDefaultDayCounter.YearFraction(ModelData.ValuationDate, PaymentDate));
            //Make sure there are some bucket dates even if not set previously.
            if (BucketedDates.Length < 1)
            {
                UpdateBucketingInterval(ModelData.ValuationDate, PeriodHelper.Parse(CDefaultBucketingInterval));
            }
            IsRealised = HasBeenRealised(ModelData.ValuationDate);
            //Add the extra metrics required
            var quotes = ModelData.AssetValuation.quote.ToList();

            if (AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, FloatingCashflowMetrics.NPV.ToString()) == null)
            {
                var quote = QuotationHelper.Create(0.0m, FloatingCashflowMetrics.LocalCurrencyNPV.ToString(), "DecimalValue", ModelData.ValuationDate);
                quotes.Add(quote);
            }
            if (AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, FloatingCashflowMetrics.LocalCurrencyNPV.ToString()) == null)
            {
                var quote = QuotationHelper.Create(0.0m, FloatingCashflowMetrics.LocalCurrencyNPV.ToString(), "DecimalValue", ModelData.ValuationDate);
                quotes.Add(quote);
            }
            if (AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.RiskNPV.ToString()) == null)
            {
                var quote = QuotationHelper.Create(0.0m, InstrumentMetrics.NPV.ToString(), "DecimalValue", ModelData.ValuationDate);
                quotes.Add(quote);
            }
            if (AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, FloatingCashflowMetrics.LocalCurrencyExpectedValue.ToString()) == null)
            {
                var quote = QuotationHelper.Create(0.0m, FloatingCashflowMetrics.LocalCurrencyExpectedValue.ToString(), "DecimalValue", ModelData.ValuationDate);
                quotes.Add(quote);
            }
            //Check if risk calc are required.
            bool delta1PDH = AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.LocalCurrencyDelta1PDH.ToString()) != null ||
                             AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.Delta1PDH.ToString()) != null;
            //Check if risk calc are required.
            bool delta0PDH = AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.LocalCurrencyDelta0PDH.ToString()) != null ||
                             AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.Delta0PDH.ToString()) != null;

            ModelData.AssetValuation.quote = quotes.ToArray();
            //Set the cash flowdetails.
            HasReset     = modelData.ValuationDate > ResetDate;
            IsRealised   = HasBeenRealised(ModelData.ValuationDate);
            TimeToExpiry = GetPaymentYearFraction(ModelData.ValuationDate, AdjustedFixingDate);
            var                volatilityCurveNodeTime = GetPaymentYearFraction(ModelData.ValuationDate, PaymentDate);
            IFxCurve           fxCurve       = null;
            IRateCurve         discountCurve = null;
            IFxCurve           currencyCurve = null;
            IVolatilitySurface volSurface    = null;
            var                metrics       = ResolveModelMetrics(AnalyticsModel.Metrics);

            //var metricsToEvaluate = metrics.ToArray();
            //if (metricsToEvaluate.Length > 0)
            //{
            YearFractionToCashFlowPayment = GetPaymentYearFraction(ModelData.ValuationDate, PaymentDate);
            var reportingCurrency = ModelData.ReportingCurrency == null
                                        ? PaymentCurrency.Value
                                        : ModelData.ReportingCurrency.Value;
            decimal?premium = null;

            if (Premium != null)
            {
                premium = Premium;
            }
            IFxRateCashflowParameters analyticModelParameters = new FxRateCashflowParameters
            {
                ValuationDate      = modelData.ValuationDate,
                PaymentDate        = PaymentDate,
                Currency           = PaymentCurrency.Value,
                ReportingCurrency  = reportingCurrency,
                IsRealised         = IsRealised,
                IsReset            = HasReset,
                NotionalAmount     = NotionalAmount.amount,
                CurveYearFraction  = YearFractionToCashFlowPayment,
                ExpiryYearFraction = TimeToExpiry,
                Premium            = premium
            };

            // Curve Related
            if (modelData.MarketEnvironment.GetType() == typeof(MarketEnvironment))
            {
                var market = (MarketEnvironment)modelData.MarketEnvironment;
                discountCurve = (IRateCurve)market.SearchForPricingStructureType(DiscountCurveName);
                discountCurve.PricingStructureEvolutionType = PricingStructureEvolutionType;
                volSurface = (IVolatilitySurface)market.SearchForPricingStructureType(VolatilitySurfaceName);
                volSurface.PricingStructureEvolutionType = PricingStructureEvolutionType;
                var currencyCurveName = MarketEnvironmentHelper.ResolveFxCurveNames(StartFxRate.quotedCurrencyPair.currency1.Value,
                                                                                    StartFxRate.quotedCurrencyPair.currency2.Value);
                currencyCurve = (IFxCurve)market.SearchForPricingStructureType(currencyCurveName);
                currencyCurve.PricingStructureEvolutionType = PricingStructureEvolutionType;
                analyticModelParameters.DiscountCurve       = discountCurve;
                if (delta1PDH)
                {
                    var riskMarket = market.SearchForPerturbedPricingStructures(DiscountCurveName, "delta1PDH");
                    analyticModelParameters.Delta1PDHCurves       = riskMarket;
                    analyticModelParameters.Delta1PDHPerturbation = 10;
                }
                if (delta0PDH)//TODO Do this for the fxrate
                {
                    //var riskMarket = market.SearchForPerturbedPricingStructures(DiscountCurveName, "delta0PDH");
                    //    //TODO The fx deltas
                    //analyticModelParameters.Delta1PDHCurves = riskMarket;
                    //analyticModelParameters.Delta1PDHPerturbation = 10;
                }
                if (modelData.ReportingCurrency.Value != PaymentCurrency.Value)
                {
                    string curveName = MarketEnvironmentHelper.ResolveFxCurveNames(PaymentCurrency.Value,
                                                                                   modelData.ReportingCurrency.Value);
                    fxCurve = (IFxCurve)market.SearchForPricingStructureType(curveName);
                    fxCurve.PricingStructureEvolutionType            = PricingStructureEvolutionType;
                    analyticModelParameters.ReportingCurrencyFxCurve = fxCurve;
                }
                if (HybridValuation)
                {
                    var currency1RateCurve =
                        (IRateCurve)market.SearchForPricingStructureType(Currency1DiscountCurveName);
                    currency1RateCurve.PricingStructureEvolutionType = PricingStructureEvolutionType;
                    var currency2RateCurve =
                        (IRateCurve)market.SearchForPricingStructureType(Currency2DiscountCurveName);
                    currency2RateCurve.PricingStructureEvolutionType = PricingStructureEvolutionType;
                    AnalyticsModel = new FxOptionAnalytic(ModelData.ValuationDate, PaymentDate, currencyCurve, currency1RateCurve,
                                                          currency2RateCurve, IsSettlementInCurrency1, !InvertFxRate, Strike, TimeToExpiry, volatilityCurveNodeTime, volSurface, FxOptionType, fxCurve);
                }
            }
            // store inputs and results from this run
            AnalyticModelParameters = analyticModelParameters;
            if (!HybridValuation)
            {
                AnalyticsModel = new FxOptionAnalytic(ModelData.ValuationDate, PaymentDate, Strike, TimeToExpiry, volatilityCurveNodeTime,
                                                      fxCurve, currencyCurve, discountCurve, volSurface, FxOptionType);
            } //TODO Fix this with a generic index curve.
            //AnalyticsModel = analyticsModel;
            CalculationResults =
                AnalyticsModel.Calculate <IFloatingCashflowResults, FloatingCashflowResults>(
                    AnalyticModelParameters, metrics.ToArray());
            CalculationPerfomedIndicator = true;
            PaymentDiscountFactor        = ((FxRateCashflowAnalytic)AnalyticsModel).PaymentDiscountFactor;
            ForecastAmount = MoneyHelper.GetAmount(CalculationResults.LocalCurrencyExpectedValue,
                                                   PaymentAmount.currency);
            NPV = MoneyHelper.GetAmount(CalculationResults.LocalCurrencyNPV, PaymentAmount.currency);
            AssetValuation valuation = GetValue(CalculationResults, modelData.ValuationDate);

            valuation.id = Id;
            return(valuation);
        }