* Trading bot Grain * Fix a bit more of the trading bot * Advance on the tradingbot grain * Fix build * Fix db script * Fix user login * Fix a bit backtest * Fix cooldown and backtest * start fixing bot start * Fix startup * Setup local db * Fix build and update candles and scenario * Add bot registry * Add reminder * Updateing the grains * fix bootstraping * Save stats on tick * Save bot data every tick * Fix serialization * fix save bot stats * Fix get candles * use dict instead of list for position * Switch hashset to dict * Fix a bit * Fix bot launch and bot view * add migrations * Remove the tolist * Add agent grain * Save agent summary * clean * Add save bot * Update get bots * Add get bots * Fix stop/restart * fix Update config * Update scanner table on new backtest saved * Fix backtestRowDetails.tsx * Fix agentIndex * Update agentIndex * Fix more things * Update user cache * Fix * Fix account load/start/restart/run
217 lines
8.8 KiB
C#
217 lines
8.8 KiB
C#
using Managing.Application.Abstractions.Services;
|
|
using Managing.Domain.Accounts;
|
|
using Managing.Domain.Candles;
|
|
using Managing.Domain.Indicators;
|
|
using Managing.Domain.Strategies.Signals;
|
|
using Managing.Domain.Strategies.Trends;
|
|
using Xunit;
|
|
using static Managing.Common.Enums;
|
|
|
|
namespace Managing.Application.Tests
|
|
{
|
|
public class IndicatorBaseTests
|
|
{
|
|
private readonly IExchangeService _exchangeService;
|
|
|
|
public IndicatorBaseTests()
|
|
{
|
|
_exchangeService = TradingBaseTests.GetExchangeService();
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(TradingExchanges.Binance, Ticker.ADA, Timeframe.OneDay)]
|
|
public async Task Should_Return_Signal_On_Rsi_BullishDivergence2(TradingExchanges exchange, Ticker ticker,
|
|
Timeframe timeframe)
|
|
{
|
|
var account = GetAccount(exchange);
|
|
// Arrange
|
|
var rsiStrategy = new RsiDivergenceIndicatorBase("unittest", 5);
|
|
var candles = await _exchangeService.GetCandles(account, ticker, DateTime.Now.AddDays(-50), timeframe);
|
|
var resultSignal = new List<LightSignal>();
|
|
|
|
// Act
|
|
foreach (var candle in candles)
|
|
{
|
|
var signals = rsiStrategy.Run(new HashSet<Candle> { candle });
|
|
}
|
|
|
|
if (rsiStrategy.Signals != null && rsiStrategy.Signals.Count > 0)
|
|
resultSignal.AddRange(rsiStrategy.Signals);
|
|
|
|
// Assert
|
|
Assert.IsType<List<LightSignal>>(resultSignal);
|
|
Assert.Contains(resultSignal, s => s.Direction == TradeDirection.Long);
|
|
}
|
|
|
|
private static Account GetAccount(TradingExchanges exchange)
|
|
{
|
|
return new Account()
|
|
{
|
|
Exchange = exchange
|
|
};
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(TradingExchanges.Binance, Ticker.ADA, Timeframe.OneDay)]
|
|
public async Task Shoud_Return_Signal_On_Rsi_BearishDivergence(TradingExchanges exchange, Ticker ticker,
|
|
Timeframe timeframe)
|
|
{
|
|
// Arrange
|
|
var account = GetAccount(exchange);
|
|
var rsiStrategy = new RsiDivergenceIndicatorBase("unittest", 5);
|
|
var candles = await _exchangeService.GetCandles(account, ticker, DateTime.Now.AddDays(-50), timeframe);
|
|
var resultSignal = new List<LightSignal>();
|
|
|
|
// Act
|
|
foreach (var candle in candles)
|
|
{
|
|
var signals = rsiStrategy.Run(new HashSet<Candle> { candle });
|
|
}
|
|
|
|
if (rsiStrategy.Signals != null && rsiStrategy.Signals.Count > 0)
|
|
resultSignal.AddRange(rsiStrategy.Signals);
|
|
|
|
// Assert
|
|
Assert.IsType<List<LightSignal>>(resultSignal);
|
|
Assert.Contains(resultSignal, s => s.Direction == TradeDirection.Short);
|
|
}
|
|
|
|
|
|
[Theory]
|
|
[InlineData(TradingExchanges.Ftx, Ticker.ADA, Timeframe.OneDay, -500)]
|
|
public async Task Shoud_Return_Signal_On_Macd_Cross(TradingExchanges exchange, Ticker ticker,
|
|
Timeframe timeframe, int days)
|
|
{
|
|
// Arrange
|
|
var account = GetAccount(exchange);
|
|
var rsiStrategy = new MacdCrossIndicatorBase("unittest", 12, 26, 9);
|
|
var candles = await _exchangeService.GetCandles(account, ticker, DateTime.Now.AddDays(days), timeframe);
|
|
var resultSignal = new List<LightSignal>();
|
|
|
|
// Act
|
|
foreach (var candle in candles)
|
|
{
|
|
var signals = rsiStrategy.Run(new HashSet<Candle> { candle });
|
|
}
|
|
|
|
if (rsiStrategy.Signals != null && rsiStrategy.Signals.Count > 0)
|
|
resultSignal.AddRange(rsiStrategy.Signals);
|
|
|
|
// Assert
|
|
Assert.IsType<List<LightSignal>>(resultSignal);
|
|
Assert.Contains(resultSignal, s => s.Direction == TradeDirection.Short);
|
|
Assert.Contains(resultSignal, s => s.Direction == TradeDirection.Long);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(TradingExchanges.Ftx, Ticker.ADA, Timeframe.OneDay, -500)]
|
|
public async Task Shoud_Return_Signal_On_SuperTrend(TradingExchanges exchange, Ticker ticker,
|
|
Timeframe timeframe,
|
|
int days)
|
|
{
|
|
// Arrange
|
|
var account = GetAccount(exchange);
|
|
var superTrendStrategy = new SuperTrendIndicatorBase("unittest", 10, 3);
|
|
var candles = await _exchangeService.GetCandles(account, ticker, DateTime.Now.AddDays(days), timeframe);
|
|
var resultSignal = new List<LightSignal>();
|
|
|
|
// Act
|
|
foreach (var candle in candles)
|
|
{
|
|
var signals = superTrendStrategy.Run(new HashSet<Candle> { candle });
|
|
}
|
|
|
|
if (superTrendStrategy.Signals != null && superTrendStrategy.Signals.Count > 0)
|
|
resultSignal.AddRange(superTrendStrategy.Signals);
|
|
|
|
// Assert
|
|
Assert.IsType<List<LightSignal>>(resultSignal);
|
|
Assert.Contains(resultSignal, s => s.Direction == TradeDirection.Short);
|
|
Assert.Contains(resultSignal, s => s.Direction == TradeDirection.Long);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(TradingExchanges.Ftx, Ticker.ADA, Timeframe.OneDay, -500)]
|
|
public async Task Shoud_Return_Signal_On_ChandelierExist(TradingExchanges exchange, Ticker ticker,
|
|
Timeframe timeframe, int days)
|
|
{
|
|
// Arrange
|
|
var account = GetAccount(exchange);
|
|
var chandelierExitStrategy = new ChandelierExitIndicatorBase("unittest", 22, 3);
|
|
var candles =
|
|
await _exchangeService.GetCandles(account, ticker, DateTime.Now.AddDays(days), timeframe, false);
|
|
var resultSignal = new List<LightSignal>();
|
|
|
|
// Act
|
|
foreach (var candle in candles)
|
|
{
|
|
var signals = chandelierExitStrategy.Run(new HashSet<Candle> { candle });
|
|
}
|
|
|
|
if (chandelierExitStrategy.Signals is { Count: > 0 })
|
|
resultSignal.AddRange(chandelierExitStrategy.Signals);
|
|
|
|
// Assert
|
|
Assert.IsType<List<LightSignal>>(resultSignal);
|
|
Assert.Contains(resultSignal, s => s.Direction == TradeDirection.Short);
|
|
Assert.Contains(resultSignal, s => s.Direction == TradeDirection.Long);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(TradingExchanges.Ftx, Ticker.ADA, Timeframe.OneDay, -500)]
|
|
public async Task Shoud_Return_Signal_On_EmaTrend(TradingExchanges exchange, Ticker ticker, Timeframe timeframe,
|
|
int days)
|
|
{
|
|
// Arrange
|
|
var account = GetAccount(exchange);
|
|
var emaTrendSrategy = new EmaTrendIndicatorBase("unittest", 200);
|
|
var candles = await _exchangeService.GetCandles(account, ticker, DateTime.Now.AddDays(days), timeframe);
|
|
var resultSignal = new List<LightSignal>();
|
|
|
|
// Act
|
|
foreach (var candle in candles)
|
|
{
|
|
var signals = emaTrendSrategy.Run(new HashSet<Candle> { candle });
|
|
}
|
|
|
|
if (emaTrendSrategy.Signals != null && emaTrendSrategy.Signals.Count > 0)
|
|
resultSignal.AddRange(emaTrendSrategy.Signals);
|
|
|
|
// Assert
|
|
Assert.IsType<List<LightSignal>>(resultSignal);
|
|
Assert.Contains(resultSignal, s => s.Direction == TradeDirection.Short);
|
|
Assert.Contains(resultSignal, s => s.Direction == TradeDirection.Long);
|
|
}
|
|
|
|
|
|
[Theory]
|
|
[InlineData(TradingExchanges.Evm, Ticker.BTC, Timeframe.FifteenMinutes, -50)]
|
|
public async Task Shoud_Return_Signal_On_StochRsi(TradingExchanges exchange, Ticker ticker, Timeframe timeframe,
|
|
int days)
|
|
{
|
|
// Arrange
|
|
var account = GetAccount(exchange);
|
|
var stochRsiStrategy = new StochRsiTrendIndicatorBase("unittest", 14, 14, 3, 1);
|
|
var candles = await _exchangeService.GetCandles(account, ticker, DateTime.Now.AddDays(days), timeframe);
|
|
var resultSignal = new List<LightSignal>();
|
|
|
|
// var json = JsonConvert.SerializeObject(candles);
|
|
// File.WriteAllText($"{ticker.ToString()}-{timeframe.ToString()}-candles.json", json);
|
|
// var json2 = FileHelpers.ReadJson<List<Candle>>($"{ticker.ToString()}-{timeframe.ToString()}-candles.json");
|
|
|
|
// Act
|
|
foreach (var candle in candles)
|
|
{
|
|
var signals = stochRsiStrategy.Run(new HashSet<Candle> { candle });
|
|
}
|
|
|
|
if (stochRsiStrategy.Signals != null && stochRsiStrategy.Signals.Count > 0)
|
|
resultSignal.AddRange(stochRsiStrategy.Signals);
|
|
|
|
// Assert
|
|
Assert.IsType<List<LightSignal>>(resultSignal);
|
|
Assert.Contains(resultSignal, s => s.Direction == TradeDirection.Short);
|
|
Assert.Contains(resultSignal, s => s.Direction == TradeDirection.Long);
|
|
}
|
|
}
|
|
} |