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;
}
}
}