Trading bot grain (#33)

* 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
This commit is contained in:
Oda
2025-08-04 23:07:06 +02:00
committed by GitHub
parent cd378587aa
commit 082ae8714b
215 changed files with 9562 additions and 14028 deletions

View File

@@ -4,14 +4,14 @@ using Managing.Application.Abstractions;
using Managing.Application.Abstractions.Repositories;
using Managing.Application.Abstractions.Services;
using Managing.Application.Backtesting;
using Managing.Application.Bots.Base;
using Managing.Application.Hubs;
using Managing.Application.ManageBot;
using Managing.Core;
using Managing.Domain.Bots;
using Managing.Domain.Candles;
using Managing.Domain.MoneyManagements;
using Managing.Domain.Scenarios;
using Managing.Domain.Strategies;
using Managing.Domain.Strategies.Signals;
using Microsoft.AspNetCore.SignalR;
using Moq;
using Newtonsoft.Json;
@@ -22,7 +22,6 @@ namespace Managing.Application.Tests
{
public class BotsTests : BaseTests
{
private readonly IBotFactory _botFactory;
private readonly IBacktester _backtester;
private readonly string _reportPath;
private string _analysePath;
@@ -37,19 +36,11 @@ namespace Managing.Application.Tests
var scenarioService = new Mock<IScenarioService>().Object;
var messengerService = new Mock<IMessengerService>().Object;
var kaigenService = new Mock<IKaigenService>().Object;
var backupBotService = new Mock<IBackupBotService>().Object;
var hubContext = new Mock<IHubContext<BacktestHub>>().Object;
var tradingBotLogger = TradingBaseTests.CreateTradingBotLogger();
var backtestLogger = TradingBaseTests.CreateBacktesterLogger();
var botService = new Mock<IBotService>().Object;
_botFactory = new BotFactory(
_exchangeService,
tradingBotLogger,
discordService,
_accountService.Object,
_tradingService.Object,
botService, backupBotService);
_backtester = new Backtester(_exchangeService, _botFactory, backtestRepository, backtestLogger,
_backtester = new Backtester(_exchangeService, backtestRepository, backtestLogger,
scenarioService, _accountService.Object, messengerService, kaigenService, hubContext, null);
_elapsedTimes = new List<double>();
@@ -68,7 +59,6 @@ namespace Managing.Application.Tests
// Arrange
var scenario = new Scenario("FlippingScenario");
var strategy = ScenarioHelpers.BuildIndicator(IndicatorType.RsiDivergence, "RsiDiv", period: 14);
scenario.AddIndicator(strategy);
var localCandles =
FileHelpers.ReadJson<List<Candle>>($"{ticker.ToString()}-{timeframe.ToString()}-candles.json");
@@ -93,10 +83,11 @@ namespace Managing.Application.Tests
// Act
var backtestResult =
await _backtester.RunTradingBotBacktest(config, localCandles.TakeLast(500).ToList(), null, false);
await _backtester.RunTradingBotBacktest(config, DateTime.UtcNow.AddDays(-6),
DateTime.UtcNow, null, false, false);
var json = JsonConvert.SerializeObject(backtestResult, Formatting.None);
File.WriteAllText($"{ticker.ToString()}-{timeframe.ToString()}-{Guid.NewGuid()}.json", json);
File.WriteAllText($"{ticker}-{timeframe}-{Guid.NewGuid()}.json", json);
// WriteCsvReport(backtestResult.GetStringReport());
// Assert
@@ -119,8 +110,6 @@ namespace Managing.Application.Tests
{
// Arrange
var scenario = new Scenario("ScalpingScenario");
var strategy = ScenarioHelpers.BuildIndicator(IndicatorType.RsiDivergence, "RsiDiv", period: 5);
scenario.AddIndicator(strategy);
var config = new TradingBotConfig
{
@@ -158,10 +147,13 @@ namespace Managing.Application.Tests
int days)
{
// Arrange
var scenario = new Scenario("ScalpingScenario");
var strategy = ScenarioHelpers.BuildIndicator(IndicatorType.MacdCross, "RsiDiv", fastPeriods: 12,
slowPeriods: 26, signalPeriods: 9);
scenario.AddIndicator(strategy);
var scenario = new Scenario("ScalpingScenario")
{
Indicators = new List<IndicatorBase>
{
new MacdCrossIndicatorBase("MacdCross", 12, 26, 9)
}
};
var moneyManagement = new MoneyManagement()
{
@@ -236,8 +228,10 @@ namespace Managing.Application.Tests
Parallel.For((long)periodRange[0], periodRange[1], options, i =>
{
var scenario = new Scenario("ScalpingScenario");
var strategy = ScenarioHelpers.BuildIndicator(indicatorType, "RsiDiv", period: (int)i);
scenario.AddIndicator(strategy);
scenario.Indicators = new List<IndicatorBase>
{
new RsiDivergenceIndicatorBase("RsiDiv", (int)i)
};
// -0.5 to -5
for (decimal s = stopLossRange[0]; s < stopLossRange[1]; s += stopLossRange[2])
@@ -278,7 +272,8 @@ namespace Managing.Application.Tests
FlipOnlyWhenInProfit = true,
MaxPositionTimeHours = null,
CloseEarlyWhenProfitable = false
}, candles, null, false).Result,
}, DateTime.UtcNow.AddDays(-6),
DateTime.UtcNow, null, false, false).Result,
BotType.FlippingBot => _backtester.RunTradingBotBacktest(new TradingBotConfig
{
AccountName = _account.Name,
@@ -296,7 +291,8 @@ namespace Managing.Application.Tests
FlipOnlyWhenInProfit = true,
MaxPositionTimeHours = null,
CloseEarlyWhenProfitable = false
}, candles, null, false).Result,
}, DateTime.UtcNow.AddDays(-6),
DateTime.UtcNow, null, false, false).Result,
_ => throw new NotImplementedException(),
};
timer.Stop();
@@ -376,9 +372,10 @@ namespace Managing.Application.Tests
return;
var scenario = new Scenario("ScalpingScenario");
var strategy = ScenarioHelpers.BuildIndicator(indicatorType, "RsiDiv", fastPeriods: 12,
slowPeriods: 26, signalPeriods: 9);
scenario.AddIndicator(strategy);
scenario.Indicators = new List<IndicatorBase>
{
new MacdCrossIndicatorBase("MacdCross", 12, 26, 9)
};
// -0.5 to -5
for (decimal s = stopLossRange[0]; s < stopLossRange[1]; s += stopLossRange[2])
@@ -418,7 +415,8 @@ namespace Managing.Application.Tests
FlipOnlyWhenInProfit = true,
MaxPositionTimeHours = null,
CloseEarlyWhenProfitable = false
}, candles, null).Result,
}, DateTime.UtcNow.AddDays(-6),
DateTime.UtcNow, null, false, false).Result,
BotType.FlippingBot => _backtester.RunTradingBotBacktest(new TradingBotConfig
{
AccountName = _account.Name,
@@ -436,7 +434,8 @@ namespace Managing.Application.Tests
FlipOnlyWhenInProfit = true,
MaxPositionTimeHours = null,
CloseEarlyWhenProfitable = false
}, candles, null).Result,
}, DateTime.UtcNow.AddDays(-6),
DateTime.UtcNow, null, false, false).Result,
_ => throw new NotImplementedException(),
};
@@ -673,7 +672,8 @@ namespace Managing.Application.Tests
CloseEarlyWhenProfitable = false
};
var backtestResult = _backtester.RunTradingBotBacktest(config, candles, null).Result;
var backtestResult = _backtester.RunTradingBotBacktest(config, DateTime.UtcNow.AddDays(-6),
DateTime.UtcNow, null, false, false).Result;
timer.Stop();
@@ -1042,8 +1042,13 @@ namespace Managing.Application.Tests
{
foreach (var parameterSet in strategyConfig.ParameterSets)
{
var scenario = BuildScenario($"{strategyConfig.Name}_{parameterSet.Name}",
new[] { (strategyConfig, parameterSet) });
var scenario = new Scenario($"{strategyConfig.Name}_{parameterSet.Name}")
{
Indicators = new List<IndicatorBase>
{
new RsiDivergenceIndicatorBase("RsiDiv", (int)parameterSet.Period)
}
};
scenarios.Add(scenario);
}
}
@@ -1068,7 +1073,13 @@ namespace Managing.Application.Tests
{
var scenarioName = string.Join("_",
paramCombo.Select(p => $"{p.strategyConfig.Name}_{p.parameterSet.Name}"));
var scenario = BuildScenario(scenarioName, paramCombo);
var scenario = new Scenario(scenarioName)
{
Indicators = new List<IndicatorBase>
{
new RsiDivergenceIndicatorBase("RsiDiv", (int)paramCombo.First().parameterSet.Period)
}
};
scenario.LoopbackPeriod = 15;
scenarios.Add(scenario);
}
@@ -1077,31 +1088,6 @@ namespace Managing.Application.Tests
return scenarios;
}
private Scenario BuildScenario(string scenarioName,
IEnumerable<(StrategyConfiguration strategyConfig, ParameterSet parameterSet)> strategyParams)
{
var scenario = new Scenario(scenarioName);
foreach (var (strategyConfig, parameterSet) in strategyParams)
{
var strategy = ScenarioHelpers.BuildIndicator(
strategyConfig.Type,
$"{strategyConfig.Name}_{parameterSet.Name}",
period: parameterSet.Period,
fastPeriods: parameterSet.FastPeriods,
slowPeriods: parameterSet.SlowPeriods,
signalPeriods: parameterSet.SignalPeriods,
multiplier: parameterSet.Multiplier,
stochPeriods: parameterSet.StochPeriods,
smoothPeriods: parameterSet.SmoothPeriods,
cyclePeriods: parameterSet.CyclePeriods);
scenario.AddIndicator(strategy);
}
return scenario;
}
private IEnumerable<IEnumerable<T>> GetCombinations<T>(IEnumerable<T> elements, int k)
{
return k == 0