255 lines
11 KiB
C#
255 lines
11 KiB
C#
using YLErp.BLL.Calculation;
|
|
using YLErp.DBModels.Helpers;
|
|
using YLErp.Enums;
|
|
using YLErp.Modules.MarginModule;
|
|
using YLErp.QdpModule;
|
|
|
|
namespace YLErp.BLL.MarginCalculation
|
|
{
|
|
/// <summary>
|
|
/// 申银万国
|
|
/// </summary>
|
|
public class SYWGMarginCalculation : MarginCalculationBase
|
|
{
|
|
// 定义一个静态变量来保存类的实例
|
|
public static readonly SYWGMarginCalculation Instance;
|
|
|
|
static SYWGMarginCalculation()
|
|
{
|
|
Instance = new SYWGMarginCalculation();
|
|
}
|
|
|
|
// 定义私有构造函数,使外界不能创建该类实例
|
|
private SYWGMarginCalculation()
|
|
{
|
|
}
|
|
|
|
public override List<trade_span> RunMarginCalculation(RunMarginCalculationReq req)
|
|
{
|
|
var tradeSpans = new List<trade_span>();
|
|
|
|
if (req.tradeList == null || req.tradeList.Count < 1)
|
|
{
|
|
return tradeSpans;
|
|
}
|
|
|
|
var tempStockTradeList = req.tradeList.Where(t => t.UnderlyingInstrumentType == ConsGlobal.InstrumentType.Stock).ToList();
|
|
if (tempStockTradeList.Any())
|
|
{
|
|
var stockTradeSpanlist = StockMarginCalculation(req.Clone(tempStockTradeList));
|
|
if (stockTradeSpanlist.Count > 0)
|
|
{
|
|
tradeSpans.AddRange(stockTradeSpanlist);
|
|
}
|
|
}
|
|
|
|
var tempFutureTradeList = req.tradeList.Where(t => t.UnderlyingInstrumentType == ConsGlobal.InstrumentType.CommodityFutures).ToList();
|
|
if (tempFutureTradeList.Any())
|
|
{
|
|
var futureTradeSpanlist = FutureMarginCalculation(req.Clone(tempFutureTradeList));
|
|
if (futureTradeSpanlist.Count > 0)
|
|
{
|
|
tradeSpans.AddRange(futureTradeSpanlist);
|
|
}
|
|
}
|
|
|
|
return tradeSpans;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 股票类期权计算预付金
|
|
/// </summary>
|
|
public List<trade_span> StockMarginCalculation(RunMarginCalculationReq req)
|
|
{
|
|
var tradeSpans = new List<trade_span>();
|
|
|
|
if (req.tradeList == null || req.tradeList.Count < 1)
|
|
{
|
|
return tradeSpans;
|
|
}
|
|
|
|
var marginRation = valuedateBLL.SystemDate.MarginRatio ?? 0.15;
|
|
var helper = new RunMarginCalculationHelper(req, _underlyingDataProvider);
|
|
|
|
foreach (var t in req.tradeList)
|
|
{
|
|
if (!helper.GetSpecialMargin(t, 0, out var value))
|
|
{
|
|
var client = helper.GetClient(t);
|
|
if (client == null)
|
|
{
|
|
continue;
|
|
}
|
|
var clientRatio = client?.Ratio ?? 1.0;
|
|
//如果是股票去名义本金,如果是期货取:份额 * 即期价格
|
|
value = (t.StockEqvNotional == 0 ? TradeHelper.GetStockEqvNotional(t.Notional * t.SpotPrice, t.ParticipationRate, t.AnnualizeFactor) : t.StockEqvNotional) * marginRation * (t.BuySell == "买入" ? 1 : 0) * clientRatio;
|
|
}
|
|
|
|
tradeSpans.Add(new trade_span
|
|
{
|
|
TradeId = t.id,
|
|
OptDate = DateTime.Now,
|
|
OptId = req.userId,
|
|
OptName = req.userName,
|
|
ClientId = t.ClientId,
|
|
UnderlyingId = t.UnderlyingId,
|
|
UnderlyingCode = t.UnderlyingCode,
|
|
ValueDate = req.settleDate,
|
|
Spv1 = value,
|
|
Spv2 = value,
|
|
Spv3 = value,
|
|
Spv4 = value,
|
|
WorstCastClientPayable = value
|
|
});
|
|
}
|
|
return tradeSpans;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 商品期权计算预付金
|
|
/// </summary>
|
|
public List<trade_span> FutureMarginCalculation(RunMarginCalculationReq req)
|
|
{
|
|
var futureTradeList = req.tradeList;
|
|
|
|
if (futureTradeList == null || !futureTradeList.Any())
|
|
{
|
|
return new List<trade_span>(0);
|
|
}
|
|
|
|
var tradeSpans = new List<trade_span>();
|
|
var helper = new RunMarginCalculationHelper(req, _underlyingDataProvider);
|
|
|
|
helper.SetFieldsByTradeType();
|
|
|
|
using (var db = new YLContext())
|
|
{
|
|
var underlyingCodes = futureTradeList.Select(t => t.UnderlyingCode).ToHashSet();
|
|
var mpProvider = new MarginParamProvider(req.UserInfo, req.settleDate).Initialize(underlyingCodes, MarginParamTypeEnum.MarginRate);
|
|
|
|
var overrideVolsForTrades = VolCaculator.Instance.GetVol(futureTradeList, req.settleDate);
|
|
|
|
var tradeRiskResult = CalculatorHelper.CalculateRisksForTrades(
|
|
valueDate: req.settleDate,
|
|
tradeList: futureTradeList,
|
|
calcScenario: req.GetCalcScenario(),
|
|
priceProvider: req.PriceProvider,
|
|
pricingRequest: QdpPricingRequest.BASIC_GREEKS, addVolRateDic: null,
|
|
volType: req.volType, overrideVolsForTrade: overrideVolsForTrades, isUseTradeVol: PS.Config.IsTradeVol,
|
|
preciseTimeMode: req.CalcMarginType != CalcMarginTypeEnum.EodMargin);
|
|
logger.Info($"商品期货预付金计算,交易入:[{futureTradeList.Count}条],返回[{tradeRiskResult.Results.Count}],错误:{tradeRiskResult.ErrorMessage}");
|
|
var alphaRate = valuedateBLL.SystemDate.FutureMarginAlphaRate ?? 1;
|
|
var FutureMarginAddRatio = valuedateBLL.SystemDate.FutureMarginAddRatio ?? 0;
|
|
|
|
if (tradeRiskResult.Results.Count <= 0)
|
|
{
|
|
return tradeSpans;
|
|
}
|
|
|
|
foreach (var trade in futureTradeList)
|
|
{
|
|
var closePrice = req.PriceProvider.GetPrice(trade.UnderlyingCode);
|
|
var optionValueList = tradeRiskResult.Results.Where(t => t.Trade.id == trade.id && t.ValueResult != null && t.Trade != null && !double.IsNaN(t.ValueResult.Delta) && !double.IsNaN(t.ValueResult.Vega) && !double.IsNaN(t.ValueResult.Gamma)).ToList();
|
|
|
|
//未设置相关预付金系数默认为1.0
|
|
double clientRatio = 1, clientAddRatio = 0;
|
|
var client = helper.GetClient(trade);
|
|
if (client != null)
|
|
{
|
|
clientRatio = client.Ratio ?? 1;
|
|
clientAddRatio = client.AddRatio ?? 0;
|
|
}
|
|
|
|
if (optionValueList.Any())
|
|
{
|
|
var deltaMerge = 0.0;
|
|
var deltaShort = optionValueList.Sum(t => t.ValueResult.Delta * (t.Trade.BuySell == "买入" ? 1 : 0));
|
|
var deltaMax = optionValueList.Sum(t => t.ValueResult.DeltaMax * (t.Trade.BuySell == "买入" ? 1 : 0));
|
|
//跨式组合和宽跨式组合用到的是组合交易里面的Max Delta作为deltaMerge参与预付金的计算
|
|
deltaMerge = trade.TradeType == "结构化交易" && (trade.StructureType == "跨式组合" || trade.StructureType == "宽跨式组合") ? Math.Abs(deltaMax) : Math.Abs(deltaShort);
|
|
logger.Info("交易id为" + trade.id + "的delta:" + deltaMerge);
|
|
//if (deltaLong * deltaShort == 0)
|
|
//{
|
|
// deltaMerge = Math.Abs(deltaShort);
|
|
//}
|
|
//else if (deltaLong * deltaShort < 0)
|
|
//{
|
|
// if (Math.Abs(deltaLong) >= Math.Abs(deltaShort))
|
|
// {
|
|
// deltaMerge = 0;
|
|
// }
|
|
// else
|
|
// {
|
|
// deltaMerge = Math.Abs(deltaShort) - Math.Abs(deltaLong);
|
|
// }
|
|
//}
|
|
//else
|
|
//{
|
|
// deltaMerge = Math.Abs(deltaShort);
|
|
//}
|
|
mpProvider.TryGetMarginRate(trade.UnderlyingCode, out var marginRate);
|
|
//预付金 = (交易预付金率+公司预付金率加点)*合约名义金额(期货价格*数量)*delta
|
|
var margin = deltaMerge * closePrice * (marginRate + FutureMarginAddRatio + clientAddRatio) * alphaRate * clientRatio;
|
|
|
|
if (trade.TradeType == "自定义交易")
|
|
{
|
|
if (helper.GetSpecialMargin(trade, 0, out var value))
|
|
{
|
|
margin = value;
|
|
}
|
|
}
|
|
|
|
tradeSpans.Add(new trade_span
|
|
{
|
|
TradeId = trade.id,//默认记录为第一条交易记录中
|
|
OptDate = DateTime.Now,
|
|
OptId = req.userId,
|
|
OptName = req.userName,
|
|
ClientId = trade.ClientId,
|
|
ValueDate = req.settleDate,
|
|
UnderlyingId = trade.UnderlyingId,
|
|
UnderlyingCode = trade.UnderlyingCode,
|
|
Spv1 = margin,
|
|
Spv2 = margin,
|
|
Spv3 = margin,
|
|
Spv4 = margin,
|
|
WorstCastClientPayable = margin,
|
|
Comment = $"标的{trade.UnderlyingCode},deltaMerge:{deltaMerge},closePrice:{closePrice},Margin:{marginRate},FutureMarginAddRatio:{FutureMarginAddRatio},clientAddRatio:{clientAddRatio},alphaRate:{alphaRate},clientRatio:{clientRatio}"
|
|
});
|
|
}
|
|
else
|
|
{
|
|
var nanTradeValue = tradeRiskResult.Results.Where(t => t.Trade.id == trade.id && (double.IsNaN(t.ValueResult.Delta) || !double.IsNaN(t.ValueResult.Vega) || !double.IsNaN(t.ValueResult.Gamma))).Select(t => t.ValueResult).ToList();
|
|
nanTradeValue.ForEach(optionValue =>
|
|
{
|
|
logger.Error($"交易ID:{trade.UnderlyingId},Delta:{optionValue.Delta},DeltaCash{optionValue.DeltaCash},Vega{optionValue.Vega},Gamma:{optionValue.Gamma},vol:{optionValue.Vol}");
|
|
});
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
return 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)
|
|
{
|
|
return tradeMargin.FirstOrDefault()?.WorstCastClientPayable ?? 0.0;
|
|
}
|
|
return 0.0;
|
|
}
|
|
}
|
|
}
|