예제 #1
0
        private static List <IRateCurve> GetUniqueCurves(
            ILogger logger,
            ICoreCache cache,
            String nameSpace,
            SwapLegParametersRange_Old payLegParametersRange)
        {
            var uniqueCurves = new List <IRateCurve>();
            var curveNames   = new[]
            {
                payLegParametersRange.ForecastCurve,
                payLegParametersRange.DiscountCurve
            };

            foreach (string curveName in curveNames)
            {
                if (!String.IsNullOrEmpty(curveName) && curveName.ToLower() != "none")
                {
                    var curve = CurveLoader.LoadInterestRateCurve(logger, cache, nameSpace, curveName);
                    if (!uniqueCurves.Contains(curve))
                    {
                        uniqueCurves.Add(curve);
                    }
                }
            }

            return(uniqueCurves);
        }
예제 #2
0
        /// <summary>
        /// Create a series of CapFloor engines from a raw volatility grid and a DF curve
        /// </summary>
        /// <param name="logger">The logger.</param>
        /// <param name="cache">The cache.</param>
        /// <param name="nameSpace">The client namespace</param>
        /// <param name="properties">The properties of the engine, including the reference handle to access this engine collection</param>
        /// <param name="instruments">An array of instrument types.</param>
        /// <param name="rawVolatilityGrid">The raw grid used to build the engines. Assume that all volatility and strike values are 100x true</param>
        /// <returns>The engine handle or an error message</returns>
        public string CreateCapFloorATMCurve(ILogger logger, ICoreCache cache, string nameSpace, NamedValueSet properties,
                                             String[] instruments, Decimal[] rawVolatilityGrid)
        {
            var volatilityCheck = CheckVolatilities(rawVolatilityGrid);

            if (volatilityCheck != null)
            {
                throw new ArgumentException(volatilityCheck);
            }
            var id            = properties.GetString("EngineHandle", true);
            var baseDate      = properties.GetValue <DateTime>("BaseDate", true);
            var valuationDate = properties.GetValue("ValuationDate", DateTime.MinValue);

            if (valuationDate == DateTime.MinValue)
            {
                properties.Set("ValuationDate", baseDate);
            }
            properties.Set("PricingStructureType", PricingStructureTypeEnum.CapVolatilityCurve.ToString());
            var strikeQuoteUnits = properties.GetString("StrikeQuoteUnits", null);

            if (strikeQuoteUnits == null)
            {
                properties.Set("StrikeQuoteUnits", StrikeQuoteUnitsEnum.ATMFlatMoneyness.ToString());
            }
            var measureType = properties.GetString("MeasureType", null);

            if (measureType == null)
            {
                properties.Set("MeasureType", MeasureTypesEnum.Volatility.ToString());
            }
            var quoteUnits = properties.GetString("QuoteUnits", null);

            if (quoteUnits == null)
            {
                properties.Set("QuoteUnits", QuoteUnitsEnum.LogNormalVolatility.ToString());
            }
            var algorithm = properties.GetString("Algorithm", null);

            if (algorithm == null)
            {
                properties.Set("Algorithm", "Default");
            }
            var referenceDiscountCurve = properties.GetString("ReferenceCurveUniqueId", true);
            var referenceForecastCurve = properties.GetString("ReferenceCurrency2CurveId", referenceDiscountCurve);
            var discountCurve          = CurveLoader.LoadInterestRateCurve(logger, cache, nameSpace, null, null, referenceDiscountCurve);
            var forecastCurve          = CurveLoader.LoadInterestRateCurve(logger, cache, nameSpace, null, null, referenceForecastCurve);

            // Create the engines and either add to, or overwrite the existing, collection
            if (_capFloorEngine.ContainsKey(id))
            {
                _capFloorEngine[id] = CreateCurves(logger, cache, nameSpace, properties, discountCurve, forecastCurve, instruments, rawVolatilityGrid);
            }
            else
            {
                _capFloorEngine.Add(id, CreateCurves(logger, cache, nameSpace, properties, discountCurve, forecastCurve, instruments, rawVolatilityGrid));
            }
            return(id);
        }
예제 #3
0
        internal static Pair <ValuationResultRange, Swap> GetPriceAndGeneratedFpMLSwap(
            ILogger logger,
            ICoreCache cache,
            String nameSpace,
            IBusinessCalendar fixingCalendar,
            IBusinessCalendar paymentCalendar,
            ValuationRange valuationRange,
            TradeRange tradeRange,
            SwapLegParametersRange_Old leg1ParametersRange,
            List <DetailedCashflowRangeItem> leg1DetailedCashflowsList,
            List <PrincipalExchangeCashflowRangeItem> leg1PrincipalExchangeCashflowList,
            List <AdditionalPaymentRangeItem> leg1AdditionalPaymentList)
        {
            InterestRateStream stream1 = GetCashflowsSchedule(fixingCalendar, paymentCalendar, leg1ParametersRange);//parametric definiton + cashflows schedule
            var swap = SwapFactory.Create(stream1);

            // Update FpML cashflows
            //
            UpdateCashflowsWithDetailedCashflows(stream1.cashflows, leg1DetailedCashflowsList);
            //  Update PE
            //
            if (null != leg1PrincipalExchangeCashflowList)
            {
                CreatePrincipalExchangesFromListOfRanges(stream1.cashflows, leg1PrincipalExchangeCashflowList);
            }
            //  Add bullet payments...
            //
            if (null != leg1AdditionalPaymentList)
            {
                swap.additionalPayment = leg1AdditionalPaymentList.Select(bulletPaymentRangeItem => new Payment
                {
                    payerPartyReference    = PartyReferenceFactory.Create(leg1ParametersRange.Payer),
                    receiverPartyReference = PartyReferenceFactory.Create(leg1ParametersRange.Receiver),
                    paymentAmount          = MoneyHelper.GetNonNegativeAmount(bulletPaymentRangeItem.Amount),
                    paymentDate            = DateTypesHelper.ToAdjustableOrAdjustedDate(bulletPaymentRangeItem.PaymentDate)
                }).ToArray();
            }
            // Update FpML cashflows with DF,FV,PV, etc (LegParametersRange needed to access curve functionality)
            //
            UpdateCashflowsWithAmounts(logger, cache, nameSpace, stream1, leg1ParametersRange, valuationRange);
            //  Update additional payments
            //
            var leg1DiscountCurve = CurveLoader.LoadInterestRateCurve(logger, cache, nameSpace, leg1ParametersRange.DiscountCurve);

            SwapGenerator.UpdatePaymentsAmounts(logger, cache, nameSpace, swap, leg1ParametersRange, leg1DiscountCurve, valuationRange.ValuationDate, paymentCalendar);
            //~  Update additional payments
            string baseParty = valuationRange.BaseParty;

            return(new Pair <ValuationResultRange, Swap>(CreateValuationRange(swap, baseParty), swap));
        }
예제 #4
0
        public string CreateValuation(
            ILogger logger, ICoreCache cache,
            String nameSpace,
            IBusinessCalendar fixingCalendar,
            IBusinessCalendar paymentCalendar,
            List <StringObjectRangeItem> valuationSet,
            ValuationRange valuationRange,
            TradeRange tradeRange,
            CapFloorLegParametersRange_Old legParametersRange,
            List <InputCashflowRangeItem> legDetailedCashflowsListArray,
            List <InputPrincipalExchangeCashflowRangeItem> legPrincipleExchangeCashflowListArray,
            List <AdditionalPaymentRangeItem> legAdditionalPaymentListArray,
            List <PartyIdRangeItem> partyIdList,                     //optional
            List <OtherPartyPaymentRangeItem> otherPartyPaymentList, //optional
            List <FeePaymentRangeItem> feePaymentList                //optional
            )
        {
            Pair <ValuationResultRange, CapFloor> fpML = GetPriceAndGeneratedFpML(logger, cache, nameSpace, fixingCalendar, paymentCalendar, valuationRange, tradeRange,
                                                                                  legParametersRange, legDetailedCashflowsListArray, legPrincipleExchangeCashflowListArray,
                                                                                  legAdditionalPaymentListArray, feePaymentList);
            CapFloor capFloor = fpML.Second;
            string   valuationReportAndProductId = tradeRange.Id ?? Guid.NewGuid().ToString();

            capFloor.id = valuationReportAndProductId;
            AssetValuation assetValuation = InterestRateProduct.CreateAssetValuationFromValuationSet(valuationSet);
            //Valuation valuation = new Valuation();
            //  TODO: add Trade Id & Trade data into valuation. (Trade.Id & Trade.TradeHeader.TradeDate)
            //
            string baseParty    = valuationRange.BaseParty;
            var    uniqueCurves = new List <IRateCurve>();

            foreach (string curveName in new[] { legParametersRange.ForecastCurve, legParametersRange.DiscountCurve })
            {
                if (!String.IsNullOrEmpty(curveName))
                {
                    var curve = CurveLoader.LoadInterestRateCurve(logger, cache, nameSpace, curveName);
                    if (!uniqueCurves.Contains(curve))
                    {
                        uniqueCurves.Add(curve);
                    }
                }
            }
            Market          fpMLMarket      = InterestRateProduct.CreateFpMLMarketFromCurves(uniqueCurves);
            ValuationReport valuationReport = ValuationReportGenerator.Generate(valuationReportAndProductId, baseParty, valuationReportAndProductId, tradeRange.TradeDate, capFloor, fpMLMarket, assetValuation);

            cache.SaveObject(valuationReport, valuationReportAndProductId, null);
            InterestRateProduct.ReplacePartiesInValuationReport(valuationReport, partyIdList);
            InterestRateProduct.AddOtherPartyPayments(valuationReport, otherPartyPaymentList);
            return(valuationReportAndProductId);
        }
