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); }
/// <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); }
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)); }
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); }
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); }
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); }
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)); }
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; }
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; }
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; }
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); }
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)); }
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; }