@@ -18,6 +18,7 @@ using OpenApiSecurityScheme = NSwag.OpenApiSecurityScheme;
|
||||
|
||||
// Builder
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
builder.WebHost.UseUrls("http://localhost:5001");
|
||||
builder.Configuration.SetBasePath(AppContext.BaseDirectory);
|
||||
builder.Configuration.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
|
||||
.AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json");
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
using Managing.Application.Abstractions.Services;
|
||||
using Managing.Application.Abstractions;
|
||||
using Managing.Application.Abstractions.Services;
|
||||
using Managing.Application.Workers;
|
||||
using Managing.Application.Workers.Abstractions;
|
||||
using Managing.Domain.Accounts;
|
||||
using Managing.Domain.Trades;
|
||||
using Newtonsoft.Json;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Api.Workers.Workers;
|
||||
@@ -13,13 +16,14 @@ public class PositionManagerWorker : BaseWorker<PositionManagerWorker>
|
||||
private readonly IExchangeService _exchangeService;
|
||||
private readonly IAccountService _accountService;
|
||||
private readonly ILogger<PositionManagerWorker> _logger;
|
||||
private readonly ICacheService _cacheService;
|
||||
|
||||
public PositionManagerWorker(
|
||||
ILogger<PositionManagerWorker> logger,
|
||||
IWorkerService workerService,
|
||||
ITradingService tradingService,
|
||||
IExchangeService exchangeService,
|
||||
IAccountService accountService) : base(
|
||||
IAccountService accountService, ICacheService cacheService) : base(
|
||||
_workerType,
|
||||
logger,
|
||||
TimeSpan.FromMinutes(1),
|
||||
@@ -29,6 +33,7 @@ public class PositionManagerWorker : BaseWorker<PositionManagerWorker>
|
||||
_tradingService = tradingService;
|
||||
_exchangeService = exchangeService;
|
||||
_accountService = accountService;
|
||||
_cacheService = cacheService;
|
||||
}
|
||||
|
||||
protected override async Task Run(CancellationToken cancellationToken)
|
||||
@@ -46,21 +51,23 @@ public class PositionManagerWorker : BaseWorker<PositionManagerWorker>
|
||||
|
||||
foreach (var position in positions)
|
||||
{
|
||||
_logger.LogInformation("Managing Partilly filled position: {0} - Date: {1} - Direction: {2} - Ticker: {3}", position.Identifier, position.Date, position.OriginDirection, position.Ticker);
|
||||
_logger.LogInformation("Managing Partilly filled position: {0} - Date: {1} - Direction: {2} - Ticker: {3}",
|
||||
position.Identifier, position.Date, position.OriginDirection, position.Ticker);
|
||||
|
||||
var account = await _accountService.GetAccount(position.AccountName, false, false);
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
if (position.StopLoss.Status == TradeStatus.PendingOpen)
|
||||
{
|
||||
var stopLoss = _exchangeService.OpenStopLoss(account, position.Ticker, position.OriginDirection, position.StopLoss.Price, position.StopLoss.Quantity, false, DateTime.UtcNow).Result;
|
||||
var stopLoss = await _exchangeService.OpenStopLoss(account, position.Ticker,
|
||||
position.OriginDirection,
|
||||
position.StopLoss.Price, position.StopLoss.Quantity, false, DateTime.UtcNow);
|
||||
|
||||
if (stopLoss != null & (stopLoss.Status == TradeStatus.Requested))
|
||||
{
|
||||
position.StopLoss = stopLoss;
|
||||
_logger.LogInformation("|_ SL is requested");
|
||||
_logger.LogInformation("|_ SL is requested");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -74,7 +81,9 @@ public class PositionManagerWorker : BaseWorker<PositionManagerWorker>
|
||||
|
||||
if (position.TakeProfit1.Status == TradeStatus.PendingOpen)
|
||||
{
|
||||
var takeProfit1 = _exchangeService.OpenTakeProfit(account, position.Ticker, position.OriginDirection, position.TakeProfit1.Price, position.TakeProfit1.Quantity, false, DateTime.UtcNow).Result;
|
||||
var takeProfit1 = await _exchangeService.OpenTakeProfit(account, position.Ticker,
|
||||
position.OriginDirection, position.TakeProfit1.Price, position.TakeProfit1.Quantity, false,
|
||||
DateTime.UtcNow);
|
||||
|
||||
if (takeProfit1 != null & (takeProfit1.Status == TradeStatus.Requested))
|
||||
{
|
||||
@@ -94,7 +103,9 @@ public class PositionManagerWorker : BaseWorker<PositionManagerWorker>
|
||||
if (position.TakeProfit2 != null &&
|
||||
position.TakeProfit2.Status == TradeStatus.PendingOpen)
|
||||
{
|
||||
var takeProfit2 = _exchangeService.OpenTakeProfit(account, position.Ticker, position.OriginDirection, position.TakeProfit2.Price, position.TakeProfit2.Quantity, false, DateTime.UtcNow).Result;
|
||||
var takeProfit2 = await _exchangeService.OpenTakeProfit(account, position.Ticker,
|
||||
position.OriginDirection, position.TakeProfit2.Price, position.TakeProfit2.Quantity, false,
|
||||
DateTime.UtcNow);
|
||||
|
||||
if (takeProfit2 != null & (takeProfit2.Status == TradeStatus.Requested))
|
||||
{
|
||||
@@ -116,9 +127,9 @@ public class PositionManagerWorker : BaseWorker<PositionManagerWorker>
|
||||
_logger.LogError($"|_ Cannot fully filled position because : {ex.Message}");
|
||||
}
|
||||
|
||||
if (position.StopLoss.Status == TradeStatus.Requested
|
||||
&& position.TakeProfit1.Status == TradeStatus.Requested
|
||||
&& (position.TakeProfit2 == null || position.TakeProfit2.Status == TradeStatus.Requested))
|
||||
TradeStatus[] validStatus = [TradeStatus.Requested, TradeStatus.Filled];
|
||||
if (validStatus.Contains(position.StopLoss.Status)
|
||||
&& (validStatus.Contains(position.TakeProfit1.Status)))
|
||||
{
|
||||
position.Status = PositionStatus.Filled;
|
||||
_logger.LogInformation($"|_ Position is now open and SL/TP are correctly requested");
|
||||
@@ -136,8 +147,9 @@ public class PositionManagerWorker : BaseWorker<PositionManagerWorker>
|
||||
|
||||
foreach (var position in positions)
|
||||
{
|
||||
_logger.LogInformation("Managing filled position: {0} - Date: {1} - Direction: {2} - Ticker: {3}", position.Identifier, position.Date, position.OriginDirection, position.Ticker);
|
||||
var account = await _accountService.GetAccount(position.AccountName, false, false);
|
||||
_logger.LogInformation("Managing filled position: {0} - Date: {1} - Direction: {2} - Ticker: {3}",
|
||||
position.Identifier, position.Date, position.OriginDirection, position.Ticker);
|
||||
var account = await GetAccount(position.AccountName);
|
||||
|
||||
var updatedPosition = await _tradingService.ManagePosition(account, position);
|
||||
_tradingService.UpdatePosition(updatedPosition);
|
||||
@@ -158,9 +170,10 @@ public class PositionManagerWorker : BaseWorker<PositionManagerWorker>
|
||||
|
||||
foreach (var position in positions)
|
||||
{
|
||||
_logger.LogInformation("Managing position: {0} - Date: {1} - Direction: {2} - Ticker: {3}", position.Identifier, position.Date, position.OriginDirection, position.Ticker);
|
||||
_logger.LogInformation("Managing position: {0} - Date: {1} - Direction: {2} - Ticker: {3}",
|
||||
position.Identifier, position.Date, position.OriginDirection, position.Ticker);
|
||||
position.Status = PositionStatus.Updating;
|
||||
_tradingService.UpdatePosition(position);
|
||||
_tradingService.UpdatePosition(position);
|
||||
|
||||
// Update status if position is open since to long
|
||||
if (position.Date < DateTime.UtcNow.AddDays(-2))
|
||||
@@ -171,14 +184,15 @@ public class PositionManagerWorker : BaseWorker<PositionManagerWorker>
|
||||
continue;
|
||||
}
|
||||
|
||||
var account = await _accountService.GetAccount(position.AccountName, false, false);
|
||||
if (!(await _exchangeService.GetOpenOrders(account, position.Ticker)).Any())
|
||||
{
|
||||
position.Status = PositionStatus.Canceled;
|
||||
_tradingService.UpdatePosition(position);
|
||||
_logger.LogInformation($"|_ Position is now Canceled - Position close from exchange");
|
||||
continue;
|
||||
}
|
||||
var account = await GetAccount(position.AccountName);
|
||||
var currentOpenOrders = await _exchangeService.GetOpenOrders(account, position.Ticker);
|
||||
// if (currentOpenOrders.Any())
|
||||
// {
|
||||
// position.Status = PositionStatus.Canceled;
|
||||
// _tradingService.UpdatePosition(position);
|
||||
// _logger.LogInformation($"|_ Position is now Canceled - Position close from exchange");
|
||||
// continue;
|
||||
// }
|
||||
|
||||
var quantityInPosition = await _exchangeService.GetQuantityInPosition(account, position.Ticker);
|
||||
|
||||
@@ -198,4 +212,16 @@ public class PositionManagerWorker : BaseWorker<PositionManagerWorker>
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
private async Task<Account> GetAccount(string accountName)
|
||||
{
|
||||
var account = _cacheService.GetValue<Account>(accountName);
|
||||
|
||||
if (account == null)
|
||||
{
|
||||
account = await _accountService.GetAccount(accountName, false, false);
|
||||
_cacheService.SaveValue(accountName, JsonConvert.SerializeObject(account));
|
||||
}
|
||||
|
||||
return account;
|
||||
}
|
||||
}
|
||||
@@ -39,13 +39,14 @@ public class TradingController : ControllerBase
|
||||
ICommandHandler<OpenPositionRequest, Position> openTradeCommandHandler,
|
||||
ICommandHandler<ClosePositionCommand, Position> closeTradeCommandHandler,
|
||||
ITradingService tradingService,
|
||||
IMediator mediator)
|
||||
IMediator mediator, IMoneyManagementService moneyManagementService)
|
||||
{
|
||||
_logger = logger;
|
||||
_openTradeCommandHandler = openTradeCommandHandler;
|
||||
_closeTradeCommandHandler = closeTradeCommandHandler;
|
||||
_tradingService = tradingService;
|
||||
_mediator = mediator;
|
||||
_moneyManagementService = moneyManagementService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -112,7 +113,7 @@ public class TradingController : ControllerBase
|
||||
/// <param name="moneyManagement">The money management strategy details (optional).</param>
|
||||
/// <param name="openPrice">The opening price for the trade (optional).</param>
|
||||
/// <returns>The opened position.</returns>
|
||||
[HttpGet("OpenPosition")]
|
||||
[HttpPost("OpenPosition")]
|
||||
public async Task<ActionResult<Position>> Trade(
|
||||
string accountName,
|
||||
string moneyManagementName,
|
||||
@@ -120,7 +121,7 @@ public class TradingController : ControllerBase
|
||||
Ticker ticker,
|
||||
RiskLevel riskLevel,
|
||||
bool isForPaperTrading,
|
||||
MoneyManagement? moneyManagement = null,
|
||||
MoneyManagement? moneyManagement = null,
|
||||
decimal? openPrice = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(accountName))
|
||||
@@ -130,10 +131,11 @@ public class TradingController : ControllerBase
|
||||
|
||||
if (string.IsNullOrEmpty(moneyManagementName) && moneyManagement == null)
|
||||
{
|
||||
throw new ArgumentException($"'{nameof(moneyManagementName)}' cannot be null or empty.", nameof(moneyManagementName));
|
||||
throw new ArgumentException($"'{nameof(moneyManagementName)}' cannot be null or empty.",
|
||||
nameof(moneyManagementName));
|
||||
}
|
||||
|
||||
if (moneyManagement == null)
|
||||
if (moneyManagement != null)
|
||||
{
|
||||
moneyManagement = await _moneyManagementService.GetMoneyMangement(moneyManagementName);
|
||||
}
|
||||
|
||||
@@ -308,11 +308,14 @@ public class TradingBot : Bot, ITradingBot
|
||||
{
|
||||
await HandleClosedPosition(positionForSignal);
|
||||
}
|
||||
else if (position.Status == PositionStatus.Filled)
|
||||
else if (position.Status == (PositionStatus.Filled | PositionStatus.PartiallyFilled))
|
||||
{
|
||||
// For backtesting or force close if not executed on exchange :
|
||||
// check if position is still open
|
||||
// Check status, if still open update the status of the position
|
||||
|
||||
// Position might be partially filled, meaning that TPSL havent been sended yet
|
||||
// But the position might already been closed by the exchange so we have to check should be closed
|
||||
var lastCandle = IsForBacktest
|
||||
? OptimizedCandles.Last()
|
||||
: ExchangeService.GetCandle(Account, Ticker, DateTime.UtcNow);
|
||||
|
||||
@@ -618,7 +618,7 @@ public class EvmManager : IEvmManager
|
||||
{
|
||||
var chain = ChainService.GetChain(chainName);
|
||||
var web3 = new Web3(chain.RpcUrl);
|
||||
var quantity = await GmxService.QuantityInPosition(web3, publicAddress, ticker);
|
||||
var quantity = await _gmxV2Service.QuantityInPosition(web3, publicAddress, ticker);
|
||||
return quantity;
|
||||
}
|
||||
|
||||
|
||||
@@ -1372,4 +1372,9 @@ public class GmxV2Service
|
||||
{
|
||||
return $"{account}-{market}-{collateralToken}-{(isLong ? "true" : "false")}";
|
||||
}
|
||||
|
||||
public async Task<decimal> QuantityInPosition(Web3 web3, string publicAddress, Enums.Ticker ticker)
|
||||
{
|
||||
return (await GetTrade(web3, publicAddress, ticker)).Status == Enums.TradeStatus.Filled ? 1 : 0;
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,11 @@ const loadWidget = (component: any) => {
|
||||
const DeskWidget = React.forwardRef((props: any, ref) => {
|
||||
const widget = props
|
||||
const widgetProperties = widget['data-properties'] as IWidgetProperties
|
||||
const WidgetComponent = loadWidget(widgetProperties.id)
|
||||
|
||||
if (!widgetProperties) {
|
||||
return null
|
||||
}
|
||||
const WidgetComponent = loadWidget(widgetProperties?.id)
|
||||
return (
|
||||
<div ref={ref} {...props}>
|
||||
<Suspense fallback={<>Loading</>}>
|
||||
|
||||
@@ -47,7 +47,7 @@ const OpenPositonWidget = () => {
|
||||
form.riskLevel,
|
||||
false,
|
||||
form.stopLoss,
|
||||
form.takeProfit
|
||||
undefined
|
||||
)
|
||||
.then((result) => {
|
||||
t.update('success', 'Position created')
|
||||
|
||||
Reference in New Issue
Block a user