Files
zszq-trs/YLErpDAL/BLL/MarginCalculation/XiangCaiMarginCalculation.cs
T
2024-05-09 14:06:26 +08:00

546 lines
27 KiB
C#

using System.Collections;
using YLErp.BLL.Calculation;
using YLErp.DBModels;
using YLErp.Enums;
using YLErp.Helpers;
using YLErp.Model.Enum;
using YLErp.Modules.DataProviderModule;
using YLErp.QdpModule;
namespace YLErp.BLL.MarginCalculation
{
/// <summary>
/// 湘财证券
/// </summary>
public class XiangCaiMarginCalculation : MarginCalculationBase
{
public static readonly XiangCaiMarginCalculation Instance;
static XiangCaiMarginCalculation()
{
Instance = new XiangCaiMarginCalculation();
}
private XiangCaiMarginCalculation()
{
}
public override List<trade_span> RunMarginCalculation(RunMarginCalculationReq req)
{
if (req?.tradeList == null || !req.tradeList.Any())
{
return new List<trade_span>();
}
var calcTradeList = req.tradeList.ToList();
var resultMap = new Dictionary<int, trade_span>();
var helper = new RunMarginCalculationHelper(req, _underlyingDataProvider);
helper.SetFieldsByTradeType();
var mpProvider = helper.GetMarginParamProvider();
var upLimitPrices = new ManualPriceProvider();
var upLimitPricesTwoThirds = new ManualPriceProvider();
var upLimitPricesOneThird = new ManualPriceProvider();
var downLimitPrices = new ManualPriceProvider();
var downLimitPricesTwoThirds = new ManualPriceProvider();
var downLimitPricesOneThird = new ManualPriceProvider();
var normalLimitPrices = new ManualPriceProvider();
//根据涨跌幅限制以及当日结算价计算涨停价以及跌停价
foreach (var t in req.tradeList)
{
if (upLimitPrices.Contains(t.UnderlyingCode))
{
continue;
}
if (!mpProvider.TryGetUpdownLimit(t.UnderlyingCode, out var updownLimit, out var isFixed))
{
updownLimit = 0.05;
}
var price = 0.0;
switch (req.CalcMarginType)
{
case CalcMarginTypeEnum.InitialMargin:
price = t.SpotPrice ?? 0;//期初价
break;
case CalcMarginTypeEnum.None:
var lastDate = QdpCalendarHelper.GetNonHolidayDefore(req.settleDate.AddDays(-1));
price = new EodPriceProvider(lastDate, true).GetPrice(t.UnderlyingCode, SettlementTypeEnum.SettlePrice);//昨日结算价
break;
case CalcMarginTypeEnum.EodMargin:
price = req.PriceProvider.GetPrice(t.UnderlyingCode);//结算价
break;
}
//var eodpriceProvider = new YLErp.Modules.DataProviderModule.EodPriceProvider(req.settleDate);
//var spotPrice = eodpriceProvider.GetPrice(t.UnderlyingCode, SettlementTypeEnum.ClosePrice);//收盘价
if (isFixed)
{
upLimitPrices.SetPrice(t.UnderlyingCode, price + updownLimit);
upLimitPricesTwoThirds.SetPrice(t.UnderlyingCode, price + (updownLimit * 2.0 / 3.0));
upLimitPricesOneThird.SetPrice(t.UnderlyingCode, price + (updownLimit / 3.0));
downLimitPrices.SetPrice(t.UnderlyingCode, price - updownLimit);
downLimitPricesTwoThirds.SetPrice(t.UnderlyingCode, price - (updownLimit * 2.0 / 3.0));
downLimitPricesOneThird.SetPrice(t.UnderlyingCode, price - (updownLimit / 3.0));
}
else
{
upLimitPrices.SetPrice(t.UnderlyingCode, price * (price > 0 ? (1 + updownLimit) : (1 - updownLimit)));
upLimitPricesTwoThirds.SetPrice(t.UnderlyingCode, price * (price > 0 ? (1 + (updownLimit * 2.0 / 3.0)) : (1 - (updownLimit * 2.0 / 3.0))));
upLimitPricesOneThird.SetPrice(t.UnderlyingCode, price * (price > 0 ? (1 + (updownLimit / 3.0)) : (1 - (updownLimit / 3.0))));
downLimitPrices.SetPrice(t.UnderlyingCode, price * (price > 0 ? (1 - updownLimit) : (1 + updownLimit)));
downLimitPricesTwoThirds.SetPrice(t.UnderlyingCode, price * (price > 0 ? (1 - (updownLimit * 2.0 / 3.0)) : (1 + (updownLimit * 2.0 / 3.0))));
downLimitPricesOneThird.SetPrice(t.UnderlyingCode, price * (price > 0 ? (1 - (updownLimit / 3.0)) : (1 + (updownLimit / 3.0))));
}
//Normal
normalLimitPrices.SetPrice(t.UnderlyingCode, price);
}
var prices = new[] {
("up", upLimitPrices),("upTwoThirds", upLimitPricesTwoThirds),("upOneThird", upLimitPricesOneThird),
("down", downLimitPrices),("downTwoThirds", downLimitPricesTwoThirds),("downOneThird", downLimitPricesOneThird),
("normal", normalLimitPrices)
};
foreach (var price in prices)
{
var key = $"{price.Item1}_0";
var tradeRiskResult = CalculatorHelper.CalculateRisksForTrades(
valueDate: req.settleDate,
tradeList: calcTradeList,
calcScenario: req.GetCalcScenario(),
priceProvider: price.Item2,
pricingRequest: QdpPricingRequest.PV_ONLY,
volType: "开仓",
isUseTradeVol: PS.Config.IsTradeVol,
preciseTimeMode: req.CalcMarginType != CalcMarginTypeEnum.EodMargin);
if (tradeRiskResult.Results == null || !tradeRiskResult.Results.Any())
{
continue;
}
foreach (var item in tradeRiskResult.Results)
{
var prepayment = item.Trade.StockEqvNotional * (item.Trade.trade_snowball?.PrepaymentRatio ?? 0) * (item.Trade.BuySell == "卖出" ? -1 : 1);
var pv = double.IsNaN(item.ValueResult.Pv) ? 0 : (item.ValueResult.Pv - prepayment);
var client = helper.GetClient(item.Trade);
if (item.Trade.TradeType == "收益互换" && key != "normal_0" && client.MarginOptionType == (int)MarginOptionEnum.双向追保)
{
continue;
}
var ratio = client == null ? 1 : (req.CalcMarginType == CalcMarginTypeEnum.InitialMargin ? client.Ratio1 : client.Ratio) ?? 1;
if (!helper.GetSpecialMargin(item.Trade, pv, out var value))
{
value = pv * ratio;
}
if (req.CalcMarginType != CalcMarginTypeEnum.InitialMargin && item.Trade.TradeType == "收益互换")
{
value = pv * ratio;
}
if (req.CalcMarginType != CalcMarginTypeEnum.InitialMargin && (item.Trade.TradeType == "雪球期权" && item.Trade.trade_snowball.PrepaymentUsed || item.Trade.TradeType == "收益互换"))
{
var initialMargin = item.Trade.TradeType == "雪球期权" ? -prepayment : ((item.Trade.trade_swap.GetMarginRate ?? 0) - (item.Trade.trade_swap.PayMarginRate ?? 0)) * item.Trade.StockEqvNotional;
value = GetComparisonInitialMargin(value, client, item.Trade.TradeType, initialMargin);
}
var contains = resultMap.TryGetValue(item.Trade.id, out var tempTradeSpan);
if (!contains)
{
resultMap[item.Trade.id] = tempTradeSpan = helper.CreateTradeSpan(item.Trade);
}
switch (key)
{
case "up_0":
tempTradeSpan.Spv1 = value; break;
case "upTwoThirds_0":
tempTradeSpan.Spv2 = value; break;
case "upOneThird_0":
tempTradeSpan.Spv3 = value; break;
case "normal_0":
if (item.Trade.TradeType == "收益互换" && client.MarginOptionType == (int)MarginOptionEnum.双向追保)
{
tempTradeSpan.SetAllSpvAndWorst(value);
}
tempTradeSpan.Spv4 = value; break;
case "down_0":
tempTradeSpan.Spv5 = value; break;
case "downTwoThirds_0":
tempTradeSpan.Spv6 = value; break;
case "downOneThird_0":
tempTradeSpan.Spv7 = value; break;
}
if (contains)
{
tempTradeSpan.SetWorstCastClientPayable();
}
resultMap[item.Trade.id].UnderlyingPrice = req.PriceProvider.GetPrice(item.Trade.UnderlyingCode);
}
}
return resultMap.Values.ToList();
}
public override List<trade_span> CalcClientMargin(CalcClientMarginReq req)
{
var clientSpanNews = new List<ClientSpan>();
using var db = new YLContext();
var tradeIds = req.tradeSpans.Select(t => t.TradeId).ToList();
var tradeList = db.trade.AsNoTracking().Where(t => tradeIds.Contains(t.id)).ToList();
var underlyingIdList = tradeList.Select(t => t.UnderlyingId).ToList();
var underlyingList = db.underlying_manager.AsNoTracking().Where(t => underlyingIdList.Contains(t.id)).ToList();
var tradeSpanInfo = (from tradeSpan in req.tradeSpans
join trade in tradeList on tradeSpan.TradeId equals trade.id
join um in underlyingList on trade.UnderlyingId equals um.id
where tradeSpan.ValueDate == req.settleDate
select new { trade, tradeSpan, um.UnderlyingTypeId, UnderlyingId = um.id }).ToList();
var clientGroups = tradeSpanInfo.GroupBy(t => t.trade.ClientId);
foreach (var clientGroup in clientGroups)
{
var varietyGroups = clientGroup.GroupBy(t => t.UnderlyingTypeId).Select(t => new ClientSpan
{
VarietyId = t.Key,
ClientId = clientGroup.Key,
ValueDate = req.settleDate,
Spv1 = t.Sum(g => g.tradeSpan.Spv1) * (-1),
Spv2 = t.Sum(g => g.tradeSpan.Spv2) * (-1),
Spv3 = t.Sum(g => g.tradeSpan.Spv3) * (-1),
Spv4 = t.Sum(g => g.tradeSpan.Spv4) * (-1),
Spv5 = t.Sum(g => g.tradeSpan.Spv5) * (-1),
Spv6 = t.Sum(g => g.tradeSpan.Spv6) * (-1),
Spv7 = t.Sum(g => g.tradeSpan.Spv7) * (-1),
OptId = req.userId,
OptName = req.userName,
OptDate = DateTime.Now,
SpanType = req.SpanType
}).ToList();
foreach (var item in varietyGroups)
{
item.WorstCastClientPayable = Math.Min(Math.Min(Math.Min(Math.Min(Math.Min(Math.Min(item.Spv1 ?? 0, item.Spv2 ?? 0), item.Spv3 ?? 0), item.Spv4 ?? 0), item.Spv5 ?? 0), item.Spv6 ?? 0), item.Spv7 ?? 0);
#region 更新tradeSpan,使得每笔交易的持仓预付金和客户预付金计算用的Spv组保持一致
var tradeIdList = clientGroup.Where(x => x.UnderlyingTypeId == item.VarietyId).Select(x => x.tradeSpan.TradeId);
var tradeSpansUpdate = db.trade_span.Where(x => tradeIdList.Contains(x.TradeId) && x.ClientId == item.ClientId && x.ValueDate == req.settleDate).ToList();
var tradeSpansReq = req.tradeSpans.Where(x => tradeIdList.Contains(x.TradeId) && x.ClientId == item.ClientId && x.ValueDate == req.settleDate).ToList();
//单向追保,客户收取预付金为0
if (!HasTwoSideMargin(item.ClientId) && item.WorstCastClientPayable > 0)
{
item.WorstCastClientPayable = 0;
tradeSpansUpdate.ForEach(x => x.WorstCastClientPayable = 0);
tradeSpansReq.ForEach(x => x.WorstCastClientPayable = 0);
}
else
{
if (item.WorstCastClientPayable == item.Spv1)
{
tradeSpansUpdate.ForEach(x => x.WorstCastClientPayable = x.Spv1);
tradeSpansReq.ForEach(x => x.WorstCastClientPayable = x.Spv1);
}
else if (item.WorstCastClientPayable == item.Spv2)
{
tradeSpansUpdate.ForEach(x => x.WorstCastClientPayable = x.Spv2);
tradeSpansReq.ForEach(x => x.WorstCastClientPayable = x.Spv2);
}
else if (item.WorstCastClientPayable == item.Spv3)
{
tradeSpansUpdate.ForEach(x => x.WorstCastClientPayable = x.Spv3);
tradeSpansReq.ForEach(x => x.WorstCastClientPayable = x.Spv3);
}
else if (item.WorstCastClientPayable == item.Spv4)
{
tradeSpansUpdate.ForEach(x => x.WorstCastClientPayable = x.Spv4);
tradeSpansReq.ForEach(x => x.WorstCastClientPayable = x.Spv4);
}
else if (item.WorstCastClientPayable == item.Spv5)
{
tradeSpansUpdate.ForEach(x => x.WorstCastClientPayable = x.Spv5);
tradeSpansReq.ForEach(x => x.WorstCastClientPayable = x.Spv5);
}
else if (item.WorstCastClientPayable == item.Spv6)
{
tradeSpansUpdate.ForEach(x => x.WorstCastClientPayable = x.Spv6);
tradeSpansReq.ForEach(x => x.WorstCastClientPayable = x.Spv6);
}
else
{
tradeSpansUpdate.ForEach(x => x.WorstCastClientPayable = x.Spv7);
tradeSpansReq.ForEach(x => x.WorstCastClientPayable = x.Spv7);
}
}
#endregion
}
var clientSpan = new ClientSpan
{
ClientId = clientGroup.Key,
ValueDate = req.settleDate,
Spv1 = varietyGroups.Sum(g => g.Spv1),
Spv2 = varietyGroups.Sum(g => g.Spv2),
Spv3 = varietyGroups.Sum(g => g.Spv3),
Spv4 = varietyGroups.Sum(g => g.Spv4),
Spv5 = varietyGroups.Sum(g => g.Spv5),
Spv6 = varietyGroups.Sum(g => g.Spv6),
Spv7 = varietyGroups.Sum(g => g.Spv7),
//负数代表客户应缴预付金,正数代表客户应收预付金
WorstCastClientPayable = varietyGroups.Sum(g => g.WorstCastClientPayable),
OptId = req.userId,
OptName = req.userName,
OptDate = DateTime.Now,
SpanType = req.SpanType,
AdditionalWorstCastClientPayable = req.clientAdditionalMarginDic != null && req.clientAdditionalMarginDic.TryGetValue(clientGroup.Key, out var dd) ? dd : 0
};
clientSpanNews.Add(clientSpan);
}
//span类型为实时删除所有实时计算的交易的预付金信息
if (req.SpanType == ClientSpan.SpanType_RealTime)
{
if (req.RefreshClientIds != null)
{
db.BulkDelete<ClientSpan>($"{nameof(ClientSpan.ClientId)} in @ids", new { ids = req.RefreshClientIds });
}
else
{
db.BulkDelete<ClientSpan>($"{nameof(ClientSpan.SpanType)}=@SpanType", new { req.SpanType });
}
}
else
{
if (req.ClientIds != null)
{
var sql = $"{nameof(ClientSpan.ClientId)} in @ids and {nameof(ClientSpan.ValueDate)}='{req.settleDate.ToSqlDate()}' and {nameof(ClientSpan.SpanType)}={req.SpanType} and {nameof(ClientSpan.ModifiedFlag)}=0";
db.BulkDelete<ClientSpan>(sql, new { ids = req.ClientIds });
}
else
{
var sql = $"{nameof(ClientSpan.ValueDate)}='{req.settleDate.ToSqlDate()}' and {nameof(ClientSpan.SpanType)}={req.SpanType} and {nameof(ClientSpan.ModifiedFlag)}=0";
db.BulkDelete<ClientSpan>(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.SaveChanges();
return req.tradeSpans;
}
/// <summary>
/// 根据追保方向判断和初始预付金比较逻辑
/// </summary>
/// <returns></returns>
private double GetComparisonInitialMargin(double value, InnerClient client, string tradeType, double initialMargin)
{
if (client.MarginOptionType == (int)MarginOptionEnum.双向追保 || tradeType == "雪球期权")
{
if (initialMargin >= 0)
{
value = Math.Max(initialMargin, value);
}
else
{
value = Math.Min(initialMargin, value);
}
}
else if (client.MarginOptionType == (int)MarginOptionEnum.单向追保)
{
if (initialMargin >= 0)
{
value = Math.Max(initialMargin, Math.Max(value, 0));
}
else
{
value = Math.Min(initialMargin, Math.Min(value, 0));
}
}
return value;
}
public static double TradeMargin(RunMarginCalculationReq req, trade t)
{
var _underlyingDataProvider = new UnderlyingDataProvider();
var helper = new RunMarginCalculationHelper(req, _underlyingDataProvider);
helper.SetFieldsByTradeType();
var mpProvider = helper.GetMarginParamProvider();
var upLimitPrices = new ManualPriceProvider();
var upLimitPricesTwoThirds = new ManualPriceProvider();
var upLimitPricesOneThird = new ManualPriceProvider();
var downLimitPrices = new ManualPriceProvider();
var downLimitPricesTwoThirds = new ManualPriceProvider();
var downLimitPricesOneThird = new ManualPriceProvider();
var normalLimitPrices = new ManualPriceProvider();
//根据涨跌幅限制以及当日结算价计算涨停价以及跌停价
//if (upLimitPrices.Contains(t.UnderlyingCode))
//{
// continue;
//}
if (!mpProvider.TryGetUpdownLimit(t.UnderlyingCode, out var updownLimit, out var isFixed))
{
updownLimit = 0.05;
}
var price = 0.0;
switch (req.CalcMarginType)
{
case CalcMarginTypeEnum.InitialMargin:
price = t.SpotPrice ?? 0;//期初价
break;
case CalcMarginTypeEnum.None:
var lastDate = QdpCalendarHelper.GetNonHolidayDefore(req.settleDate.AddDays(-1));
price = new EodPriceProvider(lastDate, true).GetPrice(t.UnderlyingCode, SettlementTypeEnum.SettlePrice);//昨日结算价
break;
case CalcMarginTypeEnum.EodMargin:
price = req.PriceProvider.GetPrice(t.UnderlyingCode);//结算价
break;
}
if (isFixed)
{
upLimitPrices.SetPrice(t.UnderlyingCode, price + updownLimit);
upLimitPricesTwoThirds.SetPrice(t.UnderlyingCode, price + (updownLimit * 2.0 / 3.0));
upLimitPricesOneThird.SetPrice(t.UnderlyingCode, price + (updownLimit / 3.0));
downLimitPrices.SetPrice(t.UnderlyingCode, price - updownLimit);
downLimitPricesTwoThirds.SetPrice(t.UnderlyingCode, price - (updownLimit * 2.0 / 3.0));
downLimitPricesOneThird.SetPrice(t.UnderlyingCode, price - (updownLimit / 3.0));
}
else
{
upLimitPrices.SetPrice(t.UnderlyingCode, price * (price > 0 ? (1 + updownLimit) : (1 - updownLimit)));
upLimitPricesTwoThirds.SetPrice(t.UnderlyingCode, price * (price > 0 ? (1 + (updownLimit * 2.0 / 3.0)) : (1 - (updownLimit * 2.0 / 3.0))));
upLimitPricesOneThird.SetPrice(t.UnderlyingCode, price * (price > 0 ? (1 + (updownLimit / 3.0)) : (1 - (updownLimit / 3.0))));
downLimitPrices.SetPrice(t.UnderlyingCode, price * (price > 0 ? (1 - updownLimit) : (1 + updownLimit)));
downLimitPricesTwoThirds.SetPrice(t.UnderlyingCode, price * (price > 0 ? (1 - (updownLimit * 2.0 / 3.0)) : (1 + (updownLimit * 2.0 / 3.0))));
downLimitPricesOneThird.SetPrice(t.UnderlyingCode, price * (price > 0 ? (1 - (updownLimit / 3.0)) : (1 + (updownLimit / 3.0))));
}
//Normal
normalLimitPrices.SetPrice(t.UnderlyingCode, price);
var prices = new[] {
("up", upLimitPrices),("upTwoThirds", upLimitPricesTwoThirds),("upOneThird", upLimitPricesOneThird),
("down", downLimitPrices),("downTwoThirds", downLimitPricesTwoThirds),("downOneThird", downLimitPricesOneThird),
("normal", normalLimitPrices)
};
var values = new ArrayList();
foreach (var p in prices)
{
var key = $"{p.Item1}_0";
var tradeRiskResult = CalculatorHelper.CalculateRisksForTrades(
valueDate: req.settleDate,
tradeList: new[] { t },
calcScenario: req.GetCalcScenario(),
priceProvider: p.Item2,
pricingRequest: QdpPricingRequest.PV_ONLY,
volType: "开仓",
isUseTradeVol: PS.Config.IsTradeVol,
preciseTimeMode: req.CalcMarginType != CalcMarginTypeEnum.EodMargin);
if (tradeRiskResult.Results == null || !tradeRiskResult.Results.Any())
{
continue;
}
foreach (var item in tradeRiskResult.Results)
{
var pv = double.IsNaN(item.ValueResult.Pv) ? 0 : (item.ValueResult.Pv - item.Trade.StockEqvNotional * (item.Trade.trade_snowball?.PrepaymentRatio ?? 0) * (item.Trade.BuySell == "卖出" ? -1 : 1));
double value = 0;
if (item.Trade.TradeType == "收益互换")
{
var client = helper.GetClient(item.Trade);
var ratio = client == null ? 1 : (req.CalcMarginType == CalcMarginTypeEnum.InitialMargin ? client.Ratio1 : client.Ratio) ?? 1;
value = pv * ratio;
}
else
{
if (!helper.GetSpecialMargin(item.Trade, pv, out value))
{
var client = helper.GetClient(item.Trade);
var ratio = client == null ? 1 : (req.CalcMarginType == CalcMarginTypeEnum.InitialMargin ? client.Ratio1 : client.Ratio) ?? 1;
value = pv * ratio;
}
}
values.Add(value);
}
}
return (double)values.ToArray().Max();
}
private List<trade_span> RunTradeSpanMarginCalculation(RunMarginCalculationReq req)
{
//结果集
var resultMap = new List<trade_span>();
var subTradeList = req.tradeList.Where(x => x.ParentTradeId != 0 && x.IsGroup == 0).GroupBy(x => x.ParentTradeId);
if (subTradeList.Count() > 0)
{
foreach (var item in subTradeList)
{
var spans = RunMarginCalculation(req.Clone(item.ToList()));
var spv1 = spans.Sum(O => O.Spv1 ?? 0);
var spv2 = spans.Sum(O => O.Spv2 ?? 0);
var spv3 = spans.Sum(O => O.Spv3 ?? 0);
var spv4 = spans.Sum(O => O.Spv4 ?? 0);
var spv5 = spans.Sum(O => O.Spv5 ?? 0);
var spv6 = spans.Sum(O => O.Spv6 ?? 0);
var spv7 = spans.Sum(O => O.Spv7 ?? 0);
var spvArr = new[] { spv1, spv2, spv3, spv4, spv5, spv6, spv7 };
var maxSpv = spvArr.Max();
var index = Array.IndexOf(spvArr, maxSpv);
spans.ForEach(x => x.WorstCastClientPayable = new[] { x.Spv1, x.Spv2, x.Spv3, x.Spv4, x.Spv5, x.Spv6, x.Spv7 }[index]);
resultMap.AddRange(spans);
}
}
var singleTradeList = req.tradeList.Where(O => O.ParentTradeId == 0).ToList();
if (singleTradeList.Count > 0)
{
resultMap.AddRange(RunMarginCalculation(req.Clone(singleTradeList)));
}
return resultMap;
}
public override double GetTradeMargin(GetTradeMarginReq req)
{
using var db = new YLContext();
if (req.trade.TradeType == "结构化交易")
{
req.trade.SubTrades = db.trade.Where(x => x.ParentTradeId == req.realTradeId).ToList();
}
var marginReq = req.GetRunMarginCalculationReq();
if (req.trade.IsGroup == 1)
{
marginReq.tradeList = db.trade.Where(x => x.ParentTradeId == req.realTradeId).ToList();
}
var tradeMargin = RunMarginCalculation(marginReq);
if (null != tradeMargin)
{
var margin = req.trade.IsGroup == 1 ? tradeMargin.Sum(x => x.WorstCastClientPayable ?? 0) : (tradeMargin.FirstOrDefault()?.WorstCastClientPayable ?? 0);
return margin;
}
return 0.0;
}
}
}