Postgres (#30)
* Add postgres * Migrate users * Migrate geneticRequest * Try to fix Concurrent call * Fix asyncawait * Fix async and concurrent * Migrate backtests * Add cache for user by address * Fix backtest migration * Fix not open connection * Fix backtest command error * Fix concurrent * Fix all concurrency * Migrate TradingRepo * Fix scenarios * Migrate statistic repo * Save botbackup * Add settings et moneymanagement * Add bot postgres * fix a bit more backups * Fix bot model * Fix loading backup * Remove cache market for read positions * Add workers to postgre * Fix workers api * Reduce get Accounts for workers * Migrate synth to postgre * Fix backtest saved * Remove mongodb * botservice decorrelation * Fix tradingbot scope call * fix tradingbot * fix concurrent * Fix scope for genetics * Fix account over requesting * Fix bundle backtest worker * fix a lot of things * fix tab backtest * Remove optimized moneymanagement * Add light signal to not use User and too much property * Make money management lighter * insert indicators to awaitable * Migrate add strategies to await * Refactor scenario and indicator retrieval to use asynchronous methods throughout the application * add more async await * Add services * Fix and clean * Fix bot a bit * Fix bot and add message for cooldown * Remove fees * Add script to deploy db * Update dfeeploy script * fix script * Add idempotent script and backup * finish script migration * Fix did user and agent name on start bot
This commit is contained in:
@@ -23,7 +23,7 @@ public class ClosePositionCommandHandler(
|
||||
var account = await accountService.GetAccount(request.Position.AccountName, false, false);
|
||||
if (request.Position == null)
|
||||
{
|
||||
_ = exchangeService.CancelOrder(account, request.Position.Ticker).Result;
|
||||
_ = await exchangeService.CancelOrder(account, request.Position.Ticker);
|
||||
return request.Position;
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ public class ClosePositionCommandHandler(
|
||||
|
||||
var lastPrice = request.Position.Initiator == PositionInitiator.PaperTrading
|
||||
? request.ExecutionPrice.GetValueOrDefault()
|
||||
: exchangeService.GetPrice(account, request.Position.Ticker, DateTime.UtcNow);
|
||||
: await exchangeService.GetPrice(account, request.Position.Ticker, DateTime.UtcNow);
|
||||
|
||||
// Check if position still open
|
||||
if (!request.IsForBacktest)
|
||||
@@ -46,7 +46,7 @@ public class ClosePositionCommandHandler(
|
||||
request.Position.ProfitAndLoss =
|
||||
TradingBox.GetProfitAndLoss(request.Position, request.Position.Open.Quantity, lastPrice,
|
||||
request.Position.Open.Leverage);
|
||||
tradingService.UpdatePosition(request.Position);
|
||||
await tradingService.UpdatePositionAsync(request.Position);
|
||||
return request.Position;
|
||||
}
|
||||
}
|
||||
@@ -67,7 +67,7 @@ public class ClosePositionCommandHandler(
|
||||
request.Position.Open.Leverage);
|
||||
|
||||
if (!request.IsForBacktest)
|
||||
tradingService.UpdatePosition(request.Position);
|
||||
await tradingService.UpdatePositionAsync(request.Position);
|
||||
}
|
||||
|
||||
return request.Position;
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
using Managing.Common;
|
||||
using Managing.Domain.Trades;
|
||||
using MediatR;
|
||||
|
||||
namespace Managing.Application.Trading.Commands
|
||||
{
|
||||
public class GetPositionsCommand : IRequest<List<Position>>
|
||||
{
|
||||
public GetPositionsCommand(Enums.PositionInitiator initiator)
|
||||
{
|
||||
Initiator = initiator;
|
||||
}
|
||||
|
||||
public Enums.PositionInitiator Initiator { get; internal set; }
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using Managing.Domain.MoneyManagements;
|
||||
using Managing.Domain.Trades;
|
||||
using Managing.Domain.Trades;
|
||||
using Managing.Domain.Users;
|
||||
using MediatR;
|
||||
using static Managing.Common.Enums;
|
||||
@@ -10,7 +9,7 @@ namespace Managing.Application.Trading.Commands
|
||||
{
|
||||
public OpenPositionRequest(
|
||||
string accountName,
|
||||
MoneyManagement moneyManagement,
|
||||
LightMoneyManagement moneyManagement,
|
||||
TradeDirection direction,
|
||||
Ticker ticker,
|
||||
PositionInitiator initiator,
|
||||
@@ -43,7 +42,7 @@ namespace Managing.Application.Trading.Commands
|
||||
|
||||
public string SignalIdentifier { get; set; }
|
||||
public string AccountName { get; }
|
||||
public MoneyManagement MoneyManagement { get; }
|
||||
public LightMoneyManagement MoneyManagement { get; }
|
||||
public TradeDirection Direction { get; }
|
||||
public Ticker Ticker { get; }
|
||||
public bool IsForPaperTrading { get; }
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
using Managing.Application.Abstractions.Services;
|
||||
using Managing.Application.Trading.Commands;
|
||||
using Managing.Domain.Trades;
|
||||
using MediatR;
|
||||
|
||||
namespace Managing.Application.Trading
|
||||
{
|
||||
public class GetPositionsCommandHandler : IRequestHandler<GetPositionsCommand, List<Position>>
|
||||
{
|
||||
private readonly ITradingService _tradingService;
|
||||
|
||||
public GetPositionsCommandHandler(ITradingService tradingService)
|
||||
{
|
||||
_tradingService = tradingService;
|
||||
}
|
||||
|
||||
public Task<List<Position>> Handle(GetPositionsCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var positions = _tradingService.GetPositions(request.Initiator);
|
||||
return Task.FromResult(positions.ToList());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,9 +15,9 @@ public class GetTradeCommandHandler : IRequestHandler<GetTradeCommand, Trade>
|
||||
_accountService = accountService;
|
||||
}
|
||||
|
||||
public Task<Trade> Handle(GetTradeCommand request, CancellationToken cancellationToken)
|
||||
public async Task<Trade> Handle(GetTradeCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var account = _accountService.GetAccount(request.AccountName, true, false).Result;
|
||||
return _exchangeService.GetTrade(account, request.ExchangeOrderId, request.Ticker);
|
||||
var account = await _accountService.GetAccount(request.AccountName, true, false);
|
||||
return await _exchangeService.GetTrade(account, request.ExchangeOrderId, request.Ticker);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,10 +16,10 @@ namespace Managing.Application.Trading
|
||||
_accountService = accountService;
|
||||
}
|
||||
|
||||
public Task<List<Trade>> Handle(GetTradesCommand request, CancellationToken cancellationToken)
|
||||
public async Task<List<Trade>> Handle(GetTradesCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var account = _accountService.GetAccount(request.AccountName, true, false).Result;
|
||||
return _exchangeService.GetTrades(account, request.Ticker);
|
||||
var account = await _accountService.GetAccount(request.AccountName, true, false);
|
||||
return await _exchangeService.GetTrades(account, request.Ticker);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,12 +49,12 @@ namespace Managing.Application.Trading
|
||||
|
||||
var price = request.IsForPaperTrading && request.Price.HasValue
|
||||
? request.Price.Value
|
||||
: exchangeService.GetPrice(account, request.Ticker, DateTime.Now);
|
||||
: await exchangeService.GetPrice(account, request.Ticker, DateTime.Now);
|
||||
var quantity = balanceToRisk / price;
|
||||
|
||||
var openPrice = request.IsForPaperTrading || request.Price.HasValue
|
||||
? request.Price.Value
|
||||
: exchangeService.GetBestPrice(account, request.Ticker, price, quantity, request.Direction);
|
||||
: await exchangeService.GetBestPrice(account, request.Ticker, price, quantity, request.Direction);
|
||||
|
||||
// Determine SL/TP Prices
|
||||
var stopLossPrice = RiskHelpers.GetStopLossPrice(request.Direction, openPrice, request.MoneyManagement);
|
||||
@@ -107,22 +107,12 @@ namespace Managing.Application.Trading
|
||||
|
||||
if (!request.IsForPaperTrading)
|
||||
{
|
||||
tradingService.InsertPosition(position);
|
||||
await tradingService.InsertPositionAsync(position);
|
||||
}
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
private static TradeStatus GetExpectedStatus(OpenPositionRequest request)
|
||||
{
|
||||
if (request.IsForPaperTrading)
|
||||
{
|
||||
return TradeStatus.Filled;
|
||||
}
|
||||
|
||||
return TradeStatus.Requested;
|
||||
}
|
||||
|
||||
private static bool IsOpenTradeHandled(TradeStatus tradeStatus, TradingExchanges exchange)
|
||||
{
|
||||
return tradeStatus == TradeStatus.Filled
|
||||
|
||||
@@ -51,85 +51,70 @@ public class TradingService : ITradingService
|
||||
_synthPredictionService = synthPredictionService;
|
||||
}
|
||||
|
||||
public void DeleteScenario(string name)
|
||||
public async Task DeleteScenarioAsync(string name)
|
||||
{
|
||||
_tradingRepository.DeleteScenario(name);
|
||||
await _tradingRepository.DeleteScenarioAsync(name);
|
||||
}
|
||||
|
||||
public void DeleteScenarios()
|
||||
public async Task DeleteStrategyAsync(string name)
|
||||
{
|
||||
_tradingRepository.DeleteScenarios();
|
||||
await _tradingRepository.DeleteIndicatorAsync(name);
|
||||
}
|
||||
|
||||
public void DeleteStrategies()
|
||||
public async Task<Position> GetPositionByIdentifierAsync(string identifier)
|
||||
{
|
||||
_tradingRepository.DeleteIndicators();
|
||||
return await _tradingRepository.GetPositionByIdentifierAsync(identifier);
|
||||
}
|
||||
|
||||
public void DeleteStrategy(string name)
|
||||
public async Task<IEnumerable<Position>> GetPositionsAsync(PositionInitiator positionInitiator)
|
||||
{
|
||||
_tradingRepository.DeleteIndicator(name);
|
||||
return await _tradingRepository.GetPositionsAsync(positionInitiator);
|
||||
}
|
||||
|
||||
public Position GetPositionByIdentifier(string identifier)
|
||||
public async Task<IEnumerable<Position>> GetPositionsByStatusAsync(PositionStatus postionStatus)
|
||||
{
|
||||
return _tradingRepository.GetPositionByIdentifier(identifier);
|
||||
}
|
||||
|
||||
public IEnumerable<Position> GetPositions(PositionInitiator positionInitiator)
|
||||
{
|
||||
return _tradingRepository.GetPositions(positionInitiator);
|
||||
}
|
||||
|
||||
public IEnumerable<Position> GetPositionsByStatus(PositionStatus postionStatus)
|
||||
{
|
||||
return _tradingRepository.GetPositionsByStatus(postionStatus);
|
||||
return await _tradingRepository.GetPositionsByStatusAsync(postionStatus);
|
||||
}
|
||||
|
||||
|
||||
public Scenario GetScenarioByName(string scenario)
|
||||
public async Task<Scenario> GetScenarioByNameAsync(string scenario)
|
||||
{
|
||||
return _tradingRepository.GetScenarioByName(scenario);
|
||||
return await _tradingRepository.GetScenarioByNameAsync(scenario);
|
||||
}
|
||||
|
||||
public IEnumerable<Scenario> GetScenarios()
|
||||
public async Task<IEnumerable<Scenario>> GetScenariosAsync()
|
||||
{
|
||||
return _tradingRepository.GetScenarios();
|
||||
return await _tradingRepository.GetScenariosAsync();
|
||||
}
|
||||
|
||||
public IEnumerable<Indicator> GetStrategies()
|
||||
public async Task<IEnumerable<Indicator>> GetStrategiesAsync()
|
||||
{
|
||||
return _tradingRepository.GetIndicators();
|
||||
return await _tradingRepository.GetStrategiesAsync();
|
||||
}
|
||||
|
||||
public Indicator GetStrategyByName(string strategy)
|
||||
public async Task<Indicator> GetStrategyByNameAsync(string strategy)
|
||||
{
|
||||
return _tradingRepository.GetStrategyByName(strategy);
|
||||
return await _tradingRepository.GetStrategyByNameAsync(strategy);
|
||||
}
|
||||
|
||||
public void InsertPosition(Position position)
|
||||
public async Task InsertPositionAsync(Position position)
|
||||
{
|
||||
_tradingRepository.InsertPosition(position);
|
||||
await _tradingRepository.InsertPositionAsync(position);
|
||||
}
|
||||
|
||||
public void InsertScenario(Scenario scenario)
|
||||
public async Task InsertScenarioAsync(Scenario scenario)
|
||||
{
|
||||
_tradingRepository.InsertScenario(scenario);
|
||||
await _tradingRepository.InsertScenarioAsync(scenario);
|
||||
}
|
||||
|
||||
public void InsertSignal(Signal signal)
|
||||
public async Task InsertStrategyAsync(Indicator indicator)
|
||||
{
|
||||
_tradingRepository.InsertSignal(signal);
|
||||
}
|
||||
|
||||
public void InsertStrategy(Indicator indicator)
|
||||
{
|
||||
_tradingRepository.InsertStrategy(indicator);
|
||||
await _tradingRepository.InsertStrategyAsync(indicator);
|
||||
}
|
||||
|
||||
public async Task<Position> ManagePosition(Account account, Position position)
|
||||
{
|
||||
var lastPrice = _exchangeService.GetPrice(account, position.Ticker, DateTime.UtcNow);
|
||||
var lastPrice = await _exchangeService.GetPrice(account, position.Ticker, DateTime.UtcNow);
|
||||
var quantityInPosition = await _exchangeService.GetQuantityInPosition(account, position.Ticker);
|
||||
var orders = await _exchangeService.GetOpenOrders(account, position.Ticker);
|
||||
|
||||
@@ -184,54 +169,19 @@ public class TradingService : ITradingService
|
||||
return position;
|
||||
}
|
||||
|
||||
public void UpdateFee(TradingExchanges exchange)
|
||||
{
|
||||
var lastFee = _tradingRepository.GetFee(exchange);
|
||||
var account = _accountService.GetAccounts(false, false).FirstOrDefault(a => a.Exchange == exchange);
|
||||
if (lastFee != null)
|
||||
{
|
||||
if (DateTime.UtcNow.AddHours(-6) >= lastFee.LastUpdate)
|
||||
{
|
||||
lastFee.Cost = _exchangeService.GetFee(account);
|
||||
lastFee.LastUpdate = DateTime.UtcNow;
|
||||
_tradingRepository.UpdateFee(lastFee);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lastFee = new Fee
|
||||
{
|
||||
Cost = _exchangeService.GetFee(account),
|
||||
Exchange = exchange,
|
||||
LastUpdate = DateTime.UtcNow
|
||||
};
|
||||
|
||||
_tradingRepository.InsertFee(lastFee);
|
||||
}
|
||||
|
||||
public async Task UpdatePositionAsync(Position position)
|
||||
{
|
||||
await _tradingRepository.UpdatePositionAsync(position);
|
||||
}
|
||||
|
||||
public decimal GetFee(Account account, bool isForPaperTrading = false)
|
||||
{
|
||||
if (isForPaperTrading && account.Exchange != TradingExchanges.Evm)
|
||||
{
|
||||
return 0.000665M;
|
||||
}
|
||||
|
||||
return _cacheService.GetOrSave($"Fee-{account.Exchange}",
|
||||
() => { return (decimal)_tradingRepository.GetFee(TradingExchanges.Evm)?.Cost; }, TimeSpan.FromHours(2));
|
||||
}
|
||||
|
||||
public void UpdatePosition(Position position)
|
||||
{
|
||||
_tradingRepository.UpdatePosition(position);
|
||||
}
|
||||
|
||||
public IEnumerable<Position> GetPositions()
|
||||
public async Task<IEnumerable<Position>> GetPositionsAsync()
|
||||
{
|
||||
var positions = new List<Position>();
|
||||
positions.AddRange(GetPositionsByStatus(PositionStatus.New));
|
||||
positions.AddRange(GetPositionsByStatus(PositionStatus.Filled));
|
||||
positions.AddRange(GetPositionsByStatus(PositionStatus.PartiallyFilled));
|
||||
positions.AddRange(await GetPositionsByStatusAsync(PositionStatus.New));
|
||||
positions.AddRange(await GetPositionsByStatusAsync(PositionStatus.Filled));
|
||||
positions.AddRange(await GetPositionsByStatusAsync(PositionStatus.PartiallyFilled));
|
||||
return positions;
|
||||
}
|
||||
|
||||
@@ -239,7 +189,7 @@ public class TradingService : ITradingService
|
||||
public async Task WatchTrader()
|
||||
{
|
||||
var availableTickers = new List<Ticker> { Ticker.BTC, Ticker.ETH, Ticker.UNI, Ticker.LINK };
|
||||
var watchAccount = GetTradersWatch();
|
||||
var watchAccount = await GetTradersWatch();
|
||||
var key = $"AccountsQuantityInPosition";
|
||||
var aqip = _cacheService.GetValue<List<TraderFollowup>>(key);
|
||||
|
||||
@@ -264,10 +214,11 @@ public class TradingService : ITradingService
|
||||
_cacheService.SaveValue(key, aqip, TimeSpan.FromMinutes(10));
|
||||
}
|
||||
|
||||
public IEnumerable<Trader> GetTradersWatch()
|
||||
public async Task<IEnumerable<Trader>> GetTradersWatch()
|
||||
{
|
||||
var watchAccount = _statisticRepository.GetBestTraders();
|
||||
var customWatchAccount = _accountService.GetAccounts(true, false).Where(a => a.Type == AccountType.Watch)
|
||||
var watchAccount = await _statisticRepository.GetBestTradersAsync();
|
||||
var customWatchAccount = (await _accountService.GetAccountsAsync(true, false))
|
||||
.Where(a => a.Type == AccountType.Watch)
|
||||
.ToList().MapToTraders();
|
||||
watchAccount.AddRange(customWatchAccount.Where(a =>
|
||||
!watchAccount.Any(w => w.Address.Equals(a.Address, StringComparison.InvariantCultureIgnoreCase))));
|
||||
@@ -279,14 +230,14 @@ public class TradingService : ITradingService
|
||||
var fundingRates = _exchangeService.GetFundingRates();
|
||||
}
|
||||
|
||||
public void UpdateScenario(Scenario scenario)
|
||||
public async Task UpdateScenarioAsync(Scenario scenario)
|
||||
{
|
||||
_tradingRepository.UpdateScenario(scenario);
|
||||
await _tradingRepository.UpdateScenarioAsync(scenario);
|
||||
}
|
||||
|
||||
public void UpdateStrategy(Indicator indicator)
|
||||
public async Task UpdateStrategyAsync(Indicator indicator)
|
||||
{
|
||||
_tradingRepository.UpdateStrategy(indicator);
|
||||
await _tradingRepository.UpdateStrategyAsync(indicator);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<Position>> GetBrokerPositions(Account account)
|
||||
@@ -407,7 +358,7 @@ public class TradingService : ITradingService
|
||||
}
|
||||
|
||||
// Synth API integration methods
|
||||
public async Task<SignalValidationResult> ValidateSynthSignalAsync(Signal signal, decimal currentPrice,
|
||||
public async Task<SignalValidationResult> ValidateSynthSignalAsync(LightSignal signal, decimal currentPrice,
|
||||
TradingBotConfig botConfig, bool isBacktest)
|
||||
{
|
||||
return await _synthPredictionService.ValidateSignalAsync(signal, currentPrice, botConfig, isBacktest);
|
||||
@@ -433,12 +384,12 @@ public class TradingService : ITradingService
|
||||
/// <param name="scenario">The scenario containing indicators.</param>
|
||||
/// <param name="candles">The candles to calculate indicators for.</param>
|
||||
/// <returns>A dictionary of indicator types to their calculated values.</returns>
|
||||
public async Task<Dictionary<IndicatorType, IndicatorsResultBase>> CalculateIndicatorsValuesAsync(
|
||||
Scenario scenario,
|
||||
public Dictionary<IndicatorType, IndicatorsResultBase> CalculateIndicatorsValuesAsync(
|
||||
Scenario scenario,
|
||||
List<Candle> candles)
|
||||
{
|
||||
var indicatorsValues = new Dictionary<IndicatorType, IndicatorsResultBase>();
|
||||
|
||||
|
||||
if (scenario?.Indicators == null || scenario.Indicators.Count == 0)
|
||||
{
|
||||
return indicatorsValues;
|
||||
@@ -459,13 +410,13 @@ public class TradingService : ITradingService
|
||||
// Build the indicator using ScenarioHelpers
|
||||
var builtIndicator = ScenarioHelpers.BuildIndicator(indicator, 10000);
|
||||
builtIndicator.Candles = fixedCandles;
|
||||
|
||||
|
||||
indicatorsValues[indicator.Type] = builtIndicator.GetIndicatorValues();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Log the error but continue with other indicators
|
||||
_logger.LogError(ex, "Error calculating indicator {IndicatorName}: {ErrorMessage}",
|
||||
_logger.LogError(ex, "Error calculating indicator {IndicatorName}: {ErrorMessage}",
|
||||
indicator.Name, ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user