예제 #5
0
        private static void UpdateCashflowsWithAmounts(ILogger logger, ICoreCache cache,
                                                       String nameSpace, InterestRateStream stream,
                                                       CapFloorLegParametersRange_Old legParametersRange, ValuationRange valuationRange)
        {
            //  Get a forecast curve
            //
            IRateCurve forecastCurve = null;

            if (!String.IsNullOrEmpty(legParametersRange.ForecastCurve) && legParametersRange.ForecastCurve.ToLower() != "none")
            {
                forecastCurve = CurveLoader.LoadInterestRateCurve(logger, cache, nameSpace, legParametersRange.ForecastCurve);
            }
            //  Get a discount curve
            //
            var discountCurve = CurveLoader.LoadInterestRateCurve(logger, cache, nameSpace, legParametersRange.DiscountCurve);

            FixedAndFloatingRateStreamCashflowGenerator.UpdateCashflowsAmounts(stream, forecastCurve, discountCurve, valuationRange.ValuationDate);
        }
예제 #6
0
        static void Main(string[] args)
        {
            //SortedDictionary<double, double> myDictionary = new SortedDictionary<double, double>();

            //for(double x = 0.25; x<=5; x+=0.25)
            //{
            //    myDictionary.Add(x,x * x + 1);
            //}

            //for(int i = 0; i<myDictionary.Count(); i++)
            //{
            //    Console.WriteLine($"Key: {myDictionary.ElementAt(i).Key}  \t  Value: {myDictionary.ElementAt(i).Value}");
            //}
            string filePath = @"C:\Users\Steeve\source\repos\RateCurve\Utils\ratecurve1.csv";
            char   sep      = ';';
            SortedDictionary <double, double> myDictionary = CurveLoader.LoadFromFile(filePath, sep, true);

            double value = Tools.FindLowestAbove(myDictionary, 2.37);

            double value2 = Tools.FindIndex(myDictionary.Keys.ToArray <double>(), 5);
        }
예제 #7
0
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            #region Whole Curve
            string filePath = @"C:\Users\Steeve\source\repos\RateCurve\Utils\ratecurve1.csv";
            char   sep      = ';';
            SortedDictionary <double, double> myDictionary = CurveLoader.LoadFromFile(filePath, sep, true);
            #endregion

            #region Euribor Rates
            string euriborRatesPath = @"C:\Users\Steeve\source\repos\RateCurve\Input\Euribor_Rates.csv";
            SortedDictionary <double, double> euriborRates = CurveLoader.LoadFromFile(euriborRatesPath, sep, true);
            #endregion

            #region Swap Rates
            string swapRatesPath = @"C:\Users\Steeve\source\repos\RateCurve\Input\ICESwapRateHistoricalRates.csv";
            SortedDictionary <double, double> swapRates = CurveLoader.LoadFromFile(swapRatesPath, sep, true);
            #endregion

            #region building custom path
            CustomCurve customCurve = null;
            try
            {
                customCurve = new CustomCurve(euriborRates, swapRates);
            }
            catch (Exception ex)
            {
                string errMessage = "Error: unable to build custom curve.\n" + ex.Message;
                MessageBox.Show(errMessage);
            }
            #endregion

            //Application.Run(new RateCurvePlots(myDictionary));
            SortedDictionary <double, double> points = customCurve.GetCurvePoints();

            Application.Run(new RateCurvePlots(points));
        }
