From 292a48d10896ca56819009f05238b3c255db8aa6 Mon Sep 17 00:00:00 2001 From: cryptooda Date: Thu, 11 Dec 2025 12:23:01 +0700 Subject: [PATCH] Fix close position --- src/Managing.Application/Bots/SpotBot.cs | 27 ++++++------------- .../CloseSpotPositionCommandHandler.cs | 14 ++++++++-- .../test/plugins/swap-tokens.test.ts | 2 +- 3 files changed, 21 insertions(+), 22 deletions(-) diff --git a/src/Managing.Application/Bots/SpotBot.cs b/src/Managing.Application/Bots/SpotBot.cs index afc4eafb..59b562b2 100644 --- a/src/Managing.Application/Bots/SpotBot.cs +++ b/src/Managing.Application/Bots/SpotBot.cs @@ -1,4 +1,3 @@ -using Managing.Application.Abstractions; using Managing.Application.Abstractions.Grains; using Managing.Application.Abstractions.Services; using Managing.Application.Trading.Commands; @@ -18,7 +17,7 @@ using static Managing.Common.Enums; namespace Managing.Application.Bots; -public class SpotBot : TradingBotBase, ITradingBot +public class SpotBot : TradingBotBase { public SpotBot( ILogger logger, @@ -288,16 +287,9 @@ public class SpotBot : TradingBotBase, ITradingBot } // Calculate and update PnL based on current price - var currentPrice = LastCandle?.Close ?? 0; - if (currentPrice == 0) - { - currentPrice = await ServiceScopeHelpers.WithScopedService( - _scopeFactory, - async exchangeService => - { - return await exchangeService.GetCurrentPrice(Account, Config.Ticker); - }); - } + var currentPrice = await ServiceScopeHelpers.WithScopedService( + _scopeFactory, + async exchangeService => { return await exchangeService.GetCurrentPrice(Account, Config.Ticker); }); if (currentPrice > 0) { @@ -728,14 +720,11 @@ public class SpotBot : TradingBotBase, ITradingBot var command = new CloseSpotPositionCommand(position, position.AccountId, lastPrice); try { - Position closedPosition = null; - await ServiceScopeHelpers.WithScopedServices( - _scopeFactory, async (exchangeService, accountService, tradingService) => - { - closedPosition = + Position closedPosition = await ServiceScopeHelpers + .WithScopedServices( + _scopeFactory, async (exchangeService, accountService, tradingService) => await new CloseSpotPositionCommandHandler(exchangeService, accountService, tradingService) - .Handle(command); - }); + .Handle(command)); if (closedPosition.Status == PositionStatus.Finished || closedPosition.Status == PositionStatus.Flipped) { diff --git a/src/Managing.Application/Trading/Handlers/CloseSpotPositionCommandHandler.cs b/src/Managing.Application/Trading/Handlers/CloseSpotPositionCommandHandler.cs index 5d33fa16..984deb38 100644 --- a/src/Managing.Application/Trading/Handlers/CloseSpotPositionCommandHandler.cs +++ b/src/Managing.Application/Trading/Handlers/CloseSpotPositionCommandHandler.cs @@ -23,6 +23,7 @@ public class CloseSpotPositionCommandHandler( { // For backtest, use execution price directly var lastPrice = request.ExecutionPrice.GetValueOrDefault(); + var amountToSwap = request.Position.Open.Quantity; // Calculate closing direction (opposite of opening direction) var direction = request.Position.OriginDirection == TradeDirection.Long @@ -47,12 +48,21 @@ public class CloseSpotPositionCommandHandler( { // For live trading, call SwapGmxTokensAsync var account = await accountService.GetAccountById(request.AccountId); + var tokenBalance = await exchangeService.GetBalance(account, request.Position.Ticker); + + if (tokenBalance == null || tokenBalance.Amount <= 0) + { + throw new InvalidOperationException( + $"No available balance to close spot position for {request.Position.Ticker}"); + } + + amountToSwap = tokenBalance.Amount; swapResult = await tradingService.SwapGmxTokensAsync( request.Position.User, account.Name, request.Position.Ticker, Ticker.USDC, - (double)request.Position.Open.Quantity, + (double)amountToSwap, "market", null, 0.5); @@ -68,7 +78,7 @@ public class CloseSpotPositionCommandHandler( var closedTrade = exchangeService.BuildEmptyTrade( request.Position.Open.Ticker, lastPrice, - request.Position.Open.Quantity, + amountToSwap, direction, 1, // Spot trading has no leverage TradeType.Market, diff --git a/src/Managing.Web3Proxy/test/plugins/swap-tokens.test.ts b/src/Managing.Web3Proxy/test/plugins/swap-tokens.test.ts index 302a7ed9..758a7f87 100644 --- a/src/Managing.Web3Proxy/test/plugins/swap-tokens.test.ts +++ b/src/Managing.Web3Proxy/test/plugins/swap-tokens.test.ts @@ -15,7 +15,7 @@ describe('swap tokens implementation', () => { sdk, Ticker.BTC, Ticker.USDC, - 0.00007555 + 0.00007559 ) assert.strictEqual(typeof result, 'string')