using YLErp.Abstract.DataProviders; using YLErp.Modules.DataProviderModule; namespace YLErp.Modules.TradeModule { /// /// 气囊结构服务 /// 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 afterKnowInOut = null, System.Collections.Generic.IEnumerable 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; } } /// /// 设置敲入敲出状态 /// 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; } } }