예제 #8
0
        public void ProcessRequest(RequestBase request, HandlerResponse response)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }
            var tradeValRequest = request as TradeValuationRequest;

            if (tradeValRequest == null)
            {
                throw new InvalidCastException(
                          $"{typeof(RequestBase).Name} is not a {typeof(TradeValuationRequest).Name}");
            }

            DateTime lastStatusPublishedAt = DateTime.Now;
            var      nameSpace             = tradeValRequest.NameSpace;
            // common properties
            string reportingCurrency = tradeValRequest.ReportingCurrency;
            string market            = tradeValRequest.MarketName;

            // build a single trade portfolio
            var           tradeItemInfos = new Dictionary <string, ICoreItemInfo>();
            ICoreItemInfo tradeItemInfo  = Context.Cache.LoadItemInfo <Trade>(tradeValRequest.TradeItemName);

            if (tradeItemInfo != null)
            {
                tradeItemInfos[tradeValRequest.TradeItemName] = tradeItemInfo;
            }

            // define scenario loops
            // - always include un-stressed scenario (null)
            var irScenarios = new List <string> {
                null
            };

            if (tradeValRequest.IRScenarioNames != null)
            {
                irScenarios.AddRange(tradeValRequest.IRScenarioNames);
            }
            string[] irScenarioNames = irScenarios.Distinct().ToArray();

            var fxScenarios = new List <string> {
                null
            };

            if (tradeValRequest.FXScenarioNames != null)
            {
                fxScenarios.AddRange(tradeValRequest.FXScenarioNames);
            }
            string[] fxScenarioNames = fxScenarios.Distinct().ToArray();

            // update progress status
            response.ItemCount = irScenarios.Count * fxScenarios.Count * tradeItemInfos.Count;
            response.Status    = RequestStatusEnum.InProgress;
            Context.Cache.SaveObject(response);

            // preload *all* curves into the cache
            // note: this is required to optimise all subsequent curve queries
            Context.Cache.LoadItems <Market>(Expr.ALL);

            // load and sort scenario definition rules
            var clauses = new List <IExpression> {
                Expr.IsEQU(EnvironmentProp.NameSpace, nameSpace)
            };
            var scenarioRules       = Context.Cache.LoadObjects <ScenarioRule>(Expr.BoolAND(clauses.ToArray()));
            var sortedScenarioRules = new List <CachedScenarioRule>();

            {
                sortedScenarioRules.AddRange(from scenarioRule in scenarioRules
                                             where !scenarioRule.Disabled
                                             select new CachedScenarioRule(scenarioRule.ScenarioId, scenarioRule.RuleId, scenarioRule.Priority, (scenarioRule.FilterExpr != null) ? Expr.Create(scenarioRule.FilterExpr) : Expr.ALL, scenarioRule.StressId));
            }
            sortedScenarioRules.Sort();

            // build distinct lists of curve names and currencies required by the Trade
            var curvenamesList = new List <string>();
            var currenciesList = new List <string>();

            foreach (var item in tradeItemInfos.Values)
            {
                curvenamesList.AddRange(item.AppProps.GetArray <string>(TradeProp.RequiredPricingStructures));
                currenciesList.AddRange(item.AppProps.GetArray <string>(TradeProp.RequiredCurrencies));
            }
            curvenamesList = new List <string>(curvenamesList.Distinct().Where(x => !String.IsNullOrEmpty(x)));
            currenciesList = new List <string>(currenciesList.Distinct().Where(x => !String.IsNullOrEmpty(x)));

            IEnumerable <string> metrics = GetSwapMetrics();

            // run the scenario rules ONCE for each IR and FX scenario to determine which
            // stressed curves to use when pricing.
            var resolvedCurveProps = new Dictionary <string, NamedValueSet>();
            // IR loop
            var irScenarioCurveMap = new List <CurveStressPair> [irScenarioNames.Length];

            for (int i = 0; i < irScenarioNames.Length; i++)
            {
                string irScenario = irScenarioNames[i];
                irScenarioCurveMap[i] = new List <CurveStressPair>();
                foreach (string curveName in curvenamesList)
                {
                    string        curveSignature = CurveLoader.IrCurveSignature(market, curveName, null);
                    NamedValueSet curveProperties;
                    if (!resolvedCurveProps.TryGetValue(curveSignature, out curveProperties))
                    {
                        // not cached - resolve and cache
                        curveProperties = PricingStructureFactory.GetInterestRateCurveProperties(Context.Logger, Context.Cache, request.NameSpace, market, curveName, null);
                        resolvedCurveProps[curveSignature] = curveProperties;
                    }
                    string stressName = CachedScenarioRule.RunScenarioRules(sortedScenarioRules, irScenario, curveProperties);
                    irScenarioCurveMap[i].Add(new CurveStressPair(curveName, stressName));
                }
            }
            // FX loop
            var fxScenarioCurveMap = new List <CurveStressPair> [fxScenarioNames.Length];

            for (int j = 0; j < fxScenarioNames.Length; j++)
            {
                string fxScenario = fxScenarioNames[j];
                fxScenarioCurveMap[j] = new List <CurveStressPair>();
                foreach (string currency in currenciesList)
                {
                    string        curveSignature = CurveLoader.FxCurveSignature(market, currency, reportingCurrency, null);
                    NamedValueSet curveProperties;
                    if (!resolvedCurveProps.TryGetValue(curveSignature, out curveProperties))
                    {
                        // not cached - resolve and cache
                        curveProperties = PricingStructureFactory.GetFxCurveProperties(Context.Logger, Context.Cache, request.NameSpace, market, currency, reportingCurrency);
                        resolvedCurveProps[curveSignature] = curveProperties;
                    }
                    string stressName = CachedScenarioRule.RunScenarioRules(sortedScenarioRules, fxScenario, curveProperties);
                    fxScenarioCurveMap[j].Add(new CurveStressPair(currency, stressName));
                }
            }
            // iterate the scenario loops
            var resolvedCurveCache = new Dictionary <string, ICurve>();
            var reportNameCache    = new Dictionary <string, string>();

            for (int i = 0; i < irScenarioNames.Length; i++)
            {
                string irScenario = irScenarioNames[i];
                for (int j = 0; j < fxScenarioNames.Length; j++)
                {
                    string fxScenario = fxScenarioNames[j];

                    // check for workflow cancellation (user abort, server shutdown etc.)
                    if (Cancelled)
                    {
                        throw new OperationCanceledException(CancelReason);
                    }

                    // initialise the pricer with the IR/FX scenario curve maps
                    var pricer = new PortfolioPricer(irScenarioCurveMap[i], fxScenarioCurveMap[j]);

                    // now price the Trade
                    if (metrics != null)
                    {
                        var enumerable = metrics.ToArray();
                        pricer.PriceAndPublish(
                            Context.Logger, Context.Cache,
                            resolvedCurveCache,
                            reportNameCache, response,
                            tradeItemInfos.Keys, tradeValRequest,
                            irScenario, fxScenario, reportingCurrency,
                            tradeValRequest.BaseParty, enumerable, false);
                    }

                    // export to valuation database
                    //foreach (var valuationItem in valuationItems)
                    //{
                    //    ExportValuation(valuationItem);
                    //}

                    DateTime dtNow = DateTime.Now;
                    if ((dtNow - lastStatusPublishedAt) > TimeSpan.FromSeconds(5))
                    {
                        lastStatusPublishedAt = dtNow;
                        response.Status       = RequestStatusEnum.InProgress;
                        Context.Cache.SaveObject(response);
                    }
                } // foreach ir scenario
            }     // foreach fx scenario

            // success
            response.Status = RequestStatusEnum.Completed;
        }
