@@ -2,6 +2,7 @@
|
||||
using Managing.Application.Abstractions.Services;
|
||||
using Managing.Application.Trading;
|
||||
using Managing.Application.Trading.Commands;
|
||||
using Managing.Core.FixedSizedQueue;
|
||||
using Managing.Domain.Accounts;
|
||||
using Managing.Domain.Bots;
|
||||
using Managing.Domain.Candles;
|
||||
@@ -27,6 +28,7 @@ public class TradingBot : Bot, ITradingBot
|
||||
|
||||
public Account Account { get; set; }
|
||||
public HashSet<IStrategy> Strategies { get; set; }
|
||||
public FixedSizeQueue<Candle> OptimizedCandles { get; set; }
|
||||
public HashSet<Candle> Candles { get; set; }
|
||||
public HashSet<Signal> Signals { get; set; }
|
||||
public List<Position> Positions { get; set; }
|
||||
@@ -80,6 +82,7 @@ public class TradingBot : Bot, ITradingBot
|
||||
|
||||
Strategies = new HashSet<IStrategy>();
|
||||
Signals = new HashSet<Signal>();
|
||||
OptimizedCandles = new FixedSizeQueue<Candle>(600);
|
||||
Candles = new HashSet<Candle>();
|
||||
Positions = new List<Position>();
|
||||
WalletBalances = new Dictionary<DateTime, decimal>();
|
||||
@@ -160,13 +163,13 @@ public class TradingBot : Bot, ITradingBot
|
||||
Logger.LogInformation(
|
||||
$"Time : {DateTime.Now} - Server time {DateTime.Now.ToUniversalTime()} - Bot : {Name} - Type {BotType} - Ticker : {Ticker}");
|
||||
|
||||
var previousCandleCount = Candles.Count;
|
||||
var previousCandleCount = OptimizedCandles.Count;
|
||||
|
||||
if (!IsForBacktest)
|
||||
await UpdateCandles();
|
||||
|
||||
if (Candles.Count > previousCandleCount || IsForBacktest)
|
||||
await UpdateSignals(Candles);
|
||||
if (OptimizedCandles.Count > previousCandleCount || IsForBacktest)
|
||||
await UpdateSignals(OptimizedCandles);
|
||||
else
|
||||
Logger.LogInformation($"No need to update signals for {Ticker}");
|
||||
|
||||
@@ -177,35 +180,38 @@ public class TradingBot : Bot, ITradingBot
|
||||
SaveBackup();
|
||||
|
||||
await UpdateWalletBalances();
|
||||
Logger.LogInformation($"Candles : {Candles.Count}");
|
||||
Logger.LogInformation($"Signals : {Signals.Count}");
|
||||
Logger.LogInformation($"ExecutionCount : {ExecutionCount}");
|
||||
Logger.LogInformation($"Positions : {Positions.Count}");
|
||||
Logger.LogInformation("__________________________________________________");
|
||||
if (OptimizedCandles.Count % 100 == 0) // Log every 10th execution
|
||||
{
|
||||
Logger.LogInformation($"Candle date : {OptimizedCandles.Last().Date:u}");
|
||||
Logger.LogInformation($"Signals : {Signals.Count}");
|
||||
Logger.LogInformation($"ExecutionCount : {ExecutionCount}");
|
||||
Logger.LogInformation($"Positions : {Positions.Count}");
|
||||
Logger.LogInformation("__________________________________________________");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task PreloadCandles()
|
||||
{
|
||||
if (Candles.Any())
|
||||
if (OptimizedCandles.Any())
|
||||
return;
|
||||
|
||||
var candles = await ExchangeService.GetCandlesInflux(Account.Exchange, Ticker, PreloadSince, Timeframe);
|
||||
|
||||
foreach (var candle in candles.Where(c => c.Date < DateTime.Now.ToUniversalTime()))
|
||||
{
|
||||
if (!Candles.Any(c => c.Date == candle.Date))
|
||||
if (!OptimizedCandles.Any(c => c.Date == candle.Date))
|
||||
{
|
||||
Candles.Add(candle);
|
||||
await UpdateSignals(Candles);
|
||||
OptimizedCandles.Enqueue(candle);
|
||||
await UpdateSignals(OptimizedCandles);
|
||||
}
|
||||
}
|
||||
|
||||
PreloadedCandlesCount = Candles.Count();
|
||||
PreloadedCandlesCount = OptimizedCandles.Count();
|
||||
}
|
||||
|
||||
private async Task UpdateSignals(HashSet<Candle> candles)
|
||||
private async Task UpdateSignals(FixedSizeQueue<Candle> candles)
|
||||
{
|
||||
var signal = TradingBox.GetSignal(candles, Strategies, Signals);
|
||||
var signal = TradingBox.GetSignal(candles.ToHashSet(), Strategies, Signals);
|
||||
|
||||
if (signal == null) return;
|
||||
|
||||
@@ -236,15 +242,15 @@ public class TradingBot : Bot, ITradingBot
|
||||
|
||||
protected async Task UpdateCandles()
|
||||
{
|
||||
if (Candles.Count == 0 || ExecutionCount == 0)
|
||||
if (OptimizedCandles.Count == 0 || ExecutionCount == 0)
|
||||
return;
|
||||
|
||||
var lastCandle = Candles.Last();
|
||||
var lastCandle = OptimizedCandles.Last();
|
||||
var newCandle = await ExchangeService.GetCandlesInflux(Account.Exchange, Ticker, lastCandle.Date, Timeframe);
|
||||
|
||||
foreach (var candle in newCandle.Where(c => c.Date < DateTime.Now.ToUniversalTime()))
|
||||
{
|
||||
Candles.Add(candle);
|
||||
OptimizedCandles.Enqueue(candle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,17 +275,25 @@ public class TradingBot : Bot, ITradingBot
|
||||
|
||||
private async Task UpdateWalletBalances()
|
||||
{
|
||||
var lastCandle = OptimizedCandles.LastOrDefault();
|
||||
if (lastCandle == null) return;
|
||||
|
||||
var date = lastCandle.Date;
|
||||
|
||||
if (WalletBalances.Count == 0)
|
||||
{
|
||||
WalletBalances.Add(Candles.LastOrDefault().Date, await ExchangeService.GetBalance(Account, IsForBacktest));
|
||||
WalletBalances[date] = await ExchangeService.GetBalance(Account, IsForBacktest);
|
||||
return;
|
||||
}
|
||||
else if (!WalletBalances.Any(w => w.Key == Candles.LastOrDefault().Date))
|
||||
|
||||
if (!WalletBalances.ContainsKey(date))
|
||||
{
|
||||
var walletBalance = WalletBalances.FirstOrDefault().Value + GetProfitAndLoss();
|
||||
WalletBalances.Add(Candles.LastOrDefault().Date, walletBalance);
|
||||
var previousBalance = WalletBalances.First().Value;
|
||||
WalletBalances[date] = previousBalance + GetProfitAndLoss();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private async Task UpdatePosition(Signal signal, Position positionForSignal)
|
||||
{
|
||||
try
|
||||
@@ -293,7 +307,6 @@ public class TradingBot : Bot, ITradingBot
|
||||
if (position.Status == (PositionStatus.Finished | PositionStatus.Flipped))
|
||||
{
|
||||
await HandleClosedPosition(positionForSignal);
|
||||
return;
|
||||
}
|
||||
else if (position.Status == PositionStatus.Filled)
|
||||
{
|
||||
@@ -301,7 +314,7 @@ public class TradingBot : Bot, ITradingBot
|
||||
// check if position is still open
|
||||
// Check status, if still open update the status of the position
|
||||
var lastCandle = IsForBacktest
|
||||
? Candles.Last()
|
||||
? OptimizedCandles.Last()
|
||||
: ExchangeService.GetCandle(Account, Ticker, DateTime.UtcNow);
|
||||
|
||||
if (positionForSignal.OriginDirection == TradeDirection.Long)
|
||||
@@ -401,7 +414,7 @@ public class TradingBot : Bot, ITradingBot
|
||||
&& p.SignalIdentifier != signal.Identifier);
|
||||
|
||||
var lastPrice = IsForBacktest
|
||||
? Candles.Last().Close
|
||||
? OptimizedCandles.Last().Close
|
||||
: ExchangeService.GetPrice(Account, Ticker, DateTime.UtcNow);
|
||||
|
||||
// If position open
|
||||
@@ -511,7 +524,7 @@ public class TradingBot : Bot, ITradingBot
|
||||
if (lastPosition == null)
|
||||
return true;
|
||||
|
||||
var tenCandleAgo = Candles.TakeLast(10).First();
|
||||
var tenCandleAgo = OptimizedCandles.TakeLast(10).First();
|
||||
var positionSignal = Signals.FirstOrDefault(s => s.Identifier == lastPosition.SignalIdentifier);
|
||||
|
||||
return positionSignal.Date < tenCandleAgo.Date;
|
||||
@@ -543,8 +556,8 @@ public class TradingBot : Bot, ITradingBot
|
||||
try
|
||||
{
|
||||
var closedPosition =
|
||||
await (new ClosePositionCommandHandler(ExchangeService, AccountService, TradingService))
|
||||
.Handle(command);
|
||||
(new ClosePositionCommandHandler(ExchangeService, AccountService, TradingService)
|
||||
.Handle(command)).Result;
|
||||
|
||||
if (closedPosition.Status == (PositionStatus.Finished | PositionStatus.Flipped))
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user