using BaseOUDAL; using Dapper; using YLErp.BLL; using YLErp.DBModels.Consts; using YLErp.Model; using YLErp.Model.Enum; using YLErp.Modules.SalesModule; using YLErp.Modules.TagModule; using YLErp.Modules.TradeModule.OrderModule; using YLErp.QdpModule; namespace YLErp.Modules.TradeModule.ForwardModule { /// /// 远期交易服务 /// public class TradeForwardService : TradeServiceBase { public TradeForwardService(OptUserInfo userInfo) : base(userInfo) { } /// /// 查询trade /// public SearchListResult SearchList(TradeReq req, bool isUnionToday = false, bool isExerciseDateReport = false) { var query = CreateTradeQuery(req, isUnionToday, isExerciseDateReport); var gsum = new tradeGridSum(); if (query.Where(x => x.TradeStatus != "已执行" && x.TradeStatus != "已到期" && x.TradeStatus != "已平仓").Any()) { gsum.TradeAmountSum = query.Where(x => x.TradeStatus != "已执行" && x.TradeStatus != "已到期" && x.TradeStatus != "已平仓")?.Sum(q => q.TradeAmount); } var retListResult = query.ToSearchList(req); retListResult.Sum = gsum; //获取销售提成信息 foreach (var item in retListResult.rows) { item.SalesCommission = new SalesCommissionDataService(OptUser).GetTradeCommissionInfo(item.id); if (PS.Config.ErpElement.SalesCommissionCalculation == "公式1" && item.SalesCommission?.Commission != null) { item.SalesCommission.Commission = item.SalesCommission.Commission * item.SalesCommission.SalesIds.Count(); } item.UnderlyingName = DataCacheModule.DataCacheManager.GetUnderlyingDataSource().GetData(item.UnderlyingCode).UnderlyingName; } return retListResult; } private IQueryable CreateTradeQuery(TradeReq req, bool isUnionToday = false, bool isExerciseDateReport = false) { var predicate = PredicateBuilder.Create(t => t.ValidState != "InValid" && t.TradeType == "远期"); if (req.UserAssets != null && req.UserClients != null) { predicate = predicate.And(t => req.UserAssets.Contains(t.AssetId) || req.UserClients.Contains(t.ClientId)); } var query = DbContext.trade.Where(predicate); if (!string.IsNullOrEmpty(req.ContractCode)) { query = from source in query join tcrConfirm in DbContext.trade_contract_r.Where(aa => aa.Type == ContractTypeEnum.Trade && aa.IsValid) on new { id = source.ParentTradeId > 0 ? source.ParentTradeId : source.id } equals new { id = tcrConfirm.TradeId } into tcrConfirms from tcrConfirm in tcrConfirms.DefaultIfEmpty() where tcrConfirm.ContractCode.Contains(req.ContractCode) select source; } if (!string.IsNullOrEmpty(req.UnderlyingAssetClass)) { query = query.Where(d => d.UnderlyingAssetClass.Contains(req.UnderlyingAssetClass)); } if (!string.IsNullOrEmpty(req.UnderlyingInstrumentTypes)) { query = query.Where(d => req.UnderlyingInstrumentTypesList.Contains(d.UnderlyingInstrumentType)); } if (!string.IsNullOrEmpty(req.OptIds)) { query = query.Where(d => req.OptIdsList.Contains(d.OptId + "")); } if (!string.IsNullOrEmpty(req.Comments)) { query = query.Where(d => d.Comments.Contains(req.Comments)); } if (!string.IsNullOrEmpty(req.UnderlyingIds)) { query = query.Where(d => req.UnderlyingIdsInt.Contains(d.UnderlyingId)); } if (!string.IsNullOrEmpty(req.TradeIds)) { query = query.Where(d => req.TradeIdList.Contains(d.id)); } //获取当日成交的数据 //当日成交包括操作日期和交易日为当前系统日期的数据 if (req.TabIndex == (int)TradeTabIndexEnum.今日成交) { var optDateStart = valuedateBLL.ValueDate; var optDateEnd = valuedateBLL.ValueDate.AddDays(1); var tradeDateStart = valuedateBLL.ValueDate; var tradeDateEnd = valuedateBLL.ValueDate.AddDays(1); query = query.Where(d => (d.TradeDate >= tradeDateStart && d.TradeDate < tradeDateEnd) || (d.OptDate >= optDateStart && d.OptDate < tradeDateEnd)); } else { if (req.TradeDateStart != DateTime.MinValue) { query = query.Where(d => d.TradeDate >= req.TradeDateStart); } if (req.TradeDateEnd != DateTime.MinValue) { var TradeDateTemp = req.TradeDateEnd.AddDays(1); query = query.Where(d => d.TradeDate < TradeDateTemp); } if (req.OptDateStart != DateTime.MinValue) { query = query.Where(d => d.OptDate >= req.OptDateStart); } if (req.OptDateEnd != DateTime.MinValue) { var OptDateTemp = req.OptDateEnd.AddDays(1); query = query.Where(d => d.OptDate < OptDateTemp); } } //获取当日到期日数据 if (req.TabIndex == (int)TradeTabIndexEnum.今日到期) { query = query.Where(d => d.ExerciseDate == valuedateBLL.ValueDate); } //获取明日到期日数据 else if (req.TabIndex == (int)TradeTabIndexEnum.明日到期) { var tommorow = QdpCalendarHelper.GetNonHoliday(valuedateBLL.ValueDate.AddDays(1)); query = query.Where(d => d.ExerciseDate == tommorow); } else { if (req.ExerciseDateEnd == null) { req.ExerciseDateEnd = DateTime.MaxValue; } if (req.ExerciseDateStart == null) { req.ExerciseDateStart = DateTime.MinValue; } if (isExerciseDateReport) { query = query.Where(d => d.ExerciseDate >= req.ExerciseDateStart && d.ExerciseDate <= req.ExerciseDateEnd); } else { query = query.Where(d => d.ExerciseDate == null || (d.ExerciseDate >= req.ExerciseDateStart && d.ExerciseDate <= req.ExerciseDateEnd)); } } if (!string.IsNullOrEmpty(req.TraderNames)) { query = query.Where(d => req.TraderNamesList.Contains(d.TraderId)); } if (!string.IsNullOrEmpty(req.TradeNumber)) { query = query.Where(d => d.TradeNumber == req.TradeNumber || d.TradeNumber.Contains(req.TradeNumber)); } if (req.ClientId != null) { query = query.Where(d => d.ClientId == req.ClientId); } if (!string.IsNullOrEmpty(req.ClientName)) { query = query.Where(d => d.ClientName.Contains(req.ClientName)); } if (!string.IsNullOrEmpty(req.UnderlyingCode)) { query = query.Where(d => d.UnderlyingCode.Contains(req.UnderlyingCode)); } if (req.UnderlyingCodeList != null) { query = query.Where(d => req.UnderlyingCodeList.Contains(d.UnderlyingCode)); } if (req.UnderlyingId != null) { query = query.Where(d => d.UnderlyingId == req.UnderlyingId); } if (!string.IsNullOrEmpty(req.BuySell)) { query = query.Where(d => d.BuySell.Contains(req.BuySell)); } if (!string.IsNullOrEmpty(req.OptionType)) { query = query.Where(d => d.OptionType == req.OptionType); } if (req.StartDateStart != DateTime.MinValue) { query = query.Where(d => d.StartDate >= req.StartDateStart); } if (req.StartDateEnd != DateTime.MinValue) { var StartDateTemp = req.StartDateEnd.AddDays(1); query = query.Where(d => d.StartDate < StartDateTemp); } //过滤已平仓,已到期,已执行数据 else if (req.TabIndex == (int)TradeTabIndexEnum.今日到期 || req.TabIndex == (int)TradeTabIndexEnum.明日到期) { query = query.Where(d => d.TradeStatus != ConsTrade.已平仓 && d.TradeStatus != ConsTrade.已到期 && d.TradeStatus != ConsTrade.已执行); } if (!string.IsNullOrEmpty(req.TradeStatus)) { var statuses = req.TradeStatus.Split(',').ToList(); query = query.Where(d => statuses.Contains(d.TradeStatus)); } if (req.TradeStatusList != null) { query = query.Where(d => req.TradeStatusList.Contains(d.TradeStatus)); } if (req.AssetIdList.Any()) { query = query.Where(d => req.AssetIdList.Contains(d.AssetId)); } if (req.ClientIdsInt.Any()) { query = query.Where(d => req.ClientIdsInt.Contains(d.ClientId)); } if (!string.IsNullOrEmpty(req.OptName)) { query = query.Where(d => d.OptName.Contains(req.OptName)); } if (req.TagIds != null && req.TagIds.Count > 0) { var tradeTagIdQuery = from tt in DbContext.trade_tag where req.TagIds.Contains(tt.TagId) select tt.TradeId; query = query.Where(p => tradeTagIdQuery.Contains(p.id)); } query = query.Where(d => !d.ValidState.Equals("InValid")); if (string.IsNullOrEmpty(req.sidx)) { req.sidx = "id"; req.sord = "desc"; } if (isUnionToday) { var todaybalanceStatus = new List { "已到期", "已执行", "已平仓" }; var curDate = valuedateBLL.ValueDate; //+ trade今天被exercise/expire的option. 排序按照optDate,从新到旧排 query = query.Union(from s in DbContext.trade where s.ClientId == req.ClientId && todaybalanceStatus.Contains(s.TradeStatus) && s.OptDate >= curDate select s); } query = query.OrderByDescending(s => s.OptDate); return query; } /// /// 获取数据详情 /// public OtcTradeForward GetDetail(int id) { var tdResult = DbContext.Database.GetDbConnection().Query("select * from trade where id=" + id).FirstOrDefault(); if (tdResult == null) { return null; } var forward = DbContext.trade_forward.FirstOrDefault(n => n.TradeId == id); if (forward == null) { throw new ServiceException("交易数据损坏,扩展数据未找到"); } YLAutoMapper.Map(forward, tdResult); tdResult.MetaDic = new TradeMetaService(this).GetTradeMeta(tdResult.id); if (!tdResult.MetaDic.ContainsKey("IsSupplyForwardValue")) { if (PS.Config.ErpElement.ForwardValueIsSupplyOrPay == YLErp.Configuration.Enums.ForwardValueIsSupplyOrPay.Type2) { tdResult.MetaDic.Add("IsSupplyForwardValue", "-1"); } else { tdResult.MetaDic.Add("IsSupplyForwardValue", "0"); } } tdResult.VarietyId = UnderlyingDataProvider.GetUnderlying(tdResult.UnderlyingCode)?.UnderlyingTypeId ?? 0; var un = UnderlyingDataProvider.GetUnderlying(tdResult.UnderlyingId); if (un != null && un.IsSynthetic() && !tdResult.MetaDic.ContainsKey("组合标的")) { var synthetic = UnderlyingDataProvider.GetSyntheticUnderlying(tdResult.UnderlyingCode); if (synthetic != null) { tdResult.MetaDic["组合标的"] = synthetic.GetSyntheticPriceModel().ToJson(); } } tdResult.SalesCommission = new SalesCommissionDataService(this).GetTradeCommissionInfo(tdResult.id); return tdResult; } /// /// 删除交易 /// public void InValidTrade(int id) { var r = DbContext.trade.Find(id); if (r == null) { throw new ServiceException("找不到交易信息"); } r.ValidState = ConsGlobal.InValid; if (!string.IsNullOrWhiteSpace(r.TradeNumber)) { var contractBll = new TradeContractBLL(UserId, UserName); contractBll.DeleteConfirmBook(r.id); if (r.TradeNumber.StartsWith("CW")) { r.TradeNumber = r.TradeNumber.Replace("CW", "XX"); } else //if (PS.Config.Is光大光子) { r.TradeNumber = r.TradeNumber.Insert(0, "XX"); } } //设置相关提成失效 new SalesCommissionDataService(OptUser).SetCommissionInVaild(r.id); RemoveEodTradeAndFutureInfo(false, r.id, DateTime.MinValue); new DealModule.TradeConfirmService(this).EditReportStatus(r.id); AddTradeOperationHistoryAndSetParentTradeInfo(false, r, "删除交易"); //删除所有trade关联表中数据 DbContext.SaveChanges(); } /// /// 保存交易 /// public trade SaveData(OtcTradeForward req) { req.TradeType = "远期"; var td = TradeConverter.ConvertForward(req); td = new TradeSaveService(this).SaveTrade(td, TradeSourceEnum.系统交易); var variety = UnderlyingDataProvider.GetVariety(td.UnderlyingCode); if (variety != null) { td.QuoteUnit = variety.QuoteUnit; td.QuoteUnitSingle = variety.QuoteUnitSingle; } using (var tagService = new TagService(OptUser)) { tagService.SetTradeTagForTradeEdit(new TagModule.Dto.SetTradeTagForTradeEditRequest { TradeId = td.id, Tags = req.Tags }); } return td; } public TradeCheckModel GetCheckTrade(int? id) { var service = new TradeMetaService(this); var model = new TradeCheckModel { Trade = DbContext.trade.FirstOrDefault(n => n.id == id) }; if (model.Trade == null) { throw new ServiceException("没有找到数据"); } var forward = DbContext.trade_forward.FirstOrDefault(t => t.TradeId == model.Trade.id); if (forward == null) { throw new ServiceException("没有找到远期数据"); } model.Trade.trade_forward = forward; model.UnderlyingInfo = UnderlyingDataProvider.GetUnderlying(model.Trade.UnderlyingCode); var tradeCheck = DbContext.trade_check.FirstOrDefault(t => t.TradeId == model.Trade.id && t.ValidState != "InValid"); if (tradeCheck != null) { model.diffList = TradeCheckUtil.GetDiffs(model.Trade, tradeCheck.TradeModel); model.Trade.ExerciseDate = tradeCheck.TradeModel.ExerciseDate; model.Trade.TradeDate = tradeCheck.TradeModel.TradeDate; model.Trade.SettlementDate = tradeCheck.TradeModel.SettlementDate; model.Trade.Strike = tradeCheck.TradeModel.Strike; model.Trade.TradeAmount = tradeCheck.TradeModel.TradeAmount; model.Trade.TradeSinglePrice = tradeCheck.TradeModel.TradeSinglePrice; model.Trade.TradeDate = tradeCheck.TradeModel.TradeDate; model.Trade.SpotPrice = tradeCheck.TradeModel.SpotPrice; model.Trade.StockEqvNotional = tradeCheck.TradeModel.StockEqvNotional; model.Trade.TradeOpenVolatility = tradeCheck.TradeModel.TradeOpenVolatility; model.Trade.TradeCloseVolatility = tradeCheck.TradeModel.TradeCloseVolatility; model.Trade.NumOfSmoothingDays = tradeCheck.TradeModel.NumOfSmoothingDays; model.Trade.TradePrice = tradeCheck.TradeModel.TradePrice; model.Trade.BuySell = tradeCheck.TradeModel.BuySell; model.Trade.ExerciseMode = tradeCheck.TradeModel.ExerciseMode; model.Trade.OptionType = tradeCheck.TradeModel.OptionType; model.Trade.SettlementType = tradeCheck.TradeModel.SettlementType; model.Trade.Lots = tradeCheck.TradeModel.Lots; model.Trade.SalesCommission = new SalesCommissionDataService(OptUser).GetTradeCommissionInfo(model.Trade.id); if (PS.Config.ErpElement.SalesCommissionCalculation == "公式1") {//计提法只支持百分比; if (model.Trade.SalesCommission.Commission.Normalize() == 0) { model.Trade.SalesCommission.Commission = 1; model.Trade.SalesCommission.CommissionFixed = false; } else { model.Trade.SalesCommission.Commission = model.Trade.SalesCommission.Commission * model.Trade.SalesCommission.SalesIds.Count(); } } model.Trade.NoRiskRate = tradeCheck.TradeModel.NoRiskRate; model.Trade.trade_forward = tradeCheck.TradeModel.trade_forward; model.Trade.MetaDic = service.GetTradeMeta(model.Trade.id); if (model.Trade.MetaDic.ContainsKey("ActualExerciseDate") && DateTime.TryParse(model.Trade.MetaDic["ActualExerciseDate"],out DateTime ActualExerciseDate)) { model.Trade.ActualExerciseDate = ActualExerciseDate; } return model; } model.Trade.ExerciseDate = null; model.Trade.Strike = null; model.Trade.TradeAmount = 0; model.Trade.TradeSinglePrice = null; model.Trade.TradeDate = null; model.Trade.SpotPrice = null; model.Trade.StockEqvNotional = 0; model.Trade.TradeOpenVolatility = null; model.Trade.TradeCloseVolatility = null; model.Trade.NumOfSmoothingDays = null; model.Trade.TradePrice = null; model.Trade.BuySell = null; model.Trade.ExerciseMode = null; model.Trade.OptionType = null; model.Trade.SettlementType = 0; model.Trade.Lots = null; model.Trade.SalesCommission = new SalesCommissionDataService(OptUser).GetTradeCommissionInfo(model.Trade.id); if (PS.Config.ErpElement.SalesCommissionCalculation == "公式1") {//计提法只支持百分比; if (model.Trade.SalesCommission.Commission.Normalize() == 0) { model.Trade.SalesCommission.Commission = 1; model.Trade.SalesCommission.CommissionFixed = false; } else { model.Trade.SalesCommission.Commission = model.Trade.SalesCommission.Commission * model.Trade.SalesCommission.SalesIds.Count(); } } //将无风险利率和年华预付金利率数值从小数转换百分数 model.Trade.NoRiskRate *= 100; forward.AnnualMarginRate *= 100; forward.OpenCommission = 0; model.Trade.trade_forward = forward; model.Trade.MetaDic = service.GetTradeMeta(model.Trade.id); if (model.Trade.MetaDic.ContainsKey("ActualExerciseDate") && DateTime.TryParse(model.Trade.MetaDic["ActualExerciseDate"], out DateTime newActualExerciseDate)) { model.Trade.ActualExerciseDate = newActualExerciseDate; } return model; } } public class TradeCheckModel { /// /// 交易信息 /// public trade Trade { get; set; } /// /// 标的信息 /// public underlying_manager UnderlyingInfo { get; set; } public HashSet diffList { get; set; } /// /// 是否显示初始预付金 /// public bool ShowInitialMargin => valuedateBLL.SystemDate.CanSetInitialMargin; } }