예제 #9
0
        public void ProcessRequest(RequestBase baseRequest, HandlerResponse response)
        {
            if (baseRequest == null)
            {
                throw new ArgumentNullException(nameof(baseRequest));
            }
            var request = baseRequest as OrdinaryCurveGenRequest;

            if (request == null)
            {
                throw new InvalidCastException(
                          $"{typeof(RequestBase).Name} is not a {typeof(OrdinaryCurveGenRequest).Name}");
            }
            CurveSelection[] curveSelectors = request.CurveSelector ?? new List <CurveSelection>().ToArray();
            response.ItemCount = curveSelectors.Length;
            DateTime lastStatusPublishedAt = DateTime.Now;

            // check for workflow cancellation
            if (Cancelled)
            {
                throw new OperationCanceledException(CancelReason);
            }
            // iterate selected curves
            foreach (CurveSelection curveSelector in curveSelectors)
            {
                // publish 'intermediate' in-progress result (throttled)
                if ((DateTime.Now - lastStatusPublishedAt) > TimeSpan.FromSeconds(5))
                {
                    lastStatusPublishedAt = DateTime.Now;
                    response.Status       = RequestStatusEnum.InProgress;
                    Context.Cache.SaveObject(response);
                }
                string nameSpace       = curveSelector.NameSpace;
                string inputMarketName = curveSelector.MarketName;
                string inputCurveName  = curveSelector.CurveName;
                string inputCurveType  = curveSelector.CurveType;
                // given a curve definition, this workflow generates:
                // - a live base curve using current market data
                // load curve definition
                Context.Logger.LogDebug("Building ordinary curve: {0}.{1}.{2}", inputMarketName, inputCurveType, inputCurveName);
                string curveUniqueId =
                    $"Configuration.PricingStructures.{inputMarketName}.{inputCurveType}.{inputCurveName}";
                //TODO This does not work for MArket=Test_EOD because the market date propeerty
                //is not included in the identifier and unique identifier!
                ICoreItem marketItem = LoadAndCheckMarketItem(Context.Cache, nameSpace, curveUniqueId);
                // check data is not mutated
                //AssertNotModified<Market>(marketItem);
                // note: we must clone the definition to avoid updating it in the cache!
                var market = marketItem.GetData <Market>(true);
                //AssertSomeQuotesMissing(((YieldCurveValuation)(cachedMarket.Items1[0])).inputs);
                //Market clonedMarket = BinarySerializerHelper.Clone<Market>(cachedMarket);
                PricingStructure          ps  = market.Items[0];
                PricingStructureValuation psv = market.Items1[0];
                // supply base data and  build datetime
                psv.baseDate = new IdentifiedDate {
                    Value = request.BaseDate
                };
                QuotedAssetSet curveDefinition;
                if (psv is YieldCurveValuation curveValuation)
                {
                    curveDefinition = curveValuation.inputs;
                }
                else
                {
                    if (psv is FxCurveValuation valuation)
                    {
                        curveDefinition = valuation.spotRate;
                    }
                    else
                    {
                        throw new NotSupportedException("Unsupported PricingStructureValuation type: " + psv.GetType().Name);
                    }
                }
                //AssertSomeQuotesMissing(curveDefinition);
                // default outputs
                var    curveDefProps      = new NamedValueSet(marketItem.AppProps);
                var    curveType          = PropertyHelper.ExtractPricingStructureType(curveDefProps);//.GetValue<string>(CurveProp.PricingStructureType, true));
                var    curveName          = curveDefProps.GetValue <string>(CurveProp.CurveName, true);
                string marketDataItemName = String.Format(FunctionProp.QuotedAssetSet.ToString() + ".{0}.{1}.{2}", inputMarketName, curveType, curveName);
                curveDefProps.Set("BootStrap", true);
                curveDefProps.Set(CurveProp.BaseDate, request.BaseDate);
                IPricingStructureIdentifier liveCurveId = PricingStructureIdentifier.CreateMarketCurveIdentifier(curveDefProps, inputMarketName, null, null, null, null);
                NamedValueSet liveCurveProps            = liveCurveId.Properties;
                var           liveCurveItemName         = liveCurveProps.GetValue <string>(CurveProp.UniqueIdentifier, true);
                var           liveCurve = new Market(); // empty
                try
                {
                    // build a request/response map (indexed by instrument id)
                    var instrumentMap = new Dictionary <string, Asset>();
                    foreach (Asset asset in curveDefinition.instrumentSet.Items)
                    {
                        instrumentMap[asset.id.ToLower()] = asset;
                    }
                    int bavNum = 0;
                    foreach (BasicAssetValuation quoteInstr in curveDefinition.assetQuote)
                    {
                        if (quoteInstr.objectReference?.href == null)
                        {
                            throw new ApplicationException($"Missing objectReference in BasicAssetValuation[{bavNum}]");
                        }
                        string instrId = quoteInstr.objectReference.href;
                        if (!instrumentMap.TryGetValue(instrId.ToLower(), out _))
                        {
                            throw new ApplicationException($"Cannot find instrument '{instrId}' for assetQuote");
                        }
                        bavNum++;
                    }
                    // request market data from MDS
                    QuotedAssetSet marketData;
                    if (request.UseSavedMarketData)
                    {
                        // get saved market data
                        marketData = Context.Cache.LoadObject <QuotedAssetSet>(nameSpace + "." + marketDataItemName);
                        if (marketData == null)
                        {
                            throw new ApplicationException(
                                      $"Could not load saved market data with name: '{marketDataItemName}'");
                        }
                    }
                    else
                    {
                        //throw new NotImplementedException();
                        using (var mdc = MarketDataFactory.Create(Reference <ILogger> .Create(Context.Logger), Assembly.GetExecutingAssembly(), null))
                        {
                            // call MDS
                            //AssertSomeQuotesMissing(curveDefinition);
                            Guid mdsRequestId = Guid.NewGuid();
                            MDSResult <QuotedAssetSet> mdsResponse = mdc.GetMarketQuotes(
                                MDSProviderId.Bloomberg, null, mdsRequestId, true, null,
                                curveDefinition);
                            if (mdsResponse.Error != null)
                            {
                                throw mdsResponse.Error;
                            }
                            marketData = mdsResponse.Result;
                            if ((marketData.assetQuote == null) || marketData.assetQuote.Length < 1)
                            {
                                throw new ApplicationException($"MDS response contains no quotes! ({mdsRequestId})");
                            }

                            // save transient market data for later offline use
                            if (request.SaveMarketData)
                            {
                                var marketDataProps = new NamedValueSet();
                                marketDataProps.Set(liveCurveProps.Get(EnvironmentProp.NameSpace));//TODO Added to filter on client namespace!
                                marketDataProps.Set(liveCurveProps.Get(CurveProp.Market));
                                marketDataProps.Set(liveCurveProps.Get(CurveProp.PricingStructureType));
                                marketDataProps.Set(liveCurveProps.Get(CurveProp.CurveName));
                                marketDataProps.Set(liveCurveProps.Get(CurveProp.Currency1));
                                Context.Cache.SaveObject(marketData, marketDataItemName, marketDataProps, true, TimeSpan.FromDays(7));
                            }
                        }
                    }
                    // check market data for undefined/invalid quotes
                    foreach (BasicAssetValuation asset in marketData.assetQuote)
                    {
                        if (asset.quote.Any(quote => quote.measureType.Value.Equals("undefined", StringComparison.OrdinalIgnoreCase)))
                        {
                            throw new ApplicationException(
                                      $"Market quote undefined/missing for asset '{asset.objectReference.href}'");
                        }
                    }
                    // merge MDS results with stored quotes in the curve definition
                    curveDefinition.Replace(marketData);//Merge(marketData, true, false, true);
                    // generate ordinary base curve
                    if (psv is YieldCurveValuation valuation)
                    {
                        valuation.inputs = curveDefinition;
                    }
                    else
                    {
                        ((FxCurveValuation)psv).spotRate = new FxRateSet
                        {
                            instrumentSet = curveDefinition.instrumentSet,
                            assetQuote    = curveDefinition.assetQuote
                        };
                    }
                    // hack - if rate basis curve then call new triplet fn, else call old pair fn.
                    IPricingStructure ips;
                    switch (curveType)
                    {
                    case PricingStructureTypeEnum.RateBasisCurve:
                    {
                        // rate basis curves require a reference curve
                        string refCurveUniqueId =
                            $"Market.{inputMarketName}.{curveDefProps.GetValue<string>(CurveProp.ReferenceCurveName, true)}";
                        // load the reference curve
                        ICoreItem refCurveItem = LoadAndCheckMarketItem(Context.Cache, nameSpace, refCurveUniqueId);
                        var       refCurve     = (Market)refCurveItem.Data;
                        //Format the ref curve data and call the pricing structure helper.
                        var refCurveFpMLTriplet = new Triplet <PricingStructure, PricingStructureValuation, NamedValueSet>(refCurve.Items[0],
                                                                                                                           refCurve.Items1[0], refCurveItem.AppProps);
                        liveCurveProps.Set(CurveProp.ReferenceCurveUniqueId, refCurveUniqueId);
                        var spreadCurveFpMLTriplet = new Triplet <PricingStructure, PricingStructureValuation, NamedValueSet>(ps, psv, liveCurveProps);
                        //create and set the pricingstructure
                        ips = CurveLoader.LoadInterestRateCurve(Context.Logger, Context.Cache, nameSpace, refCurveFpMLTriplet, spreadCurveFpMLTriplet);
                        //Creator.Create(refCurveFpMLTriplet, spreadCurveFpMLTriplet);
                    }
                    break;

                    case PricingStructureTypeEnum.RateXccyCurve:
                    {
                        // rate basis curves require a base curve
                        string baseCurveUniqueId = String.Format(nameSpace + ".Market.{0}.{1}",
                                                                 inputMarketName, curveDefProps.GetValue <string>(CurveProp.ReferenceCurveName, true));
                        // load the reference curve
                        ICoreItem baseCurveItem = LoadAndCheckMarketItem(Context.Cache, nameSpace, baseCurveUniqueId);
                        var       baseCurve     = (Market)baseCurveItem.Data;
                        // rate basis curves require an fx curve
                        string fxCurveUniqueId = String.Format(nameSpace + ".Market.{0}.{1}",
                                                               inputMarketName, curveDefProps.GetValue <string>(CurveProp.ReferenceFxCurveName, true));
                        // load the reference curve
                        ICoreItem fxCurveItem = LoadAndCheckMarketItem(Context.Cache, nameSpace, fxCurveUniqueId);
                        var       fxCurve     = (Market)fxCurveItem.Data;
                        // rate basis curves require a reference curve
                        string refCurveUniqueId = String.Format(nameSpace + ".Market.{0}.{1}",
                                                                inputMarketName, curveDefProps.GetValue <string>(CurveProp.ReferenceCurrency2CurveName, true));
                        // load the reference curve
                        ICoreItem refCurveItem = LoadAndCheckMarketItem(Context.Cache, nameSpace, refCurveUniqueId);
                        var       refCurve     = (Market)refCurveItem.Data;
                        //Format the ref curve data and call the pricing structure helper.
                        var baseCurveFpMLTriplet = new Triplet <PricingStructure, PricingStructureValuation, NamedValueSet>(baseCurve.Items[0],
                                                                                                                            baseCurve.Items1[0], baseCurveItem.AppProps);
                        var fxCurveFpMLTriplet = new Triplet <PricingStructure, PricingStructureValuation, NamedValueSet>(fxCurve.Items[0],
                                                                                                                          fxCurve.Items1[0], fxCurveItem.AppProps);
                        var refCurveFpMLTriplet = new Triplet <PricingStructure, PricingStructureValuation, NamedValueSet>(refCurve.Items[0],
                                                                                                                           refCurve.Items1[0], refCurveItem.AppProps);
                        liveCurveProps.Set(CurveProp.ReferenceCurveUniqueId, baseCurveUniqueId);
                        liveCurveProps.Set(CurveProp.ReferenceFxCurveUniqueId, fxCurveUniqueId);
                        liveCurveProps.Set(CurveProp.ReferenceCurrency2CurveId, refCurveUniqueId);
                        var spreadCurveFpMLTriplet = new Triplet <PricingStructure, PricingStructureValuation, NamedValueSet>(ps, psv, liveCurveProps);
                        //create and set the pricingstructure
                        ips = CurveLoader.LoadInterestRateCurve(Context.Logger, Context.Cache, nameSpace, baseCurveFpMLTriplet,
                                                                fxCurveFpMLTriplet, refCurveFpMLTriplet, spreadCurveFpMLTriplet);
                        //Creator.Create(baseCurveFpMLTriplet, fxCurveFpMLTriplet, refCurveFpMLTriplet, spreadCurveFpMLTriplet);
                    }
                    break;        //TODO Add Volatility types as well

                    default:
                    {
                        ips = CurveLoader.LoadCurve(Context.Logger, Context.Cache,
                                                    nameSpace, new Pair <PricingStructure, PricingStructureValuation>(ps, psv),
                                                    liveCurveProps);
                        //Creator.Create(new Pair<PricingStructure, PricingStructureValuation>(ps, psv), liveCurveProps);
                    }
                    break;
                    }
                    // retrieve curve
                    liveCurve = PricingStructureHelper.CreateMarketFromFpML(
                        ips.GetPricingStructureId().UniqueIdentifier,
                        ips.GetFpMLData());
                    // curve done
                    response.IncrementItemsPassed();
                }
                catch (Exception innerExcp)
                {
                    response.IncrementItemsFailed();
                    Context.Logger.Log(innerExcp);
                    liveCurveProps.Set(WFPropName.ExcpName, WFHelper.GetExcpName(innerExcp));
                    liveCurveProps.Set(WFPropName.ExcpText, WFHelper.GetExcpText(innerExcp));
                }

                // ================================================================================
                // calculate curve lifetimes
                //   SOD = 8am, EOD = 4:30pm
                // live curves
                // - publish anytime
                // - expires SOD next day
                // EOD (today) curves
                // - publish for 15 minutes prior to EOD today
                // - expires in 7 days
                // EOD (dated) - 7 days
                // - publish for 15 minutes prior to EOD today
                // - expires in 7 days
                DateTime dtNow             = DateTime.Now;
                DateTime dtToday           = dtNow.Date;
                DateTime dtEODPublishBegin = dtToday.AddHours(16.25);  // 4:15pm today
                DateTime dtEODPublishUntil = dtToday.AddHours(16.5);   // 4:30pm today
                DateTime dtSODTomorrow     = dtToday.AddHours(24 + 8); // 8am tomorrow
                //DateTime dtEODTomorrow = dtToday.AddHours(24 + 16); // 4pm tomorrow
                // publish live curve
                Context.Cache.SaveObject(liveCurve, nameSpace + "." + liveCurveItemName, liveCurveProps, true, dtSODTomorrow);
                // republish as latest EOD curve
                if (request.ForceGenerateEODCurves || ((dtNow >= dtEODPublishBegin) && (dtNow <= dtEODPublishUntil)))
                {
                    NamedValueSet itemProps = PricingStructureIdentifier.CreateMarketCurveIdentifier(liveCurveProps, CurveConst.QR_EOD, null, null, null, null).Properties;
                    var           itemName  = itemProps.GetValue <string>(CurveProp.UniqueIdentifier, true);
                    // persistent
                    Context.Cache.SaveObject(liveCurve, nameSpace + "." + itemName, itemProps, false, TimeSpan.FromDays(7));
                }
                // republish as dated EOD curve
                if (request.ForceGenerateEODCurves || ((dtNow >= dtEODPublishBegin) && (dtNow <= dtEODPublishUntil)))
                {
                    NamedValueSet itemProps = PricingStructureIdentifier.CreateMarketCurveIdentifier(liveCurveProps, CurveConst.QR_EOD, dtToday, null, null, null).Properties;
                    var           itemName  = itemProps.GetValue <string>(CurveProp.UniqueIdentifier, true);
                    // persistent
                    Context.Cache.SaveObject(liveCurve, nameSpace + "." + itemName, itemProps, false, TimeSpan.FromDays(7));
                }
            } // foreach curve
            // success
            response.Status = RequestStatusEnum.Completed;
        }
