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

148 lines
5.7 KiB
C#

using YLErp.Abstract.DataProviders;
using YLErp.Modules.DataProviderModule;
namespace YLErp.Modules.TradeModule
{
/// <summary>
/// 气囊结构服务
/// </summary>
public class TradeAirbagService : TradeServiceBase
{
public TradeAirbagService(OptUserInfo userInfo) : base(userInfo)
{
}
public TradeAirbagService(YLBaseService baseService) : base(baseService)
{
}
public void SetKnockIn(DateTime valueDate, IEodPriceProviderV2 priceProvider, DateTime? startDate = null
, Action<OtcTrade, trade_airbag> afterKnowInOut = null, System.Collections.Generic.IEnumerable<int> clienIds = null)
{
if (priceProvider is null)
{
priceProvider = new EodPriceProvider(valueDate);
}
if (startDate == null)
{
startDate = valueDate.AddYears(-5);
}
var query = from trade in DbContext.trade
join airbag in DbContext.trade_airbag on trade.id equals airbag.TradeId
where trade.TradeDate > startDate.Value && trade.TradeDate <= valueDate
&& string.IsNullOrEmpty(airbag.KnockInOutStatus)
&& trade.TradeType == "气囊结构"
&& ConsTrade.确认成交 == trade.TradeStatus
&& trade.ValidState != ConsGlobal.InValid
&& trade.DividendDate < valueDate
select new
{
trade,
tradeAirbag = airbag
};
#region 增加客户筛选 tw
if (clienIds != null)
{
query = query.Where(l => clienIds.Contains(l.trade.ClientId));
}
#endregion
var trades = query.ToList();
if (trades == null || !trades.Any())
{
return;
}
var tradeIds = trades.Select(x => x.trade.id).ToArray();
var manuallyTradeObservationPrices = DbContext.manually_trade_observation_price
.Where(x => tradeIds.Contains(x.TradeId) && x.ValueDate == valueDate).ToDictionary(n => n.TradeId);
foreach (var tr in trades)
{
if (tr.trade.ExerciseDate < valueDate)
{
continue;//已到期交易不再观察;
}
var tradeStatus = tr.trade.TradeStatus;
double? closePrice;
if (manuallyTradeObservationPrices.TryGetValue(tr.trade.id, out var manuallyTradeObservationPrice))
{
closePrice = manuallyTradeObservationPrice.Price;
}
else if (!priceProvider.TryGetEodPrice(tr.trade.UnderlyingCode, out var eodprice))
{
throw new Exception($"[{tr.trade.TradeType}:{tr.trade.TradeNumber}]标的:{tr.trade.UnderlyingCode} 未找到结算价");
}
else
{
closePrice = eodprice.ClosePrice;
}
var oldKnockInOutStatus = tr.tradeAirbag.KnockInOutStatus;
CheckAirbagKnockInStatus(tr.trade, tr.tradeAirbag, valueDate, closePrice);
if (oldKnockInOutStatus != tr.tradeAirbag.KnockInOutStatus)
{
var KnockInOutStatus = tr.tradeAirbag.KnockInOutStatus == ConsTrade.KnockState.KnockedIn ? "敲入" : "敲出";
AddTradeOperationHistoryAndSetParentTradeInfo(false, tr.trade, KnockInOutStatus, KnockInOutStatus);
}
if (tradeStatus != tr.trade.TradeStatus|| oldKnockInOutStatus != tr.tradeAirbag.KnockInOutStatus)
{
//删除E/Bod_Trade记录
RemoveEodTradeAndFutureInfo(false, tr.trade.id, valueDate);
}
if (afterKnowInOut != null && DbContext.Entry(tr.tradeAirbag).State == EntityState.Modified)
{
afterKnowInOut(tr.trade, tr.tradeAirbag);
}
}
//更新
DbContext.SaveChanges();
}
public void CheckAirbagKnockInStatus(OtcTradeBase td, trade_airbag tradeAirbag, DateTime valueDate, double? closePrice)
{
//气囊结构暂时都是每日连续观察,不用考虑观察周期问题
//气囊结构暂时都是向下敲入
if (closePrice <= (td.IsMoneynessOptionData ? tradeAirbag.Barrier * td.SpotPrice : tradeAirbag.Barrier))
{
tradeAirbag.KnockInOutStatus = ConsTrade.KnockState.KnockedIn;
tradeAirbag.KnockInOutDate = valueDate;
tradeAirbag.KnockInOutNotional = td.Notional;
}
}
/// <summary>
/// 设置敲入敲出状态
/// </summary>
public trade_airbag SaveKnockInOutStatus(int tradeId, DateTime? KnockInOutDate, string KnockInOutStatus)
{
var airbag = DbContext.trade_airbag.FirstOrDefault(x => x.TradeId == tradeId);
if (airbag != null)
{
airbag.KnockInOutDate = KnockInOutDate;
airbag.KnockInOutStatus = KnockInOutStatus;
airbag.OptId = UserId;
airbag.OptName = UserName;
airbag.OptDate = DateTime.Now;
DbContext.SaveChanges();
var td = DbContext.trade.Find(tradeId);
SaveTradeOperationHistory(td, airbag.KnockInOutStatusCn);
}
return airbag;
}
}
}