using System.Text; using YLErp.BLL; using YLErp.Modules.DataProviderModule; using YLErp.Modules.MarginModule; using YLErp.QdpModule; namespace YLErp.Modules.TradeModule.DealModule { public class TradeDelaySettlementService : TradeServiceBase { public TradeDelaySettlementService(YLBaseService baseService) : base(baseService) { } public TradeDelaySettlementService(OptUserInfo userInfo) : base(userInfo) { } private const string key = "ExerciseTradeUnderly"; public ExerciseTradeUnderly GetCacheExerciseTradeUnderly() { var _reture = DataCacheProvider.GetCache("ExerciseTradeUnderly"); ExerciseTradeUnderly exerciseTradeUnderly = (ExerciseTradeUnderly)_reture; if (_reture == null) { exerciseTradeUnderly = CheckExerciseTradeUnderly(); } return exerciseTradeUnderly; } /// /// 检察当日到期交易的标的状态 /// /// public ExerciseTradeUnderly CheckExerciseTradeUnderly() { ExerciseTradeUnderly exerciseTradeUnderly = new ExerciseTradeUnderly(); List delays = GetDelaySettlements(); exerciseTradeUnderly.underlystr = ""; exerciseTradeUnderly.datetime = DateTime.Now.ToString("yyyy/MM/dd/ HH:mm:ss"); if (delays.Any()) { StringBuilder underlyStr = new StringBuilder(); foreach (var item in delays) { underlyStr.Append(item.UnderlyCode).Append("(").Append(item.UnderlyState).Append(")").Append(","); } exerciseTradeUnderly.underlystr = underlyStr.ToString().Substring(0, underlyStr.Length - 1); } DataCacheProvider.SetCache(key, exerciseTradeUnderly, DateTime.Today.AddDays(1)); return exerciseTradeUnderly; } /// /// 获取异常标的列表 /// /// public List GetDelaySettlements(DateTime? date = null) { var valueDate = date ?? valuedateBLL.ValueDate; var lastDate = QdpCalendarHelper.GetNonHolidayDefore(valueDate.AddDays(-1)); List delays = new List(); //结构化交易主交易除外(没有主交易概念),组合交易主交易子交易都得考虑延期处理 var query = DbContext.trade.Where(x => (x.TradeType != "结构化交易" || x.IsGroup == 1) && x.ValidState != ConsGlobal.InValid && (x.ExerciseDate >= valueDate || x.SettlementFlag == 1) && ConsTrade.PositionTradeStatusList.Contains(x.TradeStatus)); var arrUnderlyingCode = query.Select(n => n.UnderlyingCode).Distinct().ToArray(); MarginParamProvider marginParam = new MarginParamProvider(OptUser, valueDate); marginParam.Initialize(arrUnderlyingCode.ToHashSet(), MarginParamTypeEnum.UpDownLimit); if (arrUnderlyingCode.Any()) { var eodPriceProvider = new EodPriceProvider(valueDate); var eodPriceProvidlast = new EodPriceProvider(lastDate); foreach (var item in arrUnderlyingCode) { if (eodPriceProvider.TryGetEodPrice(item, out var eodPrice)) { DelaySettlement delay = new DelaySettlement(); if (eodPrice.UnderlyingStatus == "停牌") { delay.UnderlyState = "停牌"; } else if (eodPriceProvidlast.TryGetPrice(item, SettlementTypeEnum.SettlePrice, out double price)) { if (marginParam.TryGetUpdownLimit(item, out var limit, out var isFixed)) { if (!isFixed) { limit *= price; } } else { limit = price * 0.05; } //注意:price价格可能为负值 limit = Math.Abs(limit); //涨跌停暂时不使用精确等于处理 if (price + limit <= eodPrice.ClosePrice) { delay.UnderlyState = "涨停"; } else if (price - limit >= eodPrice.ClosePrice) { delay.UnderlyState = "跌停"; } } else if (eodPrice.HighPrice == eodPrice.LowPrice && eodPrice.HighPrice != null) { delay.UnderlyState = "涨跌停"; } if (!string.IsNullOrWhiteSpace(delay.UnderlyState)) { delay.UnderlyCode = item; delays.Add(delay); } } } } return delays; } /// /// 获取需要延期交易的交易编号 /// /// public string GetDelayTradeNumber(List updownUnderly) { var date = valuedateBLL.ValueDate; var lastDate = QdpCalendarHelper.GetNonHolidayDefore(date.AddDays(-1)); var predicate = PredicateBuilder.Create(t => t.ExerciseDate >= lastDate && t.ExerciseDate <= date && t.TradeStatus == ConsTrade.确认成交 && t.ClientId > 0 && updownUnderly.Contains(t.UnderlyingId) && t.SettlementFlag == 0 //检查费停牌状态下所有 持仓交易的是否已执行到期 && t.ValidState != ConsGlobal.InValid); var tradeNumber = DbContext.trade.Where(predicate).Select(x => x.TradeNumber).ToHashSet(); return "
需要延期结算的交易:
" + string.Join(",
", tradeNumber); } /// /// 获取需要延期交易的异常标的id /// /// public IEnumerable GetDelayUnderlyIds(DateTime? date = null) { var valueDate = date ?? valuedateBLL.ValueDate; var lastDate = QdpCalendarHelper.GetNonHolidayDefore(valueDate.AddDays(-1)); //结构化交易主交易除外(没有主交易概念),组合交易主交易子交易都得考虑延期处理 var query = DbContext.trade.Where(x => (x.TradeType != "结构化交易" || x.IsGroup == 1) && x.ValidState != ConsGlobal.InValid && x.ExerciseDate == valueDate && ConsTrade.PositionTradeStatusList.Contains(x.TradeStatus) && x.TradeType == "收益互换" && x.SettlementFlag != 1); var arrUnderlyingCode = query.Select(n => n.UnderlyingCode).Distinct().ToArray(); MarginParamProvider marginParam = new MarginParamProvider(OptUser, valueDate); marginParam.Initialize(arrUnderlyingCode.ToHashSet(), MarginParamTypeEnum.UpDownLimit); List ret = new List(); if (arrUnderlyingCode.Any()) { var eodPriceProvider = new EodPriceProvider(valueDate); var eodPriceProvidlast = new EodPriceProvider(lastDate); foreach (var item in arrUnderlyingCode) { if (eodPriceProvider.TryGetEodPrice(item, out var eodPrice)) { if (eodPrice.UnderlyingStatus == "停牌") { ret.Add(eodPrice.UnderlyingId); } else if (eodPriceProvidlast.TryGetPrice(item, SettlementTypeEnum.SettlePrice, out double price)) { if (marginParam.TryGetUpdownLimit(item, out var limit, out var isFixed)) { if (!isFixed) { limit *= price; } } else { limit = price * 0.05; } //注意:price价格可能为负值 limit = Math.Abs(limit); //涨跌停暂时不使用精确等于处理 if (price + limit <= eodPrice.ClosePrice || price - limit >= eodPrice.ClosePrice) { ret.Add(eodPrice.UnderlyingId); } } else if (eodPrice.HighPrice == eodPrice.LowPrice && eodPrice.HighPrice != null) { ret.Add(eodPrice.UnderlyingId); } } } } return ret; } public void ExecuteDelaySettlements(string tradeids, int settlementvalue, out string msg) { msg = ""; List ids = new List(); var _ids = tradeids.Split(',').ToList(); foreach (var item in _ids) { ids.Add(Convert.ToInt32(item)); } var Alltrades = DbContext.trade.Where(x => ids.Contains(x.id)); if (Alltrades.Any(x => x.TradeStatus != ConsTrade.确认成交)) { throw new ServiceException("交易:" + string.Join(".", Alltrades.Where(x => x.TradeStatus != ConsTrade.确认成交).Select(x => x.TradeNumber).ToList()) + ",当前交易状态不符合延期结算要求,无法进行延期结算"); } var notChange = Alltrades.Where(x => x.SettlementFlag == settlementvalue).Count(); if (Alltrades.Any(x => x.SettlementFlag != settlementvalue)) { var optType = settlementvalue == 1 ? "手动延期结算" : "延期结算放弃"; var trades = Alltrades.Where(x => x.SettlementFlag != settlementvalue).ToList(); using (var trans = BeginTransaction()) { foreach (var item in trades) { UpdateDelayStatus(item, optType, settlementvalue); } DbContext.SaveChanges(); trans.Commit(); } } else { throw new ServiceException("不存在需要修改延期结算状态的交易"); } if (notChange > 0) { msg = "成功修改" + (Alltrades.Count() - notChange) + "条,不需要修改延期结算状态" + notChange + "条"; } else { msg = "修改延期结算状态成功"; } } /// /// 修改交易延期状态 /// /// public void UpdateDelayStatus(trade td, string optType, int SettlementFlag = 1) { td.SettlementFlag = SettlementFlag; td.SettlementFlagDate = DateTime.Now; td.SettlementFlagOptId = UserId; td.OptId = UserId; td.OptName = UserName; td.OptDate = DateTime.Now; AddTradeOperationHistoryAndSetParentTradeInfo(true, td, optType); } } public class ExerciseTradeUnderly { public string datetime { get; set; } public string underlystr { get; set; } } public class DelaySettlement { public string UnderlyCode { get; set; } public string UnderlyState { get; set; } } }