using YLErp.BLL.Calculation; using YLErp.Enums; using YLErp.Model.Enum; using YLErp.Modules.CalculationModule; using YLErp.QdpModule; namespace YLErp.BLL.MarginCalculation { public class HongYeMarginCalculation : MarginCalculationBase { //定义一个静态变量来保存类的实例(单例模式) public static readonly HongYeMarginCalculation Instance; static HongYeMarginCalculation() { Instance = new HongYeMarginCalculation(); } //定义私有构造函数,使外界不能创建该类实例 private HongYeMarginCalculation() { } public override List RunMarginCalculation(RunMarginCalculationReq req) { if (req.tradeList == null || !req.tradeList.Any()) { return new List(); } return CalcMargin(req).ToList(); } private IEnumerable CalcMargin(RunMarginCalculationReq req) { var resultMap = new Dictionary(); var helper = new RunMarginCalculationHelper(req, _underlyingDataProvider); //为了算客户角度的一个预付金数值 helper.ReverseTradeSide(); helper.SetFieldsByTradeType(); var calcReq = helper.GetCalculateRisksForTradesReq(req.PriceProvider, null, null, QdpPricingRequest.BASIC_PRICING); switch (req.CalcMarginType) { case CalcMarginTypeEnum.InitialMargin: calcReq.volType = "开仓"; calcReq.isUseTradeVol = false; break; case CalcMarginTypeEnum.None: case CalcMarginTypeEnum.EodMargin: default: calcReq.volType = "交易"; calcReq.isUseTradeVol = true; break; } var tradeRiskResult = CalculatorHelper.CalculateRisksForTrades(calcReq); foreach (var item in tradeRiskResult.Results) { resultMap[item.Trade.id] = generateTradeSpan( (resultMap.ContainsKey(item.Trade.id) ? resultMap[item.Trade.id] : null), item, helper, req); } var structureIds = new List(); var tDict = (from r in tradeRiskResult.Results join ts in resultMap on r.Trade.id equals ts.Key where r.Trade.TradeType == "结构化交易" || r.Trade.ParentTradeId != 0 group new { r, ts } by r.Trade.ParentTradeId into rGroup select rGroup).ToDictionary(K => K.First().r.Trade, V => V.ToList()); if (tDict.Count > 0) { foreach (var structureItem in tDict) { var client = GetClientInfo(structureItem.Key.ClientId); var direction = structureItem.Value.Select(O => O.r.Trade.BuySell).ToHashSet(); double value = 0; var index = 0; if ((structureItem.Key.StructureType == "牛市价差" || structureItem.Key.StructureType == "熊市价差") && structureItem.Value.Count >= 2) { if (client != null && (MarginOptionEnum)client.MarginOptionType == MarginOptionEnum.单向追保) { var buyLeg = structureItem.Value.Where(O => O.r.Trade.BuySell == "买入").FirstOrDefault(); var buyMargin = (buyLeg?.ts.Value.WorstCastClientPayable) ?? 0; foreach (var item in structureItem.Value) { setTradeSpanValue(item.ts.Value, 0); } if (structureItem.Value.Sum(O => O.r.ValueResult.Pv) > 0) { var strikes = structureItem.Value.Select(O => ((O.r.Trade.IsMoneynessOption == "是" ? (O.r.Trade.SpotPrice * O.r.Trade.Strike) : O.r.Trade.Strike) ?? 0)).ToArray(); value = Math.Abs((strikes[0] - strikes[1]) * structureItem.Key.Notional); setTradeSpanValue(buyLeg.ts.Value, Math.Min(value, buyMargin)); } } else if (client != null && (MarginOptionEnum)client.MarginOptionType == MarginOptionEnum.对手方单向追保) { var sellLeg = structureItem.Value.Where(O => O.r.Trade.BuySell == "卖出").FirstOrDefault(); var sellMargin = (sellLeg?.ts.Value.WorstCastClientPayable) ?? 0; foreach (var item in structureItem.Value) { setTradeSpanValue(item.ts.Value, 0); } if (structureItem.Value.Sum(O => O.r.ValueResult.Pv) < 0) { var strikes = structureItem.Value.Select(O => ((O.r.Trade.IsMoneynessOption == "是" ? (O.r.Trade.SpotPrice * O.r.Trade.Strike) : O.r.Trade.Strike) ?? 0)).ToArray(); value = Math.Abs((strikes[0] - strikes[1]) * structureItem.Key.Notional); setTradeSpanValue(sellLeg.ts.Value, Math.Min(value, sellMargin)); } } } else if (structureItem.Key.StructureType.Contains("跨式") && structureItem.Value.Count == 2) { var minLeg = structureItem.Value[1]; if (Math.Abs(structureItem.Value[0].r.ValueResult.Delta) < Math.Abs(structureItem.Value[1].r.ValueResult.Delta)) { minLeg = structureItem.Value[0]; } setTradeSpanValue(minLeg.ts.Value, minLeg.r.ValueResult.Pv); } else { if (client != null) { switch ((MarginOptionEnum)client.MarginOptionType) { case MarginOptionEnum.对手方单向追保: if (direction.Count == 1) { value = double.MaxValue; //最小值 for (var i = 0; i < structureItem.Value.Count; i++) { if (value > structureItem.Value[i].ts.Value.WorstCastClientPayable) { index = i; value = structureItem.Value[i].ts.Value.WorstCastClientPayable ?? 0; } setTradeSpanValue(structureItem.Value[i].ts.Value, 0); structureIds.Add(structureItem.Value[i].ts.Key); } setTradeSpanValue(structureItem.Value[index].ts.Value, value); } break; case MarginOptionEnum.单向追保: case MarginOptionEnum.双向追保: default: if (direction.Count == 1) { value = double.MinValue; //最大值 for (var i = 0; i < structureItem.Value.Count; i++) { if (value < structureItem.Value[i].ts.Value.WorstCastClientPayable) { index = i; value = structureItem.Value[i].ts.Value.WorstCastClientPayable ?? 0; } setTradeSpanValue(structureItem.Value[i].ts.Value, 0); structureIds.Add(structureItem.Value[i].ts.Key); } setTradeSpanValue(structureItem.Value[index].ts.Value, value); } break; } } else { if (direction.Count == 1) { value = double.MinValue; //最大值 for (var i = 0; i < structureItem.Value.Count; i++) { if (value < structureItem.Value[i].ts.Value.WorstCastClientPayable) { index = i; value = structureItem.Value[i].ts.Value.WorstCastClientPayable ?? 0; } setTradeSpanValue(structureItem.Value[i].ts.Value, 0); structureIds.Add(structureItem.Value[i].ts.Key); } setTradeSpanValue(structureItem.Value[index].ts.Value, value); } } } } } var tList = (from r in tradeRiskResult.Results join ts in resultMap on r.Trade.id equals ts.Key where !structureIds.Contains(r.Trade.id) select new { r, ts }).ToList(); if (tList.Count > 0) { foreach (var item in tList) { double value = 0; var client = GetClientInfo(item.r.Trade.ClientId); if (client != null) { switch ((MarginOptionEnum)client.MarginOptionType) { case MarginOptionEnum.单向追保: value = item.ts.Value.WorstCastClientPayable ?? 0; value = Math.Max(value, 0); break; case MarginOptionEnum.对手方单向追保: value = item.ts.Value.WorstCastClientPayable ?? 0; value = Math.Max(value, 0); break; case MarginOptionEnum.双向追保: default: value = item.ts.Value.WorstCastClientPayable ?? 0; break; } } else { value = item.ts.Value.WorstCastClientPayable ?? 0; } item.ts.Value.Spv1 = value; item.ts.Value.Spv2 = value; item.ts.Value.Spv3 = value; item.ts.Value.Spv4 = value; item.ts.Value.SetWorstCastClientPayable(); } } return resultMap.Values.ToList(); } private trade_span generateTradeSpan(trade_span trade_Span, TradeRiskResultRecord record, RunMarginCalculationHelper helper, RunMarginCalculationReq req) { if (trade_Span == null) { trade_Span = helper.CreateTradeSpan(record.Trade); } var client = GetClientInfo(record.Trade.ClientId); double value; if (req.CalcMarginType == CalcMarginTypeEnum.InitialMargin && record.Trade.TradeType == "收益互换") { var pnl = record.Trade.trade_swap.GetTradePrice.GetValueOrDefault() - record.Trade.trade_swap.PayTradePrice.GetValueOrDefault() - record.ValueResult.Pv; helper.GetSpecialMargin(record.Trade, pnl, out value); } else if (record.Trade.TradeType == "远期" || record.Trade.TradeType == "收益互换") { var marginRate = helper.GetMarginParamProvider().GetMarginRate(record.Trade.UnderlyingCode) ?? 0; var price = req.PriceProvider.GetPrice(record.Trade.UnderlyingCode); value = price * marginRate * record.Trade.Notional + Math.Max((record.ValueResult.Pv - record.Trade.TradePrice ?? 0), 0); } else { var marginRate = helper.GetMarginParamProvider().GetMarginRate(record.Trade.UnderlyingCode) ?? 0; var price = req.PriceProvider.GetPrice(record.Trade.UnderlyingCode); var delta = Math.Abs(record.ValueResult.Delta); if (record.ValueResult.Pv < 0) { delta = -delta; } if (HasTwoSideMargin(record.Trade.ClientId)) { value = record.ValueResult.Pv + delta * marginRate * price; } else if (!helper.GetSpecialMargin(record.Trade, 0, out value)) { double ratio; switch (req.CalcMarginType) { case CalcMarginTypeEnum.InitialMargin: ratio = client?.Ratio1 ?? 1; break; case CalcMarginTypeEnum.None: case CalcMarginTypeEnum.EodMargin: default: ratio = client?.Ratio ?? 1; break; } value = record.ValueResult.Pv + ratio * delta * marginRate * price; } } trade_Span.Spv1 = value; trade_Span.Spv2 = value; trade_Span.Spv3 = value; trade_Span.Spv4 = value; trade_Span.SetWorstCastClientPayable(); return trade_Span; } private void setTradeSpanValue(trade_span obj, double value) { obj.Spv1 = value; obj.Spv2 = value; obj.Spv3 = value; obj.Spv4 = value; obj.SetWorstCastClientPayable(); } public override double GetTradeMargin(GetTradeMarginReq req) { var trade = req.trade; if (trade.TradeType == "结构化交易" && (trade.SubTrades == null || trade.SubTrades.Count() == 0)) { using (var db = new YLContext()) { trade.SubTrades = db.trade.Where(x => x.ParentTradeId == trade.id).ToList(); } } var tradeMargin = RunMarginCalculation(req.GetRunMarginCalculationReq()); if (null != tradeMargin) { return tradeMargin.FirstOrDefault()?.WorstCastClientPayable ?? 0.0; } return 0.0; } } }