예제 #10
0
        public void ProcessRequest(RequestBase baseRequest, HandlerResponse response)
        {
            if (baseRequest == null)
            {
                throw new ArgumentNullException(nameof(baseRequest));
            }
            if (!(baseRequest is PortfolioValuationRequest request))
            {
                throw new InvalidCastException(
                          $"{typeof(RequestBase).Name} is not a {typeof(PortfolioValuationRequest).Name}");
            }
            DateTime lastStatusPublishedAt = DateTime.Now;
            // common properties
            var    nameSpace         = request.NameSpace;
            string reportingCurrency = request.ReportingCurrency;
            string baseParty         = request.BaseParty;
            string market            = request.MarketName;
            // resolve portfolio valuation request
            var identifier = (new PortfolioSpecification(request.PortfolioId, request.NameSpace)).NetworkKey;
            var portfolio  =
                Context.Cache.LoadObject <PortfolioSpecification>(identifier);

            if (portfolio == null)
            {
                throw new ArgumentException($"Unknown portfolio id: '{request.PortfolioId}'");
            }
            // build trade query from portfolio definition
            var tradeItemInfos = new Dictionary <string, ICoreItemInfo>();

            if (portfolio.PortfolioSubqueries != null)
            {
                foreach (var subQuery in portfolio.PortfolioSubqueries.OrderBy(x => x.SequenceOrder))
                {
                    var clauses = new List <IExpression> {
                        Expr.IsEQU(EnvironmentProp.NameSpace, nameSpace)
                    };
                    if (subQuery.CounterpartyId != null)
                    {
                        clauses.Add(Expr.IsEQU(TradeProp.CounterPartyId, subQuery.CounterpartyId));
                    }
                    if (subQuery.TradingBookId != null)
                    {
                        clauses.Add(Expr.IsEQU(TradeProp.TradingBookId, subQuery.TradingBookId));
                    }
                    // load trades defined by the query
                    if (clauses.Count <= 0)
                    {
                        continue;
                    }
                    List <ICoreItemInfo> subQueryItems = Context.Cache.LoadItemInfos <Trade>(Expr.BoolAND(clauses.ToArray()));
                    //TODO again have to handle confirmation
                    foreach (var tradeItemInfo in subQueryItems)
                    {
                        if (subQuery.ExcludeItems)
                        {
                            tradeItemInfos.Remove(tradeItemInfo.Name);
                        }
                        else
                        {
                            tradeItemInfos[tradeItemInfo.Name] = tradeItemInfo;
                        }
                    }
                }
            }
            // process included/excluded trades ids
            if (portfolio.ExcludeOverridesInclude)
            {
                // add included names
                if (portfolio.IncludedTradeItemNames != null)
                {
                    foreach (var name in portfolio.IncludedTradeItemNames)
                    {
                        var tradeItemInfo = name.Contains(FpML5R10NameSpaces.Confirmation) ? Context.Cache.LoadItemInfo <FpML.V5r10.Confirmation.Trade>(name)
                            : Context.Cache.LoadItemInfo <Trade>(name);
                        if (tradeItemInfo != null)
                        {
                            tradeItemInfos[name] = tradeItemInfo;
                        }
                    }
                }
            }
            // remove excluded names
            if (portfolio.ExcludedTradeItemNames != null)
            {
                foreach (var name in portfolio.ExcludedTradeItemNames)
                {
                    tradeItemInfos.Remove(name);
                }
            }
            if (!portfolio.ExcludeOverridesInclude)
            {
                // add included names
                if (portfolio.IncludedTradeItemNames != null)
                {
                    foreach (var name in portfolio.IncludedTradeItemNames)
                    {
                        var tradeItemInfo = name.Contains(FpML5R10NameSpaces.Confirmation) ? Context.Cache.LoadItemInfo <FpML.V5r10.Confirmation.Trade>(name)
                            : Context.Cache.LoadItemInfo <Trade>(name);
                        if (tradeItemInfo != null)
                        {
                            tradeItemInfos[name] = tradeItemInfo;
                        }
                    }
                }
            }
            // define scenario loops
            // - always include un-stressed scenario (null)
            var irScenarios = new List <string> {
                null
            };

            if (request.IRScenarioNames != null)
            {
                irScenarios.AddRange(request.IRScenarioNames);
            }
            string[] irScenarioNames = irScenarios.Distinct().ToArray();
            var      fxScenarios     = new List <string> {
                null
            };

            if (request.FXScenarioNames != null)
            {
                fxScenarios.AddRange(request.FXScenarioNames);
            }
            string[] fxScenarioNames = fxScenarios.Distinct().ToArray();
            // update progress status
            response.ItemCount = irScenarios.Count * fxScenarios.Count * tradeItemInfos.Count;
            response.Status    = RequestStatusEnum.InProgress;
            Context.Cache.SaveObject(response);
            // preload *all* curves into the cache
            // note: this is required to optimise all subsequent curve queries
            if (market.Contains(CurveConst.NAB_EOD) || market.Contains(CurveConst.TEST_EOD))
            {
                Context.Cache.LoadItems <Market>(Expr.ALL);//TODO make specific to the namespace
            }
            // load and sort scenario definition rules
            var scenarioRules       = Context.Cache.LoadObjects <ScenarioRule>(Expr.IsEQU(EnvironmentProp.NameSpace, nameSpace));
            var sortedScenarioRules = new List <CachedScenarioRule>();

            {
                sortedScenarioRules.AddRange(from scenarioRule in scenarioRules
                                             where !scenarioRule.Disabled
                                             select new CachedScenarioRule(scenarioRule.ScenarioId, scenarioRule.RuleId, scenarioRule.Priority, (scenarioRule.FilterExpr != null)
                                                 ? Expr.Create(scenarioRule.FilterExpr) : Expr.ALL, scenarioRule.StressId));
            }
            sortedScenarioRules.Sort();
            // build distinct lists of curve names and currencies required by the portfolio
            var curvenamesList = new List <string>();
            var currenciesList = new List <string>();

            foreach (var item in tradeItemInfos.Values)
            {
                curvenamesList.AddRange(item.AppProps.GetArray <string>(TradeProp.RequiredPricingStructures));
                currenciesList.AddRange(item.AppProps.GetArray <string>(TradeProp.RequiredCurrencies));
            }
            curvenamesList = new List <string>(curvenamesList.Distinct().Where(x => !String.IsNullOrEmpty(x)));
            currenciesList = new List <string>(currenciesList.Distinct().Where(x => !String.IsNullOrEmpty(x)));
            var metrics = GetSwapMetrics();
            // run the scenario rules ONCE for each IR and FX scenario to determine which
            // stressed curves to use when pricing.
            var resolvedCurveProps = new Dictionary <string, NamedValueSet>();
            // IR loop
            var irScenarioCurveMap = new List <CurveStressPair> [irScenarioNames.Length];

            for (int i = 0; i < irScenarioNames.Length; i++)
            {
                string irScenario = irScenarioNames[i];
                irScenarioCurveMap[i] = new List <CurveStressPair>();
                foreach (string curveName in curvenamesList)
                {
                    string curveSignature = CurveLoader.IrCurveSignature(market, curveName, null);
                    if (!resolvedCurveProps.TryGetValue(curveSignature, out var curveProperties))
                    {
                        // not cached - resolve and cache
                        curveProperties = PricingStructureFactory.GetInterestRateCurveProperties(Context.Logger, Context.Cache, request.NameSpace, market, curveName, null);//TODO not this namespace. Use the curves.
                        resolvedCurveProps[curveSignature] = curveProperties;
                    }
                    var stressName = CachedScenarioRule.RunScenarioRules(sortedScenarioRules, irScenario, curveProperties);
                    irScenarioCurveMap[i].Add(new CurveStressPair(curveName, stressName));
                }
            }
            // FX loop
            var fxScenarioCurveMap = new List <CurveStressPair> [fxScenarioNames.Length];

            for (var j = 0; j < fxScenarioNames.Length; j++)
            {
                string fxScenario = fxScenarioNames[j];
                fxScenarioCurveMap[j] = new List <CurveStressPair>();
                foreach (string currency in currenciesList)
                {
                    string curveSignature = CurveLoader.FxCurveSignature(market, currency, reportingCurrency, null);
                    if (!resolvedCurveProps.TryGetValue(curveSignature, out var curveProperties))
                    {
                        // not cached - resolve and cache
                        if (currency != reportingCurrency)
                        {
                            curveProperties = PricingStructureFactory.GetFxCurveProperties(Context.Logger, Context.Cache, request.NameSpace, market, currency, reportingCurrency);
                            resolvedCurveProps[curveSignature] = curveProperties;
                        }
                    }
                    string stressName = CachedScenarioRule.RunScenarioRules(sortedScenarioRules, fxScenario, curveProperties);
                    fxScenarioCurveMap[j].Add(new CurveStressPair(currency, stressName));
                }
            }
            // iterate the scenario loops
            var resolvedCurveCache = new Dictionary <string, ICurve>();
            var reportNameCache    = new Dictionary <string, string>();

            for (int i = 0; i < irScenarioNames.Length; i++)
            {
                string irScenario = irScenarioNames[i];
                for (int j = 0; j < fxScenarioNames.Length; j++)
                {
                    string fxScenario = fxScenarioNames[j];
                    // check for workflow cancellation (user abort, server shutdown etc.)
                    if (Cancelled)
                    {
                        throw new OperationCanceledException(CancelReason);
                    }
                    // initialise the pricer with the IR/FX scenario curve maps
                    var portfolioPricer = new PortfolioPricer(irScenarioCurveMap[i], fxScenarioCurveMap[j]);
                    // now price the portfolio
                    portfolioPricer.PriceAndPublish(
                        Context.Logger, Context.Cache,
                        resolvedCurveCache,
                        reportNameCache, response,
                        tradeItemInfos.Keys, request,
                        irScenario, fxScenario, reportingCurrency,
                        baseParty, metrics, false);
                    var dtNow = DateTime.Now;
                    if ((dtNow - lastStatusPublishedAt) <= TimeSpan.FromSeconds(5))
                    {
                        continue;
                    }
                    lastStatusPublishedAt = dtNow;
                    response.Status       = RequestStatusEnum.InProgress;
                    Context.Cache.SaveObject(response);
                } // foreach ir scenario
            }     // foreach fx scenario
            // success
            response.Status = RequestStatusEnum.Completed;
        }
