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

514 lines
30 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using YLErp.BLL.Calculation;
using YLErp.Enums;
using YLErp.Helpers;
using YLErp.Modules;
using YLErp.Modules.DataProviderModule;
using YLErp.Modules.MarginModule;
using YLErp.QdpModule;
namespace YLErp.BLL.MarginCalculation
{
/// <summary>
/// 格林大华
/// </summary>
public class GLDHMarginCalculation : MarginCalculationBase
{
// 定义一个静态变量来保存类的实例
public static readonly GLDHMarginCalculation Instance;
static GLDHMarginCalculation()
{
Instance = new GLDHMarginCalculation();
}
// 定义私有构造函数,使外界不能创建该类实例
private GLDHMarginCalculation()
{
}
public override List<trade_span> RunMarginCalculation(RunMarginCalculationReq req)
{
var resultList = new List<trade_span>();
if (req.CalcMarginType == Enums.CalcMarginTypeEnum.InitialMargin)
{
resultList = calcInitialMargin(req);
}
else
{
resultList = calcPositionMargin(req);
}
return resultList;
}
/// <summary>
/// 初始预付金
/// </summary>
/// <param name="req"></param>
/// <returns></returns>
private List<trade_span> calcInitialMargin(RunMarginCalculationReq req)
{
Dictionary<int, trade_span> resultMap = new Dictionary<int, trade_span>();
var _helper = new RunMarginCalculationHelper(req, _underlyingDataProvider);
var marginProvider = _helper.GetMarginParamProvider(Modules.MarginModule.MarginParamTypeEnum.MarginRate);
var tradeTypes = new List<string>() { "远期", "收益互换" };
var forword = req.tradeList.Where(O => O.TradeType == "远期");
foreach (var item in forword)
{
var margin =
item.Notional * (item.SpotPrice ?? 0)
* (marginProvider.TryGetMarginRate(item.UnderlyingCode, out var m) ? m : 0);
var sp = _helper.CreateTradeSpan(item).SetAllSpvAndWorst(margin);
LogFactory.GetLogger<MarginCalculationBase>().Debug($"{margin}={item.Notional}*{item.SpotPrice}* {(marginProvider.TryGetMarginRate(item.UnderlyingCode, out var ms) ? ms : 0)})");
sp.SetWorstCastClientPayable();
resultMap[sp.TradeId] = sp;
}
var swap = req.tradeList.Where(O => O.TradeType == "收益互换");
tradeBLL.SetFieldsByTradeType(swap);
foreach (var item in swap)
{
var rate = (item.trade_swap?.GetMarginRate ?? 0) - (item.trade_swap?.PayMarginRate ?? 0);
var margin = 0d;
if (rate > 0)
{
margin =
item.StockEqvNotional
* rate;
var client = DataCacheProvider.GetClientDataSource().GetData(item.ClientId);
var clientLevel = DataCacheProvider.GetClientLevelDataSource().GetData(client.LevelId ?? 0);
var clientRatio = clientLevel?.Ratio ?? 1.0;
margin *= clientRatio;
}
var sp = _helper.CreateTradeSpan(item).SetAllSpvAndWorst(margin);
sp.SetWorstCastClientPayable();
resultMap[sp.TradeId] = sp;
}
//所有客户买入的交易都不收取预付金,包含买入单腿,跨式期权,风险反转期权以及其他多腿组合期权(买入牛市价差或熊市价差时,卖出的那条腿也不收取预付金)
var sellList = req.tradeList.Where(O => !tradeTypes.Contains(O.TradeType) && O.BuySell == "卖出");
foreach (var item in sellList)
{
var sp = _helper.CreateTradeSpan(item).SetAllSpvAndWorst(0);
sp.SetWorstCastClientPayable();
resultMap[sp.TradeId] = sp;
}
var buyList = req.tradeList.Where(O => !tradeTypes.Contains(O.TradeType) && !resultMap.Keys.Contains(O.id));
var calcReq =
_helper.GetCalculateRisksForTradesReq(
req.PriceProvider,
null,
null,
Qdp.Pricing.Base.Implementations.PricingRequest.Delta);
calcReq.tradeList = buyList;
var tradeRiskResult = CalculatorHelper.CalculateRisksForTrades(calcReq);
//客户卖出跨式期权
//初始预付金 = max(D1,D2)×S×交易所期货预付金率×数量;
//其中 D1,D2 分别为跨式期权两腿的 Delta 绝对值。
var tradeIds = buyList.Where(O => (O.StructureType ?? O.TradeType).Contains("跨式") && O.BuySell == "买入").Select(O => O.id);
var resultDict = tradeRiskResult.Results.Where(O => tradeIds.Contains(O.Trade.id)).GroupBy(O => O.Trade.ParentTradeId).ToDictionary(K => K.Key, V => V.ToList());
foreach (var item in resultDict)
{
var margin =
item.Value
.Max(O => Math.Abs(O.ValueResult.DeltaCash)
* (marginProvider.TryGetMarginRate(O.Trade.UnderlyingCode, out var m) ? m : 0));
var sp = _helper.CreateTradeSpan(item.Value[0].Trade).SetAllSpvAndWorst(margin);
sp.SetWorstCastClientPayable();
resultMap[item.Value[0].Trade.id] = sp;
for (int i = 1; i < item.Value.Count; i++)
{
sp = _helper.CreateTradeSpan(item.Value[i].Trade).SetAllSpvAndWorst(0);
sp.SetWorstCastClientPayable();
resultMap[item.Value[i].Trade.id] = sp;
}
}
//客户卖出单腿期权
//初始预付金 = D×S×交易所期货预付金率×数量;
tradeIds = buyList.Where(O => !((O.StructureType ?? O.TradeType).Contains("跨式")) && O.BuySell == "买入").Select(O => O.id);
var resultList = tradeRiskResult.Results.Where(O => tradeIds.Contains(O.Trade.id));
resultList.ToList().ForEach(O =>
{
var margin = Math.Abs(O.ValueResult.DeltaCash * (marginProvider.TryGetMarginRate(O.Trade.UnderlyingCode, out var m) ? m : 0));
LogFactory.GetLogger<MarginCalculationBase>().Info("初始预付金 = D×S×交易所期货预付金率×数量;");
LogFactory.GetLogger<MarginCalculationBase>().Info($"{margin}=Math.Abs({O.ValueResult.DeltaCash} * {(marginProvider.TryGetMarginRate(O.Trade.UnderlyingCode, out var ms) ? ms : 0)})");
var sp = _helper.CreateTradeSpan(O.Trade).SetAllSpvAndWorst(margin);
sp.SetWorstCastClientPayable();
resultMap[sp.TradeId] = sp;
});
return resultMap.Values.ToList();
}
/// <summary>
/// 计算每笔预付金
/// </summary>
/// <param name="req"></param>
/// <returns></returns>
private List<trade_span> calcPositionMargin(RunMarginCalculationReq req)
{
var resultMap = new Dictionary<int, trade_span>();
var tradeTypes = new List<string>() { "远期", "收益互换" };
//结算s
req.PriceProvider = new EodPriceProvider(req.settleDate).GetPriceProvider(SettlementTypeEnum.SettlePrice);
//收盘
var closePriceProvider = new EodPriceProvider(req.settleDate).GetPriceProvider(SettlementTypeEnum.ClosePrice);
var _helper = new RunMarginCalculationHelper(req, _underlyingDataProvider);
var marginProvider = _helper.GetMarginParamProvider(Modules.MarginModule.MarginParamTypeEnum.MarginRate);
//获取涨跌停价格字典
_helper.GetUpDownLimitPrices(out var upPrices, out var downPrices);
//获取持仓波动率字典
_helper.GetUpDownVolRateDic(out var upVolRateDic, out _);
var clientGroup = req.tradeList.GroupBy(O => new { O.ClientId, O.UnderlyingCode }).ToDictionary(K => K.Key, V => V.ToList());
foreach (var item in clientGroup)
{
var forword = req.tradeList.Where(O => O.TradeType == "远期");
foreach (var t in forword)
{
var margin =
t.Notional * (t.SpotPrice ?? 0)
* (marginProvider.TryGetMarginRate(t.UnderlyingCode, out var m) ? m : 0);
LogFactory.GetLogger<MarginCalculationBase>().Info($"该交易{t.TradeNumber}id{t.id};远期" +
$"{margin} ={t.Notional * (t.SpotPrice ?? 0) * (marginProvider.TryGetMarginRate(t.UnderlyingCode, out var s) ? s : 0)}");
var sp = _helper.CreateTradeSpan(t).SetAllSpvAndWorst(margin);
sp.SetWorstCastClientPayable();
resultMap[sp.TradeId] = sp;
}
var swap = req.tradeList.Where(O => O.TradeType == "收益互换");
tradeBLL.SetFieldsByTradeType(swap);
foreach (var t in swap)
{
var rate = (t.trade_swap?.GetMarginRate ?? 0) - (t.trade_swap?.PayMarginRate ?? 0);
var margin = 0d;
if (rate > 0)
{
margin =
t.StockEqvNotional
* (marginProvider.TryGetMarginRate(t.UnderlyingCode, out var m) ? m : 0);
LogFactory.GetLogger<MarginCalculationBase>().Info($"该交易{t.TradeNumber}id{t.id}收益互换{margin}");
var client = DataCacheProvider.GetClientDataSource().GetData(t.ClientId);
var clientLevel = DataCacheProvider.GetClientLevelDataSource().GetData(client.LevelId ?? 0);
var clientRatio = clientLevel?.Ratio ?? 1.0;
margin *= clientRatio;
LogFactory.GetLogger<MarginCalculationBase>().Info($"该交易 margin *= clientRatio {t.TradeNumber} id{t.id}收益互换{margin}");
}
var sp = _helper.CreateTradeSpan(t).SetAllSpvAndWorst(margin);
sp.SetWorstCastClientPayable();
resultMap[sp.TradeId] = sp;
}
/*计算总维持预付金时,先分标的计算,再进行汇总计算。
* 如果客户在标的 i 上只有买权合约,则该标的不计入预付金计算范围;
* 如果客户在在标的 i 上有卖权合约,则该标的的所有合约都纳入预付金计算范围。
*/
var option = item.Value.Where(O => !tradeTypes.Contains(O.TradeType));
if (option.All(O => O.BuySell == "卖出"))
{
foreach (var t in option)
{
var sp = _helper.CreateTradeSpan(t).SetAllSpvAndWorst(0);
sp.SetWorstCastClientPayable();
resultMap[sp.TradeId] = sp;
}
}
else
{
var prices = new Dictionary<int, Dictionary<string, double>>();
var umCodeList = option.Select(O => O.UnderlyingCode).ToHashSet();
foreach (var code in umCodeList)
{
prices[1] = new Dictionary<string, double>();
prices[2] = new Dictionary<string, double>();
prices[3] = new Dictionary<string, double>();
prices[4] = new Dictionary<string, double>();
prices[5] = new Dictionary<string, double>();
prices[6] = new Dictionary<string, double>();
prices[7] = new Dictionary<string, double>();
prices[8] = new Dictionary<string, double>();
var upPrice = upPrices.GetPrice(code);
var downPrice = downPrices.GetPrice(code);
LogFactory.GetLogger<MarginCalculationBase>().Info($"涨跌价格:{upPrice} {downPrice}");
var interval = (upPrice - downPrice) / 6;
var settlePrice = req.PriceProvider.GetPrice(code);
LogFactory.GetLogger<MarginCalculationBase>().Info($"settlePrice:{settlePrice} interval:=(upPrice - downPrice) / 6={interval}={(upPrice - downPrice)} / {6}");
prices[1][code] = settlePrice - 3 * interval;
LogFactory.GetLogger<MarginCalculationBase>().Info($"格林持仓预付金1:prices[1][{code}] = settlePrice - 3 * interval;{prices[1][code]}={settlePrice}- 3 * {interval}");
prices[2][code] = settlePrice - 2 * interval;
LogFactory.GetLogger<MarginCalculationBase>().Info($"格林持仓预付金2:prices[2][{code}] = settlePrice - 2 * interval:{prices[2][code]}={settlePrice}- 2 * {interval}");
prices[3][code] = settlePrice - 1 * interval;
LogFactory.GetLogger<MarginCalculationBase>().Info($"格林持仓预付金3:prices[3][{code}] = settlePrice - 1 * interval:{prices[3][code]}={settlePrice}- 1 * {interval}");
prices[4][code] = settlePrice;
LogFactory.GetLogger<MarginCalculationBase>().Info($"格林持仓预付金4:prices[4][{code}] = settlePrice:{prices[4][code] = settlePrice}");
prices[5][code] = settlePrice + 1 * interval;
LogFactory.GetLogger<MarginCalculationBase>().Info($"格林持仓预付金5:prices[5][{code}] = settlePrice - 1 * interval:{prices[5][code]}={settlePrice}+ 1 * {interval}");
prices[6][code] = settlePrice + 2 * interval;
LogFactory.GetLogger<MarginCalculationBase>().Info($"格林持仓预付金6:prices[6][{code}] = settlePrice - 2 * interval:{prices[6][code]}={settlePrice}+ 2 * {interval}");
prices[7][code] = settlePrice + 3 * interval;
LogFactory.GetLogger<MarginCalculationBase>().Info($"格林持仓预付金7:prices[7][{code}] = settlePrice - 3 * interval:{prices[7][code]} ={settlePrice}+3 * {interval}");
prices[8][code] = closePriceProvider.GetPrice(code);
LogFactory.GetLogger<MarginCalculationBase>().Info($"格林持仓预付金8收盘价算Detal:{prices[8][code] = closePriceProvider.GetPrice(code)}");
}
foreach (var p in prices)
{
var tradeRiskResult = CalculatorHelper.CalculateRisksForTrades(
valueDate: req.settleDate,
calcScenario: req.GetCalcScenario(),
tradeList: item.Value,
priceProvider: new ManualPriceProvider(p.Value),
pricingRequest: QdpPricingRequest.BASIC_PRICING,
addVolRateDic: p.Key < 8 ? upVolRateDic : null, //1~7为PM,波动率应当上浮,第8个为DM,波动率不用变化
volType: req.volType,
isUseTradeVol: PS.Config.IsTradeVol,
preciseTimeMode: req.CalcMarginType != CalcMarginTypeEnum.EodMargin,
isAddVolPercent: true);
foreach (var risk in tradeRiskResult.Results)
{
var code = risk.Trade.UnderlyingCode;
var pric = p.Value[risk.Trade.UnderlyingCode];
LogFactory.GetLogger<MarginCalculationBase>().Info($"格林持仓预付金该交易编号:{risk.Trade.TradeNumber} id{risk.Trade.id}标的:{code} 交易价格为:{pric}");
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<MarginCalculationBase>().Info($"格林持仓预付金该交易的PV1为:{tradeSpan.Spv1}");
break;
case 2:
tradeSpan.Spv2 = risk.ValueResult.Pv;
LogFactory.GetLogger<MarginCalculationBase>().Info($"格林持仓预付金该交易的PV2为:{tradeSpan.Spv2}");
break;
case 3:
tradeSpan.Spv3 = risk.ValueResult.Pv;
LogFactory.GetLogger<MarginCalculationBase>().Info($"格林持仓预付金该交易的PV3为:{tradeSpan.Spv3}");
break;
case 4:
tradeSpan.Spv4 = risk.ValueResult.Pv;
LogFactory.GetLogger<MarginCalculationBase>().Info($"格林持仓预付金该交易的PV4为:{tradeSpan.Spv4}");
break;
case 5:
tradeSpan.Spv5 = risk.ValueResult.Pv;
LogFactory.GetLogger<MarginCalculationBase>().Info($"格林持仓预付金该交易的PV5为:{tradeSpan.Spv5}");
break;
case 6:
tradeSpan.Spv6 = risk.ValueResult.Pv;
LogFactory.GetLogger<MarginCalculationBase>().Info($"格林持仓预付金该交易的PV6为:{tradeSpan.Spv6}");
break;
case 7:
tradeSpan.Spv7 = risk.ValueResult.Pv;
LogFactory.GetLogger<MarginCalculationBase>().Info($"格林持仓预付金该交易的PV7为:{tradeSpan.Spv7}");
break;
case 8:
tradeSpan.Spv8 = risk.ValueResult.Pv;
LogFactory.GetLogger<MarginCalculationBase>().Info($"格林持仓预付金该交易的PV8为:{tradeSpan.Spv8}");
tradeSpan.DeltaMargin = risk.ValueResult.DeltaCash;
break;
default:
break;
}
//第八个pv不参与pm计算
if (p.Key < 8)
{
tradeSpan.SetWorstCastClientPayable();
}
}
}
}
}
return resultMap.Values.ToList();
}
/// <summary>
/// 计算每个客户预付金
/// </summary>
/// <param name="req"></param>
/// <returns></returns>
public override List<trade_span> CalcClientMargin(CalcClientMarginReq req)
{
var clientSpanNews = new List<ClientSpan>();
var _mpProvider = new MarginParamProvider(req.UserInfo, req.settleDate);
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 umCode = tradeList.Select(O => O.UnderlyingCode).ToHashSet();
var marginProvider = _mpProvider.Initialize(umCode, MarginParamTypeEnum.MarginRate);
var clientGroups = tradeSpanInfo.GroupBy(t => t.trade.ClientId);
foreach (var item in clientGroups)
{
var tradeTypes = new List<string>() { "远期", "收益互换" };
var forword = item.Where(O => O.trade.TradeType == "远期");
var swap = item.Where(O => O.trade.TradeType == "收益互换");
var worstCastClientPayable_forward = -forword.Sum(O => O.tradeSpan.WorstCastClientPayable ?? 0);
LogFactory.GetLogger<MarginCalculationBase>().Info($"格林维持预付金远期为:{worstCastClientPayable_forward}");
var worstCastClientPayable_swap = -swap.Sum(O => O.tradeSpan.WorstCastClientPayable ?? 0);
LogFactory.GetLogger<MarginCalculationBase>().Info($"格林维持预付金收益互换为:{worstCastClientPayable_swap}");
var worstCastClientPayable_option = 0d;
var option = item.Where(O => !tradeTypes.Contains(O.trade.TradeType));
if (option.Any(O => O.trade.BuySell == "买入"))
{
var dm = option.Sum(O =>
{
var margin = (marginProvider.TryGetMarginRate(O.trade.UnderlyingCode, out var m) ? m : 0);
var a = Math.Abs((O.tradeSpan.DeltaMargin ?? 0) * margin) - O.tradeSpan.Spv8 ?? 0;
LogFactory.GetLogger<MarginCalculationBase>().Info($"格林维持保证的dm为:{a}");
return Math.Abs((O.tradeSpan.DeltaMargin ?? 0) * margin) - O.tradeSpan.Spv8 ?? 0;
});
dm = Math.Max(dm, 0);
LogFactory.GetLogger<MarginCalculationBase>().Info($"格林维持保证最大的dm{dm}");
//计算标的 i 在上 7 种情形下客户持仓的持仓价值 MVi,k(k=1,2,3…7)(客户卖出期权,期权价值取负值),
//则客户在标的 i 上隔日最大亏损 Li = -min(Vi,k),对第 i 个标的取维持预付金 PMi = Max(Li,0);
//var pm = option.GroupBy(O => O.trade.UnderlyingCode).Sum(O => Math.Max(O.Sum(B => B.tradeSpan.WorstCastClientPayable ?? 0), 0));
var underlyingGroup = option.GroupBy(O => O.trade.UnderlyingCode);
var pmList = new List<double>();
foreach (var unItem in underlyingGroup)
{
var list = new List<double>()
{
unItem.Sum(O => O.tradeSpan.Spv1??0),
unItem.Sum(O => O.tradeSpan.Spv2??0),
unItem.Sum(O => O.tradeSpan.Spv3??0),
unItem.Sum(O => O.tradeSpan.Spv4??0),
unItem.Sum(O => O.tradeSpan.Spv5??0),
unItem.Sum(O => O.tradeSpan.Spv6??0),
unItem.Sum(O => O.tradeSpan.Spv7??0),
}; LogFactory.GetLogger<MarginCalculationBase>().Info($"格林维持预付金 7 种情形下客户持仓值为1:" +
$"{unItem.Sum(O => O.tradeSpan.Spv1 ?? 0)}" +
" 2:" + $"{unItem.Sum(O => O.tradeSpan.Spv2 ?? 0)}" +
" 3:" + $"{unItem.Sum(O => O.tradeSpan.Spv3 ?? 0)}" +
" 4:" + $"{unItem.Sum(O => O.tradeSpan.Spv4 ?? 0)}" +
" 5:" + $"{unItem.Sum(O => O.tradeSpan.Spv5 ?? 0)}" +
" 6:" + $"{unItem.Sum(O => O.tradeSpan.Spv6 ?? 0)}" +
" 7:" + $"{unItem.Sum(O => O.tradeSpan.Spv7 ?? 0)} 代码角度若为卖出期权则为负数(-min)所以最小的加-则为正数");
var pmi = list.Max(O => O);
LogFactory.GetLogger<MarginCalculationBase>().Info($"格林维持预付金PM为Max(Li,0){pmi}");
pmList.Add(pmi);
}
var pm = pmList.Sum();
worstCastClientPayable_option = Math.Max(dm, pm);
LogFactory.GetLogger<MarginCalculationBase>().Info($"格林维持保证标的i维持预付金M=Max(dmpm){worstCastClientPayable_option}={Math.Max(dm, pm)}");
LogFactory.GetLogger<MarginCalculationBase>().Info($"格林维持保证标的i维持预付金M=Max(dmpm){worstCastClientPayable_option}");
#region 更新tradeSpan,使得每笔交易的持仓预付金和客户预付金计算用的Spv组保持一致
var sumDelta = option.Sum(O => Math.Abs(O.tradeSpan.DeltaMargin ?? 0));
tradeIds = option.Select(x => x.trade.id).ToList();
var tradeSpansUpdate = db.trade_span.Where(x => tradeIds.Contains(x.TradeId) && x.ClientId == item.Key && x.ValueDate == req.settleDate).ToList();
var tradeSpansReq = req.tradeSpans.Where(x => tradeIds.Contains(x.TradeId) && x.ClientId == item.Key && x.ValueDate == req.settleDate).ToList();
tradeSpansUpdate.ForEach(x => x.WorstCastClientPayable = worstCastClientPayable_option * Math.Abs(x.DeltaMargin ?? 0) / sumDelta);
tradeSpansReq.ForEach(x => x.WorstCastClientPayable = worstCastClientPayable_option * Math.Abs(x.DeltaMargin ?? 0) / sumDelta);
#endregion
}
var worstCastClientPayable = -worstCastClientPayable_option + worstCastClientPayable_forward + worstCastClientPayable_swap;
LogFactory.GetLogger<MarginCalculationBase>().Info($"{worstCastClientPayable = -worstCastClientPayable_option + worstCastClientPayable_forward + worstCastClientPayable_swap}");
var clientSpan = new ClientSpan
{
ClientId = item.Key,
ValueDate = req.settleDate,
Spv1 = worstCastClientPayable,
Spv2 = worstCastClientPayable,
Spv3 = worstCastClientPayable,
Spv4 = worstCastClientPayable,
//负数代表客户应缴预付金,正数代表客户应收预付金
WorstCastClientPayable = worstCastClientPayable,
SwapWorstCastClientPayable = worstCastClientPayable_swap,
MySideMargin = worstCastClientPayable,
OptId = req.userId,
OptName = req.userName,
OptDate = DateTime.Now,
SpanType = req.SpanType,
AdditionalWorstCastClientPayable = req.clientAdditionalMarginDic != null
&& req.clientAdditionalMarginDic.TryGetValue(item.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)}={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.client_span.AddRange(clientSpanNews);
}
db.SaveChanges();
}
return req.tradeSpans;
}
public override double GetTradeMargin(GetTradeMarginReq req)
{
var trade = req.trade;
using (YLContext 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)
{
return tradeMargin.FirstOrDefault()?.WorstCastClientPayable ?? 0.0;
}
return 0.0;
}
}
}