using YLErp.BLL.Calculation; using YLErp.Enums; using YLErp.Helpers; using YLErp.Model.Enum; using YLErp.Modules; using YLErp.Modules.ClientModule; using YLErp.Modules.DataProviderModule; using YLErp.Modules.UnderlyingModule; using YLErp.QdpModule; namespace YLErp.BLL.MarginCalculation { /// /// 广发商贸 /// public class GFSMMarginCalculation : MarginCalculationBase { /// /// 定义一个静态变量保存类的实例 /// public static readonly GFSMMarginCalculation Instance; static GFSMMarginCalculation() { Instance = new GFSMMarginCalculation(); } /// /// 定义私有结构函数,使外界不能创建该类实例 /// public GFSMMarginCalculation() { } /// /// 单交易维持预付金(初始预付金) /// /// /// public override List RunMarginCalculation(RunMarginCalculationReq req) { var result = new List(); var clientIds = req.tradeList.Select(s => s.ClientId); var marginFactorDict = new ClientMarginTemplateService(OptUserInfo.SystemUser).GetMarginFactorDict(req.settleDate, clientIds, true); clientIds = marginFactorDict.Where(m => m.Value.SpanRateType == DetailSpanRateTypeEnum.Span涨跌幅度2) .Select(m => m.Key).ToList(); //} //客户id和标的代码 var span2Dict = req.tradeList .Where(O => clientIds.Contains(O.ClientId)) .GroupBy(O => O.ClientId) .ToDictionary( K => K.Key, V => V.Select(O => O.UnderlyingCode).ToList()); //初始预付金在维持预付金的基础上*1.05 if (req.CalcMarginType == Enums.CalcMarginTypeEnum.InitialMargin) { result = calcInitialMargin(req, span2Dict, marginFactorDict); } else { result = calcPositionMargin(req, span2Dict); } return result; } /// /// 初始预付金 /// /// /// private List calcInitialMargin(RunMarginCalculationReq req, Dictionary> span2Dict, Dictionary marginFactorDict) { var resultMap = new Dictionary(); var service = new UnderlyingSpanTwoService(OptUserInfo.SystemUser); var preValueDate = QdpCalendarHelper.GetNonHolidayDefore(req.settleDate.AddDays(-1)); //结算价格为当前日期前一个 req.PriceProvider = new EodPriceProvider(preValueDate).GetPriceProvider(SettlementTypeEnum.SettlePrice); //收盘价为前一天的收盘价 var closePriceProvider = new EodPriceProvider(preValueDate).GetPriceProvider(SettlementTypeEnum.ClosePrice); var _helper = new RunMarginCalculationHelper(req, _underlyingDataProvider); //获取涨跌停价格字典 _helper.GetUpDownLimitPrices(out var upLimitPrices, out var downLimitPrices); //获取波动率价格字典 _helper.GetUpDownVolRateDic(out var tradeVolRateDicUp, out var tradeVolRateDicDown); LogFactory.GetLogger().Info($"广发商贸计算初始波动率为涨:{tradeVolRateDicUp} 跌{tradeVolRateDicDown} "); //TradeId var clientGroup = req.tradeList.GroupBy(O => new { O.ClientId, O.UnderlyingCode }).ToDictionary(K => K.Key, V => V.ToList()); //客户分组 foreach (var item in clientGroup) { var span2rateDict = new Dictionary(); if (span2Dict.ContainsKey(item.Key.ClientId)) { var undelyingCodes = span2Dict[item.Key.ClientId];//标的代码 span2rateDict = service.GetLatestList(undelyingCodes, req.settleDate).ToDictionary(K => K.UnderlyingCode, V => V.SpanRate ?? 0); } var prices = new Dictionary>(); var pricesY = new Dictionary>(); var umCodeList = item.Value.Select(O => O.UnderlyingCode).ToHashSet(); foreach (var code in umCodeList) { double upPrice; var downPrice = downLimitPrices.GetPrice(code); if (span2rateDict.ContainsKey(code)) { var price = req.PriceProvider.GetPrice(code); var obj = _helper.GetUpDownLimitByRate(price, span2rateDict[code]); upPrice = obj.UpLimitPrice; downPrice = obj.DownLimitPrice; } else { upPrice = upLimitPrices.GetPrice(code); downPrice = downLimitPrices.GetPrice(code); } var interval = (upPrice - downPrice) / 6; LogFactory.GetLogger().Info($"广发商贸计算初始涨跌价格:{upPrice} {downPrice} 涨跌取均值所以a为涨-跌/6:{interval}"); var closePricePrice = closePriceProvider.GetPrice(code);//收盘价 var settlePrice = req.PriceProvider.GetPrice(code);//结算价 LogFactory.GetLogger().Info($"广发商贸计算初始结算价格S(i,n){settlePrice}和收盘价 {closePricePrice}都为前一个交易日的"); var forword = item.Value.Where(s => s.TradeType == "远期" || s.TradeType == "收益互换"); var tradeRiskResult_forword = CalculatorHelper.CalculateRisksForTrades( valueDate: req.settleDate, calcScenario: req.GetCalcScenario(), tradeList: forword, priceProvider: req.PriceProvider, pricingRequest: QdpPricingRequest.BASIC_PRICING, addVolRateDic: null, volType: req.volType, isUseTradeVol: PS.Config.IsTradeVol, preciseTimeMode: req.CalcMarginType != CalcMarginTypeEnum.EodMargin, isAddVolPercent: true); foreach (var tResult in tradeRiskResult_forword.Results) { var t = tResult.Trade; closePricePrice = t.SpotPrice ?? 0;//#OTC-8565 广发-远期预付金 P(T)修改为期初价格 var initialMargin = marginFactorDict.TryGetValue(t.ClientId, out var spanConfig) ? spanConfig.InitialMarginFactor : 1.05; //根据交易编号输出spv if (!resultMap.TryGetValue(t.id, out var tradeSpan)) { resultMap[t.id] = tradeSpan = _helper.CreateTradeSpan(t); } if (t.TradeType == "收益互换") { tradeSpan.SetAllSpvAndWorst(0); continue; } if (t.OptionType == "看跌") { tradeSpan.Spv1 = -t.TradeAmount * (settlePrice + (interval * 3) - closePricePrice); LogFactory.GetLogger().Info($"广发商贸远期计算初始预付金情景一和八为:空头方向*持仓数量*[(𝑆(𝑖,𝑛)×(1+𝑎)-P(T)]={tradeSpan.Spv1}={-t.TradeAmount}* ({settlePrice} + {interval}*3)-{closePricePrice})"); tradeSpan.Spv2 = -t.TradeAmount * (settlePrice + (interval * 2) - closePricePrice); LogFactory.GetLogger().Info($"广发商贸远期计算初始预付金情景二和九为:空头方向*持仓数量*[(𝑆(𝑖,𝑛)×(1+2/3𝑎)-P(T)]={tradeSpan.Spv2}={-t.TradeAmount}* ({settlePrice} + {interval}* 2-{closePricePrice})"); tradeSpan.Spv3 = -t.TradeAmount * (settlePrice + (interval * 1) - closePricePrice); LogFactory.GetLogger().Info($"广发商贸远期计算初始预付金情景三和十为:空头方向*持仓数量*" + $"[(𝑆(𝑖,𝑛)×(1+1/3𝑎)-P(T)]={tradeSpan.Spv3}={-t.TradeAmount}* ({settlePrice} + {interval * 1}-{closePricePrice})"); tradeSpan.Spv4 = -t.TradeAmount * (settlePrice - closePricePrice); LogFactory.GetLogger().Info($"广发商贸远期计算初始预付金情景四和十一为:空头方向*持仓数量*[(𝑆(𝑖,𝑛)×(𝑎)-P(T)]={tradeSpan.Spv4}={-t.TradeAmount}* ({settlePrice}-{closePricePrice})"); tradeSpan.Spv5 = -t.TradeAmount * (settlePrice - (interval * 1) - closePricePrice); LogFactory.GetLogger().Info($"广发商贸远期计算初始预付金情景五和十二为:空头方向*持仓数量*[(𝑆(𝑖,𝑛)×(1-1/3𝑎)-P(T)]={tradeSpan.Spv5}={-t.TradeAmount}* ({settlePrice}-{interval}*1-{closePricePrice})"); tradeSpan.Spv6 = -t.TradeAmount * (settlePrice - (interval * 2) - closePricePrice); LogFactory.GetLogger().Info($"广发商贸远期计算初始预付金情景六和十三为:空头方向*持仓数量*[(𝑆(𝑖,𝑛)×(1-2/3𝑎)-P(T)]={tradeSpan.Spv6}={-t.TradeAmount}* ({settlePrice} - {interval}*2-{closePricePrice})"); tradeSpan.Spv7 = -t.TradeAmount * (settlePrice - (interval * 3) - closePricePrice); LogFactory.GetLogger().Info($"广发商贸远期计算初始预付金情景七和十四为:空头方向*持仓数量*[(𝑆(𝑖,𝑛)×(1-𝑎)-P(T)]={tradeSpan.Spv7}={-t.TradeAmount}* ({settlePrice} - {interval}*3)-{closePricePrice})"); tradeSpan.Spv8 = tradeSpan.Spv1; tradeSpan.Spv9 = tradeSpan.Spv2; tradeSpan.Spv10 = tradeSpan.Spv3; tradeSpan.Spv11 = tradeSpan.Spv4; tradeSpan.Spv12 = tradeSpan.Spv5; tradeSpan.Spv13 = tradeSpan.Spv6; tradeSpan.Spv14 = tradeSpan.Spv7; tradeSpan.SetWorstCastClientPayable(); tradeSpan.Spv15 = tResult.ValueResult.Pv;//用收盘价算的持仓市值 var variety = DataCacheProvider.GetVariety(tResult.Trade.UnderlyingCode); var rate = variety.Margin ?? 1; tradeSpan.Delta = t.Notional * closePricePrice * rate;//detalCash LogFactory.GetLogger().Info($"广发商贸远期计算初始预付金持仓市值用收盘价为:{tradeSpan.Spv15}"); } else { tradeSpan.Spv1 = t.TradeAmount * (settlePrice - (interval * 3) - closePricePrice); LogFactory.GetLogger().Info($"广发商贸远期计算初始预付金情景一和八为:多头方向*持仓数量*[(𝑆(𝑖,𝑛)×(1+𝑎)-P(T)]={tradeSpan.Spv1}={t.TradeAmount}* ({settlePrice}- {interval}*3) )-{closePricePrice}"); tradeSpan.Spv2 = t.TradeAmount * (settlePrice - (interval * 2) - closePricePrice); LogFactory.GetLogger().Info($"广发商贸远期计算初始预付金情景二和九为:多头方向*持仓数量*[(𝑆(𝑖,𝑛)×(1+2/3𝑎)-P(T)]={tradeSpan.Spv2}={t.TradeAmount}* ({settlePrice}- {interval} * 2-{closePricePrice})"); tradeSpan.Spv3 = t.TradeAmount * (settlePrice - (interval * 1) - closePricePrice); LogFactory.GetLogger().Info($"广发商贸远期计算初始预付金情景三和十为:多头方向*持仓数量*" + $"[(𝑆(𝑖,𝑛)×(1+1/3𝑎)-P(T)]={tradeSpan.Spv3}={t.TradeAmount}* ({settlePrice}- {interval * 1}-{closePricePrice})"); tradeSpan.Spv4 = t.TradeAmount * (settlePrice - closePricePrice); LogFactory.GetLogger().Info($"广发商贸远期计算初始预付金情景四和十一为:多头方向*持仓数量*[(𝑆(𝑖,𝑛)×(𝑎)-P(T)]={tradeSpan.Spv4}={t.TradeAmount}* ({settlePrice} -{closePricePrice})"); tradeSpan.Spv5 = t.TradeAmount * (settlePrice + (interval * 1) - closePricePrice); LogFactory.GetLogger().Info($"广发商贸远期计算初始预付金情景五和十二为:多头方向*持仓数量*[(𝑆(𝑖,𝑛)×(1-1/3𝑎)-P(T)]={tradeSpan.Spv5}={t.TradeAmount}* ({settlePrice}-{interval}*1-{closePricePrice})"); tradeSpan.Spv6 = t.TradeAmount * (settlePrice + (interval * 2) - closePricePrice); LogFactory.GetLogger().Info($"广发商贸远期计算初始预付金情景六和十三为:多头方向*持仓数量*[(𝑆(𝑖,𝑛)×(1-2/3𝑎)-P(T)]={tradeSpan.Spv6}={t.TradeAmount}* ({settlePrice} - {interval}*2-{closePricePrice})"); tradeSpan.Spv7 = t.TradeAmount * (settlePrice + (interval * 3) - closePricePrice); LogFactory.GetLogger().Info($"广发商贸远期计算初始预付金情景七和十四为:多头方向*持仓数量*[(𝑆(𝑖,𝑛)×(1-𝑎)-P(T)]={tradeSpan.Spv7}={t.TradeAmount}* ({settlePrice} - {interval}*3)-{closePricePrice})"); tradeSpan.Spv8 = tradeSpan.Spv1; tradeSpan.Spv9 = tradeSpan.Spv2; tradeSpan.Spv10 = tradeSpan.Spv3; tradeSpan.Spv11 = tradeSpan.Spv4; tradeSpan.Spv12 = tradeSpan.Spv5; tradeSpan.Spv13 = tradeSpan.Spv6; tradeSpan.Spv14 = tradeSpan.Spv7; tradeSpan.SetWorstCastClientPayable(); tradeSpan.Spv15 = tResult.ValueResult.Pv;//用收盘价算的持仓市值 var variety = DataCacheProvider.GetVariety(tResult.Trade.UnderlyingCode); var rate = variety.Margin ?? 1; tradeSpan.Delta = t.Notional * closePricePrice * rate;//detalCash LogFactory.GetLogger().Info($"广发商贸远期计算初始预付金持仓市值用收盘价为:{tradeSpan.Spv15}"); } tradeSpan.SetWorstCastClientPayable(); var Margin1 = tradeSpan.WorstCastClientPayable ?? 0; LogFactory.GetLogger().Info($"广发商贸远期初始预付金Mdetal为十四情景种最大的:{Margin1}"); var Margin2 = (tradeSpan.Delta ?? 0) * t.MarginRate; LogFactory.GetLogger().Info($"广发商贸远期初始预付金Mdeta2为N个合约是否则为0:{Margin2}"); //标的持仓时值(用收盘价计算) var presentValue = tradeSpan.Spv15 ?? 0; LogFactory.GetLogger().Info($"广发商贸远期初始预付金标的持仓时值presentValue用收盘价计算{presentValue}"); //判断最终应该缴纳初始预付金 if (Margin1 > 0 && presentValue > 0) { tradeSpan.WorstCastClientPayable = Math.Max(Margin1, Margin2) * initialMargin; LogFactory.GetLogger().Info($"最终预付金在Margin1和Margin2中取最大存入数据库:{tradeSpan.WorstCastClientPayable} = Math.Max({Margin1}, {Margin2})* {initialMargin};"); } if (Margin1 > 0 && presentValue < 0) { tradeSpan.WorstCastClientPayable = Margin1 * initialMargin; LogFactory.GetLogger().Info($"判断应该缴纳初始预付金如Margin1>0&&presentValue<0))则为{tradeSpan.WorstCastClientPayable}={Margin1}结果*{initialMargin}"); } else { tradeSpan.WorstCastClientPayable = 0; } } var tradeTypes = new List() { "远期", "收益互换" }; var option = item.Value.Where(o => !tradeTypes.Contains(o.TradeType)).ToList(); if (option.Any()) { prices[1] = new Dictionary(); prices[2] = new Dictionary(); prices[3] = new Dictionary(); prices[4] = new Dictionary(); prices[5] = new Dictionary(); prices[6] = new Dictionary(); prices[7] = new Dictionary(); prices[8] = new Dictionary(); prices[9] = new Dictionary(); prices[10] = new Dictionary(); prices[11] = new Dictionary(); prices[12] = new Dictionary(); prices[13] = new Dictionary(); prices[14] = new Dictionary(); prices[15] = new Dictionary(); //该detal存入PV15用收盘价来计算 prices[1][code] = settlePrice + (interval * 3); LogFactory.GetLogger().Info($"广发商贸期权计算初始预付金情景一为:𝑆(𝑖,𝑛)×(1+𝑎):{prices[1][code]}={settlePrice}+({interval}*3)"); prices[2][code] = settlePrice + (interval * 2); LogFactory.GetLogger().Info($"广发商贸期权计算初始预付金情景二为:𝑆(𝑖,𝑛)×( 1+2/3𝑎):{prices[2][code]}={settlePrice}+({interval}*2)"); prices[3][code] = settlePrice + (interval * 1); LogFactory.GetLogger().Info($"广发商贸期权计算初始预付金情景三为:𝑆(𝑖,𝑛)×(1+1/3𝑎):{prices[3][code]}={settlePrice}+({interval}*1)"); prices[4][code] = settlePrice; LogFactory.GetLogger().Info($"广发商贸期权计算初始预付金情景四为:𝑆(𝑖,𝑛):{prices[4][code]}={settlePrice}"); prices[5][code] = settlePrice - (interval * 1); LogFactory.GetLogger().Info($"广发商贸期权计算初始预付金情景五为:𝑆(𝑖,𝑛)×(1–1/3 𝑎):{prices[5][code]}={settlePrice}-{interval}*1"); prices[6][code] = settlePrice - (interval * 2); LogFactory.GetLogger().Info($"广发商贸期权计算初始预付金情景六为:𝑆(𝑖,𝑛)×(1–2/3𝑎):{prices[6][code]}={settlePrice}-{interval}*2"); prices[7][code] = settlePrice - (interval * 3); LogFactory.GetLogger().Info($"广发商贸期权计算初始预付金情景七为:𝑆(𝑖,𝑛)×(1−𝑎):{prices[7][code]}={settlePrice}-{interval}*3"); prices[8][code] = settlePrice + (interval * 3); LogFactory.GetLogger().Info($"广发商贸期权计算初始预付金情景八为:𝑆(𝑖,𝑛)×(1+𝑎):{prices[8][code]}={settlePrice}+({interval}*3)"); prices[9][code] = settlePrice + (interval * 2); LogFactory.GetLogger().Info($"广发商贸期权计算初始预付金情景九为:𝑆(𝑖,𝑛)×( 1+2/3𝑎):{prices[9][code]}={settlePrice}+{interval}*2)"); prices[10][code] = settlePrice + (interval * 1); LogFactory.GetLogger().Info($"广发商贸期权计算初始预付金情景十为:𝑆(𝑖,𝑛)×(1+1/3𝑎):{prices[10][code]}={settlePrice}+{interval}*1)"); prices[11][code] = settlePrice; LogFactory.GetLogger().Info($"广发商贸期权计算初始预付金情景十一为:𝑆(𝑖,𝑛):{prices[11][code]}={settlePrice}"); prices[12][code] = settlePrice - (interval * 1); LogFactory.GetLogger().Info($"广发商贸期权计算初始预付金情景十二为:𝑆(𝑖,𝑛)×(1–1/3 𝑎):{prices[12][code]}={settlePrice}-{interval}*1"); prices[13][code] = settlePrice - (interval * 2); LogFactory.GetLogger().Info($"广发商贸期权计算初始预付金情景十三为:𝑆(𝑖,𝑛)×(1–2/3𝑎):{prices[13][code]}={settlePrice}-{interval}*2"); prices[14][code] = settlePrice - (interval * 3); LogFactory.GetLogger().Info($"广发商贸期权计算初始预付金情景十四为:𝑆(𝑖,𝑛)×(1−𝑎):{prices[14][code]}={settlePrice}-{interval}*3"); prices[15][code] = closePriceProvider.GetPrice(code); LogFactory.GetLogger().Info($"广发商贸期权计算初始预付金情景十五收盘价算detal:{prices[15][code] = closePriceProvider.GetPrice(code)}"); foreach (var p in prices) { Dictionary tradeVolRateDic = null; if (p.Key <= 7) { tradeVolRateDic = tradeVolRateDicUp; } else if (p.Key <= 14) { tradeVolRateDic = tradeVolRateDicDown; } //var overrideVol = new Dictionary(); //foreach (var t in option) //{ // overrideVol[t.id] = t.Vol ?? 0.3; //} var tradeRiskResult = CalculatorHelper.CalculateRisksForTrades( valueDate: req.settleDate, calcScenario: req.GetCalcScenario(), tradeList: option, priceProvider: new ManualPriceProvider(p.Value), pricingRequest: QdpPricingRequest.BASIC_PRICING, addVolRateDic: tradeVolRateDic, volType: valuedateBLL.SystemDate.EodSettleVolMode ?? req.volType, //overrideVolsForTrade: overrideVol, isUseTradeVol: PS.Config.IsTradeVol, preciseTimeMode: req.CalcMarginType != CalcMarginTypeEnum.EodMargin, isAddVolPercent: true); foreach (var risk in tradeRiskResult.Results) { var initialMargin = marginFactorDict.TryGetValue(risk.Trade.ClientId, out var spanConfig) ? spanConfig.InitialMarginFactor : 1.05; //根据交易编号输出spv if (!resultMap.TryGetValue(risk.Trade.id, out var tradeSpan)) { resultMap[risk.Trade.id] = tradeSpan = _helper.CreateTradeSpan(risk.Trade); } LogFactory.GetLogger().Info($"期权初始预付金场景{p.Key},pv:{risk.ValueResult.Pv},price:{risk.ValueResult.SpotPrice},vol:{risk.ValueResult.Vol},t:{risk.ValueResult.PricingT},delta:{risk.ValueResult.Delta}"); switch (p.Key) { case 1: tradeSpan.Spv1 = risk.ValueResult.Pv; break; case 2: tradeSpan.Spv2 = risk.ValueResult.Pv; break; case 3: tradeSpan.Spv3 = risk.ValueResult.Pv; break; case 4: tradeSpan.Spv4 = risk.ValueResult.Pv; break; case 5: tradeSpan.Spv5 = risk.ValueResult.Pv; break; case 6: tradeSpan.Spv6 = risk.ValueResult.Pv; break; case 7: tradeSpan.Spv7 = risk.ValueResult.Pv; break; case 8: tradeSpan.Spv8 = risk.ValueResult.Pv; break; case 9: tradeSpan.Spv9 = risk.ValueResult.Pv; break; case 10: tradeSpan.Spv10 = risk.ValueResult.Pv; break; case 11: tradeSpan.Spv11 = risk.ValueResult.Pv; break; case 12: tradeSpan.Spv12 = risk.ValueResult.Pv; break; case 13: tradeSpan.Spv13 = risk.ValueResult.Pv; break; case 14: tradeSpan.Spv14 = risk.ValueResult.Pv; break; //pv用收盘价来结算detal case 15: tradeSpan.Spv15 = risk.ValueResult.Pv;//持仓市值 var variety = DataCacheProvider.GetVariety(risk.Trade.UnderlyingCode); var rate = variety?.Margin ?? 1; tradeSpan.Delta = risk.ValueResult.DeltaCash * rate;//magrin2 break; default: break; } tradeSpan.SetWorstCastClientPayable(); var Margin1 = tradeSpan.WorstCastClientPayable ?? 0; LogFactory.GetLogger().Info($"广发商贸初始预付金Mdetal为十四情景种最大的:{Margin1}"); var Margin2 = tradeSpan.Delta ?? 0; LogFactory.GetLogger().Info($"广发商贸初始预付金Mdeta2为N个合约是:{Margin2}"); //标的持仓时值(用收盘价计算) var presentValue = tradeSpan.Spv15 ?? 0; LogFactory.GetLogger().Info($"广发商贸初始预付金标的持仓时值presentValue用收盘价计算{presentValue}"); //判断最终应该缴纳初始预付金 if (Margin1 > 0 && presentValue > 0) { tradeSpan.WorstCastClientPayable = Math.Max(Margin1, Margin2) * initialMargin; LogFactory.GetLogger().Info($"判断初始预付金Margin1 > 0 && presentValue > 0在Margin1和Margin2中取最大存入数据库:{tradeSpan.WorstCastClientPayable} = Math.Max({Margin1}, {Margin2})*{initialMargin};"); } else if (Margin1 > 0 && presentValue < 0) { tradeSpan.WorstCastClientPayable = Margin1 * initialMargin; LogFactory.GetLogger().Info($"判断初始预付金如果(Margin1>0&&presentValue<0)则为Margin1:{tradeSpan.WorstCastClientPayable}={Margin1}*{initialMargin}"); } else { tradeSpan.WorstCastClientPayable = 0; } } } } } } return resultMap.Values.ToList(); } /// /// 维持预付金 /// /// /// private List calcPositionMargin(RunMarginCalculationReq req, Dictionary> span2Dict) { var resultMap = new Dictionary(); var service = new UnderlyingSpanTwoService(OptUserInfo.SystemUser); //结算价格为 req.PriceProvider = new EodPriceProvider(req.settleDate).GetPriceProvider(SettlementTypeEnum.SettlePrice); //收盘 var closePriceProvider = new EodPriceProvider(req.settleDate).GetPriceProvider(SettlementTypeEnum.ClosePrice); var _helper = new RunMarginCalculationHelper(req, _underlyingDataProvider); //获取涨跌停价格字典 _helper.GetUpDownLimitPrices(out var upLimitPrices, out var downLimitPrices); //获取波动率价格字典 _helper.GetUpDownVolRateDic(out var tradeVolRateDicUp, out var tradeVolRateDicDown); //TradeId var clientGroup = req.tradeList.GroupBy(O => new { O.ClientId, O.UnderlyingCode }).ToDictionary(K => K.Key, V => V.ToList()); //客户分组 foreach (var item in clientGroup) { var span2rateDict = new Dictionary(); if (span2Dict.ContainsKey(item.Key.ClientId)) { var undelyingCodes = span2Dict[item.Key.ClientId];//标的代码 span2rateDict = service.GetLatestList(undelyingCodes, req.settleDate).ToDictionary(K => K.UnderlyingCode, V => V.SpanRate ?? 0); } var prices = new Dictionary>(); var pricesY = new Dictionary>(); var umCodeList = item.Value.Select(O => O.UnderlyingCode).ToHashSet(); foreach (var code in umCodeList) { double upPrice; var downPrice = downLimitPrices.GetPrice(code); if (span2rateDict.ContainsKey(code)) { var settlePrices = req.PriceProvider.GetPrice(code); var obj = _helper.GetUpDownLimitByRate(settlePrices, span2rateDict[code]); upPrice = obj.UpLimitPrice; downPrice = obj.DownLimitPrice; } else { upPrice = upLimitPrices.GetPrice(code); downPrice = downLimitPrices.GetPrice(code); } var interval = (upPrice - downPrice) / 6; LogFactory.GetLogger().Info($"广发商贸计算维持涨跌价格:{upPrice} {downPrice} 涨跌取均值所以a为:{interval}"); var closePrice = closePriceProvider.GetPrice(code);//收盘价 var settlePrice = req.PriceProvider.GetPrice(code);//结算价 LogFactory.GetLogger().Info($"广发商贸计算维持结算价格S(i,n)为:{settlePrice} "); var forword = item.Value.Where(s => s.TradeType == "远期" || s.TradeType == "收益互换");//分组后的交易 var tradeRiskResult_forword = CalculatorHelper.CalculateRisksForTrades( valueDate: req.settleDate, calcScenario: req.GetCalcScenario(), tradeList: forword, priceProvider: closePriceProvider, pricingRequest: QdpPricingRequest.BASIC_PRICING, addVolRateDic: null, volType: req.volType, isUseTradeVol: PS.Config.IsTradeVol, preciseTimeMode: req.CalcMarginType != CalcMarginTypeEnum.EodMargin, isAddVolPercent: true); foreach (var tResult in tradeRiskResult_forword.Results) { var t = tResult.Trade; closePrice = t.SpotPrice ?? 0;//#OTC-8565 广发-远期预付金 P(T)修改为期初价格 //根据交易编号输出spv if (!resultMap.TryGetValue(t.id, out var tradeSpan)) { resultMap[t.id] = tradeSpan = _helper.CreateTradeSpan(t); } if (t.TradeType == "收益互换") { tradeSpan.SetAllSpvAndWorst(0); continue; } if (t.OptionType == "看跌") { tradeSpan.Spv1 = -t.TradeAmount * (settlePrice + (interval * 3) - closePrice); LogFactory.GetLogger().Info($"广发商贸远期计算维持预付金情景一和八为:空头方向*持仓数量*[(𝑆(𝑖,𝑛)×(1+𝑎)-P(T)]={tradeSpan.Spv1}={-t.TradeAmount}* ({settlePrice} + {interval}*3)-{closePrice})"); tradeSpan.Spv2 = -t.TradeAmount * (settlePrice + (interval * 2) - closePrice); LogFactory.GetLogger().Info($"广发商贸远期计算维持预付金情景二和九为:空头方向*持仓数量*[(𝑆(𝑖,𝑛)×(1+2/3𝑎)-P(T)]={tradeSpan.Spv2}={-t.TradeAmount}* ({settlePrice} + {interval} * 2-{closePrice})"); tradeSpan.Spv3 = -t.TradeAmount * (settlePrice + (interval * 1) - closePrice); LogFactory.GetLogger().Info($"广发商贸远期计算维持预付金情景三和十为:空头方向*持仓数量*" + $"[(𝑆(𝑖,𝑛)×(1+1/3𝑎)-P(T)]={tradeSpan.Spv3}={-t.TradeAmount}* ({settlePrice} + {interval * 1}-{closePrice})"); tradeSpan.Spv4 = -t.TradeAmount * (settlePrice - closePrice); LogFactory.GetLogger().Info($"广发商贸远期计算维持预付金情景四和十一为:空头方向*持仓数量*[(𝑆(𝑖,𝑛)×(𝑎)-P(T)]={tradeSpan.Spv4}={-t.TradeAmount}* ({settlePrice}-{closePrice})"); tradeSpan.Spv5 = -t.TradeAmount * (settlePrice - (interval * 1) - closePrice); LogFactory.GetLogger().Info($"广发商贸远期计算维持预付金情景五和十二为:空头方向*持仓数量*[(𝑆(𝑖,𝑛)×(1-1/3𝑎)-P(T)]={tradeSpan.Spv5}={-t.TradeAmount}* ({settlePrice}-{interval}*1-{closePrice})"); tradeSpan.Spv6 = -t.TradeAmount * (settlePrice - (interval * 2) - closePrice); LogFactory.GetLogger().Info($"广发商贸远期计算维持预付金情景六和十三为:空头方向*持仓数量*[(𝑆(𝑖,𝑛)×(1-2/3𝑎)-P(T)]={tradeSpan.Spv6}={-t.TradeAmount}* ({settlePrice} - {interval}*2-{closePrice})"); tradeSpan.Spv7 = -t.TradeAmount * (settlePrice - (interval * 3) - closePrice); LogFactory.GetLogger().Info($"广发商贸远期计算维持预付金情景七和十四为:空头方向*持仓数量*[(𝑆(𝑖,𝑛)×(1-𝑎)-P(T)]={tradeSpan.Spv7}={-t.TradeAmount}* ({settlePrice} - {interval}*3)-{closePrice})"); tradeSpan.Spv8 = tradeSpan.Spv1; tradeSpan.Spv9 = tradeSpan.Spv2; tradeSpan.Spv10 = tradeSpan.Spv3; tradeSpan.Spv11 = tradeSpan.Spv4; tradeSpan.Spv12 = tradeSpan.Spv5; tradeSpan.Spv13 = tradeSpan.Spv6; tradeSpan.Spv14 = tradeSpan.Spv7; tradeSpan.SetWorstCastClientPayable(); tradeSpan.Spv15 = tResult.ValueResult.Pv;//用收盘价算的持仓市值 var variety = DataCacheProvider.GetVariety(tResult.Trade.UnderlyingCode); var rate = variety.Margin ?? 1; tradeSpan.Delta = t.Notional * closePrice * rate;//detalCash LogFactory.GetLogger().Info($"广发商贸远期计算维持预付金持仓市值用收盘价为:{tradeSpan.Spv15}"); } else { tradeSpan.Spv1 = t.TradeAmount * (settlePrice - (interval * 3) - closePrice); LogFactory.GetLogger().Info($"广发商贸远期计算维持预付金情景一和八为:多头方向*持仓数量*[(𝑆(𝑖,𝑛)×(1+𝑎)-P(T)]={tradeSpan.Spv1}={t.TradeAmount}* ({settlePrice}- {interval}*3) -{closePrice})"); tradeSpan.Spv2 = t.TradeAmount * (settlePrice - (interval * 2) - closePrice); LogFactory.GetLogger().Info($"广发商贸远期计算维持预付金情景二和九为:多头方向*持仓数量*[(𝑆(𝑖,𝑛)×(1+2/3𝑎)-P(T)]={tradeSpan.Spv2}={t.TradeAmount}* ({settlePrice}- {interval}* 2-{closePrice})"); tradeSpan.Spv3 = t.TradeAmount * (settlePrice - (interval * 1) - closePrice); LogFactory.GetLogger().Info($"广发商贸远期计算维持预付金情景三和十为:多头方向*持仓数量*" + $"[(𝑆(𝑖,𝑛)×(1+1/3𝑎)-P(T)]={tradeSpan.Spv3}={t.TradeAmount}* ({settlePrice}- {interval * 1}-{closePrice})"); tradeSpan.Spv4 = t.TradeAmount * (settlePrice - closePrice); LogFactory.GetLogger().Info($"广发商贸远期计算维持预付金情景四和十一为:多头方向*持仓数量*[(𝑆(𝑖,𝑛)×(𝑎)-P(T)]={tradeSpan.Spv4}={t.TradeAmount}* ({settlePrice}-{closePrice})"); tradeSpan.Spv5 = t.TradeAmount * (settlePrice + (interval * 1) - closePrice); LogFactory.GetLogger().Info($"广发商贸远期计算维持预付金情景五和十二为:多头方向*持仓数量*[(𝑆(𝑖,𝑛)×(1-1/3𝑎)-P(T)]={tradeSpan.Spv5}={t.TradeAmount}* ({settlePrice}-{interval}*1)-{closePrice}"); tradeSpan.Spv6 = t.TradeAmount * (settlePrice + (interval * 2) - closePrice); LogFactory.GetLogger().Info($"广发商贸远期计算维持预付金情景六和十三为:多头方向*持仓数量*[(𝑆(𝑖,𝑛)×(1-2/3𝑎)-P(T)]={tradeSpan.Spv6}={t.TradeAmount}* ({settlePrice} - {interval}*2)-{closePrice}"); tradeSpan.Spv7 = t.TradeAmount * (settlePrice + (interval * 3) - closePrice); LogFactory.GetLogger().Info($"广发商贸远期计算维持预付金情景七和十四为:多头方向*持仓数量*[(𝑆(𝑖,𝑛)×(1-𝑎)-P(T)]={tradeSpan.Spv7}={t.TradeAmount}* ({settlePrice} - {interval}*3)-{closePrice})"); tradeSpan.Spv8 = tradeSpan.Spv1; tradeSpan.Spv9 = tradeSpan.Spv2; tradeSpan.Spv10 = tradeSpan.Spv3; tradeSpan.Spv11 = tradeSpan.Spv4; tradeSpan.Spv12 = tradeSpan.Spv5; tradeSpan.Spv13 = tradeSpan.Spv6; tradeSpan.Spv14 = tradeSpan.Spv7; tradeSpan.SetWorstCastClientPayable(); tradeSpan.Spv15 = tResult.ValueResult.Pv;//用收盘价算的持仓市值 var variety = DataCacheProvider.GetVariety(tResult.Trade.UnderlyingCode); var rate = variety.Margin ?? 1; tradeSpan.Delta = t.Notional * closePrice * rate;//detalCash LogFactory.GetLogger().Info($"广发商贸远期计算维持预付金持仓市值用收盘价为:{tradeSpan.Spv15}"); } } var tradeTypes = new List() { "远期", "收益互换" }; var option = item.Value.Where(o => !tradeTypes.Contains(o.TradeType)).ToList(); if (option.Any()) { prices[1] = new Dictionary(); prices[2] = new Dictionary(); prices[3] = new Dictionary(); prices[4] = new Dictionary(); prices[5] = new Dictionary(); prices[6] = new Dictionary(); prices[7] = new Dictionary(); prices[8] = new Dictionary(); prices[9] = new Dictionary(); prices[10] = new Dictionary(); prices[11] = new Dictionary(); prices[12] = new Dictionary(); prices[13] = new Dictionary(); prices[14] = new Dictionary(); prices[15] = new Dictionary(); //该detal存入PV15用收盘价来计算 prices[1][code] = settlePrice + (interval * 3); LogFactory.GetLogger().Info($"广发商贸期权计算维持预付金情景一为:𝑆(𝑖,𝑛)×(1+𝑎):{prices[1][code]}={settlePrice}+({interval}*3)"); prices[2][code] = settlePrice + (interval * 2); LogFactory.GetLogger().Info($"广发商贸期权计算维持预付金情景二为:𝑆(𝑖,𝑛)×( 1+2/3𝑎):{prices[2][code]}={settlePrice}+({interval}*2)"); prices[3][code] = settlePrice + (interval * 1); LogFactory.GetLogger().Info($"广发商贸期权计算初始预付金情景三为:𝑆(𝑖,𝑛)×(1+1/3𝑎):{prices[3][code]}={settlePrice}+({interval}*1)"); prices[4][code] = settlePrice; LogFactory.GetLogger().Info($"广发商贸期权计算初始预付金情景四为:𝑆(𝑖,𝑛):{prices[4][code]}={settlePrice}"); prices[5][code] = settlePrice - (interval * 1); LogFactory.GetLogger().Info($"广发商贸期权计算初始预付金情景五为:𝑆(𝑖,𝑛)×(1–1/3 𝑎):{prices[5][code]}={settlePrice}-{interval}*1"); prices[6][code] = settlePrice - (interval * 2); LogFactory.GetLogger().Info($"广发商贸期权计算初始预付金情景六为:𝑆(𝑖,𝑛)×(1–2/3𝑎):{prices[6][code]}={settlePrice}-{interval}*2"); prices[7][code] = settlePrice - (interval * 3); LogFactory.GetLogger().Info($"广发商贸期权计算初始预付金情景七为:𝑆(𝑖,𝑛)×(1−𝑎):{prices[7][code]}={settlePrice}-{interval}*3"); prices[8][code] = settlePrice + (interval * 3); LogFactory.GetLogger().Info($"广发商贸期权计算初始预付金情景八为:𝑆(𝑖,𝑛)×(1+𝑎):{prices[8][code]}={settlePrice}+({interval}*3)"); prices[9][code] = settlePrice + (interval * 2); LogFactory.GetLogger().Info($"广发商贸期权计算初始预付金情景九为:𝑆(𝑖,𝑛)×( 1+2/3𝑎):{prices[9][code]}={settlePrice}+{interval}*2)"); prices[10][code] = settlePrice + (interval * 1); LogFactory.GetLogger().Info($"广发商贸期权计算初始预付金情景十为:𝑆(𝑖,𝑛)×(1+1/3𝑎):{prices[10][code]}={settlePrice}+{interval}*1)"); prices[11][code] = settlePrice; LogFactory.GetLogger().Info($"广发商贸期权计算初始预付金情景十一为:𝑆(𝑖,𝑛):{prices[11][code]}={settlePrice}"); prices[12][code] = settlePrice - (interval * 1); LogFactory.GetLogger().Info($"广发商贸期权计算初始预付金情景十二为:𝑆(𝑖,𝑛)×(1–1/3 𝑎):{prices[12][code]}={settlePrice}-{interval}*1"); prices[13][code] = settlePrice - (interval * 2); LogFactory.GetLogger().Info($"广发商贸期权计算初始预付金情景十三为:𝑆(𝑖,𝑛)×(1–2/3𝑎):{prices[13][code]}={settlePrice}-{interval}*2"); prices[14][code] = settlePrice - (interval * 3); LogFactory.GetLogger().Info($"广发商贸期权计算初始预付金情景十四为:𝑆(𝑖,𝑛)×(1−𝑎):{prices[14][code]}={settlePrice}-{interval}*3"); prices[15][code] = closePriceProvider.GetPrice(code); LogFactory.GetLogger().Info($"广发商贸期权计算维持预付金情景十五收盘价算detal:{prices[15][code] = closePriceProvider.GetPrice(code)}"); foreach (var p in prices) { Dictionary tradeVolRateDic = null; if (p.Key <= 7) { tradeVolRateDic = tradeVolRateDicUp; } else if (p.Key <= 14) { tradeVolRateDic = tradeVolRateDicDown; } var tradeRiskResult = CalculatorHelper.CalculateRisksForTrades( valueDate: req.settleDate, calcScenario: req.GetCalcScenario(), tradeList: option, priceProvider: new ManualPriceProvider(p.Value), pricingRequest: QdpPricingRequest.BASIC_PRICING, addVolRateDic: tradeVolRateDic, volType: req.volType, isUseTradeVol: PS.Config.IsTradeVol, preciseTimeMode: req.CalcMarginType != CalcMarginTypeEnum.EodMargin, isAddVolPercent: true); foreach (var risk in tradeRiskResult.Results) { var pric = p.Value[risk.Trade.UnderlyingCode]; LogFactory.GetLogger().Info($"广发商贸持仓计算维持预付金该交易编号:{risk.Trade.TradeNumber} id:{risk.Trade.id}标的:{code} 交易价格为:{pric}"); //根据交易编号输出spv if (!resultMap.TryGetValue(risk.Trade.id, out var tradeSpan)) { resultMap[risk.Trade.id] = tradeSpan = _helper.CreateTradeSpan(risk.Trade); } switch (p.Key) { case 1: tradeSpan.Spv1 = risk.ValueResult.Pv; LogFactory.GetLogger().Info($"广发商贸计算维持预付金pv1为:{tradeSpan.Spv1}"); break; case 2: tradeSpan.Spv2 = risk.ValueResult.Pv; LogFactory.GetLogger().Info($"广发商贸计算维持预付金pv2为:{tradeSpan.Spv2}"); break; case 3: tradeSpan.Spv3 = risk.ValueResult.Pv; LogFactory.GetLogger().Info($"广发商贸计算维持预付金pv3为:{tradeSpan.Spv3}"); break; case 4: tradeSpan.Spv4 = risk.ValueResult.Pv; LogFactory.GetLogger().Info($"广发商贸计算维持预付金pv4为:{tradeSpan.Spv4}"); break; case 5: tradeSpan.Spv5 = risk.ValueResult.Pv; LogFactory.GetLogger().Info($"广发商贸计算维持预付金pv5为:{tradeSpan.Spv5}"); break; case 6: tradeSpan.Spv6 = risk.ValueResult.Pv; LogFactory.GetLogger().Info($"广发商贸计算维持预付金pv6为:{tradeSpan.Spv6}"); break; case 7: tradeSpan.Spv7 = risk.ValueResult.Pv; LogFactory.GetLogger().Info($"广发商贸计算维持预付金pv7为:{tradeSpan.Spv7}"); break; case 8: tradeSpan.Spv8 = risk.ValueResult.Pv; LogFactory.GetLogger().Info($"广发商贸计算维持预付金pv8为:{tradeSpan.Spv8}"); break; case 9: tradeSpan.Spv9 = risk.ValueResult.Pv; LogFactory.GetLogger().Info($"广发商贸计算维持预付金pv9为:{tradeSpan.Spv9}"); break; case 10: tradeSpan.Spv10 = risk.ValueResult.Pv; LogFactory.GetLogger().Info($"广发商贸计算维持预付金pv10为:{tradeSpan.Spv10}"); break; case 11: tradeSpan.Spv11 = risk.ValueResult.Pv; LogFactory.GetLogger().Info($"广发商贸计算维持预付金pv11为:{tradeSpan.Spv11}"); break; case 12: tradeSpan.Spv12 = risk.ValueResult.Pv; LogFactory.GetLogger().Info($"广发商贸计算维持预付金pv12为:{tradeSpan.Spv12}"); break; case 13: tradeSpan.Spv13 = risk.ValueResult.Pv; LogFactory.GetLogger().Info($"广发商贸计算维持预付金pv13为:{tradeSpan.Spv13}"); break; case 14: tradeSpan.Spv14 = risk.ValueResult.Pv; LogFactory.GetLogger().Info($"广发商贸计算维持预付金pv14为:{tradeSpan.Spv14}"); break; //pv用收盘价来结算detal case 15: tradeSpan.Spv15 = risk.ValueResult.Pv;//持仓市值收盘价 LogFactory.GetLogger().Info($"广发商贸计算维持情景十五用收盘价计算detal因此不参与计算为:{tradeSpan.Spv15}"); var variety = DataCacheProvider.GetVariety(risk.Trade.UnderlyingCode); var rate = variety.Margin ?? 1; tradeSpan.Delta = risk.ValueResult.DeltaCash * rate;//用detal计算 LogFactory.GetLogger().Info($"广发商贸计算维持期权Margin2为:{tradeSpan.Delta}"); break; default: break; } //spv15不参与所以为0 if (p.Key < 15) { tradeSpan.SetWorstCastClientPayable(); } } } } } } return resultMap.Values.ToList(); } /// /// 同客户预付金占用 /// /// /// public override List CalcClientMargin(CalcClientMarginReq req) { var clientSpanNews = new List(); using var db = new YLContext(); if (req.tradeSpans != null && req.tradeSpans.Count > 0) { var tradeIds = req.tradeSpans.Select(t => t.TradeId).ToList(); var tradeList = db.trade.AsNoTracking().Where(t => tradeIds.Contains(t.id)).ToList(); var tradeSpanInfo = (from tradeSpan in req.tradeSpans join trade in tradeList on tradeSpan.TradeId equals trade.id where tradeSpan.ValueDate == req.settleDate select new { trade, tradeSpan }).ToList(); //客户分组 var clientGroups = tradeSpanInfo.GroupBy(t => t.trade.ClientId); var worstCastClientPayable_option = 0d; foreach (var clientGroup in clientGroups) { var client = DataCacheProvider.GetClientDataSource().GetData(clientGroup.Key); //同标的加总 var varietyGroup = clientGroup.GroupBy(d => DataCacheProvider.GetVariety(d.trade.UnderlyingCode ?? "")?.VarietyCode ?? ""); var pmList = new List(); foreach (var item in varietyGroup) { var list = new List() { item.Sum(s=>s.tradeSpan.Spv1??0), item.Sum(s=>s.tradeSpan.Spv2??0), item.Sum(s=>s.tradeSpan.Spv3??0), item.Sum(s=>s.tradeSpan.Spv4??0), item.Sum(s=>s.tradeSpan.Spv5??0), item.Sum(s=>s.tradeSpan.Spv6??0), item.Sum(s=>s.tradeSpan.Spv7??0), item.Sum(s=>s.tradeSpan.Spv8??0), item.Sum(s=>s.tradeSpan.Spv9??0), item.Sum(s=>s.tradeSpan.Spv10??0), item.Sum(s=>s.tradeSpan.Spv11??0), item.Sum(s=>s.tradeSpan.Spv12??0), item.Sum(s=>s.tradeSpan.Spv13??0), item.Sum(s=>s.tradeSpan.Spv14??0), }; //magrin1十四PV总和最大 var pmi = list.Max(s => s); LogFactory.GetLogger().Info($"广发商贸维持预付金14 种情形下客户持仓值为:" + $"pv1{item.Sum(O => O.tradeSpan.Spv1 ?? 0)}" + "pv2:" + $"{item.Sum(O => O.tradeSpan.Spv2 ?? 0)}" + "pv3:" + $"{item.Sum(O => O.tradeSpan.Spv3 ?? 0)}" + "pv4:" + $"{item.Sum(O => O.tradeSpan.Spv4 ?? 0)}" + "pv5:" + $"{item.Sum(O => O.tradeSpan.Spv5 ?? 0)}" + "pv6:" + $"{item.Sum(O => O.tradeSpan.Spv6 ?? 0)}" + "pv7:" + $"{item.Sum(O => O.tradeSpan.Spv7 ?? 0)}" + "pv8:" + $"{item.Sum(O => O.tradeSpan.Spv8 ?? 0)}" + "pv9:" + $"{item.Sum(O => O.tradeSpan.Spv9 ?? 0)}" + "pv10:" + $"{item.Sum(O => O.tradeSpan.Spv10 ?? 0)}" + "pv11:" + $"{item.Sum(O => O.tradeSpan.Spv11 ?? 0)}" + "pv12:" + $"{item.Sum(O => O.tradeSpan.Spv12 ?? 0)}" + "pv13:" + $"{item.Sum(O => O.tradeSpan.Spv13 ?? 0)}" + "pv14:" + $"{item.Sum(O => O.tradeSpan.Spv14 ?? 0)}取最大所以广发商贸该客户magrin1为:{pmi}"); //magrin2为detal var pmMargin2 = item.Sum(s => s.tradeSpan.Delta ?? 0); LogFactory.GetLogger().Info($"广发商贸该客户magrin2为:{pmMargin2}"); //持仓市值为Pv十五加总 var pmt = item.Sum(s => s.tradeSpan.Spv15 ?? 0); LogFactory.GetLogger().Info($"广发商贸该客户持仓市值为:{pmt}"); double endMoney = 0; if (pmi > 0 && pmt > 0) { endMoney = Math.Max(pmi, pmMargin2); LogFactory.GetLogger().Info($"广发商贸该客户14PV持仓市值都大于0两者取最大为:{endMoney}"); } else if (pmi > 0 && pmt < 0) { endMoney = pmi; LogFactory.GetLogger().Info($"广发商贸该客户14PV大于0和持仓市值小于0则取最大pv为:{endMoney}"); } else { endMoney = 0; } LogFactory.GetLogger().Info($"广发商贸该客户相比结果最后为:{endMoney}"); if (endMoney < 0 && client.MarginOptionType == (int)MarginOptionEnum.单向追保) { endMoney = 0; } pmList.Add(endMoney); } //期权汇总 var pml = pmList.Sum(); LogFactory.GetLogger().Info($"广发商贸该客户预付金期权+远期(多标的汇总一起有可能为负所以加总也有可能会变小):{pml}"); //该客户该日期的总交易为:期权+远期 worstCastClientPayable_option = pml; //产品确认暂不分配 //var tradeSpansUpdate = db.trade_span.Where(x => tradeIds.Contains(x.TradeId) && x.ClientId == clientGroup.Key && x.ValueDate == req.settleDate).ToList(); //var tradeSpansReq = req.tradeSpans.Where(x => tradeIds.Contains(x.TradeId) && x.ClientId == clientGroup.Key && x.ValueDate == req.settleDate).ToList(); //var sumDelta = clientGroup.Sum(O => Math.Max(O.tradeSpan.Delta ?? 0, 0)); //tradeSpansUpdate.ForEach(x => x.WorstCastClientPayable = worstCastClientPayable_option * Math.Max(x.Delta ?? 0, 0) / sumDelta); //tradeSpansReq.ForEach(x => x.WorstCastClientPayable = worstCastClientPayable_option * Math.Max(x.Delta ?? 0, 0) / sumDelta); worstCastClientPayable_option *= -1; LogFactory.GetLogger().Info($"广发商贸未分配前期权远期:{worstCastClientPayable_option}"); var clientSpan = new ClientSpan { ClientId = clientGroup.Key,//客户名称 ValueDate = req.settleDate, //负数代表客户应缴预付金,正数代表客户应收预付金 WorstCastClientPayable = worstCastClientPayable_option,//期权和远期同标的加总一起 OptId = req.userId, OptName = req.userName, OptDate = DateTime.Now, SpanType = req.SpanType, AdditionalWorstCastClientPayable = req.clientAdditionalMarginDic != null && req.clientAdditionalMarginDic.TryGetValue(1, out var dd) ? dd : 0 }; if (client.MarginOptionType == (int)MarginOptionEnum.单向追保) { clientSpan.WorstCastClientPayable = Math.Min(clientSpan.WorstCastClientPayable.Value, 0); LogFactory.GetLogger().Info($"广发商贸单向追保时与0相比取最小:{clientSpan.WorstCastClientPayable}"); } else if (client.MarginOptionType == (int)MarginOptionEnum.双向追保) { clientSpan.WorstCastClientPayable = clientSpan.WorstCastClientPayable.Value; LogFactory.GetLogger().Info($"广发商贸双向追保时汇总为(正/负):{clientSpan.WorstCastClientPayable}"); } clientSpanNews.Add(clientSpan); } } //span类型为实时删除所有实时计算的交易的预付金信息 if (req.SpanType == ClientSpan.SpanType_RealTime) { if (req.RefreshClientIds != null) { db.BulkDelete($"{nameof(ClientSpan.ClientId)} in @ids", new { ids = req.RefreshClientIds }); } else { db.BulkDelete($"{nameof(ClientSpan.SpanType)}={req.SpanType}"); } } else { var sql = $"{nameof(ClientSpan.ValueDate)}='{req.settleDate.ToSqlDate()}' and {nameof(ClientSpan.SpanType)}={req.SpanType} and {nameof(ClientSpan.ModifiedFlag)}=0"; db.BulkDelete(sql); var clientSpanOldsWithFlag = db.client_span.Where(t => t.ValueDate == req.settleDate && t.SpanType == req.SpanType && t.ModifiedFlag) .Select(n => new { n.ValueDate, n.ClientId }).ToList(); //筛选出可以修改的clientSpan clientSpanNews = clientSpanNews.Where(c => !clientSpanOldsWithFlag.Any(t => t.ValueDate == c.ValueDate && t.ClientId == c.ClientId)).ToList(); } if (clientSpanNews.Count > 0) { //MySqlBulkExtensions.BulkInsert(db, clientSpanNews); db.client_span.AddRange(clientSpanNews); } db.SaveChanges(); return req.tradeSpans; } /// /// 结构化交易特殊处理 /// /// /// public override double GetTradeMargin(GetTradeMarginReq req) { var trade = req.trade; using (var db = new YLContext()) { if (trade.TradeType == "结构化交易") { trade.SubTrades = db.trade.Where(x => x.ParentTradeId == trade.id).ToList(); } } var tradeMargin = RunMarginCalculation(req.GetRunMarginCalculationReq()); if (null != tradeMargin && tradeMargin.FirstOrDefault() != null) { var margin = tradeMargin.FirstOrDefault().WorstCastClientPayable ?? 0.0; return margin; } return 0.0; } } }