예제 #11
0
        public void should_load_data_from_correct_rate_curve_file()
        {
            string filePath  = @"C:\Users\Steeve\source\repos\RateCurve\Utils\ratecurve.csv";
            char   separator = ';';

            // First create the file
            SortedDictionary <double, double> originalRateCurve = new SortedDictionary <double, double>()
            {
                { 0.0833333333333333, 0.00465 },
                { 0.166666666666667, 0.00473 },
                { 0.25, 0.0048 },
                { 0.5, 0.007 },
                { 0.75, 0.0073 },
                { 1, 0.00893 },
                { 2, 0.00899 },
                { 3, 0.0115 },
                { 4, 0.01457 },
                { 5, 0.01714 },
                { 6, 0.01953 },
                { 7, 0.02166 },
                { 8, 0.02355 },
                { 9, 0.02518 },
                { 10, 0.02656 },
                { 11, 0.02768 },
                { 12, 0.02859 },
                { 13, 0.02935 },
                { 14, 0.02999 },
                { 15, 0.03054 },
                { 16, 0.03102 },
                { 17, 0.03143 },
                { 18, 0.03179 },
                { 19, 0.0321 },
                { 20, 0.03236 },
                { 21, 0.03258 },
                { 22, 0.03275 },
                { 23, 0.0329 },
                { 24, 0.03302 },
                { 25, 0.03311 },
                { 26, 0.03319 },
                { 27, 0.03325 },
                { 28, 0.03331 },
                { 29, 0.03335 },
                { 30, 0.03339 },
                { 31, 0.03343 },
                { 32, 0.03346 },
                { 33, 0.03349 },
                { 34, 0.03353 },
                { 35, 0.03355 },
                { 36, 0.03358 },
                { 37, 0.0336 },
                { 38, 0.03362 },
                { 39, 0.03364 },
                { 40, 0.03366 },
                { 41, 0.03367 },
                { 42, 0.03368 },
                { 43, 0.03368 },
                { 44, 0.03369 },
                { 45, 0.03369 },
                { 46, 0.03369 },
                { 47, 0.03369 },
                { 48, 0.03369 },
                { 49, 0.03369 },
                { 50, 0.03369 }
            };

            // create file
            using (StreamWriter writetext = new StreamWriter(filePath))
            {
                foreach (var pair in originalRateCurve)
                {
                    writetext.WriteLine($"{pair.Key}{separator}{pair.Value}");
                }
            }

            SortedDictionary <double, double> rateCurve = CurveLoader.LoadFromFile(filePath, separator, true);

            // delete file
            if (File.Exists(filePath))
            {
                File.Delete(filePath);
            }

            bool check = true;

            double[] rateCurveKeys         = rateCurve.Keys.ToArray();
            double[] originalRateCurveKeys = originalRateCurve.Keys.ToArray();

            for (int i = 0; i < rateCurve.Count; i++)
            {
                var y = rateCurve[0.25];
                check = check && rateCurve[rateCurveKeys[i]].Equals(rateCurve[rateCurveKeys[i]]);
                if (!check)
                {
                    break;
                }
            }

            Assert.IsTrue(rateCurve != null);
        }
