277 lines
12 KiB
C#
277 lines
12 KiB
C#
using System.Linq.Expressions;
|
|
using YLErp.Helpers;
|
|
using YLErp.Model;
|
|
using YLErp.Modules.DataProviderModule;
|
|
using YLErp.Modules.SwapModule;
|
|
using YLErp.Modules.TradeModule;
|
|
using YLErp.Modules.TradeModule.DealModule;
|
|
using YLErp.Modules.TradeModule.ExoticOptionModule;
|
|
using YLErp.QdpModule;
|
|
|
|
namespace YLErp.Modules.EodModule.SettlementModule
|
|
{
|
|
/// <summary>
|
|
/// 检查障碍期权、美式二元等待观察的期权交易状态 并同步日终快照信息
|
|
/// </summary>
|
|
class EodCheckMonitoredTrade : EodSettleServiceBaseV2
|
|
{
|
|
public const string Step = "检查期权观察状态";
|
|
|
|
private static IYcLogger logger = LogFactory.GetLogger<EodCheckMonitoredTrade>();
|
|
|
|
readonly IEnumerable<trade> _trades;
|
|
|
|
public EodCheckMonitoredTrade(EodSettlementContextV2 context) : base(context)
|
|
{
|
|
if (_context is EodSettlementContextV2 contextV2)
|
|
{
|
|
_trades = contextV2.OtcTrades;
|
|
}
|
|
}
|
|
|
|
private Action<OtcTrade, T> getAfterKnowInOut<T>(Expression<Func<trade, T>> propExp)
|
|
{
|
|
if (_trades == null) return null;
|
|
|
|
var valueParam = Expression.Parameter(typeof(T));
|
|
|
|
var assign = Expression.Lambda<Action<trade, T>>(
|
|
Expression.Assign(propExp.Body, valueParam), propExp.Parameters.Single(), valueParam).Compile();
|
|
|
|
return new Action<OtcTrade, T>((td, tdex) =>
|
|
{
|
|
if (td != null && tdex != null)
|
|
{
|
|
var otd = _trades.FirstOrDefault(t => t.id == td.id);
|
|
if (otd != null)
|
|
{
|
|
assign(otd, tdex);
|
|
otd.MetaDic.Remove("from_eod_trade");
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// 检查障碍期权、美式二元等待观察的期权交易状态 并同步日终快照信息
|
|
/// </summary>
|
|
public void ExecuteTask1(Action<string> setTaskStep)
|
|
{
|
|
var blReset = false;
|
|
var settleDate = _context.SettleDate;
|
|
var clienIds = _context.Request.ClientIds;
|
|
var eodPriceProvider = _context.GetEodPriceProvider();
|
|
|
|
//设置障碍期权敲入敲出
|
|
setTaskStep?.Invoke("设置障碍期权敲入敲出");
|
|
new BarrierOptionKnockioService(OptUser).SetKnockInOut(settleDate, eodPriceProvider, _context.StartDate
|
|
, getAfterKnowInOut(t => t.trade_barrier_option),clienIds);
|
|
|
|
//检查美式二元期权状态
|
|
|
|
setTaskStep?.Invoke("检查美式二元期权状态");
|
|
|
|
new BinaryOptionDealService(OptUser).CheckTouchStatus(settleDate, eodPriceProvider, _context.StartDate
|
|
, getAfterKnowInOut(t => t.trade_binary_option), clienIds);
|
|
|
|
//检查双鲨期权
|
|
|
|
setTaskStep?.Invoke("检查双鲨期权");
|
|
|
|
new DoubleSharkOptionKnockoutService(OptUser).CheckKnockoutStatus(settleDate, eodPriceProvider, _context.StartDate
|
|
, getAfterKnowInOut(t => t.trade_double_sharkfin_option), clienIds);
|
|
|
|
//检查区间累积期权
|
|
|
|
setTaskStep?.Invoke("检查区间累积期权");
|
|
|
|
new TradeRangeAccrualService(OptUser).CheckStatus(settleDate, eodPriceProvider, _context.StartDate
|
|
, getAfterKnowInOut(t => t.trade_rangeaccrual), clienIds);
|
|
|
|
//检查气囊结构
|
|
|
|
setTaskStep?.Invoke("检查气囊结构");
|
|
|
|
new TradeAirbagService(OptUser).SetKnockIn(settleDate, eodPriceProvider, _context.StartDate
|
|
, getAfterKnowInOut(t => t.trade_airbag), clienIds);
|
|
|
|
//检查互换结算日资金处理
|
|
setTaskStep?.Invoke("检查互换结算日处理");
|
|
new TradeSwapService(OptUser).HandleSwapTradeCashPre(settleDate, clienIds);
|
|
|
|
//检查累计期权
|
|
|
|
setTaskStep?.Invoke("检查累计期权");
|
|
|
|
new TradeModule.AccumulatorOptionModule.TradeAccumulatorService(OptUser).CheckSettleStatus(settleDate, eodPriceProvider, out var tdForwadList, _context.StartDate, (td, tdAcc) =>
|
|
{
|
|
blReset = ConsTrade.TradeCompleteStatus.Contains(td.TradeStatus);
|
|
}, clienIds);
|
|
|
|
if (blReset)
|
|
{
|
|
_context.InitOtcTrades();
|
|
}
|
|
else if (tdForwadList != null && tdForwadList.Any())
|
|
{
|
|
_context.OtcTrades.AddRange(tdForwadList);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 检查障碍期权、美式二元等待观察的期权交易状态 并同步日终快照信息
|
|
/// </summary>
|
|
public void ExecuteTask2(Action<string> setTaskStep)
|
|
{
|
|
var settleDate = _context.SettleDate;
|
|
|
|
var eodPriceProvider = _context.GetEodPriceProvider();
|
|
|
|
var clienIds = _context.Request.ClientIds;
|
|
//检查凤凰期权
|
|
|
|
setTaskStep?.Invoke("检查凤凰期权");
|
|
|
|
new TradeAutocallBLL(OptUser).CheckStatus(settleDate, eodPriceProvider, _context.StartDate
|
|
, getAfterKnowInOut(t => t.trade_autocall), clienIds);
|
|
|
|
//检查雪球期权
|
|
|
|
setTaskStep?.Invoke("检查雪球期权");
|
|
|
|
new TradeSnowballBLL(OptUser).CheckStatus(settleDate, eodPriceProvider, _context.StartDate
|
|
, getAfterKnowInOut(t => t.trade_snowball), clienIds);
|
|
}
|
|
/// <summary>
|
|
/// 自动定期计算互换收益
|
|
/// </summary>
|
|
/// <param name="setTaskStep"></param>
|
|
public void ExecuteBalanceSwapProfit(Action<string> setTaskStep)
|
|
{
|
|
setTaskStep?.Invoke("定期结算互换收益");
|
|
var settleDate = _context.SettleDate;
|
|
var clientIds=_context.Request.ClientIds;
|
|
new EodSwapSettleService(OptUser).BalanceSwapTrade(settleDate, clientIds);
|
|
}
|
|
/// <summary>
|
|
/// 自动归档收益互换
|
|
/// </summary>
|
|
/// <param name="setTaskStep"></param>
|
|
public void ExecuteEodSwapPosition(Action<string> setTaskStep)
|
|
{
|
|
setTaskStep?.Invoke("定期归档收益互换");
|
|
var settleDate = _context.SettleDate;
|
|
var clientIds = _context.Request.ClientIds;
|
|
var nextSettleDate = QdpCalendarHelper.GetNonHoliday(settleDate.AddDays(1));
|
|
var days = (nextSettleDate - settleDate).Days;
|
|
logger.Info("settleDate:" + settleDate.ToString("yyyy-MM-dd") + " nextSettleDate:" + nextSettleDate + " days:" + days);
|
|
for (var i = 0; i < days; i++)
|
|
{
|
|
var yesterday = settleDate.AddDays(i - 1);
|
|
var today = settleDate.AddDays(i);
|
|
new SwapEodPositionService(OptUser).SwapPositionCompose(today, yesterday, clientIds);
|
|
CalculateMargin(today, yesterday, clientIds);
|
|
new SwapEodPositionService(OptUser).SwapEodCompose(today, yesterday, clientIds);
|
|
}
|
|
|
|
}
|
|
/// <summary>
|
|
/// 计算互换预付金(保证金模板V2 引擎,本端闭环)。
|
|
/// 2026-08-26 收口:原实现 HTTP 调 bond-oms /marginAlgorithm/triggerMarginCalc——Java 按 marginrate
|
|
/// (旧预付金率维护数据)对在市互换算盯市并清写当天 trade_span/client_span;现改为直接跑本端预付金引擎
|
|
/// EodWorstClientPayableCalc(模板V2 三级层解析:无预付金=0、区间追保结构 x/y 或方案B收盘落档,
|
|
/// 产出 trade_span.Spv 并聚合 client_span),保证金计算→追加预付金生成闭环全部在 .NET。
|
|
/// 交易范围与原 Java selectPreCloseTradeList 同口径:在市收益互换(确认成交未到期 + 平仓日落在区间),
|
|
/// 剔除多空组合子交易(引擎本身跳过);"日终持仓结算"步骤随后会对确认成交全集幂等重算覆盖。
|
|
/// Java 侧自此仅保留资金通知书邮件与 DMA 实时预付金(RealtimePnlCalc.CalcDMAMargin,迁移方案阶段三待切项)。
|
|
/// preSettleDate 参数保留以维持调用签名,引擎取数按 settleDate 自行解析。
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public bool CalculateMargin(DateTime settleDate, DateTime preSettleDate, IEnumerable<int> ClientIds)
|
|
{
|
|
var clientIds = ClientIds?.Where(x => x > 0).Distinct().ToList();
|
|
List<trade> tradeList;
|
|
using (var db = new YLErp.BLL.YLContext())
|
|
{
|
|
var query = db.trade.Where(t => t.TradeType == "收益互换"
|
|
&& t.ValidState != YLErp.ConsGlobal.InValid
|
|
&& t.ParentTradeId == 0
|
|
&& ((t.TradeStatus == YLErp.DBModels.ConsTrade.确认成交 && t.TradeDate <= settleDate && t.ExerciseDate >= settleDate)
|
|
|| (t.TradeStatus == YLErp.DBModels.ConsTrade.已平仓 && t.TradeDate <= settleDate
|
|
&& t.UnWindDate > settleDate && t.UnWindDate > t.StartDate)));
|
|
if (clientIds != null && clientIds.Count > 0)
|
|
{
|
|
var idScope = clientIds;
|
|
query = query.Where(t => idScope.Contains(t.ClientId));
|
|
}
|
|
tradeList = query.ToList();
|
|
}
|
|
new EodWorstClientPayableCalc(_context).WorstClientPayableCalc(tradeList);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 检查障碍期权、美式二元等待观察的期权交易状态 并同步日终快照信息
|
|
/// </summary>
|
|
public class EodCheckMonitoredTradeSingle
|
|
{
|
|
public const string Step = "检查期权观察状态";
|
|
|
|
OptUserInfo user;
|
|
|
|
public EodCheckMonitoredTradeSingle(OptUserInfo opt)
|
|
{
|
|
user = opt;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 检查障碍期权、美式二元等待观察的期权交易状态 并同步日终快照信息
|
|
/// </summary>
|
|
public void ExecuteTask(DateTime StartDate, List<int> ClientIds)
|
|
{
|
|
var blReset = false;
|
|
var settleDate = StartDate;
|
|
var clienIds = ClientIds;
|
|
var eodPriceProvider = new EodPriceProvider(settleDate);
|
|
|
|
//设置障碍期权敲入敲出
|
|
new BarrierOptionKnockioService(user).SetKnockInOut(settleDate, eodPriceProvider, null
|
|
, null, clienIds);
|
|
|
|
//检查美式二元期权状态
|
|
new BinaryOptionDealService(user).CheckTouchStatus(settleDate, eodPriceProvider, null
|
|
, null, clienIds);
|
|
|
|
//检查双鲨期权
|
|
new DoubleSharkOptionKnockoutService(user).CheckKnockoutStatus(settleDate, eodPriceProvider, null
|
|
, null, clienIds);
|
|
|
|
//检查区间累积期权
|
|
new TradeRangeAccrualService(user).CheckStatus(settleDate, eodPriceProvider, null
|
|
, null, clienIds);
|
|
|
|
//检查气囊结构
|
|
new TradeAirbagService(user).SetKnockIn(settleDate, eodPriceProvider, null
|
|
, null, clienIds);
|
|
|
|
//检查互换结算日资金处理
|
|
new TradeSwapService(user).HandleSwapTradeCashPre(settleDate, clienIds);
|
|
|
|
//检查累计期权
|
|
new TradeModule.AccumulatorOptionModule.TradeAccumulatorService(user).CheckSettleStatus(settleDate, eodPriceProvider, out var tdForwadList, null, (td, tdAcc) =>
|
|
{
|
|
blReset = ConsTrade.TradeCompleteStatus.Contains(td.TradeStatus);
|
|
}, clienIds);
|
|
|
|
//检查凤凰期权
|
|
new TradeAutocallBLL(user).CheckStatus(settleDate, eodPriceProvider, null
|
|
, null, clienIds);
|
|
|
|
//检查雪球期权
|
|
new TradeSnowballBLL(user).CheckStatus(settleDate, eodPriceProvider, null
|
|
, null, clienIds);
|
|
}
|
|
}
|
|
}
|