Add manual close for bot positions
This commit is contained in:
@@ -1,23 +1,13 @@
|
||||
using Managing.Api.Models.Requests;
|
||||
using Managing.Api.Models.Responses;
|
||||
using Managing.Application.Abstractions;
|
||||
using Managing.Application.Abstractions.Services;
|
||||
using Managing.Application.Hubs;
|
||||
using Managing.Application.ManageBot.Commands;
|
||||
using Managing.Common;
|
||||
using Managing.Domain.Bots;
|
||||
using Managing.Domain.Users;
|
||||
using Managing.Domain.Trades;
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Managing.Domain.Trades;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using static Managing.Common.Enums;
|
||||
using ApplicationTradingBot = Managing.Application.Bots.TradingBot;
|
||||
using ApiTradingBot = Managing.Api.Models.Responses.TradingBot;
|
||||
@@ -464,4 +454,84 @@ public class BotController : BaseController
|
||||
return StatusCode(500, $"Error opening position: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes a specific position for a trading bot
|
||||
/// </summary>
|
||||
/// <param name="request">The request containing the position close parameters</param>
|
||||
/// <returns>The closed position or an error</returns>
|
||||
[HttpPost]
|
||||
[Route("ClosePosition")]
|
||||
public async Task<ActionResult<Position>> ClosePosition([FromBody] ClosePositionRequest request)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Check if user owns the account
|
||||
if (!await UserOwnsBotAccount(request.BotName))
|
||||
{
|
||||
return Forbid("You don't have permission to close positions for this bot");
|
||||
}
|
||||
|
||||
var activeBots = _botService.GetActiveBots();
|
||||
var bot = activeBots.FirstOrDefault(b => b.Name == request.BotName) as ApplicationTradingBot;
|
||||
|
||||
if (bot == null)
|
||||
{
|
||||
return NotFound($"Bot {request.BotName} not found or is not a trading bot");
|
||||
}
|
||||
|
||||
if (bot.GetStatus() != BotStatus.Up.ToString())
|
||||
{
|
||||
return BadRequest($"Bot {request.BotName} is not running");
|
||||
}
|
||||
|
||||
// Find the position to close
|
||||
var position = bot.Positions.FirstOrDefault(p => p.Identifier == request.PositionId);
|
||||
if (position == null)
|
||||
{
|
||||
return NotFound($"Position with ID {request.PositionId} not found for bot {request.BotName}");
|
||||
}
|
||||
|
||||
// Find the signal associated with this position
|
||||
var signal = bot.Signals.FirstOrDefault(s => s.Identifier == position.SignalIdentifier);
|
||||
if (signal == null)
|
||||
{
|
||||
return NotFound($"Signal not found for position {request.PositionId}");
|
||||
}
|
||||
|
||||
// Get current price
|
||||
var lastCandle = bot.OptimizedCandles.LastOrDefault();
|
||||
if (lastCandle == null)
|
||||
{
|
||||
return BadRequest("Cannot get current price to close position");
|
||||
}
|
||||
|
||||
// Close the position at market price
|
||||
await bot.CloseTrade(signal, position, position.Open, lastCandle.Close, true);
|
||||
|
||||
await NotifyBotSubscriberAsync();
|
||||
return Ok(position);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error closing position");
|
||||
return StatusCode(500, $"Error closing position: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Request model for closing a position
|
||||
/// </summary>
|
||||
public class ClosePositionRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of the bot
|
||||
/// </summary>
|
||||
public string BotName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The ID of the position to close
|
||||
/// </summary>
|
||||
public string PositionId { get; set; }
|
||||
}
|
||||
Reference in New Issue
Block a user