public static BasicAssetValuation Add(BasicAssetValuation basicAssetValuation1, BasicAssetValuation basicAssetValuation2) { BasicAssetValuation result = BinarySerializerHelper.Clone(basicAssetValuation1); var proccessedMeasureTypes = new List <string>(); foreach (BasicQuotation bq1 in result.quote) { proccessedMeasureTypes.Add(bq1.measureType.Value); BasicQuotation bq2 = GetQuotationByMeasureType(basicAssetValuation2, bq1.measureType.Value); if (null != bq2) { bq1.value += bq2.value; } } var bqToAddToList = new List <BasicQuotation>(); foreach (BasicQuotation bq2 in basicAssetValuation2.quote) { if (-1 == proccessedMeasureTypes.IndexOf(bq2.measureType.Value))//if hasn't been processed in the first pass { bqToAddToList.Add(bq2); } } bqToAddToList.AddRange(result.quote); result.quote = bqToAddToList.ToArray(); return(result); }
/// <summary> /// Gets the closest non-zero volatility strike to money. /// </summary> /// <param name="expiry">The expiry.</param> /// <returns></returns> /// public static Strike GetClosestStrikeToMoney(ForwardExpiry expiry) { decimal fwdPrice = expiry.FwdPrice; var expiryCopy = BinarySerializerHelper.Clone(expiry); /* Bin search bitwise complement returns first element larger than search key * Returns Array Length + 1 if search key greater than all elements */ expiryCopy.RawStrikePrices.Sort(); double[] strikes = expiryCopy.RawStrikePrices.ToArray(); int index = Array.BinarySearch(strikes, Convert.ToDouble(fwdPrice)); if (index < 0) { index = ~index; } if (expiryCopy.Strikes.Length == 0) { return(null); } if (index < expiryCopy.Strikes.Length) { double dist1 = Math.Abs(strikes[index] - Convert.ToDouble(fwdPrice)); double dist2 = 0.0; if (index >= 1) { dist2 = Math.Abs(strikes[index - 1] - Convert.ToDouble(fwdPrice)); } if (dist1 <= dist2 || index == 0) { return(expiryCopy.Strikes[index]); } return(expiryCopy.Strikes[index - 1]); } return(expiryCopy.Strikes[expiryCopy.RawStrikePrices.Count - 1]); }
/// <summary> /// /// </summary> /// <param name="dataType"></param> /// <param name="binaryClone"></param> /// <returns></returns> public object GetData(Type dataType, bool binaryClone) { // deserialise if required Deserialise(dataType); if (binaryClone) { return(BinarySerializerHelper.Clone(_data)); } return(_data); }
public static BasicQuotation Add(BasicQuotation basicQuotation1, BasicQuotation basicQuotation2) { if (basicQuotation1.measureType.Value != basicQuotation2.measureType.Value) { string errorMessage = $"Error: can't add BasicQuotations with different 'measureTypes'. MeasureType for basicQuotation1 is {basicQuotation1.measureType.Value}, MeasureType for basicQuotation2 is {basicQuotation2.measureType.Value}"; throw new System.Exception(errorMessage); } BasicQuotation result = BinarySerializerHelper.Clone(basicQuotation1); result.value += basicQuotation2.value; return(result); }
public void AddQuotedAssetSet(QuotedAssetSet quotedAssetSet) { quotedAssetSet = BinarySerializerHelper.Clone(quotedAssetSet); //_lastQuotedAssetSet = quotedAssetSet; if (null == _lastQuotedAssetSet) { _lastQuotedAssetSet = quotedAssetSet; } else { MergeQuotedAssetSet(quotedAssetSet); } }
///// <summary> ///// Creates the surface from expiry node list. ///// </summary> ///// <param name="assetId">The asset id.</param> ///// <param name="expiryNodes">The expiry nodes.</param> ///// <returns></returns> //public static IVolatilitySurface CreateSurfaceFromNodalExpiryNodeList(string assetId, XmlNodeList expiryNodes) //{ // IVolatilitySurface surface = new VolatilitySurface(assetId); // List<ForwardExpiry> expiries = ForwardExpiryHelper.CreateExpiriesFromExpiryNodeList(expiryNodes); // if (expiries != null) // { // foreach (ForwardExpiry expiry in expiries) // { // surface.AddExpiry(expiry); // } // } // else // { // throw new IncompleteInputDataException("Surface has no expiries"); // } // return surface; //} /// <summary> /// Gets the closest non-zero volatility strike to money. /// </summary> /// <param name="expiry">The expiry.</param> /// <returns></returns> /// public static double GetClosestNonZeroVolStrikeToMoney(ForwardExpiry expiry) { decimal fwdPrice = expiry.FwdPrice; var expiryCopy = BinarySerializerHelper.Clone(expiry); //Remove strikes with zero vol in the search object //Want to return the location of the nearest *non-zero* strike foreach (Strike strike in expiryCopy.Strikes) { if (strike.Volatility.Value == 0) { expiryCopy.RemoveStrike(strike.StrikePrice); } } /* Bin search bitwise complement returns first element larger than search key * Returns Array Length + 1 if search key greater than all elements */ expiryCopy.RawStrikePrices.Sort(); double[] strikes = expiryCopy.RawStrikePrices.ToArray(); int index = Array.BinarySearch(strikes, Convert.ToDouble(fwdPrice)); if (index < 0) { index = ~index; } if (expiryCopy.RawStrikePrices.Count == 0) { return(0.0); } if (index < expiryCopy.RawStrikePrices.Count) { double dist1 = Math.Abs(strikes[index] - Convert.ToDouble(fwdPrice)); double dist2 = 0.0; if (index >= 1) { dist2 = Math.Abs(strikes[index - 1] - Convert.ToDouble(fwdPrice)); } if (dist1 <= dist2 || index == 0) { return(expiryCopy.RawStrikePrices[index]); } return(expiryCopy.RawStrikePrices[index - 1]); } return(expiryCopy.RawStrikePrices[expiryCopy.RawStrikePrices.Count - 1]); }
public static void ResolveBusinessCenters(object objectGraph) { foreach (BusinessDayAdjustments businessDayAdjustment in GetBusinessDayAdjustments(objectGraph)) { // "NONE" adjustments have neither businessCenters nor businessCentersReference. // if ((null != businessDayAdjustment) && (null == businessDayAdjustment.businessCenters) && (null != businessDayAdjustment.businessCentersReference) && (!String.IsNullOrEmpty(businessDayAdjustment.businessCentersReference.href))) { var businessCenters = ObjectLookupHelper.GetById <BusinessCenters>(objectGraph, businessDayAdjustment.businessCentersReference.href); var businessCentersCloneWithNoId = BinarySerializerHelper.Clone(businessCenters); businessCentersCloneWithNoId.id = null; businessDayAdjustment.businessCenters = businessCentersCloneWithNoId; } } }
public static BasicQuotation Sum(List <BasicQuotation> basicQuotationList) { if (0 == basicQuotationList.Count) { throw new ArgumentException("basicQuotationList is empty"); } if (1 == basicQuotationList.Count) { return(BinarySerializerHelper.Clone(basicQuotationList[0])); } // clone collection internally - just to keep invariant of the method. // List <BasicQuotation> clonedCollection = BinarySerializerHelper.Clone(basicQuotationList); BasicQuotation firstElement = clonedCollection[0]; clonedCollection.RemoveAt(0); BasicQuotation sumOfTheTail = Sum(clonedCollection); return(Add(firstElement, sumOfTheTail)); }
/// <summary> /// Gets the i-th closest non-zero volatility strike to money. /// </summary> /// <param name="expiry">The expiry.</param> /// <param name="i"></param> /// <returns></returns> public static double GetClosestNonZeroVolStrikeToMoney(ForwardExpiry expiry, int i) { decimal fwdPrice = expiry.FwdPrice; var expiryCopy = BinarySerializerHelper.Clone(expiry); //Remove strikes with zero vol in the search object //Want to return the location of the nearest *non-zero* strike foreach (Strike strike in expiryCopy.Strikes) { if (strike.Volatility.Value == 0) { expiryCopy.RemoveStrike(strike.StrikePrice); } } var newStrikes = new double[expiryCopy.RawStrikePrices.Count]; expiryCopy.RawStrikePrices.Sort(); double[] strikes = expiryCopy.RawStrikePrices.ToArray(); if (strikes.Length < i) { return(0); } var keys = new int[strikes.Length]; for (int idx = 0; idx < strikes.Length; idx++) { newStrikes[idx] = strikes[idx] - (double)fwdPrice; keys[idx] = idx; } //Get min distance to forward Array.Sort(newStrikes, keys, new DistanceComparer()); if (i > 0) { return(expiryCopy.Strikes[keys[i - 1]].StrikePrice); } return(0); /* Bin search bitwise complement returns first element larger than search key * Returns Array Length + 1 if search key greater than all elements */ }
/// <summary> /// Initializes a new instance of the <see cref="PriceableFxOptionPremium"/> class. /// </summary> /// <param name="id">The identifier.</param> /// <param name="receiverPartyReference">The receiver.</param> /// <param name="payerIsBase">The flag determining if the payer is the base party.</param> /// <param name="amount">The amount.</param> /// <param name="settlementDate">The adjusted payment date.</param> /// <param name="payerPartyReference">The payer.</param> /// <param name="premiumQuote">The premium quote </param> /// <param name="settlementInformation">The settlement information. </param> /// <param name="paymentCalendar">Type paymentCalendar.</param> public PriceableFxOptionPremium ( string id , string payerPartyReference , string receiverPartyReference , bool payerIsBase , Money amount , DateTime settlementDate , PremiumQuote premiumQuote , SettlementInformation settlementInformation , IBusinessCalendar paymentCalendar) : base(id, "DiscountedCashflow", payerIsBase, amount, AdjustableOrAdjustedDateHelper.CreateAdjustedDate(settlementDate), PaymentTypeHelper.Create("Certain"), CashflowTypeHelper.Create(CashflowTypeEnum.Premium.ToString()), false, paymentCalendar) { PayerPartyReference = PartyReferenceFactory.Create(payerPartyReference); ReceiverPartyReference = PartyReferenceFactory.Create(receiverPartyReference); OrderedPartyNames.Add(PayerPartyReference.href); OrderedPartyNames.Add(ReceiverPartyReference.href); if (premiumQuote != null) { PremiumQuote = new PremiumQuote { quoteBasis = premiumQuote.quoteBasis, quoteBasisSpecified = true, value = premiumQuote.value, valueSpecified = true }; } if (settlementInformation == null) { return; } SettlementInformation = new SettlementInformation(); var item = BinarySerializerHelper.Clone(settlementInformation.Item); SettlementInformation.Item = item; }
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; }
private static PricingStructureValuation ApplyStress(CachedStressRule stressRule, PricingStructureValuation psvInput) { string marketQuote = AssetMeasureScheme.GetEnumString(AssetMeasureEnum.MarketQuote); string decimalRate = PriceQuoteUnitsScheme.GetEnumString(PriceQuoteUnitsEnum.DecimalRate); var psv = BinarySerializerHelper.Clone(psvInput); // extract the market quotes from the cloned base curve QuotedAssetSet curveDefinition; if (psv is YieldCurveValuation yieldCurveValuation) { curveDefinition = yieldCurveValuation.inputs; } else { if (psv is FxCurveValuation curveValuation) { curveDefinition = new QuotedAssetSet { instrumentSet = curveValuation.spotRate.instrumentSet, assetQuote = curveValuation.spotRate.assetQuote }; } else { throw new NotSupportedException("Unsupported PricingStructureValuation type: " + psv.GetType().Name); } } // stress the market quotes foreach (BasicAssetValuation asset in curveDefinition.assetQuote) { var stressDefQuotes = new List <BasicQuotation>(); foreach (BasicQuotation quote in asset.quote) { if (quote.measureType.Value.Equals(marketQuote) && quote.quoteUnits.Value.Equals(decimalRate)) { var exprProps = new NamedValueSet(new NamedValue("MarketQuote", quote.value)); quote.valueSpecified = true; quote.value = Convert.ToDecimal(stressRule.UpdateExpr.Evaluate(exprProps)); } quote.informationSource = null; quote.timeSpecified = false; quote.valuationDateSpecified = false; stressDefQuotes.Add(quote); } asset.quote = stressDefQuotes.ToArray(); } // replace the market quotes in the cloned base curve with the stressed values if (psv is YieldCurveValuation valuation) { valuation.inputs = curveDefinition; valuation.discountFactorCurve = null; valuation.zeroCurve = null; } else { ((FxCurveValuation)psv).spotRate = new FxRateSet { instrumentSet = curveDefinition.instrumentSet, assetQuote = curveDefinition.assetQuote }; } return(psv); }