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

328 lines
16 KiB
C#

using YLErp.BLL.Calculation;
using YLErp.Enums;
using YLErp.Model.Enum;
using YLErp.Modules.CalculationModule;
using YLErp.QdpModule;
namespace YLErp.BLL.MarginCalculation
{
public class HongYeMarginCalculation : MarginCalculationBase
{
//定义一个静态变量来保存类的实例(单例模式)
public static readonly HongYeMarginCalculation Instance;
static HongYeMarginCalculation()
{
Instance = new HongYeMarginCalculation();
}
//定义私有构造函数,使外界不能创建该类实例
private HongYeMarginCalculation()
{
}
public override List<trade_span> RunMarginCalculation(RunMarginCalculationReq req)
{
if (req.tradeList == null || !req.tradeList.Any())
{
return new List<trade_span>();
}
return CalcMargin(req).ToList();
}
private IEnumerable<trade_span> CalcMargin(RunMarginCalculationReq req)
{
var resultMap = new Dictionary<int, trade_span>();
var helper = new RunMarginCalculationHelper(req, _underlyingDataProvider);
//为了算客户角度的一个预付金数值
helper.ReverseTradeSide();
helper.SetFieldsByTradeType();
var calcReq = helper.GetCalculateRisksForTradesReq(req.PriceProvider, null, null, QdpPricingRequest.BASIC_PRICING);
switch (req.CalcMarginType)
{
case CalcMarginTypeEnum.InitialMargin:
calcReq.volType = "开仓";
calcReq.isUseTradeVol = false;
break;
case CalcMarginTypeEnum.None:
case CalcMarginTypeEnum.EodMargin:
default:
calcReq.volType = "交易";
calcReq.isUseTradeVol = true;
break;
}
var tradeRiskResult = CalculatorHelper.CalculateRisksForTrades(calcReq);
foreach (var item in tradeRiskResult.Results)
{
resultMap[item.Trade.id] = generateTradeSpan(
(resultMap.ContainsKey(item.Trade.id) ? resultMap[item.Trade.id] : null),
item,
helper,
req);
}
var structureIds = new List<int>();
var tDict =
(from r in tradeRiskResult.Results
join ts in resultMap
on r.Trade.id equals ts.Key
where r.Trade.TradeType == "结构化交易" ||
r.Trade.ParentTradeId != 0
group new { r, ts } by r.Trade.ParentTradeId into rGroup
select rGroup).ToDictionary(K => K.First().r.Trade, V => V.ToList());
if (tDict.Count > 0)
{
foreach (var structureItem in tDict)
{
var client = GetClientInfo(structureItem.Key.ClientId);
var direction = structureItem.Value.Select(O => O.r.Trade.BuySell).ToHashSet();
double value = 0;
var index = 0;
if ((structureItem.Key.StructureType == "牛市价差" || structureItem.Key.StructureType == "熊市价差") && structureItem.Value.Count >= 2)
{
if (client != null && (MarginOptionEnum)client.MarginOptionType == MarginOptionEnum.单向追保)
{
var buyLeg = structureItem.Value.Where(O => O.r.Trade.BuySell == "买入").FirstOrDefault();
var buyMargin = (buyLeg?.ts.Value.WorstCastClientPayable) ?? 0;
foreach (var item in structureItem.Value)
{
setTradeSpanValue(item.ts.Value, 0);
}
if (structureItem.Value.Sum(O => O.r.ValueResult.Pv) > 0)
{
var strikes = structureItem.Value.Select(O => ((O.r.Trade.IsMoneynessOption == "是" ? (O.r.Trade.SpotPrice * O.r.Trade.Strike) : O.r.Trade.Strike) ?? 0)).ToArray();
value = Math.Abs((strikes[0] - strikes[1]) * structureItem.Key.Notional);
setTradeSpanValue(buyLeg.ts.Value, Math.Min(value, buyMargin));
}
}
else if (client != null && (MarginOptionEnum)client.MarginOptionType == MarginOptionEnum.对手方单向追保)
{
var sellLeg = structureItem.Value.Where(O => O.r.Trade.BuySell == "卖出").FirstOrDefault();
var sellMargin = (sellLeg?.ts.Value.WorstCastClientPayable) ?? 0;
foreach (var item in structureItem.Value)
{
setTradeSpanValue(item.ts.Value, 0);
}
if (structureItem.Value.Sum(O => O.r.ValueResult.Pv) < 0)
{
var strikes = structureItem.Value.Select(O => ((O.r.Trade.IsMoneynessOption == "是" ? (O.r.Trade.SpotPrice * O.r.Trade.Strike) : O.r.Trade.Strike) ?? 0)).ToArray();
value = Math.Abs((strikes[0] - strikes[1]) * structureItem.Key.Notional);
setTradeSpanValue(sellLeg.ts.Value, Math.Min(value, sellMargin));
}
}
}
else if (structureItem.Key.StructureType.Contains("跨式") && structureItem.Value.Count == 2)
{
var minLeg = structureItem.Value[1];
if (Math.Abs(structureItem.Value[0].r.ValueResult.Delta) < Math.Abs(structureItem.Value[1].r.ValueResult.Delta))
{
minLeg = structureItem.Value[0];
}
setTradeSpanValue(minLeg.ts.Value, minLeg.r.ValueResult.Pv);
}
else
{
if (client != null)
{
switch ((MarginOptionEnum)client.MarginOptionType)
{
case MarginOptionEnum.对手方单向追保:
if (direction.Count == 1)
{
value = double.MaxValue;
//最小值
for (var i = 0; i < structureItem.Value.Count; i++)
{
if (value > structureItem.Value[i].ts.Value.WorstCastClientPayable)
{
index = i;
value = structureItem.Value[i].ts.Value.WorstCastClientPayable ?? 0;
}
setTradeSpanValue(structureItem.Value[i].ts.Value, 0);
structureIds.Add(structureItem.Value[i].ts.Key);
}
setTradeSpanValue(structureItem.Value[index].ts.Value, value);
}
break;
case MarginOptionEnum.单向追保:
case MarginOptionEnum.双向追保:
default:
if (direction.Count == 1)
{
value = double.MinValue;
//最大值
for (var i = 0; i < structureItem.Value.Count; i++)
{
if (value < structureItem.Value[i].ts.Value.WorstCastClientPayable)
{
index = i;
value = structureItem.Value[i].ts.Value.WorstCastClientPayable ?? 0;
}
setTradeSpanValue(structureItem.Value[i].ts.Value, 0);
structureIds.Add(structureItem.Value[i].ts.Key);
}
setTradeSpanValue(structureItem.Value[index].ts.Value, value);
}
break;
}
}
else
{
if (direction.Count == 1)
{
value = double.MinValue;
//最大值
for (var i = 0; i < structureItem.Value.Count; i++)
{
if (value < structureItem.Value[i].ts.Value.WorstCastClientPayable)
{
index = i;
value = structureItem.Value[i].ts.Value.WorstCastClientPayable ?? 0;
}
setTradeSpanValue(structureItem.Value[i].ts.Value, 0);
structureIds.Add(structureItem.Value[i].ts.Key);
}
setTradeSpanValue(structureItem.Value[index].ts.Value, value);
}
}
}
}
}
var tList = (from r in tradeRiskResult.Results
join ts in resultMap
on r.Trade.id equals ts.Key
where !structureIds.Contains(r.Trade.id)
select new { r, ts }).ToList();
if (tList.Count > 0)
{
foreach (var item in tList)
{
double value = 0;
var client = GetClientInfo(item.r.Trade.ClientId);
if (client != null)
{
switch ((MarginOptionEnum)client.MarginOptionType)
{
case MarginOptionEnum.单向追保:
value = item.ts.Value.WorstCastClientPayable ?? 0;
value = Math.Max(value, 0);
break;
case MarginOptionEnum.对手方单向追保:
value = item.ts.Value.WorstCastClientPayable ?? 0;
value = Math.Max(value, 0);
break;
case MarginOptionEnum.双向追保:
default:
value = item.ts.Value.WorstCastClientPayable ?? 0;
break;
}
}
else
{
value = item.ts.Value.WorstCastClientPayable ?? 0;
}
item.ts.Value.Spv1 = value;
item.ts.Value.Spv2 = value;
item.ts.Value.Spv3 = value;
item.ts.Value.Spv4 = value;
item.ts.Value.SetWorstCastClientPayable();
}
}
return resultMap.Values.ToList();
}
private trade_span generateTradeSpan(trade_span trade_Span, TradeRiskResultRecord record, RunMarginCalculationHelper helper, RunMarginCalculationReq req)
{
if (trade_Span == null)
{
trade_Span = helper.CreateTradeSpan(record.Trade);
}
var client = GetClientInfo(record.Trade.ClientId);
double value;
if (req.CalcMarginType == CalcMarginTypeEnum.InitialMargin && record.Trade.TradeType == "收益互换")
{
var pnl = record.Trade.trade_swap.GetTradePrice.GetValueOrDefault() - record.Trade.trade_swap.PayTradePrice.GetValueOrDefault() - record.ValueResult.Pv;
helper.GetSpecialMargin(record.Trade, pnl, out value);
}
else if (record.Trade.TradeType == "远期" || record.Trade.TradeType == "收益互换")
{
var marginRate = helper.GetMarginParamProvider().GetMarginRate(record.Trade.UnderlyingCode) ?? 0;
var price = req.PriceProvider.GetPrice(record.Trade.UnderlyingCode);
value = price * marginRate * record.Trade.Notional + Math.Max((record.ValueResult.Pv - record.Trade.TradePrice ?? 0), 0);
}
else
{
var marginRate = helper.GetMarginParamProvider().GetMarginRate(record.Trade.UnderlyingCode) ?? 0;
var price = req.PriceProvider.GetPrice(record.Trade.UnderlyingCode);
var delta = Math.Abs(record.ValueResult.Delta);
if (record.ValueResult.Pv < 0)
{
delta = -delta;
}
if (HasTwoSideMargin(record.Trade.ClientId))
{
value = record.ValueResult.Pv + delta * marginRate * price;
}
else if (!helper.GetSpecialMargin(record.Trade, 0, out value))
{
double ratio;
switch (req.CalcMarginType)
{
case CalcMarginTypeEnum.InitialMargin:
ratio = client?.Ratio1 ?? 1;
break;
case CalcMarginTypeEnum.None:
case CalcMarginTypeEnum.EodMargin:
default:
ratio = client?.Ratio ?? 1;
break;
}
value = record.ValueResult.Pv + ratio * delta * marginRate * price;
}
}
trade_Span.Spv1 = value;
trade_Span.Spv2 = value;
trade_Span.Spv3 = value;
trade_Span.Spv4 = value;
trade_Span.SetWorstCastClientPayable();
return trade_Span;
}
private void setTradeSpanValue(trade_span obj, double value)
{
obj.Spv1 = value;
obj.Spv2 = value;
obj.Spv3 = value;
obj.Spv4 = value;
obj.SetWorstCastClientPayable();
}
public override double GetTradeMargin(GetTradeMarginReq req)
{
var trade = req.trade;
if (trade.TradeType == "结构化交易" && (trade.SubTrades == null || trade.SubTrades.Count() == 0))
{
using (var db = new YLContext())
{ 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;
}
}
}