예제 #12
0
        public static Pair <ValuationResultRange, CapFloor> GetPriceAndGeneratedFpML(
            ILogger logger, ICoreCache cache,
            String nameSpace,
            IBusinessCalendar fixingCalendar,
            IBusinessCalendar paymentCalendar,
            ValuationRange valuationRange, TradeRange tradeRange,
            CapFloorLegParametersRange_Old leg1ParametersRange,
            List <InputCashflowRangeItem> leg1DetailedCashflowsList,
            List <InputPrincipalExchangeCashflowRangeItem> legPrincipalExchangeCashflowListArray,
            List <AdditionalPaymentRangeItem> leg1AdditionalPaymentList,
            List <FeePaymentRangeItem> feePaymentList
            )
        {
            //Check if the calendars are null. If not build them!
            InterestRateStream stream1 = GetCashflowsSchedule(fixingCalendar, paymentCalendar, leg1ParametersRange);//parametric definiton + cashflows schedule

            // Update FpML cashflows
            //
            stream1.cashflows = UpdateCashflowsWithDetailedCashflows(leg1DetailedCashflowsList);
            if (null != legPrincipalExchangeCashflowListArray)
            {
                // create principal exchanges
                //
                InterestRateSwapPricer.CreatePrincipalExchangesFromListOfRanges(stream1.cashflows, legPrincipalExchangeCashflowListArray);
            }
            //  Add bullet payments...
            //
            var bulletPaymentList = new List <Payment>();

            if (null != leg1AdditionalPaymentList)
            {
                bulletPaymentList.AddRange(leg1AdditionalPaymentList.Select(bulletPaymentRangeItem => new Payment
                {
                    payerPartyReference    = PartyReferenceFactory.Create(leg1ParametersRange.Payer),
                    receiverPartyReference = PartyReferenceFactory.Create(leg1ParametersRange.Receiver),
                    paymentAmount          = MoneyHelper.GetNonNegativeAmount(bulletPaymentRangeItem.Amount, bulletPaymentRangeItem.Currency),
                    paymentDate            = DateTypesHelper.ToAdjustableOrAdjustedDate(bulletPaymentRangeItem.PaymentDate)
                }));
            }
            CapFloor capFloor = CapFloorFactory.Create(stream1);

            capFloor.additionalPayment = bulletPaymentList.ToArray();
            var feeList = new List <Payment>();

            if (null != feePaymentList)
            {
                feeList.AddRange(feePaymentList.Select(feePaymentRangeItem => new Payment
                {
                    paymentDate            = DateTypesHelper.ToAdjustableOrAdjustedDate(feePaymentRangeItem.PaymentDate),
                    paymentAmount          = MoneyHelper.GetNonNegativeAmount(feePaymentRangeItem.Amount, feePaymentRangeItem.Currency),
                    payerPartyReference    = PartyReferenceFactory.Create(feePaymentRangeItem.Payer),
                    receiverPartyReference = PartyReferenceFactory.Create(feePaymentRangeItem.Receiver)
                }));
            }
            capFloor.premium = feeList.ToArray();
            // Update FpML cashflows with DF,FV,PV, etc (LegParametersRange needed to access curve functionality)
            //
            UpdateCashflowsWithAmounts(logger, cache, nameSpace, stream1, leg1ParametersRange, valuationRange);
            //  Update additional payments
            //
            var leg1DiscountCurve = CurveLoader.LoadInterestRateCurve(logger, cache, nameSpace, leg1ParametersRange.DiscountCurve);

            CapFloorGenerator.UpdatePaymentsAmounts(paymentCalendar, capFloor, leg1ParametersRange, leg1DiscountCurve, valuationRange.ValuationDate);
            //~  Update additional payments
            string baseParty = valuationRange.BaseParty;

            return(new Pair <ValuationResultRange, CapFloor>(CreateValuationRange(capFloor, baseParty), capFloor));
        }
