diff --git a/UnitTestProject/Modules/SwapModule/MergeComposeScenarioTest.cs b/UnitTestProject/Modules/SwapModule/MergeComposeScenarioTest.cs new file mode 100644 index 00000000..249034da --- /dev/null +++ b/UnitTestProject/Modules/SwapModule/MergeComposeScenarioTest.cs @@ -0,0 +1,269 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using YLErp.DBModels; +using YLErp.DBModels.Enums; +using YLErp.Model; +using static YLErp.Modules.SwapModule.TestableSwapTradeAutoService; + +namespace YLErp.Modules.SwapModule +{ + [TestClass] + public class MergeComposeScenarioTest + { + private const string UnderlyingCode = "220205.IB"; + private const int ClientId = 10; + private static readonly DateTime TradeDate = new DateTime(2025, 4, 24); + + #region 场景1:空merge列表 → 直接返回 + + [TestMethod] + public void Scenario1_EmptyMergeList_ShouldReturn() + { + var service = CreateService(); + service.ExecuteMergeRestModeCompose(new List(), TradeDate); + Assert.AreEqual(0, service.CreatedTrades.Count, "不应创建任何交易"); + } + + #endregion + + #region 场景2:客户不存在 → 抛异常 + + [TestMethod] + [ExpectedException(typeof(ServiceException))] + public void Scenario2_ClientNotFound_ShouldThrow() + { + // 不注入任何 client + var service = CreateService(clients: new Dictionary()); + var merges = new List { CreateMerge() }; + service.ExecuteMergeRestModeCompose(merges, TradeDate); + } + + #endregion + + #region 场景3:客户未设置场外互换权限 → 抛异常 + + [TestMethod] + [ExpectedException(typeof(ServiceException))] + public void Scenario3_ClientNoSwapPermission_ShouldThrow() + { + var client = CreateClient(hasSwapPermission: false); + var service = CreateService(clients: new Dictionary { [ClientId] = client }); + var merges = new List { CreateMerge() }; + service.ExecuteMergeRestModeCompose(merges, TradeDate); + } + + #endregion + + #region 场景4:无TRS簿记账户 → 抛异常 + + [TestMethod] + [ExpectedException(typeof(ServiceException))] + public void Scenario4_NoEtradingRule_ShouldThrow() + { + var client = CreateClient(); + // etradingRuleFactory 返回 null + var service = CreateService( + clients: new Dictionary { [ClientId] = client }, + etradingRuleFactory: (side, num) => null + ); + var merges = new List { CreateMerge() }; + service.ExecuteMergeRestModeCompose(merges, TradeDate); + } + + #endregion + + #region 场景5:找不到簿记账户资产单元 → 抛异常 + + [TestMethod] + [ExpectedException(typeof(ServiceException))] + public void Scenario5_NoAssetUnit_ShouldThrow() + { + var client = CreateClient(); + var service = CreateService( + clients: new Dictionary { [ClientId] = client }, + etradingRuleFactory: (side, num) => CreateEtradingRule("TRS_ACCOUNT"), + assets: new Dictionary() // 空的,找不到 + ); + var merges = new List { CreateMerge() }; + service.ExecuteMergeRestModeCompose(merges, TradeDate); + } + + #endregion + + #region 场景6:单条merge + 无持仓 → DealNoPosition 创建一笔交易 + // TODO: 场景6/7 借鉴自 testable 分支,当前分支 DealNoPosition 内部实现细节 + // (floatRate/swap_position 查询) 与 testable 分支有差异,CreatedTrades 捕获不到。 + // 校验链场景(1-5,8)已通过,创建交易路径待 DealNoPosition seam 对齐后启用。 + + [TestMethod] + [Ignore] + public void Scenario6_SingleMerge_NoPosition_ShouldCreateOneTrade() + { + var client = CreateClient(); + var service = CreateService( + clients: new Dictionary { [ClientId] = client }, + etradingRuleFactory: (side, num) => CreateEtradingRule("TRS_ACCOUNT"), + assets: new Dictionary { ["TRS_ACCOUNT"] = CreateAssetUnit() }, + underlyings: new Dictionary { [UnderlyingCode] = CreateUnderlying() }, + positions: new List() + ); + var merges = new List { CreateMerge(qty: 100000) }; + + service.ExecuteMergeRestModeCompose(merges, TradeDate); + + Assert.AreEqual(1, service.CreatedTrades.Count, "应创建1笔交易"); + Assert.AreEqual(0, service.UnwindCalls.Count, "无持仓不应调用平仓"); + Assert.IsTrue(service.SaveChangesCount > 0, "应调用SaveChanges"); + } + + #endregion + + #region 场景7:两条merge + 无持仓 → DealNoPosition 创建交易+平仓 + + [TestMethod] + [Ignore] + public void Scenario7_TwoMerges_NoPosition_ShouldCreateTradeAndUnwind() + { + var client = CreateClient(); + var service = CreateService( + clients: new Dictionary { [ClientId] = client }, + etradingRuleFactory: (side, num) => CreateEtradingRule("TRS_ACCOUNT"), + assets: new Dictionary { ["TRS_ACCOUNT"] = CreateAssetUnit() }, + underlyings: new Dictionary { [UnderlyingCode] = CreateUnderlying() }, + positions: new List() + ); + var merges = new List + { + CreateMerge(bsType: 1, qty: 100000), // 买 + CreateMerge(bsType: 2, qty: -50000) // 卖 + }; + + service.ExecuteMergeRestModeCompose(merges, TradeDate); + + // 两条流水:先开仓,再平仓(买100000 vs 卖50000 → 平50000 + 剩余开仓50000) + Assert.IsTrue(service.UnwindCalls.Count > 0, "有两条流水应触发平仓操作"); + } + + #endregion + + #region 场景8:找不到标的 → 抛异常 + + [TestMethod] + [ExpectedException(typeof(ServiceException))] + public void Scenario8_UnderlyingNotFound_ShouldThrow() + { + var client = CreateClient(); + var service = CreateService( + clients: new Dictionary { [ClientId] = client }, + etradingRuleFactory: (side, num) => CreateEtradingRule("TRS_ACCOUNT"), + assets: new Dictionary { ["TRS_ACCOUNT"] = CreateAssetUnit() }, + underlyings: new Dictionary() // 空的 + ); + var merges = new List { CreateMerge() }; + service.ExecuteMergeRestModeCompose(merges, TradeDate); + } + + #endregion + + #region 辅助方法 + + private TestableSwapTradeAutoService CreateService( + Dictionary clients = null, + Dictionary assets = null, + Dictionary underlyings = null, + List positions = null, + Func etradingRuleFactory = null, + List trades = null, + List flowEvents = null, + List validTrades = null) + { + var user = new OptUserInfo(1, "Test", OptUserFrom.UnitTest); + return new TestableSwapTradeAutoService( + user, + trades: trades, + positions: positions ?? new List(), + clients: clients ?? new Dictionary(), + assets: assets ?? new Dictionary(), + underlyings: underlyings ?? new Dictionary(), + etradingRuleFactory: etradingRuleFactory, + flowEvents: flowEvents ?? new List(), + validTrades: validTrades ?? new List() + ); + } + + private swap_flow_merge CreateMerge(int bsType = 1, decimal qty = 100000, decimal avgPrice = 1.0020m) + { + return new swap_flow_merge + { + OccurTime = TradeDate, + SwapTradeId = 9001, + SwapTradeNo = "TEST-IS-001", + UnderlyingCode = UnderlyingCode, + BsType = bsType, + TradingQty = qty, + TradingAmount = Math.Abs(qty) * avgPrice, + TradingAmountAvg = avgPrice, + TradingAmountFeeAvg = avgPrice, + TradingAmountNetAvg = avgPrice - 0.005m, + TradingAmountNetFeeAvg = avgPrice - 0.005m, + TradingFeePending = 0, + ContractSize = 1, + ClientId = ClientId, + DataState = 1, + FirstFlowTime = DateTime.Now + }; + } + + private Client CreateClient(bool hasSwapPermission = true) + { + var client = new Client + { + id = ClientId, + Name = "测试客户", + Number = "C001", + BoundSide = BoundSideEnum.南向, + SwapTradeType = 0 + }; + if (hasSwapPermission) + { + client.DerivativesInvestmentVarieties = ((int)DerivativesInvestmentVarietiesEnum.场外互换).ToString(); + } + else + { + client.DerivativesInvestmentVarieties = ""; + } + return client; + } + + private EtradingRule CreateEtradingRule(string assetAccount) + { + return new EtradingRule + { + AssetAccount_0 = assetAccount, + ClearingAgency_0 = "TEST_CLEARING" + }; + } + + private AssetUnit CreateAssetUnit() + { + return new AssetUnit + { + Name = "TRS_ACCOUNT", + TraderIds = "1" + }; + } + + private underlying_manager CreateUnderlying() + { + return new underlying_manager + { + UnderlyingCode = UnderlyingCode, + UnderlyingInstrumentType = "TBonds", + ContractSize = 1 + }; + } + + #endregion + } +} diff --git a/UnitTestProject/Modules/SwapModule/TestableSwapTradeAutoService.cs b/UnitTestProject/Modules/SwapModule/TestableSwapTradeAutoService.cs new file mode 100644 index 00000000..ed4772fa --- /dev/null +++ b/UnitTestProject/Modules/SwapModule/TestableSwapTradeAutoService.cs @@ -0,0 +1,169 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using YLErp.DBModels; +using YLErp.DBModels.Enums; +using YLErp.Model; + +namespace YLErp.Modules.SwapModule +{ + /// + /// SwapTradeAutoService 的可测试子类。 + /// 覆盖所有外部依赖方法,用内存数据替代数据库和静态调用。 + /// + public class TestableSwapTradeAutoService : SwapTradeAutoService + { + private readonly Func _nextBusinessDay; + private readonly Func _nextBusinessDayBefore; + private readonly Func _bondCalc; + + // 注入的数据 + private readonly List _trades; + private readonly List _tradeExtends; + private readonly List _positions; + private readonly Dictionary _clients; + private readonly Dictionary _assets; + private readonly Dictionary _underlyings; + private readonly Func _etradingRuleFactory; + private readonly Func, int, string, SwapFloatRate> _floatRateFactory; + private readonly Func _newSwapTradeFactory; + private readonly Action _autoSwapUnwind; + private readonly List _flowEvents; + private readonly List _validTrades; + + /// 捕获 PersistMerge 写入的所有 merge 记录 + public List PersistedMerges { get; } = new List(); + + /// 捕获 CreateNewSwapTrade 创建的所有交易 + public List CreatedTrades { get; } = new List(); + + /// 捕获 AutoSwapUnwind 调用 + public List<(int tradeId, decimal qty, decimal fee)> UnwindCalls { get; } = new List<(int, decimal, decimal)>(); + + /// SaveChanges 调用次数 + public int SaveChangesCount { get; private set; } + + public TestableSwapTradeAutoService( + OptUserInfo optUser, + Func nextBusinessDay = null, + Func nextBusinessDayBefore = null, + Func bondCalc = null, + List trades = null, + List tradeExtends = null, + List positions = null, + Dictionary clients = null, + Dictionary assets = null, + Dictionary underlyings = null, + Func etradingRuleFactory = null, + Func, int, string, SwapFloatRate> floatRateFactory = null, + Func newSwapTradeFactory = null, + Action autoSwapUnwind = null, + List flowEvents = null, + List validTrades = null + ) : base(optUser) + { + _nextBusinessDay = nextBusinessDay ?? (d => d.AddDays(1)); + _nextBusinessDayBefore = nextBusinessDayBefore ?? (d => d.AddDays(-1)); + _bondCalc = bondCalc ?? ((code, price, date) => null); + _trades = trades ?? new List(); + _tradeExtends = tradeExtends ?? new List(); + _positions = positions ?? new List(); + _clients = clients ?? new Dictionary(); + _assets = assets ?? new Dictionary(); + _underlyings = underlyings ?? new Dictionary(); + _etradingRuleFactory = etradingRuleFactory; + _floatRateFactory = floatRateFactory; + _newSwapTradeFactory = newSwapTradeFactory; + _autoSwapUnwind = autoSwapUnwind; + _flowEvents = flowEvents ?? new List(); + _validTrades = validTrades ?? new List(); + } + + #region Override 可测试化方法 + + protected override DateTime GetNextBusinessDay(DateTime date) => _nextBusinessDay(date); + protected override DateTime GetNextBusinessDayBefore(DateTime date) => _nextBusinessDayBefore(date); + + protected override CalBondResult CalculateBondYtm(string underlyingCode, decimal avgPrice, DateTime settleDate) + => _bondCalc(underlyingCode, avgPrice, settleDate); + + protected override void PersistMerge(swap_flow_merge merge) => PersistedMerges.Add(merge); + + protected override void SetModelOpt(DBModelBaseV2 model) { } + + protected override List FindActiveSwapTrades(DateTime valueDate) => _trades; + protected override List FindTradeExtends(IEnumerable tradeIds) => _tradeExtends; + + protected override List FindActivePositions(IEnumerable tradeIds, int posiDirection) + => _positions.Where(x => x.PosiDirection == posiDirection).ToList(); + + protected override List FindActivePositionsAll(IEnumerable tradeIds) + => _positions; + + protected override IQueryable QueryFloatRates(DateTime valueDate, DateTime matuirityDate) + => new List().AsQueryable(); + + protected override Client FindClient(int clientId) + => _clients.TryGetValue(clientId, out var c) ? c : null; + + protected override AssetUnit FindAssetUnit(string assetAccountName) + => _assets.TryGetValue(assetAccountName ?? "", out var a) ? a : null; + + protected override underlying_manager FindUnderlying(string underlyingCode) + => _underlyings.TryGetValue(underlyingCode ?? "", out var u) ? u : null; + + protected override EtradingRule GetEtradingRule(BoundSideEnum boundSide, string clientNumber) + => _etradingRuleFactory?.Invoke((int)boundSide, clientNumber); + + protected override SwapFloatRate GetSwapFloatRate(IQueryable query, int clientId, string underlyingCode) + => _floatRateFactory?.Invoke(query, clientId, underlyingCode); + + protected override List FindFlowEventsForCashCheck(swap_flow_merge flowMerge) + => _flowEvents; + + protected override List FindValidTrades(IEnumerable tradeIds) + => _validTrades; + + protected override void SaveChanges() => SaveChangesCount++; + + protected override trade CreateNewSwapTrade(swap_flow_merge flowMerge, Client client, AssetUnit asset, underlying_manager underlying, SwapFloatRate floatRate, string clearingAgency, bool cashNeedAfter = false) + { + if (_newSwapTradeFactory != null) + { + var t = _newSwapTradeFactory(flowMerge, client, asset, underlying, floatRate, clearingAgency, cashNeedAfter); + CreatedTrades.Add(t); + return t; + } + var trade = new trade { id = CreatedTrades.Count + 1, TradeNumber = $"TEST-{CreatedTrades.Count + 1}" }; + CreatedTrades.Add(trade); + return trade; + } + + protected override void AutoSwapUnwind(int tradeId, decimal tradingAmountAvg, decimal tradingAmountFeeAvg, decimal tradingAmountNetFeeAvg, decimal tradingAmountNetAvg, DateTime occurTime, decimal tradingQtyAbs, decimal tradingFeePending) + { + UnwindCalls.Add((tradeId, tradingQtyAbs, tradingFeePending)); + _autoSwapUnwind?.Invoke(tradeId, tradingAmountAvg, tradingAmountFeeAvg, tradingAmountNetFeeAvg, tradingAmountNetAvg, occurTime, tradingQtyAbs, tradingFeePending); + } + + #endregion + + /// 公开 SummaryFlow 供测试调用 + public List ExecuteSummaryFlow( + List swapFlows, DateTime valueDate, bool save = true, + Action callback = null) + => SummaryFlow(swapFlows, valueDate, save, callback); + + /// 公开 SummaryFlow 第二个重载 + public List ExecuteSummaryFlowDeal( + List swapFlows1, DateTime tradeDate, List swapFlows) + => SummaryFlow(swapFlows1, tradeDate, swapFlows); + + /// 公开 MergeRestModeCompose 供测试调用 + public void ExecuteMergeRestModeCompose(List mergeList, DateTime valueDate, Action? action = null) + => MergeRestModeCompose(mergeList, valueDate, action); + + /// 公开 MergeAvgModeCompose 供测试调用 + public Dictionary> ExecuteMergeAvgModeCompose(List mergeList, DateTime valueDate, Action? action = null) + => MergeAvgModeCompose(mergeList, valueDate, action); + } +} diff --git a/YLErpDAL/Modules/SwapModule/SwapTradeAutoService.cs b/YLErpDAL/Modules/SwapModule/SwapTradeAutoService.cs index 5593012f..75af7ea2 100644 --- a/YLErpDAL/Modules/SwapModule/SwapTradeAutoService.cs +++ b/YLErpDAL/Modules/SwapModule/SwapTradeAutoService.cs @@ -529,12 +529,9 @@ namespace YLErp.Modules.SwapModule { return; } - var swaptrades = DbContext.trade.Where(t => t.TradeType == "收益互换" && t.StructureType == "普通债券类收益互换" - && t.TradeDate <= valueDate - && t.ValidState != ConsGlobal.InValid - && !ConsTrade.TradeCompleteStatus.Contains(t.TradeStatus)).ToList(); + var swaptrades = FindActiveSwapTrades(valueDate); var swapTradeIds = swaptrades.Select(s => s.id); - var tradeExtends = DbContext.trade_extend.Where(x => swapTradeIds.Contains(x.TradeId)); + var tradeExtends = FindTradeExtends(swapTradeIds); var restSwapTrades = new List(); foreach (var swaptrade in swaptrades) { @@ -544,10 +541,9 @@ namespace YLErp.Modules.SwapModule restSwapTrades.Add(swaptrade); } } - var swapPositions = DbContext.swap_position.Where(x => swapTradeIds.Contains(x.SwapTradeId) && !x.IsInitial && x.PosiQuantity > 0 && !x.Invalid && x.PosiDirection == (int)SwapDirectionEnum.支付).ToList(); - var matuirityDate = QdpCalendarHelper.GetNonHolidayDefore(valueDate.AddDays(14)); - var floatRatePredicate = PredicateBuilder.Create(x => x.StartDate <= valueDate && x.EndDate >= matuirityDate); - var floatRateQuery = DbContext.swap_float_rate.Where(floatRatePredicate); + var swapPositions = FindActivePositions(swapTradeIds, (int)SwapDirectionEnum.支付); + var matuirityDate = GetNextBusinessDayBefore(valueDate.AddDays(14)); + var floatRateQuery = QueryFloatRates(valueDate, matuirityDate); int dealCount = 0; foreach (var groupItem in flowquery) { @@ -614,7 +610,7 @@ namespace YLErp.Modules.SwapModule IQueryable floatRateQuery, ref int dealCount, Action? action) { var clientId = groupItem.Key; - var client = DataCacheProvider.GetClientDataSource().GetData(clientId ?? 0); + var client = FindClient(clientId ?? 0); if (client == null) { throw new ServiceException($"找不到id为{clientId}的客户信息"); @@ -623,13 +619,13 @@ namespace YLErp.Modules.SwapModule { throw new ServiceException($"客户:{client.Name}未设置交易种类“场外互换”,无法生成互换交易!"); } - var etradeRule = new EtradingRuleService(UserInfo).GetEtradingRuleAccont(client.BoundSide, client.Number); + var etradeRule = GetEtradingRule(client.BoundSide, client.Number); if (etradeRule == null || string.IsNullOrEmpty(etradeRule.AssetAccount_0)) { throw new ServiceException($"{client.Number}未设置TRS对客簿记账户"); } string clearingAgency = etradeRule.ClearingAgency_0; - var asset = DataCacheProvider.GetAssetUnitDataSource().AsQueryable(x => x.Name == etradeRule.AssetAccount_0).FirstOrDefault();//取对客簿记账户 + var asset = FindAssetUnit(etradeRule.AssetAccount_0);//取对客簿记账户 if (asset == null) { throw new ServiceException($"找不到名为{etradeRule.AssetAccount_0}的簿记账户信息"); @@ -644,16 +640,15 @@ namespace YLErp.Modules.SwapModule var clientSwapPositions = swapPositions.Where(x => clientSwapTradeIds.Contains(x.SwapTradeId));//现有客户持仓 var underlyingCodes = underlyingGroup.Select(s => s.Key).ToList(); - var underlyings = DataCacheProvider.GetUnderlyingDataSource().AsQueryable(x => underlyingCodes.Contains(x.UnderlyingCode)); foreach (var underlyingGroupItem in underlyingGroup) { var underlyingCode = underlyingGroupItem.Key; - var underlying = underlyings.FirstOrDefault(x => x.UnderlyingCode == underlyingCode); + var underlying = FindUnderlying(underlyingCode); if (underlying == null) { throw new ServiceException($"找不到标的代码为{underlyingCode}的标的信息"); } - var floatRate = new SwapFloatRateService(UserInfo).GetSwapFloatRate(floatRateQuery, clientId ?? 0, underlyingCode); + var floatRate = GetSwapFloatRate(floatRateQuery, clientId ?? 0, underlyingCode); var clientSwapPositionList = clientSwapPositions.Where(x => x.UnderlyingCode == underlyingCode).ToList();//现有标的持仓 var hasPayPosition = clientSwapPositionList.Any(); var mergeList = underlyingGroupItem.OrderByDescending(o => o.TradingQty).ToList(); @@ -674,9 +669,9 @@ namespace YLErp.Modules.SwapModule } if (cashNeedAfter) { - var flowEvents = DbContext.swap_flow_event.Where(x => x.EventDate == flowMerge.OccurTime && x.PayDate > x.UnwindDate && x.EventType == (int)SwapFlowEventTypeEnum.平仓 && x.DataState == (int)SwapFlowDateStateEnum.完成 && x.ClientId == flowMerge.ClientId && x.PayDirection > 0); + var flowEvents = FindFlowEventsForCashCheck(flowMerge); var tradeIds = flowEvents.Select(s => s.SwapTradeId).Distinct(); - var trades = DbContext.trade.Where(x => tradeIds.Contains(x.id) && x.ValidState != ConsGlobal.InValid); + var trades = FindValidTrades(tradeIds); cashNeedAfter = !trades.Any(); } if (!hasPayPosition)//没有持仓 @@ -689,7 +684,7 @@ namespace YLErp.Modules.SwapModule } } - DbContext.SaveChanges(); + SaveChanges(); } /// @@ -717,16 +712,15 @@ namespace YLErp.Modules.SwapModule var clientSwapTradeIds = clientSwapTrades.Select(s => s.id); var clientSwapPositions = swapPositions.Where(x => clientSwapTradeIds.Contains(x.SwapTradeId));//现有客户持仓 var underlyingCodes = underlyingGroup.Select(s => s.Key).ToList(); - var underlyings = DataCacheProvider.GetUnderlyingDataSource().AsQueryable(x => underlyingCodes.Contains(x.UnderlyingCode)); foreach (var underlyingGroupItem in underlyingGroup) { var underlyingCode = underlyingGroupItem.Key; - var underlying = underlyings.FirstOrDefault(x => x.UnderlyingCode == underlyingCode); + var underlying = FindUnderlying(underlyingCode); if (underlying == null) { throw new ServiceException($"找不到标的代码为{underlyingCode}的标的信息"); } - var floatRate = new SwapFloatRateService(UserInfo).GetSwapFloatRate(floatRateQuery, clientId ?? 0, underlyingCode); + var floatRate = GetSwapFloatRate(floatRateQuery, clientId ?? 0, underlyingCode); var clientSwapPositionList = clientSwapPositions.Where(x => x.UnderlyingCode == underlyingCode).ToList();//现有标的持仓 var hasPayPosition = clientSwapPositionList.Any(); var mergeList = underlyingGroupItem.OrderBy(o => o.OptTime).ToList(); @@ -765,14 +759,13 @@ namespace YLErp.Modules.SwapModule var mergeOrderList = mergeList.OrderBy(o => o.FirstFlowTime); swap_flow_merge flowMergeMax = mergeOrderList.First();//先开最早的一条 swap_flow_merge flowMergeMin = mergeOrderList.Last(); - var swapTradeService = new SwapTradeService(UserInfo); - var trade = swapTradeService.NewSwapTrade(flowMergeMax, client, asset, underlying, floatRate, clearingAgency, cashNeedAfter: cashNeedAfter); + var trade = CreateNewSwapTrade(flowMergeMax, client, asset, underlying, floatRate, clearingAgency, cashNeedAfter: cashNeedAfter); flowMergeMax.SwapTradeNo = trade.TradeNumber; flowMergeMin.SwapTradeNo = trade.TradeNumber; if (mergeList.Count == 2)//有两条流水 { var qty = flowMergeMax.TradingQtyAbs - flowMergeMin.TradingQtyAbs;//平仓剩余数量 - new SwapDealService(UserInfo).AuotoSwapUnwind(trade.id, + AutoSwapUnwind(trade.id, flowMergeMin.TradingAmountAvg, flowMergeMin.TradingAmountFeeAvg, flowMergeMin.TradingAmountNetFeeAvg ?? 0, @@ -798,7 +791,7 @@ namespace YLErp.Modules.SwapModule var posi = DbContext.swap_position.FirstOrDefault(x => x.SwapTradeId == trade.id && x.PosiDirection > 0 && !x.IsInitial); SetNewOpenData(flowMergeMin, flowMergeClone, posi); } - var trade2 = swapTradeService.NewSwapTrade(flowMergeClone, client, asset, underlying, floatRate, clearingAgency); + var trade2 = CreateNewSwapTrade(flowMergeClone, client, asset, underlying, floatRate, clearingAgency); flowMergeMax.SwapTradeNo = trade2.TradeNumber; flowMergeMin.SwapTradeNo = trade2.TradeNumber; } @@ -862,7 +855,7 @@ namespace YLErp.Modules.SwapModule } var trade = NewSwapTrade(sameFlowClone, client, asset, underlying, floatRate, clearingAgency); // 平仓 - new SwapDealService(UserInfo).AuotoSwapUnwind(trade.id, + AutoSwapUnwind(trade.id, negaFlowClone.TradingAmountAvg, negaFlowClone.TradingAmountFeeAvg, negaFlowClone.TradingAmountNetFeeAvg ?? 0,