Files
zszq-trs/YLErpDAL/Modules/RiskHedgingModule/TradeAutoRuleService.cs
T
2024-05-09 14:06:26 +08:00

167 lines
6.4 KiB
C#

using YLErp.Model;
using YLErp.Models;
namespace YLErp.Modules.RiskHedgingModule
{
/// <summary>
/// 自动对冲规则服务
/// </summary>
public class TradeAutoRuleService : YLBaseService
{
public TradeAutoRuleService(OptUserInfo userInfo) : base(userInfo)
{
}
/// <summary>
/// 为风险对冲页面应用自动对冲规则
/// </summary>
public void ApplyAutoRuleForShowing(int userId, IEnumerable<TradingRiskParameter> groupRisks)
{
var autoRuleDic = DbContext.trade_autorule.Where(n => n.OptId == userId && n.Enable)
.Select(n => new trade_autoruleDto
{
UnderlyingCode = n.UnderlyingCode,
DeltaPercent = n.DeltaPercent / 100,
PnlAdjust = n.PnlAdjust,
PnlAdjustType = n.PnlAdjustType
}).ToDictionary(n => n.UnderlyingCode, StringComparer.OrdinalIgnoreCase);
if (!autoRuleDic.Any())
{
return;
}
foreach (var g in groupRisks ?? Enumerable.Empty<TradingRiskParameter>())
{
if (g.viewList == null || !autoRuleDic.TryGetValue(g.UnderlyingCode, out var rule))
{
continue;
}
double notionalSum = 0, deltaSum = 0, deltaLotsSum = 0;
foreach (var item in g.viewList)
{
//对冲交易应用规则
if (ConsTrade.TradeTypesForHedge.Contains(item.TradeType))
{
if (double.IsNaN(item.ExercisePnl) || double.IsInfinity(item.ExercisePnl))
{
item.ExercisePnl = 0;
}
if (double.IsNaN(item.TotalPnl) || double.IsInfinity(item.TotalPnl))
{
item.TotalPnl = 0;
}
if (rule.PnlAdjustType == "固定")
{
item.TotalPnl += rule.PnlAdjust;
item.ExercisePnl += rule.PnlAdjust;
}
else if (rule.PnlAdjustType == "比例")
{
item.TotalPnl *= 1 + rule.PnlAdjust / 100;
item.ExercisePnl *= 1 + rule.PnlAdjust / 100;
}
if (rule.DeltaPercent > 0)
{
item.Delta /= rule.DeltaPercent;
item.DeltaInLots /= rule.DeltaPercent;
}
}
else if (!double.IsNaN(item.Notional) && !double.IsInfinity(item.Notional))
{
notionalSum += item.Notional;
}
if (!double.IsNaN(item.Delta) && !double.IsInfinity(item.Delta))
{
deltaSum += item.Delta;
deltaLotsSum += item.DeltaInLots;
}
}
//设置组数据
g.Delta = deltaSum;
g.DeltaInLots = deltaLotsSum;
g.DeltaPercent = deltaSum / notionalSum;
if (double.IsNaN(g.ExercisePnl) || double.IsInfinity(g.ExercisePnl))
{
g.ExercisePnl = 0;
}
if (double.IsNaN(g.TotalPnl) || double.IsInfinity(g.TotalPnl))
{
g.TotalPnl = 0;
}
if (rule.PnlAdjustType == "固定")
{
g.TotalPnl += rule.PnlAdjust;
g.ExercisePnl += rule.PnlAdjust;
}
else if (rule.PnlAdjustType == "比例")
{
g.TotalPnl *= 1 + rule.PnlAdjust / 100;
g.ExercisePnl *= 1 + rule.PnlAdjust / 100;
}
}
}
/// <summary>
/// 为风险对冲交易应用自动对冲规则
/// </summary>
public void ApplyAutoRuleForHedging(int userId, IEnumerable<TradingRiskParameter> groupRisks)
{
var autoRuleDic = DbContext.trade_autorule.Where(n => n.OptId == userId && n.Enable)
.Select(n => new trade_autoruleDto
{
UnderlyingCode = n.UnderlyingCode,
DeltaPercent = n.DeltaPercent / 100
}).ToDictionary(n => n.UnderlyingCode, StringComparer.OrdinalIgnoreCase);
foreach (var g in groupRisks)
{
g.DeltaPercent = 1;
if (g.viewList == null || !autoRuleDic.TryGetValue(g.UnderlyingCode, out var rule)
|| rule.DeltaPercent < 0.00001)
{
continue;
}
double otcDeltaInLotsSum = 0, hedgingDeltaInLotsSum = 0, ruleDeltaSum = 0;
foreach (var item in g.viewList)
{
if (ConsTrade.TradeTypesForHedge.Contains(item.TradeType))
{
if (double.IsNaN(item.Delta) || double.IsInfinity(item.Delta))
{
item.Delta = 0;
}
if (double.IsNaN(item.DeltaInLots) || double.IsInfinity(item.DeltaInLots))
{
item.DeltaInLots = 0;
}
hedgingDeltaInLotsSum += item.DeltaInLots;
item.Delta /= rule.DeltaPercent;
item.DeltaInLots /= rule.DeltaPercent;
}
else
{
otcDeltaInLotsSum += item.DeltaInLots;
}
if (!double.IsNaN(item.Delta) && !double.IsInfinity(item.Delta))
{
ruleDeltaSum += item.Delta;
}
}
//设置组数据
g.Delta = ruleDeltaSum;
g.DeltaPercent = rule.DeltaPercent;
g.DeltaInLots = hedgingDeltaInLotsSum + otcDeltaInLotsSum * rule.DeltaPercent;
}
}
}
}