예제 #13
0
        public void ProcessRequest(RequestBase baseRequest, HandlerResponse response)
        {
            if (baseRequest == null)
            {
                throw new ArgumentNullException(nameof(baseRequest));
            }
            var request = baseRequest as StressedCurveGenRequest;

            if (request == null)
            {
                throw new InvalidCastException(
                          $"{typeof(RequestBase).Name} is not a {typeof(StressedCurveGenRequest).Name}");
            }
            // check for workflow cancellation
            if (Cancelled)
            {
                throw new OperationCanceledException(CancelReason);
            }
            DateTime lastStatusPublishedAt = DateTime.Now;

            CurveSelection[] curveSelectors = request.CurveSelector ?? new List <CurveSelection>().ToArray();

            #region Load stress rules

            //find the uniques namespaces
            var uniquesNameSpaces = new List <string>();
            foreach (CurveSelection curveSelector in curveSelectors)
            {
                if (!uniquesNameSpaces.Contains(curveSelector.NameSpace))
                {
                    uniquesNameSpaces.Add(curveSelector.NameSpace);
                }
            }
            var cachedStressRules = new Dictionary <string, List <CachedStressRule> >();
            {
                IExpression       queryExpr         = Expr.IsEQU(EnvironmentProp.NameSpace, uniquesNameSpaces[0]);//TODO only does the first namespace....
                List <StressRule> storedStressRules = Context.Cache.LoadObjects <StressRule>(queryExpr);
                foreach (StressRule storedStressRule in storedStressRules)
                {
                    if ((storedStressRule.Disabled) || (storedStressRule.StressId == null))
                    {
                        continue;
                    }
                    string key = storedStressRule.StressId.ToLower();
                    List <CachedStressRule> rules;
                    if (!cachedStressRules.TryGetValue(key, out rules))
                    {
                        rules = new List <CachedStressRule>();
                        cachedStressRules[key] = rules;
                    }
                    rules.Add(new CachedStressRule(storedStressRule));
                    rules.Sort();
                }
            }
            #endregion

            response.ItemCount = curveSelectors.Length * cachedStressRules.Count;
            // iterate selected base curves
            foreach (CurveSelection curveSelector in curveSelectors)
            {
                // check for workflow cancellation
                if (Cancelled)
                {
                    throw new OperationCanceledException(CancelReason);
                }
                // publish 'intermediate' in-progress result (throttled)
                if ((DateTime.Now - lastStatusPublishedAt) > TimeSpan.FromSeconds(5))
                {
                    lastStatusPublishedAt = DateTime.Now;
                    response.Status       = RequestStatusEnum.InProgress;
                    Context.Cache.SaveObject(response);
                }
                string nameSpace       = curveSelector.NameSpace;
                string inputMarketName = curveSelector.MarketName;
                var    marketDate      = curveSelector.MarketDate;
                if (marketDate != null && marketDate != DateTime.MinValue)
                {
                    inputMarketName += "." + ((DateTime)marketDate).ToString(CurveProp.MarketDateFormat);
                }
                string inputCurveName = curveSelector.CurveName;
                string inputCurveType = curveSelector.CurveType;
                Context.Logger.LogDebug("Building stressed curve(s): {0}.{1}.{2}", inputMarketName, inputCurveType, inputCurveName);

                #region Load base curve

                var curveGenProps = new NamedValueSet();
                curveGenProps.Set(CurveProp.BaseDate, request.BaseDate);
                IPricingStructureIdentifier baseCurveId =
                    PricingStructureIdentifier.CreateMarketCurveIdentifier(curveGenProps, inputMarketName, null, inputCurveType, inputCurveName, null);
                var       baseCurveUniqueId = baseCurveId.Properties.GetValue <string>(CurveProp.UniqueIdentifier, true);
                ICoreItem baseCurveItem     = LoadAndCheckMarketItem(Context.Cache, nameSpace, baseCurveUniqueId);
                var       stressNameProp    = baseCurveItem.AppProps.GetValue <string>(CurveProp.StressName, null);
                if (stressNameProp != null)
                {
                    throw new ApplicationException("The Market with name '" + baseCurveUniqueId + "' is NOT a base curve! (Stress name is not null)");
                }
                var baseCurveFpml = (Market)baseCurveItem.Data;
                var baseCurveType = PropertyHelper.ExtractPricingStructureType(baseCurveItem.AppProps);

                #endregion

                #region Load the reference curves - if required

                string        fxCurveName = null, refCurveName = null, quoteCurveName = null;
                NamedValueSet fxProperties = null, refProperties = null, quoteProperties = null;
                Market        fxMarket = null, refMarket = null, quoteMarket = null;
                if (baseCurveType == PricingStructureTypeEnum.RateBasisCurve ||
                    baseCurveType == PricingStructureTypeEnum.RateXccyCurve)
                {
                    // rate basis curves require a reference curve
                    refCurveName = baseCurveItem.AppProps.GetValue <string>(CurveProp.ReferenceCurveUniqueId, true);
                    // load the reference curve
                    var refCurveItem = LoadAndCheckMarketItem(Context.Cache, nameSpace, refCurveName);
                    refMarket     = (Market)refCurveItem.Data;
                    refProperties = refCurveItem.AppProps;
                }
                if (baseCurveType == PricingStructureTypeEnum.RateXccyCurve)
                {
                    // rate basis curves require an fx curve
                    fxCurveName = baseCurveItem.AppProps.GetValue <string>(CurveProp.ReferenceFxCurveUniqueId, true);
                    // load the reference curve
                    var fxCurveItem = LoadAndCheckMarketItem(Context.Cache, nameSpace, fxCurveName);
                    fxMarket     = (Market)fxCurveItem.Data;
                    fxProperties = fxCurveItem.AppProps;
                    // rate basis curves require a reference curve
                    quoteCurveName = baseCurveItem.AppProps.GetValue <string>(CurveProp.ReferenceCurrency2CurveId, true);
                    // load the reference curve
                    var quoteCurveItem = LoadAndCheckMarketItem(Context.Cache, nameSpace, quoteCurveName);
                    quoteMarket     = (Market)quoteCurveItem.Data;
                    quoteProperties = quoteCurveItem.AppProps;
                }
                #endregion

                // process stress rules
                foreach (var kvp in cachedStressRules)
                {
                    CachedStressRule stressRule = kvp.Value.FirstOrDefault(item => (item.FilterExpr == null) || (Expr.CastTo(item.FilterExpr.Evaluate(baseCurveItem.AppProps), false)));
                    // find stress rule that applies
                    if (stressRule == null)
                    {
                        // this stress does not apply to this base curve
                        Context.Logger.LogWarning("Stress '{0}' does not apply to base curve '{1}'!", kvp.Key, baseCurveUniqueId);
                        response.IncrementItemsPassed();
                        continue;
                    }
                    // apply the stress rule
                    //_Context.Logger.LogDebug("Applying stress '{0}' (rule {1}) to base curve '{2}'", stressRule.StressId, stressRule.RuleId, baseCurveUniqueId);
                    var stressDefProps = new NamedValueSet(baseCurveItem.AppProps, curveGenProps);
                    stressDefProps.Set("Identifier", null);//THis is done for backward compatability eith the old ratecurves.
                    stressDefProps.Set(CurveProp.BaseCurveType, baseCurveType);
                    IPricingStructureIdentifier stressCurveId = PricingStructureIdentifier.CreateMarketCurveIdentifier(
                        stressDefProps, inputMarketName, null, baseCurveType.ToString(), inputCurveName, stressRule.StressId);
                    NamedValueSet stressCurveProps = stressCurveId.Properties;
                    var           stressCurveName  = stressCurveProps.GetValue <string>(CurveProp.UniqueIdentifier, true);
                    // from here on a curve will be published (with error details included)
                    var stressCurve = new Market(); // empty
                    try
                    {
                        // clone the base curve and adjust the market quotes
                        var ps = BinarySerializerHelper.Clone(baseCurveFpml.Items[0]);
                        PricingStructureValuation psv = ApplyStress(stressRule, baseCurveFpml.Items1[0]);
                        // hack - supply base date
                        psv.baseDate = new IdentifiedDate {
                            Value = request.BaseDate
                        };
                        Triplet <PricingStructure, PricingStructureValuation, NamedValueSet> refCurveFpmlTriplet = null;
                        if (baseCurveType == PricingStructureTypeEnum.RateBasisCurve ||
                            baseCurveType == PricingStructureTypeEnum.RateXccyCurve)
                        {
                            var psRef = BinarySerializerHelper.Clone(refMarket.Items[0]);
                            //var psvRef = BinarySerializerHelper.Clone<PricingStructureValuation>(refcurveFpml.Items1[0]);
                            var psvRef = ApplyStress(stressRule, refMarket.Items1[0]);
                            refCurveFpmlTriplet =
                                new Triplet <PricingStructure, PricingStructureValuation, NamedValueSet>(
                                    psRef, psvRef, refProperties);
                        }
                        IPricingStructure ips;
                        switch (baseCurveType)
                        {
                        case PricingStructureTypeEnum.RateBasisCurve:
                            stressCurveProps.Set(CurveProp.ReferenceCurveUniqueId, refCurveName);
                            var basisCurveFpmlTriplet =
                                new Triplet <PricingStructure, PricingStructureValuation, NamedValueSet>(
                                    ps, psv, stressCurveProps);
                            //create and set the pricingstructure
                            ips = CurveLoader.LoadInterestRateCurve(Context.Logger, Context.Cache, nameSpace, refCurveFpmlTriplet, basisCurveFpmlTriplet);
                            //Creator.Create(refCurveFpmlTriplet, basisCurveFpmlTriplet);
                            break;

                        case PricingStructureTypeEnum.RateXccyCurve:
                            stressCurveProps.Set(CurveProp.ReferenceCurveUniqueId, refCurveName);
                            stressCurveProps.Set(CurveProp.ReferenceFxCurveUniqueId, fxCurveName);
                            stressCurveProps.Set(CurveProp.ReferenceCurrency2CurveId, quoteCurveName);
                            var xccyCurveFpmlTriplet =
                                new Triplet <PricingStructure, PricingStructureValuation, NamedValueSet>(ps, psv,
                                                                                                         stressCurveProps);
                            //Format the ref curve data and call the pricing structure helper.
                            var psvFx = ApplyStress(stressRule, fxMarket.Items1[0]);
                            var fxCurveFpmlTriplet
                                = new Triplet <PricingStructure, PricingStructureValuation, NamedValueSet>(
                                      fxMarket.Items[0],
                                      psvFx, fxProperties);

                            var psvRef = ApplyStress(stressRule, quoteMarket.Items1[0]);
                            var quoteCurveFpmlTriplet
                                = new Triplet <PricingStructure, PricingStructureValuation, NamedValueSet>(
                                      quoteMarket.Items[0],
                                      psvRef, quoteProperties);
                            //create and set the pricingstructure
                            ips = CurveLoader.LoadInterestRateCurve(Context.Logger, Context.Cache, nameSpace, refCurveFpmlTriplet, fxCurveFpmlTriplet, quoteCurveFpmlTriplet,
                                                                    xccyCurveFpmlTriplet);
                            //Creator.Create(refCurveFpmlTriplet, fxCurveFpmlTriplet, quoteCurveFpmlTriplet, xccyCurveFpmlTriplet);
                            break;

                        default:
                            ips = CurveLoader.LoadCurve(Context.Logger, Context.Cache,
                                                        nameSpace, new Pair <PricingStructure, PricingStructureValuation>(ps, psv),
                                                        stressCurveProps);
                            //Creator.Create( new Pair<PricingStructure, PricingStructureValuation>(ps, psv), stressCurveProps);
                            break;
                        }
                        var identifier = ips.GetPricingStructureId().UniqueIdentifier;
                        // retrieve curve
                        stressCurve = PricingStructureHelper.CreateMarketFromFpML(
                            identifier,
                            ips.GetFpMLData());
                        // curve done
                        response.IncrementItemsPassed();
                    }
                    catch (Exception innerExcp)
                    {
                        response.IncrementItemsFailed();
                        Context.Logger.Log(innerExcp);
                        stressCurveProps.Set(WFPropName.ExcpName, WFHelper.GetExcpName(innerExcp));
                        stressCurveProps.Set(WFPropName.ExcpText, WFHelper.GetExcpText(innerExcp));
                    }
                    // save stressed curve with same lifetime as base curve
                    stressCurveProps.Set(EnvironmentProp.NameSpace, nameSpace);
                    Context.Cache.SaveObject(stressCurve, nameSpace + "." + stressCurveName, stressCurveProps, true, baseCurveItem.Expires);
                } // foreach stress rule
            }     // foreach base curve

            // success
            response.Status = RequestStatusEnum.Completed;
        }