using YLErp.DBModels.Converts; using YLErp.Modules.TradeModule.DealModule; namespace YLErp.Modules.TradeModule.ApiModule { /// /// for api/v1/trade/group_options_close_start /// public class TradeGroupCloseService : YLBaseService { public TradeGroupCloseService(OptUserInfo userInfo) : base(userInfo) { } /// /// for api/v1/trade/group_options_close_start /// public void ExecuteCloseStart(TradeGroupCloseRequest req) { if (req is null) { throw new ArgumentNullException(nameof(req)); } switch (req.UnwindType) { case "全部平仓": case "部分平仓": case "全部提前行权": case "部分提前行权": case "到期行权": case "到期": break; default: var message = string.IsNullOrWhiteSpace(req.UnwindType) ? "了结方式 必须填写" : "不支持的了结方式:" + req.UnwindType; throw new ServiceException(message); } if (string.IsNullOrWhiteSpace(req.TradeNumber)) { throw new ServiceException("主交易编号 必须填写"); } var tradeNumbers = new List() { req.TradeNumber }; if (req.SubTradeNumbers != null && req.SubTradeNumbers.Any()) { tradeNumbers.AddRange(req.SubTradeNumbers); } var tdList = DbContext.trade .Where(n => tradeNumbers.Contains(n.TradeNumber)) .Select(n => new { n.id, n.TradeNumber, n.TradeType, n.IsGroup, n.IsUsePremiumRate, n.BuySell, n.Notional, n.TradeAmount, n.ParentTradeId, n.ValidState, n.TradeStatus }).ToList(); var td = tdList.FirstOrDefault(n => n.TradeNumber == req.TradeNumber); if (td == null) { throw new ServiceException("交易信息不存在:" + req.TradeNumber); } if (td.TradeType != "结构化交易" || td.IsGroup != 1) { throw new ServiceException("所选交易非组合交易主交易,不支持此API调用"); } var tradeIds = tdList.Select(n => n.id).ToList(); if (tradeNumbers.Count > 1) { //缺失交易信息的交易编号 var missings = tradeNumbers.Where(tn => !tdList.Any(t => t.TradeNumber == tn)).ToArray(); if (missings.Any()) { throw new ServiceException("交易信息不存在:" + string.Join(",", missings)); } var errors = tdList.Select(n => { if (n.ParentTradeId != td.id && n != td) { return $"交易编号:{n.TradeNumber},不属于同一组合;"; } if (!ConsGlobal.IsValid(n.ValidState)) { return $"交易编号:{n.TradeNumber},已被删除;"; } if (n.TradeStatus != "确认成交") { return $"交易编号:{n.TradeNumber},,交易状态:{n.TradeStatus},确认成交状态下才可做了结操作;"; } return null; }).Where(n => n != null).ToArray(); if (errors.Any()) { throw new ServiceException(string.Join(string.Empty, errors)); } } else { //补全子交易 var subIds = DbContext.trade.Where(n => n.ParentTradeId == td.id && n.IsGroup == 2 && n.ValidState != ConsGlobal.InValid && n.TradeStatus == "确认成交") .Select(n => n.id).ToArray(); tradeIds.AddRange(subIds); } if (tradeIds.Count == 1) { throw new ServiceException("该分组交易没有可以了结操的子交易,不支持此API调用"); } var tc = new trade_cash { id = 0, TradeId = td.id, ValueDate = req.ValueDate, ExceciseType = null, TradeType = BuySellConvert.GetClientBuySell(td.BuySell), CallPut = null, Strike = null, Notional = td.Notional, Amount = 0, Action = req.UnwindType, ValidState = null, Status = null, FinalPrice = req.UnderlyingPrice, UnwindPrice = null, UnwindVol = null, VolType = null, UnwindType = null, UnwindNotional = null, ExtraAmount = null, SettleDate = null, Comments = null, ExerciseWay = null, TradeAmount = td.TradeAmount, UnwindTradeAmount = 0, UnwindPercentRate = null, UnwindPricePercentRate = null, BarrierPrice = null, HappenedDate = null, ConfirmDate = System.DateTime.MinValue, ParentTradeId = 0, ParentTradeCashId = 0, SpotPrice = null, NotionalPercentRate = null, TradePremium = 0, IsDeleted = false, AdvanceMoney = 0, IsLastAction = false }; if (td.IsUsePremiumRate == true) { if (req.UnwindAmountFlag == "百分比") { tc.UnwindPercentRate = req.UnwindAmount * 100;//要乘以100因为进入实际逻辑以后又会除以100 } else if (req.UnwindAmountFlag == "名义本金") { tc.IsUnwindStockEqvNotional = true; tc.UnwindStockEqvNotional = req.UnwindAmount; } else { throw new ServiceException("交易是以'名义本金方式'成交的,仅支持以'百分比'和'名义本金'方式平仓"); } } else { if (req.UnwindAmountFlag == "数量") { tc.UnwindTradeAmount = req.UnwindAmount; } else { throw new ServiceException("交易是以'数量方式'成交的,仅支持'数量'方式平仓"); } } new TradeUnwindService(this).SaveGroupTradeCash(new Model.SaveGroupTradeCashReq { trade_cash = tc, tradeIds = tradeIds, from_group_options_close_start_v1 = true }); } } }