private static Market GetMarket(IPricingStructure pricingStructure) { string uniqueIdentifier = pricingStructure.GetPricingStructureId().UniqueIdentifier; var fpml = pricingStructure.GetFpMLData(); Market market = PricingStructureHelper.CreateMarketFromFpML(uniqueIdentifier, fpml); return(market); }
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 static void ClassInitialize(TestContext testContext) { var baseDate = new DateTime(1998, 2, 20); //Build the EUR curves. var discountCurveProperties = new NamedValueSet(); discountCurveProperties.Set(CurveProp.PricingStructureType, "DiscountCurve"); discountCurveProperties.Set("BuildDateTime", baseDate); discountCurveProperties.Set(CurveProp.BaseDate, baseDate); discountCurveProperties.Set(CurveProp.Market, "LIVE"); discountCurveProperties.Set(CurveProp.MarketAndDate, "LIVE"); discountCurveProperties.Set("Identifier", "DiscountCurve." + "EUR-LIBOR-SENIOR" + baseDate); discountCurveProperties.Set(CurveProp.Currency1, "EUR"); discountCurveProperties.Set("CreditInstrumentId", "LIBOR"); discountCurveProperties.Set("CreditSeniority", "SENIOR"); discountCurveProperties.Set(CurveProp.CurveName, "EUR-LIBOR-SENIOR"); discountCurveProperties.Set("Algorithm", "LinearZero"); //Set the required test curves.Firstly the discount curve. var discountCurve = ControllerHelper.TestRateCurve(baseDate); var discountCurvefpML = discountCurve.GetFpMLData(); const string disId = "Highlander.Market.LIVE.DiscountCurve.EUR-LIBOR-SENIOR"; var discountCurvemarket = PricingStructureHelper.CreateMarketFromFpML(disId, discountCurvefpML); ServerStore.Client.SaveObject <Market>(discountCurvemarket, disId, discountCurveProperties, TimeSpan.MaxValue); var curvePropertiesa = new NamedValueSet(); curvePropertiesa.Set(CurveProp.PricingStructureType, "RateCurve"); curvePropertiesa.Set("BuildDateTime", baseDate); curvePropertiesa.Set(CurveProp.BaseDate, baseDate); curvePropertiesa.Set(CurveProp.Market, "LIVE"); curvePropertiesa.Set(CurveProp.MarketAndDate, "LIVE"); curvePropertiesa.Set("Identifier", "RateCurve." + "EUR-EURIBOR-Telerate" + baseDate); curvePropertiesa.Set(CurveProp.Currency1, "EUR"); curvePropertiesa.Set(CurveProp.IndexName, "EUR-EURIBOR-Telerate"); curvePropertiesa.Set(CurveProp.IndexTenor, "6M"); curvePropertiesa.Set(CurveProp.CurveName, "EUR-EURIBOR-Telerate-6M"); curvePropertiesa.Set("Algorithm", "LinearZero"); //THe forecast ratecurve var forecastCurvea = ControllerHelper.TestRateCurve(baseDate); var forecastCurvefpMLa = forecastCurvea.GetFpMLData(); const string forecastCurveIda = "Highlander.Market.LIVE.RateCurve.EUR-EURIBOR-Telerate-6M"; var forecastCurvemarketa = PricingStructureHelper.CreateMarketFromFpML(forecastCurveIda, forecastCurvefpMLa); ServerStore.Client.SaveObject <Market>(forecastCurvemarketa, forecastCurveIda, curvePropertiesa, TimeSpan.MaxValue); var curvePropertiesb = new NamedValueSet(); curvePropertiesb.Set(CurveProp.PricingStructureType, "RateCurve"); curvePropertiesb.Set("BuildDateTime", baseDate); curvePropertiesb.Set(CurveProp.BaseDate, baseDate); curvePropertiesb.Set(CurveProp.Market, "LIVE"); curvePropertiesb.Set(CurveProp.MarketAndDate, "LIVE"); curvePropertiesb.Set("Identifier", "RateCurve." + "EUR-LIBOR-BBA" + baseDate); curvePropertiesb.Set(CurveProp.Currency1, "EUR"); curvePropertiesb.Set(CurveProp.IndexName, "EUR-LIBOR-BBA"); curvePropertiesb.Set(CurveProp.IndexTenor, "6M"); curvePropertiesb.Set(CurveProp.CurveName, "EUR-LIBOR-BBA-6M"); curvePropertiesb.Set("Algorithm", "LinearZero"); //THe forecast ratecurve var forecastCurveb = ControllerHelper.TestRateCurve(baseDate); var forecastCurvefpMLb = forecastCurveb.GetFpMLData(); const string forecastCurveIdb = "Highlander.Market.LIVE.RateCurve.EUR-LIBOR-BBA-6M"; var forecastCurvemarketb = PricingStructureHelper.CreateMarketFromFpML(forecastCurveIdb, forecastCurvefpMLb); ServerStore.Client.SaveObject <Market>(forecastCurvemarketb, forecastCurveIdb, curvePropertiesb, TimeSpan.MaxValue); //var curveProperties = new NamedValueSet(); //curveProperties.Set(CurveProp.PricingStructureType, "RateCurve"); //curveProperties.Set("BuildDateTime", baseDate); //curveProperties.Set(CurveProp.BaseDate, baseDate); //curveProperties.Set(CurveProp.Market, "LIVE"); //curveProperties.Set(CurveProp.MarketAndDate, "LIVE"); //curveProperties.Set("Identifier", "RateCurve." + "EUR-LIBOR-BBA" + baseDate); //curveProperties.Set(CurveProp.Currency1, "EUR"); //curveProperties.Set(CurveProp.IndexName, "EUR-LIBOR-BBA"); //curveProperties.Set(CurveProp.IndexTenor, "6M"); //curveProperties.Set(CurveProp.CurveName, "EUR-LIBOR-BBA-6M"); //curveProperties.Set("Algorithm", "LinearZero"); ////THe forecast ratecurve //var forecastCurve = ControllerHelper.TestRateCurve(baseDate); //var forecastCurvefpML = forecastCurve.GetFpMLData(); //const string forecastCurveId = "Highlander.Market.LIVE.RateCurve.EUR-LIBOR-BBA-6M"; //var forecastCurvemarket = PricingStructureHelper.CreateMarketFromFpML(forecastCurveId, forecastCurvefpML); //ServerStore.Cache.SaveObject<Market>(forecastCurvemarket, forecastCurveId, curveProperties, TimeSpan.MaxValue); var fxProperties = new NamedValueSet(); fxProperties.Set(CurveProp.PricingStructureType, "FxCurve"); fxProperties.Set("BuildDateTime", baseDate); fxProperties.Set(CurveProp.BaseDate, baseDate); fxProperties.Set(CurveProp.Market, "LIVE"); fxProperties.Set(CurveProp.MarketAndDate, "LIVE"); fxProperties.Set("Identifier", "FxCurve.EUR-USD" + baseDate); fxProperties.Set(CurveProp.Currency1, "EUR"); fxProperties.Set(CurveProp.Currency2, "USD"); fxProperties.Set(CurveProp.CurrencyPair, "EUR-USD"); fxProperties.Set(CurveProp.QuoteBasis, "Currency2PerCurrency1"); fxProperties.Set(CurveProp.CurveName, "EUR-USD"); fxProperties.Set("Algorithm", "LinearForward"); //The fx curve. var fxCurve = ControllerHelper.TestFxCurve(baseDate); var fxCurvefpML = fxCurve.GetFpMLData(); const string fxCurveId = "Highlander.Market.LIVE.FxCurve.EUR-USD"; var fxCurvemarket = PricingStructureHelper.CreateMarketFromFpML(fxCurveId, fxCurvefpML); ServerStore.Client.SaveObject <Market>(fxCurvemarket, fxCurveId, fxProperties, TimeSpan.MaxValue); //Build the USD Curves var discountCurveProperties2 = new NamedValueSet(); discountCurveProperties2.Set(CurveProp.PricingStructureType, "DiscountCurve"); discountCurveProperties2.Set("BuildDateTime", baseDate); discountCurveProperties2.Set(CurveProp.BaseDate, baseDate); discountCurveProperties2.Set(CurveProp.Market, "LIVE"); discountCurveProperties2.Set(CurveProp.MarketAndDate, "LIVE"); discountCurveProperties2.Set("Identifier", "DiscountCurve." + "USD-LIBOR-SENIOR" + baseDate); discountCurveProperties2.Set(CurveProp.Currency1, "USD"); discountCurveProperties2.Set("CreditInstrumentId", "LIBOR"); discountCurveProperties2.Set("CreditSeniority", "SENIOR"); discountCurveProperties2.Set(CurveProp.CurveName, "USD-LIBOR-SENIOR"); discountCurveProperties2.Set("Algorithm", "LinearZero"); //Set the required test curves.Firstly the discount curve. var discountCurve2 = ControllerHelper.TestRateCurve(baseDate); var discountCurvefpML2 = discountCurve2.GetFpMLData(); const string disId2 = "Highlander.Market.LIVE.DiscountCurve.USD-LIBOR-SENIOR"; var discountCurvemarket2 = PricingStructureHelper.CreateMarketFromFpML(disId2, discountCurvefpML2); ServerStore.Client.SaveObject <Market>(discountCurvemarket2, disId2, discountCurveProperties2, TimeSpan.MaxValue); var curveProperties2 = new NamedValueSet(); curveProperties2.Set(CurveProp.PricingStructureType, "RateCurve"); curveProperties2.Set("BuildDateTime", baseDate); curveProperties2.Set(CurveProp.BaseDate, baseDate); curveProperties2.Set(CurveProp.Market, "LIVE"); curveProperties2.Set(CurveProp.MarketAndDate, "LIVE"); curveProperties2.Set("Identifier", "RateCurve." + "USD-LIBOR-BBA" + baseDate); curveProperties2.Set(CurveProp.Currency1, "USD"); curveProperties2.Set(CurveProp.IndexName, "USD-LIBOR-BBA"); curveProperties2.Set(CurveProp.IndexTenor, "6M"); curveProperties2.Set(CurveProp.CurveName, "USD-LIBOR-BBA-6M"); curveProperties2.Set("Algorithm", "LinearZero"); //THe forecast ratecurve var forecastCurve2 = ControllerHelper.TestRateCurve(baseDate); var forecastCurvefpML2 = forecastCurve2.GetFpMLData(); const string forecastCurveId2 = "Highlander.Market.LIVE.RateCurve.USD-LIBOR-BBA-6M"; var forecastCurvemarket2 = PricingStructureHelper.CreateMarketFromFpML(forecastCurveId2, forecastCurvefpML2); ServerStore.Client.SaveObject <Market>(forecastCurvemarket2, forecastCurveId2, curveProperties2, TimeSpan.MaxValue); var curvePropertiesn = new NamedValueSet(); curvePropertiesn.Set(CurveProp.PricingStructureType, "RateCurve"); curvePropertiesn.Set("BuildDateTime", baseDate); curvePropertiesn.Set(CurveProp.BaseDate, baseDate); curvePropertiesn.Set(CurveProp.Market, "LIVE"); curvePropertiesn.Set(CurveProp.MarketAndDate, "LIVE"); curvePropertiesn.Set("Identifier", "RateCurve." + "USD-LIBOR-BBA" + baseDate); curvePropertiesn.Set(CurveProp.Currency1, "USD"); curvePropertiesn.Set(CurveProp.IndexName, "USD-LIBOR-BBA"); curvePropertiesn.Set(CurveProp.IndexTenor, "3M"); curvePropertiesn.Set(CurveProp.CurveName, "USD-LIBOR-BBA-3M"); curvePropertiesn.Set("Algorithm", "LinearZero"); //THe forecast ratecurve var forecastCurven = ControllerHelper.TestRateCurve(baseDate); var forecastCurvefpMLn = forecastCurven.GetFpMLData(); const string forecastCurveIdn = "Highlander.Market.LIVE.RateCurve.USD-LIBOR-BBA-3M"; var forecastCurvemarketn = PricingStructureHelper.CreateMarketFromFpML(forecastCurveIdn, forecastCurvefpMLn); ServerStore.Client.SaveObject <Market>(forecastCurvemarketn, forecastCurveIdn, curvePropertiesn, TimeSpan.MaxValue); //var fxProperties2 = new NamedValueSet(); //fxProperties2.Set(CurveProp.PricingStructureType, "FxCurve"); //fxProperties2.Set("BuildDateTime", baseDate); //fxProperties2.Set(CurveProp.BaseDate, baseDate); //fxProperties2.Set(CurveProp.Market, "LIVE"); //fxProperties2.Set("Identifier", "FxCurve.USD-AUD" + baseDate); //fxProperties2.Set(CurveProp.Currency1, "AUD"); //fxProperties2.Set(CurveProp.Currency2, "USD"); //fxProperties2.Set(CurveProp.CurrencyPair, "USD-AUD"); //fxProperties2.Set(CurveProp.CurveName, "USD-AUD"); //fxProperties2.Set("Algorithm", "LinearForward"); ////The fx curve. //var fxCurve2 = ControllerHelper.TestFxCurve(baseDate); //var fxCurvefpML2 = fxCurve2.GetFpMLData(); //const string fxCurveId2 = "Highlander.Market.LIVE.FxCurve.USD-AUD"; //var fxCurvemarket2 = PricingStructureHelper.CreateMarketFromFpML(fxCurveId2, fxCurvefpML2); //ServerStore.Cache.SaveObject<Market>(fxCurvemarket2, fxCurveId2, fxProperties2, TimeSpan.MaxValue); //Build the JPY Curves var DiscountCurveProperties3 = new NamedValueSet(); DiscountCurveProperties3.Set(CurveProp.PricingStructureType, "DiscountCurve"); DiscountCurveProperties3.Set("BuildDateTime", baseDate); DiscountCurveProperties3.Set(CurveProp.BaseDate, baseDate); DiscountCurveProperties3.Set(CurveProp.Market, "LIVE"); DiscountCurveProperties3.Set(CurveProp.MarketAndDate, "LIVE"); DiscountCurveProperties3.Set("Identifier", "DiscountCurve." + "JPY-LIBOR-SENIOR" + baseDate); DiscountCurveProperties3.Set(CurveProp.Currency1, "JPY"); DiscountCurveProperties3.Set("CreditInstrumentId", "LIBOR"); DiscountCurveProperties3.Set("CreditSeniority", "SENIOR"); DiscountCurveProperties3.Set(CurveProp.CurveName, "JPY-LIBOR-SENIOR"); DiscountCurveProperties3.Set("Algorithm", "LinearZero"); //Set the required test curves.Firstly the discount curve. var discountCurve3 = ControllerHelper.TestRateCurve(baseDate); var discountCurvefpML3 = discountCurve3.GetFpMLData(); const string disId3 = "Highlander.Market.LIVE.DiscountCurve.JPY-LIBOR-SENIOR"; var discountCurvemarket3 = PricingStructureHelper.CreateMarketFromFpML(disId3, discountCurvefpML3); ServerStore.Client.SaveObject <Market>(discountCurvemarket3, disId3, DiscountCurveProperties3, TimeSpan.MaxValue); var curveProperties3 = new NamedValueSet(); curveProperties3.Set(CurveProp.PricingStructureType, "RateCurve"); curveProperties3.Set("BuildDateTime", baseDate); curveProperties3.Set(CurveProp.BaseDate, baseDate); curveProperties3.Set(CurveProp.Market, "LIVE"); curveProperties3.Set(CurveProp.MarketAndDate, "LIVE"); curveProperties3.Set("Identifier", "RateCurve." + "JPY-LIBOR-BBA" + baseDate); curveProperties3.Set(CurveProp.Currency1, "JPY"); curveProperties3.Set(CurveProp.IndexName, "JPY-LIBOR-BBA"); curveProperties3.Set(CurveProp.IndexTenor, "6M"); curveProperties3.Set(CurveProp.CurveName, "JPY-LIBOR-BBA-6M"); curveProperties3.Set("Algorithm", "LinearZero"); //THe forecast ratecurve var forecastCurve3 = ControllerHelper.TestRateCurve(baseDate); var forecastCurvefpML3 = forecastCurve3.GetFpMLData(); const string forecastCurveId3 = "Highlander.Market.LIVE.RateCurve.JPY-LIBOR-BBA-6M"; var forecastCurvemarket3 = PricingStructureHelper.CreateMarketFromFpML(forecastCurveId3, forecastCurvefpML3); ServerStore.Client.SaveObject <Market>(forecastCurvemarket3, forecastCurveId3, curveProperties3, TimeSpan.MaxValue); var fxProperties3 = new NamedValueSet(); fxProperties3.Set(CurveProp.PricingStructureType, "FxCurve"); fxProperties3.Set("BuildDateTime", baseDate); fxProperties3.Set(CurveProp.BaseDate, baseDate); fxProperties3.Set(CurveProp.Market, "LIVE"); fxProperties3.Set(CurveProp.MarketAndDate, "LIVE"); fxProperties3.Set("Identifier", "FxCurve.JPY-USD" + baseDate); fxProperties3.Set(CurveProp.Currency1, "JPY"); fxProperties3.Set(CurveProp.Currency2, "USD"); fxProperties3.Set(CurveProp.CurrencyPair, "JPY-USD"); fxProperties3.Set(CurveProp.QuoteBasis, "Currency2PerCurrency1"); fxProperties3.Set(CurveProp.CurveName, "JPY-AUD"); fxProperties3.Set("Algorithm", "LinearForward"); //The fx curve. var fxCurve3 = ControllerHelper.TestFxCurve(baseDate); var fxCurvefpML3 = fxCurve3.GetFpMLData(); const string fxCurveId3 = "Highlander.Market.LIVE.FxCurve.JPY-USD"; var fxCurvemarket3 = PricingStructureHelper.CreateMarketFromFpML(fxCurveId3, fxCurvefpML3); ServerStore.Client.SaveObject <Market>(fxCurvemarket3, fxCurveId3, fxProperties3, TimeSpan.MaxValue); //Build the CHF curves. var discountCurveProperties4 = new NamedValueSet(); discountCurveProperties4.Set(CurveProp.PricingStructureType, "DiscountCurve"); discountCurveProperties4.Set("BuildDateTime", baseDate); discountCurveProperties4.Set(CurveProp.BaseDate, baseDate); discountCurveProperties4.Set(CurveProp.Market, "LIVE"); discountCurveProperties4.Set(CurveProp.MarketAndDate, "LIVE"); discountCurveProperties4.Set("Identifier", "DiscountCurve." + "CHF-LIBOR-SENIOR" + baseDate); discountCurveProperties4.Set(CurveProp.Currency1, "CHF"); discountCurveProperties4.Set("CreditInstrumentId", "LIBOR"); discountCurveProperties4.Set("CreditSeniority", "SENIOR"); discountCurveProperties4.Set(CurveProp.CurveName, "CHF-LIBOR-SENIOR"); discountCurveProperties4.Set("Algorithm", "LinearZero"); //Set the required test curves.Firstly the discount curve. var discountCurve4 = ControllerHelper.TestRateCurve(baseDate); var discountCurvefpML4 = discountCurve4.GetFpMLData(); const string disId4 = "Highlander.Market.LIVE.DiscountCurve.CHF-LIBOR-SENIOR"; var discountCurvemarket4 = PricingStructureHelper.CreateMarketFromFpML(disId4, discountCurvefpML4); ServerStore.Client.SaveObject <Market>(discountCurvemarket4, disId4, discountCurveProperties4, TimeSpan.MaxValue); var curveProperties4 = new NamedValueSet(); curveProperties4.Set(CurveProp.PricingStructureType, "RateCurve"); curveProperties4.Set("BuildDateTime", baseDate); curveProperties4.Set(CurveProp.BaseDate, baseDate); curveProperties4.Set(CurveProp.Market, "LIVE"); curveProperties4.Set(CurveProp.MarketAndDate, "LIVE"); curveProperties4.Set("Identifier", "RateCurve." + "CHF-LIBOR-BBA" + baseDate); curveProperties4.Set(CurveProp.Currency1, "CHF"); curveProperties4.Set(CurveProp.IndexName, "CHF-LIBOR-BBA"); curveProperties4.Set(CurveProp.IndexTenor, "6M"); curveProperties4.Set(CurveProp.CurveName, "CHF-LIBOR-BBA-6M"); curveProperties4.Set("Algorithm", "LinearZero"); //THe forecast ratecurve var forecastCurve4 = ControllerHelper.TestRateCurve(baseDate); var forecastCurvefpML4 = forecastCurve4.GetFpMLData(); const string forecastCurveId4 = "Highlander.Market.LIVE.RateCurve.CHF-LIBOR-BBA-6M"; var forecastCurvemarket4 = PricingStructureHelper.CreateMarketFromFpML(forecastCurveId4, forecastCurvefpML4); ServerStore.Client.SaveObject <Market>(forecastCurvemarket4, forecastCurveId4, curveProperties4, TimeSpan.MaxValue); var fxProperties4 = new NamedValueSet(); fxProperties4.Set(CurveProp.PricingStructureType, "FxCurve"); fxProperties4.Set("BuildDateTime", baseDate); fxProperties4.Set(CurveProp.BaseDate, baseDate); fxProperties4.Set(CurveProp.Market, "LIVE"); fxProperties4.Set(CurveProp.MarketAndDate, "LIVE"); fxProperties4.Set("Identifier", "FxCurve.CHF-USD" + baseDate); fxProperties4.Set(CurveProp.Currency1, "USD"); fxProperties4.Set(CurveProp.Currency2, "CHF"); fxProperties4.Set(CurveProp.QuoteBasis, "Currency2PerCurrency1"); fxProperties4.Set(CurveProp.CurrencyPair, "CHF-USD"); fxProperties4.Set(CurveProp.CurveName, "CHF-USD"); fxProperties4.Set("Algorithm", "LinearForward"); //The fx curve. var fxCurve4 = ControllerHelper.TestFxCurve(baseDate); var fxCurvefpML4 = fxCurve4.GetFpMLData(); const string fxCurveId4 = "Highlander.Market.LIVE.FxCurve.CHF-USD"; var fxCurvemarket4 = PricingStructureHelper.CreateMarketFromFpML(fxCurveId4, fxCurvefpML4); ServerStore.Client.SaveObject <Market>(fxCurvemarket4, fxCurveId4, fxProperties4, TimeSpan.MaxValue); var fxProperties5 = new NamedValueSet(); fxProperties5.Set(CurveProp.PricingStructureType, "FxCurve"); fxProperties5.Set("BuildDateTime", baseDate); fxProperties5.Set(CurveProp.BaseDate, baseDate); fxProperties5.Set(CurveProp.Market, "LIVE"); fxProperties5.Set(CurveProp.MarketAndDate, "LIVE"); fxProperties5.Set("Identifier", "FxCurve.AUD-USD" + baseDate); fxProperties5.Set(CurveProp.Currency1, "AUD"); fxProperties5.Set(CurveProp.Currency2, "USD"); fxProperties5.Set(CurveProp.CurrencyPair, "AUD-USD"); fxProperties5.Set(CurveProp.QuoteBasis, "Currency2PerCurrency1"); fxProperties5.Set(CurveProp.CurveName, "AUD-USD"); fxProperties5.Set("Algorithm", "LinearForward"); //The fx curve. var fxCurve5 = ControllerHelper.TestFxCurve(baseDate); var fxCurvefpML5 = fxCurve5.GetFpMLData(); const string fxCurveId5 = "Highlander.Market.LIVE.FxCurve.AUD-USD"; var fxCurvemarket5 = PricingStructureHelper.CreateMarketFromFpML(fxCurveId5, fxCurvefpML5); ServerStore.Client.SaveObject <Market>(fxCurvemarket5, fxCurveId5, fxProperties5, TimeSpan.MaxValue); }
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; }