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

906 lines
67 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.Model.Enum;
using YLErp.Modules;
using YLErp.Modules.ClientModule;
using YLErp.Modules.DataProviderModule;
using YLErp.Modules.UnderlyingModule;
using YLErp.QdpModule;
namespace YLErp.BLL.MarginCalculation
{
/// <summary>
/// 广发商贸
/// </summary>
public class GFSMMarginCalculation : MarginCalculationBase
{
/// <summary>
/// 定义一个静态变量保存类的实例
/// </summary>
public static readonly GFSMMarginCalculation Instance;
static GFSMMarginCalculation()
{
Instance = new GFSMMarginCalculation();
}
/// <summary>
/// 定义私有结构函数,使外界不能创建该类实例
/// </summary>
public GFSMMarginCalculation()
{
}
/// <summary>
/// 单交易维持预付金(初始预付金)
/// </summary>
/// <param name="req"></param>
/// <returns></returns>
public override List<trade_span> RunMarginCalculation(RunMarginCalculationReq req)
{
var result = new List<trade_span>();
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;
}
/// <summary>
/// 初始预付金
/// </summary>
/// <param name="req"></param>
/// <returns></returns>
private List<trade_span> calcInitialMargin(RunMarginCalculationReq req, Dictionary<int, List<string>> span2Dict, Dictionary<int, SpanConfig> marginFactorDict)
{
var resultMap = new Dictionary<int, trade_span>();
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<MarginCalculationBase>().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<string, double>();
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<int, Dictionary<string, double>>();
var pricesY = new Dictionary<int, Dictionary<string, double>>();
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<MarginCalculationBase>().Info($"广发商贸计算初始涨跌价格:{upPrice} {downPrice} 涨跌取均值所以a为涨-跌/6{interval}");
var closePricePrice = closePriceProvider.GetPrice(code);//收盘价
var settlePrice = req.PriceProvider.GetPrice(code);//结算价
LogFactory.GetLogger<MarginCalculationBase>().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<MarginCalculationBase>().Info($"广发商贸远期计算初始预付金情景一和八为:空头方向*持仓数量*[(𝑆(𝑖,𝑛)×(1+𝑎)-P(T)]={tradeSpan.Spv1}={-t.TradeAmount}* ({settlePrice} + {interval}*3)-{closePricePrice})");
tradeSpan.Spv2 = -t.TradeAmount * (settlePrice + (interval * 2) - closePricePrice);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸远期计算初始预付金情景二和九为:空头方向*持仓数量*[(𝑆(𝑖,𝑛)×(1+2/3𝑎)-P(T)]={tradeSpan.Spv2}={-t.TradeAmount}* ({settlePrice} + {interval}* 2-{closePricePrice})");
tradeSpan.Spv3 = -t.TradeAmount * (settlePrice + (interval * 1) - closePricePrice);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸远期计算初始预付金情景三和十为:空头方向*持仓数量*" + $"[(𝑆(𝑖,𝑛)×(1+1/3𝑎)-P(T)]={tradeSpan.Spv3}={-t.TradeAmount}* ({settlePrice} + {interval * 1}-{closePricePrice})");
tradeSpan.Spv4 = -t.TradeAmount * (settlePrice - closePricePrice);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸远期计算初始预付金情景四和十一为:空头方向*持仓数量*[(𝑆(𝑖,𝑛)×(𝑎)-P(T)]={tradeSpan.Spv4}={-t.TradeAmount}* ({settlePrice}-{closePricePrice}");
tradeSpan.Spv5 = -t.TradeAmount * (settlePrice - (interval * 1) - closePricePrice);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸远期计算初始预付金情景五和十二为:空头方向*持仓数量*[(𝑆(𝑖,𝑛)×(1-1/3𝑎)-P(T)]={tradeSpan.Spv5}={-t.TradeAmount}* ({settlePrice}-{interval}*1-{closePricePrice})");
tradeSpan.Spv6 = -t.TradeAmount * (settlePrice - (interval * 2) - closePricePrice);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸远期计算初始预付金情景六和十三为:空头方向*持仓数量*[(𝑆(𝑖,𝑛)×(1-2/3𝑎)-P(T)]={tradeSpan.Spv6}={-t.TradeAmount}* ({settlePrice} - {interval}*2-{closePricePrice})");
tradeSpan.Spv7 = -t.TradeAmount * (settlePrice - (interval * 3) - closePricePrice);
LogFactory.GetLogger<MarginCalculationBase>().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<MarginCalculationBase>().Info($"广发商贸远期计算初始预付金持仓市值用收盘价为:{tradeSpan.Spv15}");
}
else
{
tradeSpan.Spv1 = t.TradeAmount * (settlePrice - (interval * 3) - closePricePrice);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸远期计算初始预付金情景一和八为:多头方向*持仓数量*[(𝑆(𝑖,𝑛)×(1+𝑎)-P(T)]={tradeSpan.Spv1}={t.TradeAmount}* ({settlePrice}- {interval}*3) )-{closePricePrice}");
tradeSpan.Spv2 = t.TradeAmount * (settlePrice - (interval * 2) - closePricePrice);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸远期计算初始预付金情景二和九为:多头方向*持仓数量*[(𝑆(𝑖,𝑛)×(1+2/3𝑎)-P(T)]={tradeSpan.Spv2}={t.TradeAmount}* ({settlePrice}- {interval} * 2-{closePricePrice})");
tradeSpan.Spv3 = t.TradeAmount * (settlePrice - (interval * 1) - closePricePrice);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸远期计算初始预付金情景三和十为:多头方向*持仓数量*" + $"[(𝑆(𝑖,𝑛)×(1+1/3𝑎)-P(T)]={tradeSpan.Spv3}={t.TradeAmount}* ({settlePrice}- {interval * 1}-{closePricePrice})");
tradeSpan.Spv4 = t.TradeAmount * (settlePrice - closePricePrice);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸远期计算初始预付金情景四和十一为:多头方向*持仓数量*[(𝑆(𝑖,𝑛)×(𝑎)-P(T)]={tradeSpan.Spv4}={t.TradeAmount}* ({settlePrice} -{closePricePrice}");
tradeSpan.Spv5 = t.TradeAmount * (settlePrice + (interval * 1) - closePricePrice);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸远期计算初始预付金情景五和十二为:多头方向*持仓数量*[(𝑆(𝑖,𝑛)×(1-1/3𝑎)-P(T)]={tradeSpan.Spv5}={t.TradeAmount}* ({settlePrice}-{interval}*1-{closePricePrice})");
tradeSpan.Spv6 = t.TradeAmount * (settlePrice + (interval * 2) - closePricePrice);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸远期计算初始预付金情景六和十三为:多头方向*持仓数量*[(𝑆(𝑖,𝑛)×(1-2/3𝑎)-P(T)]={tradeSpan.Spv6}={t.TradeAmount}* ({settlePrice} - {interval}*2-{closePricePrice})");
tradeSpan.Spv7 = t.TradeAmount * (settlePrice + (interval * 3) - closePricePrice);
LogFactory.GetLogger<MarginCalculationBase>().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<MarginCalculationBase>().Info($"广发商贸远期计算初始预付金持仓市值用收盘价为:{tradeSpan.Spv15}");
}
tradeSpan.SetWorstCastClientPayable();
var Margin1 = tradeSpan.WorstCastClientPayable ?? 0;
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸远期初始预付金Mdetal为十四情景种最大的:{Margin1}");
var Margin2 = (tradeSpan.Delta ?? 0) * t.MarginRate;
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸远期初始预付金Mdeta2为N个合约是否则为0:{Margin2}");
//标的持仓时值(用收盘价计算)
var presentValue = tradeSpan.Spv15 ?? 0;
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸远期初始预付金标的持仓时值presentValue用收盘价计算{presentValue}");
//判断最终应该缴纳初始预付金
if (Margin1 > 0 && presentValue > 0)
{
tradeSpan.WorstCastClientPayable = Math.Max(Margin1, Margin2) * initialMargin;
LogFactory.GetLogger<MarginCalculationBase>().Info($"最终预付金在Margin1和Margin2中取最大存入数据库:{tradeSpan.WorstCastClientPayable} = Math.Max({Margin1}, {Margin2})* {initialMargin};");
}
if (Margin1 > 0 && presentValue < 0)
{
tradeSpan.WorstCastClientPayable = Margin1 * initialMargin;
LogFactory.GetLogger<MarginCalculationBase>().Info($"判断应该缴纳初始预付金如Margin1>0&&presentValue<0))则为{tradeSpan.WorstCastClientPayable}={Margin1}结果*{initialMargin}");
}
else
{
tradeSpan.WorstCastClientPayable = 0;
}
}
var tradeTypes = new List<string>() { "远期", "收益互换" };
var option = item.Value.Where(o => !tradeTypes.Contains(o.TradeType)).ToList();
if (option.Any())
{
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>();
prices[9] = new Dictionary<string, double>();
prices[10] = new Dictionary<string, double>();
prices[11] = new Dictionary<string, double>();
prices[12] = new Dictionary<string, double>();
prices[13] = new Dictionary<string, double>();
prices[14] = new Dictionary<string, double>();
prices[15] = new Dictionary<string, double>();
//该detal存入PV15用收盘价来计算
prices[1][code] = settlePrice + (interval * 3);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸期权计算初始预付金情景一为:𝑆(𝑖,𝑛)×(1+𝑎){prices[1][code]}={settlePrice}+{interval}*3");
prices[2][code] = settlePrice + (interval * 2);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸期权计算初始预付金情景二为:𝑆(𝑖,𝑛)×( 1+2/3𝑎){prices[2][code]}={settlePrice}+{interval}*2");
prices[3][code] = settlePrice + (interval * 1);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸期权计算初始预付金情景三为:𝑆(𝑖,𝑛)×(1+1/3𝑎){prices[3][code]}={settlePrice}+{interval}*1");
prices[4][code] = settlePrice;
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸期权计算初始预付金情景四为:𝑆(𝑖,𝑛){prices[4][code]}={settlePrice}");
prices[5][code] = settlePrice - (interval * 1);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸期权计算初始预付金情景五为:𝑆(𝑖,𝑛)×(11/3 𝑎){prices[5][code]}={settlePrice}-{interval}*1");
prices[6][code] = settlePrice - (interval * 2);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸期权计算初始预付金情景六为:𝑆(𝑖,𝑛)×(12/3𝑎){prices[6][code]}={settlePrice}-{interval}*2");
prices[7][code] = settlePrice - (interval * 3);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸期权计算初始预付金情景七为:𝑆(𝑖,𝑛)×(1−𝑎){prices[7][code]}={settlePrice}-{interval}*3");
prices[8][code] = settlePrice + (interval * 3);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸期权计算初始预付金情景八为:𝑆(𝑖,𝑛)×(1+𝑎){prices[8][code]}={settlePrice}+{interval}*3");
prices[9][code] = settlePrice + (interval * 2);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸期权计算初始预付金情景九为:𝑆(𝑖,𝑛)×( 1+2/3𝑎){prices[9][code]}={settlePrice}+{interval}*2");
prices[10][code] = settlePrice + (interval * 1);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸期权计算初始预付金情景十为:𝑆(𝑖,𝑛)×(1+1/3𝑎){prices[10][code]}={settlePrice}+{interval}*1");
prices[11][code] = settlePrice;
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸期权计算初始预付金情景十一为:𝑆(𝑖,𝑛){prices[11][code]}={settlePrice}");
prices[12][code] = settlePrice - (interval * 1);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸期权计算初始预付金情景十二为:𝑆(𝑖,𝑛)×(11/3 𝑎){prices[12][code]}={settlePrice}-{interval}*1");
prices[13][code] = settlePrice - (interval * 2);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸期权计算初始预付金情景十三为:𝑆(𝑖,𝑛)×(12/3𝑎){prices[13][code]}={settlePrice}-{interval}*2");
prices[14][code] = settlePrice - (interval * 3);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸期权计算初始预付金情景十四为:𝑆(𝑖,𝑛)×(1−𝑎){prices[14][code]}={settlePrice}-{interval}*3");
prices[15][code] = closePriceProvider.GetPrice(code);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸期权计算初始预付金情景十五收盘价算detal:{prices[15][code] = closePriceProvider.GetPrice(code)}");
foreach (var p in prices)
{
Dictionary<int, double> tradeVolRateDic = null;
if (p.Key <= 7)
{
tradeVolRateDic = tradeVolRateDicUp;
}
else if (p.Key <= 14)
{
tradeVolRateDic = tradeVolRateDicDown;
}
//var overrideVol = new Dictionary<int, double>();
//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<MarginCalculationBase>().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<MarginCalculationBase>().Info($"广发商贸初始预付金Mdetal为十四情景种最大的:{Margin1}");
var Margin2 = tradeSpan.Delta ?? 0;
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸初始预付金Mdeta2为N个合约是:{Margin2}");
//标的持仓时值(用收盘价计算)
var presentValue = tradeSpan.Spv15 ?? 0;
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸初始预付金标的持仓时值presentValue用收盘价计算{presentValue}");
//判断最终应该缴纳初始预付金
if (Margin1 > 0 && presentValue > 0)
{
tradeSpan.WorstCastClientPayable = Math.Max(Margin1, Margin2) * initialMargin;
LogFactory.GetLogger<MarginCalculationBase>().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<MarginCalculationBase>().Info($"判断初始预付金如果(Margin1>0&&presentValue<0)则为Margin1{tradeSpan.WorstCastClientPayable}={Margin1}*{initialMargin}");
}
else
{
tradeSpan.WorstCastClientPayable = 0;
}
}
}
}
}
}
return resultMap.Values.ToList();
}
/// <summary>
/// 维持预付金
/// </summary>
/// <param name="req"></param>
/// <returns></returns>
private List<trade_span> calcPositionMargin(RunMarginCalculationReq req, Dictionary<int, List<string>> span2Dict)
{
var resultMap = new Dictionary<int, trade_span>();
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<string, double>();
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<int, Dictionary<string, double>>();
var pricesY = new Dictionary<int, Dictionary<string, double>>();
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<MarginCalculationBase>().Info($"广发商贸计算维持涨跌价格:{upPrice} {downPrice} 涨跌取均值所以a为:{interval}");
var closePrice = closePriceProvider.GetPrice(code);//收盘价
var settlePrice = req.PriceProvider.GetPrice(code);//结算价
LogFactory.GetLogger<MarginCalculationBase>().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<MarginCalculationBase>().Info($"广发商贸远期计算维持预付金情景一和八为:空头方向*持仓数量*[(𝑆(𝑖,𝑛)×(1+𝑎)-P(T)]={tradeSpan.Spv1}={-t.TradeAmount}* ({settlePrice} + {interval}*3)-{closePrice})");
tradeSpan.Spv2 = -t.TradeAmount * (settlePrice + (interval * 2) - closePrice);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸远期计算维持预付金情景二和九为:空头方向*持仓数量*[(𝑆(𝑖,𝑛)×(1+2/3𝑎)-P(T)]={tradeSpan.Spv2}={-t.TradeAmount}* ({settlePrice} + {interval} * 2-{closePrice})");
tradeSpan.Spv3 = -t.TradeAmount * (settlePrice + (interval * 1) - closePrice);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸远期计算维持预付金情景三和十为:空头方向*持仓数量*" + $"[(𝑆(𝑖,𝑛)×(1+1/3𝑎)-P(T)]={tradeSpan.Spv3}={-t.TradeAmount}* ({settlePrice} + {interval * 1}-{closePrice})");
tradeSpan.Spv4 = -t.TradeAmount * (settlePrice - closePrice);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸远期计算维持预付金情景四和十一为:空头方向*持仓数量*[(𝑆(𝑖,𝑛)×(𝑎)-P(T)]={tradeSpan.Spv4}={-t.TradeAmount}* ({settlePrice}-{closePrice}");
tradeSpan.Spv5 = -t.TradeAmount * (settlePrice - (interval * 1) - closePrice);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸远期计算维持预付金情景五和十二为:空头方向*持仓数量*[(𝑆(𝑖,𝑛)×(1-1/3𝑎)-P(T)]={tradeSpan.Spv5}={-t.TradeAmount}* ({settlePrice}-{interval}*1-{closePrice})");
tradeSpan.Spv6 = -t.TradeAmount * (settlePrice - (interval * 2) - closePrice);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸远期计算维持预付金情景六和十三为:空头方向*持仓数量*[(𝑆(𝑖,𝑛)×(1-2/3𝑎)-P(T)]={tradeSpan.Spv6}={-t.TradeAmount}* ({settlePrice} - {interval}*2-{closePrice})");
tradeSpan.Spv7 = -t.TradeAmount * (settlePrice - (interval * 3) - closePrice);
LogFactory.GetLogger<MarginCalculationBase>().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<MarginCalculationBase>().Info($"广发商贸远期计算维持预付金持仓市值用收盘价为:{tradeSpan.Spv15}");
}
else
{
tradeSpan.Spv1 = t.TradeAmount * (settlePrice - (interval * 3) - closePrice);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸远期计算维持预付金情景一和八为:多头方向*持仓数量*[(𝑆(𝑖,𝑛)×(1+𝑎)-P(T)]={tradeSpan.Spv1}={t.TradeAmount}* ({settlePrice}- {interval}*3) -{closePrice})");
tradeSpan.Spv2 = t.TradeAmount * (settlePrice - (interval * 2) - closePrice);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸远期计算维持预付金情景二和九为:多头方向*持仓数量*[(𝑆(𝑖,𝑛)×(1+2/3𝑎)-P(T)]={tradeSpan.Spv2}={t.TradeAmount}* ({settlePrice}- {interval}* 2-{closePrice})");
tradeSpan.Spv3 = t.TradeAmount * (settlePrice - (interval * 1) - closePrice);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸远期计算维持预付金情景三和十为:多头方向*持仓数量*" + $"[(𝑆(𝑖,𝑛)×(1+1/3𝑎)-P(T)]={tradeSpan.Spv3}={t.TradeAmount}* ({settlePrice}- {interval * 1}-{closePrice})");
tradeSpan.Spv4 = t.TradeAmount * (settlePrice - closePrice);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸远期计算维持预付金情景四和十一为:多头方向*持仓数量*[(𝑆(𝑖,𝑛)×(𝑎)-P(T)]={tradeSpan.Spv4}={t.TradeAmount}* ({settlePrice}-{closePrice}");
tradeSpan.Spv5 = t.TradeAmount * (settlePrice + (interval * 1) - closePrice);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸远期计算维持预付金情景五和十二为:多头方向*持仓数量*[(𝑆(𝑖,𝑛)×(1-1/3𝑎)-P(T)]={tradeSpan.Spv5}={t.TradeAmount}* ({settlePrice}-{interval}*1)-{closePrice}");
tradeSpan.Spv6 = t.TradeAmount * (settlePrice + (interval * 2) - closePrice);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸远期计算维持预付金情景六和十三为:多头方向*持仓数量*[(𝑆(𝑖,𝑛)×(1-2/3𝑎)-P(T)]={tradeSpan.Spv6}={t.TradeAmount}* ({settlePrice} - {interval}*2)-{closePrice}");
tradeSpan.Spv7 = t.TradeAmount * (settlePrice + (interval * 3) - closePrice);
LogFactory.GetLogger<MarginCalculationBase>().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<MarginCalculationBase>().Info($"广发商贸远期计算维持预付金持仓市值用收盘价为:{tradeSpan.Spv15}");
}
}
var tradeTypes = new List<string>() { "远期", "收益互换" };
var option = item.Value.Where(o => !tradeTypes.Contains(o.TradeType)).ToList();
if (option.Any())
{
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>();
prices[9] = new Dictionary<string, double>();
prices[10] = new Dictionary<string, double>();
prices[11] = new Dictionary<string, double>();
prices[12] = new Dictionary<string, double>();
prices[13] = new Dictionary<string, double>();
prices[14] = new Dictionary<string, double>();
prices[15] = new Dictionary<string, double>();
//该detal存入PV15用收盘价来计算
prices[1][code] = settlePrice + (interval * 3);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸期权计算维持预付金情景一为:𝑆(𝑖,𝑛)×(1+𝑎){prices[1][code]}={settlePrice}+{interval}*3");
prices[2][code] = settlePrice + (interval * 2);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸期权计算维持预付金情景二为:𝑆(𝑖,𝑛)×( 1+2/3𝑎){prices[2][code]}={settlePrice}+{interval}*2");
prices[3][code] = settlePrice + (interval * 1);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸期权计算初始预付金情景三为:𝑆(𝑖,𝑛)×(1+1/3𝑎){prices[3][code]}={settlePrice}+{interval}*1");
prices[4][code] = settlePrice;
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸期权计算初始预付金情景四为:𝑆(𝑖,𝑛){prices[4][code]}={settlePrice}");
prices[5][code] = settlePrice - (interval * 1);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸期权计算初始预付金情景五为:𝑆(𝑖,𝑛)×(11/3 𝑎){prices[5][code]}={settlePrice}-{interval}*1");
prices[6][code] = settlePrice - (interval * 2);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸期权计算初始预付金情景六为:𝑆(𝑖,𝑛)×(12/3𝑎){prices[6][code]}={settlePrice}-{interval}*2");
prices[7][code] = settlePrice - (interval * 3);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸期权计算初始预付金情景七为:𝑆(𝑖,𝑛)×(1−𝑎){prices[7][code]}={settlePrice}-{interval}*3");
prices[8][code] = settlePrice + (interval * 3);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸期权计算初始预付金情景八为:𝑆(𝑖,𝑛)×(1+𝑎){prices[8][code]}={settlePrice}+{interval}*3");
prices[9][code] = settlePrice + (interval * 2);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸期权计算初始预付金情景九为:𝑆(𝑖,𝑛)×( 1+2/3𝑎){prices[9][code]}={settlePrice}+{interval}*2");
prices[10][code] = settlePrice + (interval * 1);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸期权计算初始预付金情景十为:𝑆(𝑖,𝑛)×(1+1/3𝑎){prices[10][code]}={settlePrice}+{interval}*1");
prices[11][code] = settlePrice;
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸期权计算初始预付金情景十一为:𝑆(𝑖,𝑛){prices[11][code]}={settlePrice}");
prices[12][code] = settlePrice - (interval * 1);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸期权计算初始预付金情景十二为:𝑆(𝑖,𝑛)×(11/3 𝑎){prices[12][code]}={settlePrice}-{interval}*1");
prices[13][code] = settlePrice - (interval * 2);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸期权计算初始预付金情景十三为:𝑆(𝑖,𝑛)×(12/3𝑎){prices[13][code]}={settlePrice}-{interval}*2");
prices[14][code] = settlePrice - (interval * 3);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸期权计算初始预付金情景十四为:𝑆(𝑖,𝑛)×(1−𝑎){prices[14][code]}={settlePrice}-{interval}*3");
prices[15][code] = closePriceProvider.GetPrice(code);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸期权计算维持预付金情景十五收盘价算detal:{prices[15][code] = closePriceProvider.GetPrice(code)}");
foreach (var p in prices)
{
Dictionary<int, double> 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<MarginCalculationBase>().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<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}");
break;
case 9:
tradeSpan.Spv9 = risk.ValueResult.Pv;
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸计算维持预付金pv9为:{tradeSpan.Spv9}");
break;
case 10:
tradeSpan.Spv10 = risk.ValueResult.Pv;
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸计算维持预付金pv10为:{tradeSpan.Spv10}");
break;
case 11:
tradeSpan.Spv11 = risk.ValueResult.Pv;
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸计算维持预付金pv11为:{tradeSpan.Spv11}");
break;
case 12:
tradeSpan.Spv12 = risk.ValueResult.Pv;
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸计算维持预付金pv12为:{tradeSpan.Spv12}");
break;
case 13:
tradeSpan.Spv13 = risk.ValueResult.Pv;
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸计算维持预付金pv13为:{tradeSpan.Spv13}");
break;
case 14:
tradeSpan.Spv14 = risk.ValueResult.Pv;
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸计算维持预付金pv14为:{tradeSpan.Spv14}");
break;
//pv用收盘价来结算detal
case 15:
tradeSpan.Spv15 = risk.ValueResult.Pv;//持仓市值收盘价
LogFactory.GetLogger<MarginCalculationBase>().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<MarginCalculationBase>().Info($"广发商贸计算维持期权Margin2为:{tradeSpan.Delta}");
break;
default:
break;
}
//spv15不参与所以为0
if (p.Key < 15)
{
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>();
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<double>();
foreach (var item in varietyGroup)
{
var list = new List<double>()
{
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<MarginCalculationBase>().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<MarginCalculationBase>().Info($"广发商贸该客户magrin2为:{pmMargin2}");
//持仓市值为Pv十五加总
var pmt = item.Sum(s => s.tradeSpan.Spv15 ?? 0);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸该客户持仓市值为:{pmt}");
double endMoney = 0;
if (pmi > 0 && pmt > 0)
{
endMoney = Math.Max(pmi, pmMargin2);
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸该客户14PV持仓市值都大于0两者取最大为:{endMoney}");
}
else if (pmi > 0 && pmt < 0)
{
endMoney = pmi;
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸该客户14PV大于0和持仓市值小于0则取最大pv为:{endMoney}");
}
else
{
endMoney = 0;
}
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸该客户相比结果最后为:{endMoney}");
if (endMoney < 0 && client.MarginOptionType == (int)MarginOptionEnum.单向追保)
{
endMoney = 0;
}
pmList.Add(endMoney);
}
//期权汇总
var pml = pmList.Sum();
LogFactory.GetLogger<MarginCalculationBase>().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<MarginCalculationBase>().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<MarginCalculationBase>().Info($"广发商贸单向追保时与0相比取最小:{clientSpan.WorstCastClientPayable}");
}
else if (client.MarginOptionType == (int)MarginOptionEnum.双向追保)
{
clientSpan.WorstCastClientPayable = clientSpan.WorstCastClientPayable.Value;
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸双向追保时汇总为(正/负):{clientSpan.WorstCastClientPayable}");
}
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
{
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;
}
/// <summary>
/// 结构化交易特殊处理
/// </summary>
/// <param name="req"></param>
/// <returns></returns>
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;
}
}
}