480 lines
26 KiB
C#
480 lines
26 KiB
C#
using Microsoft.EntityFrameworkCore;
|
||
using YLErp.Abstract.DataProviders;
|
||
using YLErp.BLL.Calculation;
|
||
using YLErp.Enums;
|
||
using YLErp.Helpers;
|
||
using YLErp.Model.Enum;
|
||
using YLErp.Modules;
|
||
using YLErp.Modules.MarginModule;
|
||
using YLErp.QdpModule;
|
||
|
||
namespace YLErp.BLL.MarginCalculation
|
||
{
|
||
/// <summary>
|
||
/// 海通预付金计算
|
||
/// </summary>
|
||
public class HaiTongMarginCalculation : MarginCalculationBase
|
||
{
|
||
// 定义一个静态变量来保存类的实例
|
||
public static readonly HaiTongMarginCalculation Instance;
|
||
|
||
static HaiTongMarginCalculation()
|
||
{
|
||
Instance = new HaiTongMarginCalculation();
|
||
}
|
||
|
||
// 定义私有构造函数,使外界不能创建该类实例
|
||
protected HaiTongMarginCalculation()
|
||
{
|
||
|
||
}
|
||
|
||
public override List<trade_span> RunMarginCalculation(RunMarginCalculationReq req)
|
||
{
|
||
var resultMap = new List<trade_span>();
|
||
|
||
var list2 = new List<trade>(req.tradeList.Count);
|
||
|
||
using (var db = new YLContext())
|
||
{
|
||
var tradeIds = req.tradeList.Select(x => x.id);
|
||
var tradeMarginTemplates = db.trade_margin_template.Where(x => tradeIds.Contains(x.TradeId)).ToList();
|
||
foreach (var td in req.tradeList)
|
||
{
|
||
//交易员买客户卖的雪球,就用span算法;交易员卖客户买,就用文档里的公式
|
||
if (td.TradeType == "雪球期权" && td.BuySell == "卖出")
|
||
{
|
||
double value = 0;
|
||
var actualStrike = td.IsMoneynessOptionData ? td.Strike : td.Strike / td.SpotPrice;
|
||
var SpreadStrike = td.IsMoneynessOptionData ? td.trade_snowball.SpreadStrikeAtMaturity : td.trade_snowball.SpreadStrikeAtMaturity / td.SpotPrice;
|
||
//雪球期权 - 保底雪球(仅收初始预付金,后续不追保):逐笔交易持仓预付金=簿记预付金模板选为“雪球保底固定比例”;
|
||
//雪球期权 - 非保底雪球(不收初始预付金,后续线性追保,跌多少追多少):逐笔交易持仓预付金 = max(1 - 标的每日收盘价 / 期初价格,0)*名义本金;
|
||
//雪球期权 - 其他(系统定价类型):逐笔交易持仓预付金 = Span涨跌停行情下的雪球持仓市值 * 1.1。
|
||
if (td.trade_snowball.KIPayoffType == KIPayoffTypeEnum.ToCallSpreadOption)
|
||
{
|
||
value = ((td.StockEqvNotional) * (SpreadStrike - actualStrike)) ?? 0;
|
||
}
|
||
else if (td.trade_snowball.KIPayoffType == KIPayoffTypeEnum.ToPutSpreadOption)
|
||
{
|
||
value = ((td.StockEqvNotional) * (actualStrike - SpreadStrike)) ?? 0;
|
||
}
|
||
else
|
||
{
|
||
if (req.CalcMarginType != CalcMarginTypeEnum.InitialMargin)
|
||
{
|
||
var closePrice = req.PriceProvider.GetPrice(td.UnderlyingCode);
|
||
value = Math.Max(1 - closePrice / (double)td.SpotPrice, 0) * td.StockEqvNotional + td.InitialMargin ?? 0;
|
||
}
|
||
}
|
||
var helper = new RunMarginCalculationHelper(req, _underlyingDataProvider);
|
||
var client = helper.GetClient(td.ClientId);
|
||
var ts = new trade_span()
|
||
{
|
||
TradeId = td.id,
|
||
ClientId = td.ClientId,
|
||
ValueDate = req.settleDate,
|
||
UnderlyingId = td.UnderlyingId,
|
||
UnderlyingCode = td.UnderlyingCode,
|
||
OptId = req.userId,
|
||
OptName = req.userName,
|
||
OptDate = DateTime.Now,
|
||
IsSingleMargin = true,
|
||
Comment = "雪球特殊算法",
|
||
};
|
||
if (client != null)
|
||
{
|
||
if (client.MarginOptionType == (int)MarginOptionEnum.对手方单向追保 || client.MarginOptionType == (int)MarginOptionEnum.其他)
|
||
{
|
||
value = 0;
|
||
}
|
||
else
|
||
{
|
||
value = Math.Max((double)value, 0);
|
||
}
|
||
}
|
||
ts.SetAllSpvAndWorst((double)value);
|
||
resultMap.Add(ts);
|
||
}
|
||
else
|
||
{
|
||
list2.Add(td);
|
||
}
|
||
}
|
||
resultMap.AddRange(marginCalculation(req.Clone(list2)));
|
||
return resultMap;
|
||
}
|
||
}
|
||
private List<trade_span> marginCalculation(RunMarginCalculationReq req)
|
||
{
|
||
//结果集
|
||
var resultMap = new Dictionary<int, trade_span>();
|
||
|
||
var helper = new RunMarginCalculationHelper(req, _underlyingDataProvider);
|
||
var mpProvider = helper.GetMarginParamProvider(MarginParamTypeEnum.MarginRate | MarginParamTypeEnum.UpDownLimit);
|
||
|
||
//为了算客户角度的一个预付金数值
|
||
helper.ReverseTradeSide();
|
||
|
||
helper.SetFieldsByTradeType();
|
||
|
||
helper.GetUpDownLimitPrices(out var upLimitPrices, out var downLimitPrices);
|
||
helper.GetUpDownVolRateDic(out var tradeVolRateDicUp, out var tradeVolRateDicDown);
|
||
|
||
var prices = new (string, IPriceProvider)[] { ("up", upLimitPrices), ("down", downLimitPrices), ("normal", req.PriceProvider) };
|
||
|
||
var volRates = new (int, Dictionary<int, double>)[] {
|
||
(0, null),
|
||
(1, tradeVolRateDicUp),
|
||
(2, tradeVolRateDicDown)
|
||
};
|
||
|
||
foreach (var price in prices)
|
||
{
|
||
foreach (var itemDic in volRates)
|
||
{
|
||
var key = $"{price.Item1}_{itemDic.Item1}";
|
||
|
||
var tradeRiskResult = CalculatorHelper.CalculateRisksForTrades(
|
||
valueDate: req.settleDate,
|
||
tradeList: req.tradeList,
|
||
calcScenario: req.GetCalcScenario(),
|
||
priceProvider: price.Item2,
|
||
pricingRequest: QdpPricingRequest.PV_ONLY,
|
||
addVolRateDic: itemDic.Item2,
|
||
volType: req.volType,
|
||
isUseTradeVol: PS.Config.IsTradeVol,
|
||
preciseTimeMode: req.CalcMarginType != CalcMarginTypeEnum.EodMargin,
|
||
isAddVolPercent: false);
|
||
|
||
if (tradeRiskResult.Results == null || tradeRiskResult.Results.Count < 1)
|
||
{
|
||
continue;
|
||
}
|
||
|
||
foreach (var item in tradeRiskResult.Results)
|
||
{
|
||
var client = helper.GetClient(item.Trade.ClientId);
|
||
var clientRatio = client?.Ratio ?? 1.0;
|
||
var clientRatio1 = client?.Ratio1 ?? 1.0;
|
||
|
||
var contains = resultMap.TryGetValue(item.Trade.id, out var tempTradeSpan);
|
||
|
||
var pv = item.ValueResult.Pv;
|
||
|
||
if (!helper.GetSpecialMargin(item.Trade, pv, out var value))
|
||
{
|
||
if (req.CalcMarginType == CalcMarginTypeEnum.InitialMargin)
|
||
{
|
||
value = double.IsNaN(pv) ? 0 : pv * clientRatio1;
|
||
}
|
||
else
|
||
{
|
||
value = double.IsNaN(pv) ? 0 : pv * clientRatio;
|
||
}
|
||
}
|
||
|
||
|
||
if (!contains)
|
||
{
|
||
resultMap[item.Trade.id] = tempTradeSpan = helper.CreateTradeSpan(item.Trade);
|
||
if (item.Trade.TradeType == "雪球期权" && item.Trade.BuySell == "买入")
|
||
{
|
||
resultMap[item.Trade.id].IsSingleMargin = true;
|
||
resultMap[item.Trade.id].Comment = "雪球买入";
|
||
}
|
||
}
|
||
|
||
switch (key)
|
||
{
|
||
case "up_1":
|
||
tempTradeSpan.Spv1 = value; break;
|
||
case "up_0":
|
||
tempTradeSpan.Spv2 = value; break;
|
||
case "up_2":
|
||
tempTradeSpan.Spv3 = value; break;
|
||
case "normal_0":
|
||
tempTradeSpan.Delta = item.ValueResult.Delta;
|
||
tempTradeSpan.UnderlyingPrice = req.PriceProvider.GetPrice(item.ValueResult.UnderlyingCode);
|
||
mpProvider.TryGetMarginRate(item.ValueResult.UnderlyingCode, out var marginRate);
|
||
tempTradeSpan.DeltaMargin = (tempTradeSpan.Delta * tempTradeSpan.UnderlyingPrice * marginRate) ?? 0;
|
||
break;
|
||
case "normal_1":
|
||
tempTradeSpan.Spv4 = value; break;
|
||
case "normal_2":
|
||
tempTradeSpan.Spv5 = value; break;
|
||
case "down_1":
|
||
tempTradeSpan.Spv6 = value; break;
|
||
case "down_0":
|
||
tempTradeSpan.Spv7 = value; break;
|
||
case "down_2":
|
||
tempTradeSpan.Spv8 = value; break;
|
||
}
|
||
|
||
if (contains)
|
||
{
|
||
tempTradeSpan.SetWorstCastClientPayable();
|
||
if (client != null)
|
||
{
|
||
var value2 = (double)tempTradeSpan.WorstCastClientPayable;
|
||
if (client.MarginOptionType == (int)MarginOptionEnum.单向追保)
|
||
{
|
||
value2 = item.Trade.BuySell == "卖出" ? 0 : Math.Max(value2, 0);
|
||
}
|
||
else if (client.MarginOptionType == (int)MarginOptionEnum.对手方单向追保 || client.MarginOptionType == (int)MarginOptionEnum.其他)
|
||
{
|
||
value2 = 0;
|
||
}
|
||
else if (client.MarginOptionType == (int)MarginOptionEnum.双向追保)
|
||
{
|
||
value2 = Math.Max(value2, 0);
|
||
}
|
||
tempTradeSpan.WorstCastClientPayable = value2;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return resultMap.Values.ToList();
|
||
}
|
||
|
||
public override List<trade_span> CalcClientMargin(CalcClientMarginReq req)
|
||
{
|
||
var clientSpanNews = new List<ClientSpan>();
|
||
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();
|
||
|
||
//海通预付金保底收益率-用来计算名义本金
|
||
double GuaranteedIncome = (db.valuedate.FirstOrDefault().GuaranteedIncome ?? 100) / 100;
|
||
|
||
var clientGroups = tradeSpanInfo.GroupBy(t => t.trade.ClientId);
|
||
foreach (var clientGroup in clientGroups)
|
||
{
|
||
var client = DataCacheProvider.GetClientDataSource().GetData(clientGroup.Key);
|
||
var clientLevel = DataCacheProvider.GetClientLevelDataSource().GetData(client.LevelId ?? 0);
|
||
var clientRatio = clientLevel?.Ratio ?? 1.0;
|
||
|
||
var underlyingGroup = clientGroup.Where(x => x.tradeSpan.IsSingleMargin != true).GroupBy(t => t.trade.UnderlyingId).Select(t => new ClientSpan
|
||
{
|
||
UnderlyingId = t.Key,
|
||
ClientId = clientGroup.Key,
|
||
ValueDate = req.settleDate,
|
||
//负数代表客户应缴预付金,正数代表客户应收预付金
|
||
Spv1 = -t.Sum(g => g.tradeSpan.Spv1),
|
||
Spv2 = -t.Sum(g => g.tradeSpan.Spv2),
|
||
Spv3 = -t.Sum(g => g.tradeSpan.Spv3),
|
||
Spv4 = -t.Sum(g => g.tradeSpan.Spv4),
|
||
Spv5 = -t.Sum(g => g.tradeSpan.Spv5),
|
||
Spv6 = -t.Sum(g => g.tradeSpan.Spv6),
|
||
Spv7 = -t.Sum(g => g.tradeSpan.Spv7),
|
||
Spv8 = -t.Sum(g => g.tradeSpan.Spv8),
|
||
WorstCastClientPayable = -t.Sum(g => g.tradeSpan.WorstCastClientPayable),
|
||
OptId = req.userId,
|
||
OptName = req.userName,
|
||
OptDate = DateTime.Now,
|
||
SpanType = req.SpanType
|
||
}).ToList();
|
||
|
||
foreach (var item in underlyingGroup)
|
||
{
|
||
if (client.MarginOptionType == (int)MarginOptionEnum.单向追保 || client.MarginOptionType == (int)MarginOptionEnum.双向追保)
|
||
{
|
||
if (clientGroup.Where(m => m.trade.UnderlyingId == item.UnderlyingId && m.trade.ClientId == item.ClientId).Count() > 1)
|
||
{
|
||
item.SetWorstCastClientPayableMin();
|
||
|
||
#region 更新tradeSpan,使得每笔交易的持仓预付金和客户预付金计算用的Spv组保持一致
|
||
|
||
var tradeIdList = clientGroup.Select(x => x.tradeSpan.TradeId);
|
||
var tradeSpansUpdate = db.trade_span.Where(x => tradeIdList.Contains(x.TradeId) && x.ClientId == item.ClientId && x.UnderlyingId == item.UnderlyingId && x.ValueDate == req.settleDate).ToList();
|
||
var tradeSpansReq = req.tradeSpans.Where(x => tradeIdList.Contains(x.TradeId) && x.ClientId == item.ClientId && x.UnderlyingId == item.UnderlyingId && x.ValueDate == req.settleDate).ToList();
|
||
|
||
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 if (item.WorstCastClientPayable == item.Spv7)
|
||
{
|
||
tradeSpansUpdate.ForEach(x => x.WorstCastClientPayable = x.Spv7);
|
||
tradeSpansReq.ForEach(x => x.WorstCastClientPayable = x.Spv7);
|
||
}
|
||
else if (item.WorstCastClientPayable == item.Spv8)
|
||
{
|
||
tradeSpansUpdate.ForEach(x => x.WorstCastClientPayable = x.Spv8);
|
||
tradeSpansReq.ForEach(x => x.WorstCastClientPayable = x.Spv8);
|
||
}
|
||
|
||
#endregion
|
||
}
|
||
else
|
||
{
|
||
var tradeSpansUpdate = db.trade_span.Where(x => x.ClientId == item.ClientId && x.UnderlyingId == item.UnderlyingId && x.ValueDate == req.settleDate).ToList();
|
||
tradeSpansUpdate.ForEach(x => x.Comment = "单笔计算");
|
||
}
|
||
|
||
//客户信息中追保方向为“单向追保”或“双向追保”的客户: call 看涨
|
||
//(1)Call净名义本金 = 客户Call卖方持仓名义本金 - 客户Call买方持仓名义本金;
|
||
//(2)Put净名义本金 = 客户Put卖方持仓名义本金 - 客户Put买方持仓名义本金;
|
||
//(3)单品种预付金占用 = max(0, max(∑逐笔交易持仓预付金,(Call净名义本金 + Put净名义本金)*1 % *1.1));
|
||
//(4)预付金占用 =∑单品种预付金占用。
|
||
//客户信息追保方向“对手方单向追保”或“其他”的客户:预付金占用 = 0。
|
||
|
||
var callsale = clientGroup.Where(m => m.trade.UnderlyingId == item.UnderlyingId && m.trade.BuySell == "买入" && m.trade.OptionType == "看涨").Select(m => m.trade.StockEqvNotional).Sum();
|
||
var callbuy = clientGroup.Where(m => m.trade.UnderlyingId == item.UnderlyingId && m.trade.BuySell == "卖出" && m.trade.OptionType == "看涨").Select(m => m.trade.StockEqvNotional).Sum();
|
||
var putsale = clientGroup.Where(m => m.trade.UnderlyingId == item.UnderlyingId && m.trade.BuySell == "买入" && m.trade.OptionType == "看跌").Select(m => m.trade.StockEqvNotional).Sum();
|
||
var putbuy = clientGroup.Where(m => m.trade.UnderlyingId == item.UnderlyingId && m.trade.BuySell == "卖出" && m.trade.OptionType == "看跌").Select(m => m.trade.StockEqvNotional).Sum();
|
||
|
||
var StockEqvNotional = (double)((callsale - callbuy + putsale - putbuy) * GuaranteedIncome * clientRatio);
|
||
|
||
if (client.MarginOptionType != (int)MarginOptionEnum.双向追保)
|
||
{
|
||
item.WorstCastClientPayable = -Math.Max(0, Math.Max(-(double)item.WorstCastClientPayable, StockEqvNotional));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
item.WorstCastClientPayable = 0;
|
||
}
|
||
}
|
||
|
||
var clientSpan = new ClientSpan
|
||
{
|
||
ClientId = clientGroup.Key,
|
||
ValueDate = req.settleDate,
|
||
Spv1 = underlyingGroup.Sum(g => g.Spv1),
|
||
Spv2 = underlyingGroup.Sum(g => g.Spv2),
|
||
Spv3 = underlyingGroup.Sum(g => g.Spv3),
|
||
Spv4 = underlyingGroup.Sum(g => g.Spv4),
|
||
Spv5 = underlyingGroup.Sum(g => g.Spv5),
|
||
Spv6 = underlyingGroup.Sum(g => g.Spv6),
|
||
Spv7 = underlyingGroup.Sum(g => g.Spv7),
|
||
Spv8 = underlyingGroup.Sum(g => g.Spv8),
|
||
//负数代表客户应缴预付金,正数代表客户应收预付金
|
||
WorstCastClientPayable = underlyingGroup.Sum(g => g.WorstCastClientPayable),
|
||
DeltaMargin = tradeSpanInfo.Where(g => g.trade.ClientId == clientGroup.Key).Sum(g => g.tradeSpan.DeltaMargin * -1),
|
||
TwoSideMargin = underlyingGroup.Sum(g => g.TwoSideMargin),
|
||
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
|
||
};
|
||
|
||
#region 雪球期权单独处理
|
||
|
||
var tradeSpanSingle = clientGroup.Where(x => x.tradeSpan.IsSingleMargin == true);
|
||
clientSpan.WorstCastClientPayable += tradeSpanSingle.Sum(x => -(x.tradeSpan.WorstCastClientPayable ?? 0));
|
||
|
||
#endregion
|
||
|
||
clientSpanNews.Add(clientSpan);
|
||
}
|
||
}
|
||
|
||
//span类型为实时删除所有实时计算的交易的预付金信息
|
||
if (req.SpanType == ClientSpan.SpanType_RealTime)
|
||
{
|
||
//var clientIds = clientSpanNews.Select(t => t.ClientId).Distinct().ToList();
|
||
//var clientSpanOlds = db.client_span.Where(t => t.SpanType == SpanType);
|
||
if (req.RefreshClientIds != null)
|
||
{
|
||
//clientSpanOlds = db.client_span.Where(t => RefreshClientIds.Contains(t.ClientId ?? 0));
|
||
db.BulkDelete<ClientSpan>($"{nameof(ClientSpan.ClientId)} in @ids", new { ids = req.RefreshClientIds });
|
||
}
|
||
else
|
||
{
|
||
db.BulkDelete<ClientSpan>($"{nameof(ClientSpan.SpanType)}=@SpanType", new { req.SpanType });
|
||
}
|
||
//MySqlBulkExtensions.BulkDelete(db, clientSpanOlds);
|
||
}
|
||
else
|
||
{
|
||
if(req.ClientIds !=null)
|
||
{
|
||
|
||
}
|
||
//var clientSpanOldsWithOutFlag = db.client_span.Where(t => t.ValueDate == settleDate && t.SpanType == SpanType && !t.ModifiedFlag).ToList();
|
||
//MySqlBulkExtensions.BulkDelete(db, clientSpanOldsWithOutFlag);
|
||
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).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;
|
||
}
|
||
}
|
||
|
||
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;
|
||
}
|
||
|
||
|
||
}
|
||
}
|