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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            IEnumerable <string> metrics = GetSwapMetrics();

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

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

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

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

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

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

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

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

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

            // success
            response.Status = RequestStatusEnum.Completed;
        }
예제 #2
0
        public void ProcessRequest(RequestBase baseRequest, HandlerResponse response)
        {
            if (baseRequest == null)
            {
                throw new ArgumentNullException(nameof(baseRequest));
            }
            if (!(baseRequest is PortfolioValuationRequest request))
            {
                throw new InvalidCastException(
                          $"{typeof(RequestBase).Name} is not a {typeof(PortfolioValuationRequest).Name}");
            }
            DateTime lastStatusPublishedAt = DateTime.Now;
            // common properties
            var    nameSpace         = request.NameSpace;
            string reportingCurrency = request.ReportingCurrency;
            string baseParty         = request.BaseParty;
            string market            = request.MarketName;
            // resolve portfolio valuation request
            var identifier = (new PortfolioSpecification(request.PortfolioId, request.NameSpace)).NetworkKey;
            var portfolio  =
                Context.Cache.LoadObject <PortfolioSpecification>(identifier);

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

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

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

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

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

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

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

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

            for (int i = 0; i < irScenarioNames.Length; i++)
            {
                string irScenario = irScenarioNames[i];
                for (int j = 0; j < fxScenarioNames.Length; j++)
                {
                    string fxScenario = fxScenarioNames[j];
                    // check for workflow cancellation (user abort, server shutdown etc.)
                    if (Cancelled)
                    {
                        throw new OperationCanceledException(CancelReason);
                    }
                    // initialise the pricer with the IR/FX scenario curve maps
                    var portfolioPricer = new PortfolioPricer(irScenarioCurveMap[i], fxScenarioCurveMap[j]);
                    // now price the portfolio
                    portfolioPricer.PriceAndPublish(
                        Context.Logger, Context.Cache,
                        resolvedCurveCache,
                        reportNameCache, response,
                        tradeItemInfos.Keys, request,
                        irScenario, fxScenario, reportingCurrency,
                        baseParty, metrics, false);
                    var dtNow = DateTime.Now;
                    if ((dtNow - lastStatusPublishedAt) <= TimeSpan.FromSeconds(5))
                    {
                        continue;
                    }
                    lastStatusPublishedAt = dtNow;
                    response.Status       = RequestStatusEnum.InProgress;
                    Context.Cache.SaveObject(response);
                } // foreach ir scenario
            }     // foreach fx scenario
            // success
            response.Status = RequestStatusEnum.Completed;
        }