using YLErp.DBModels.Consts; using YLErp.DBModels.Enums; using YLErp.DBModels.Helpers; using YLErp.Helpers; using YLErp.Modules.DataProviderModule; using YLErp.Modules.TradeModule; using YLErp.Modules.TradeModule.DealModule; using YLErp.QdpModule; namespace YLErp.Modules.EodModule.SettlementModule { /// /// 日终结算除权除息 /// public class EodDividenService : EodSettleServiceBase { public const string Step = "除权除息"; readonly DateTime _bodDate; public EodDividenService(EodSettlementContextBase context) : base(context) { _bodDate = QdpCalendarHelper.GetNonHoliday(SettleDate.AddDays(1)); } //------------------------------------------------------ // 备份次日初持仓数据 // 将settleDate未了结的交易,进行除权除息 // 将场内部分结果保存到bod_trade_position表和trade_position表 // 将场外部分结果保存到trade和bodTrade表 // 次日开仓场内持仓数据从bod_trade_position表开始 // 次日开仓场外交易数据从trade表开始 //------------------------------------------------------ /// /// 场内交易除权除息处理 /// public void Execute(IEnumerable eodPositionList) { if (eodPositionList is null || !eodPositionList.Any()) { return; } var exchangePositionList = eodPositionList.Where(O => ConsTrade.TradeTypesForHedge.Contains(O.TradeType)|| ConsTrade.BondTypeList.Contains(O.TradeType)).ToList(); var bodTradePositions = new DividendService(OptUser).Execute(_context.SettleDate, exchangePositionList); foreach (var item in bodTradePositions) { item.ValueDate = _bodDate; } using (var db = DbContextFactory.GetYLDbContext()) { db.BodTradePosition.AddRange(bodTradePositions); if (_context.IsCurrentDay) { var tpList = ConvertToTradePosition(bodTradePositions); db.TradePosition.AddRange(tpList); db.BulkDelete("1=1"); } BodTradePosition t; db.BulkDelete($"{nameof(t.ValueDate)}='{_bodDate:yyyy-MM-dd}'"); db.SaveChanges(_context.CancellationToken); } } /// /// 场外交易除权除息处理 /// public void Execute(IEnumerable trades) { if (trades is null || !trades.Any()) { return; } var bodTrades = new DividendService(OptUser).Execute(SettleDate, trades, out var useSaveTrades, out var useSaveUnderlyings); foreach (var item in bodTrades) { item.ValueDate = _bodDate; } bod_trade t; using (var db = DbContextFactory.GetYLDbContext()) { db.bod_Trade.AddRange(bodTrades); //更新underlying数据 if (useSaveUnderlyings.Any()) { var service = new DbRecordChangesService(UserInfo, db); List ucList = new List(); var ids = useSaveUnderlyings.Select(O => O.id); var dbUm = db.underlying_manager.Where(O => ids.Contains(O.id)).ToArray(); foreach (var item in useSaveUnderlyings) { var um = dbUm.FirstOrDefault(O => O.id == item.id); if (um == null) { continue; } var uc = new UnderlyingChanges { ChangeType = ConsInfoChangeType.Dividend, RecordId = um.id, FieldName = nameof(underlying_manager.SubData), FieldValue = um.SubData ?? "", NewValue = item.SubData ?? "", OptDate = SettleDate, Update = DateTime.Now }; ucList.Add(uc); um.SubData = item.SubData; } service.Save(ucList, false); } //更新trade数据 if (useSaveTrades.Any()) { var ids = useSaveTrades.Select(O => O.id).ToList(); var tradeList = db.trade.Where(O => ids.Contains(O.id)).ToList(); new TradeExtendService(UserInfo, db).SetTradeExtend(tradeList, tracking: true); foreach (var item in useSaveTrades) { var td = tradeList.FirstOrDefault(O => O.id == item.id); if (td == null || td.DividendDate >= item.DividendDate || td.OriginalNotional >= item.OriginalNotional || Math.Abs((td.OriginalNotional - item.OriginalNotional) ?? 0) < 1e-5) { continue; } //var changes = TradeChangeUtil.GetAllChanges(td, item); //var changsStr = TradeChangeUtil.SerializeChanges(changes, out var auditFlag); TradeHelper2.ReduceTradeExt(td); TradeHelper2.ReduceTradeExt(item); var changsStr = DataChangeHelper.GetDataChanges(td, item).ToJson(); db.TradeAuditLog.Add(new TradeAuditLog { TradeId = td.id, Changes = changsStr, DataType = "C01", OptId = UserId, OptName = UserName, OptDate = OptDate, OptType = "除权除息", AuditFlag = TradeAuditFlag.operation //| auditFlag }); var changeList = DividendService.GetDividendChanges(td, item); new DbRecordChangesService(OptUser, db).Save(changeList, false); DividendService.SetDividendTradeData(td, item); } } if (_context.ClienIds!=null&& _context.ClienIds.Any()) { string strClientWhere=string.Join(",", _context.ClienIds); db.BulkDelete($"{nameof(t.ValueDate)}='{_bodDate:yyyy-MM-dd}' and ClientId in ({strClientWhere})"); } else { db.BulkDelete($"{nameof(t.ValueDate)}='{_bodDate:yyyy-MM-dd}'"); } db.SaveChanges(_context.CancellationToken); } } private IEnumerable ConvertToTradePosition(IEnumerable positions) { var tpList = new List(); foreach (var item in positions) { DateTime maturityDate; if (item.TradeType == "股票") { maturityDate = DateTime.Today.AddYears(10); } else if (item.TradeType == "场内期权") { ExchangeOptionDataProvider.TryGetMaturityDate(item.ExchangeOptionCode, out var date); maturityDate = date; } else if (!UnderlyingDataProvider.TryGetMaturityDate(item.UnderlyingCode, out maturityDate)) { maturityDate = DateTime.Today.AddMonths(1); } tpList.Add(new TradePosition { BookId = item.BookId, TradeType = item.TradeType, TradeType1 = TradeHelper.GetTradeType1(item.TradeType), UnderlyingId = item.UnderlyingId, UnderlyingCode = item.UnderlyingCode, PositionType = item.PositionType == "long" ? PositionTypeFlag.Long : PositionTypeFlag.Short, Position = item.Amount, PositionCost = item.Cost, MaturityDate = maturityDate, InstrumentCode = item.ExchangeOptionCode, CreateTime = DateTime.Now, UpdateTime = DateTime.Now }); } return tpList; } } }