906 lines
67 KiB
C#
906 lines
67 KiB
C#
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($"广发商贸期权计算初始预付金情景五为:𝑆(𝑖,𝑛)×(1–1/3 𝑎):{prices[5][code]}={settlePrice}-{interval}*1");
|
||
prices[6][code] = settlePrice - (interval * 2);
|
||
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸期权计算初始预付金情景六为:𝑆(𝑖,𝑛)×(1–2/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($"广发商贸期权计算初始预付金情景十二为:𝑆(𝑖,𝑛)×(1–1/3 𝑎):{prices[12][code]}={settlePrice}-{interval}*1");
|
||
prices[13][code] = settlePrice - (interval * 2);
|
||
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸期权计算初始预付金情景十三为:𝑆(𝑖,𝑛)×(1–2/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($"广发商贸期权计算初始预付金情景五为:𝑆(𝑖,𝑛)×(1–1/3 𝑎):{prices[5][code]}={settlePrice}-{interval}*1");
|
||
prices[6][code] = settlePrice - (interval * 2);
|
||
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸期权计算初始预付金情景六为:𝑆(𝑖,𝑛)×(1–2/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($"广发商贸期权计算初始预付金情景十二为:𝑆(𝑖,𝑛)×(1–1/3 𝑎):{prices[12][code]}={settlePrice}-{interval}*1");
|
||
prices[13][code] = settlePrice - (interval * 2);
|
||
LogFactory.GetLogger<MarginCalculationBase>().Info($"广发商贸期权计算初始预付金情景十三为:𝑆(𝑖,𝑛)×(1–2/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;
|
||
}
|
||
}
|
||
} |