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

@@ -0,0 +1,27 @@
namespace Managing.Application.Abstractions.Grains
{
public interface IAgentGrain : IGrainWithIntegerKey
{
/// <summary>
/// Initializes the agent grain with user-specific data.
/// </summary>
/// <param name="userId">The ID of the user (used as grain key).</param>
/// <param name="agentName">The display name of the agent.</param>
Task InitializeAsync(int userId, string agentName);
/// <summary>
/// Generates a summary of the agent's stats for the AgentRegistryGrain.
/// </summary>
Task UpdateSummary();
/// <summary>
/// Registers a new bot with this agent.
/// </summary>
Task RegisterBotAsync(Guid botId);
/// <summary>
/// Unregisters a bot from this agent.
/// </summary>
Task UnregisterBotAsync(Guid botId);
}
}

View File

@@ -0,0 +1,22 @@
using Managing.Domain.Bots;
using Managing.Domain.Candles;
using Managing.Domain.Indicators;
namespace Managing.Application.Abstractions.Grains;
/// <summary>
/// Orleans grain interface for scenario execution and signal generation.
/// This stateless grain handles candle management and signal generation for live trading.
/// </summary>
public interface IScenarioRunnerGrain : IGrainWithGuidKey
{
/// <summary>
/// Generates signals based on the current candles and scenario
/// </summary>
/// <param name="config">The trading bot configuration</param>
/// <param name="previousSignals">Previous signals to consider</param>
/// <param name="startDate">Start date</param>
/// <returns>The generated signal or null if no signal</returns>
Task<LightSignal> GetSignals(TradingBotConfig config, Dictionary<string, LightSignal> previousSignals, DateTime startDate,
Candle candle);
}

View File

@@ -1,21 +0,0 @@
using Managing.Domain.Bots;
namespace Managing.Application.Abstractions
{
public interface IBotFactory
{
/// <summary>
/// Creates a trading bot using the unified TradingBot class
/// </summary>
/// <param name="config">The trading bot configuration</param>
/// <returns>ITradingBot instance</returns>
Task<ITradingBot> CreateTradingBot(TradingBotConfig config);
/// <summary>
/// Creates a trading bot for backtesting using the unified TradingBot class
/// </summary>
/// <param name="config">The trading bot configuration</param>
/// <returns>ITradingBot instance configured for backtesting</returns>
Task<ITradingBot> CreateBacktestTradingBot(TradingBotConfig config);
}
}

View File

@@ -1,38 +1,47 @@
using Managing.Domain.Bots;
using Managing.Domain.Users;
using Managing.Domain.Workflows;
using Managing.Domain.Trades;
using static Managing.Common.Enums;
namespace Managing.Application.Abstractions;
public interface IBotService
{
Task SaveOrUpdateBotBackup(User user, string identifier, BotStatus status, TradingBotBackup data);
void AddSimpleBotToCache(IBot bot);
void AddTradingBotToCache(ITradingBot bot);
List<ITradingBot> GetActiveBots();
Task<IEnumerable<BotBackup>> GetSavedBotsAsync();
Task StartBotFromBackup(BotBackup backupBot);
Task<BotBackup> GetBotBackup(string identifier);
Task<IEnumerable<Bot>> GetBotsAsync();
Task<IEnumerable<Bot>> GetBotsByStatusAsync(BotStatus status);
Task<BotStatus> StopBot(Guid identifier);
Task<BotStatus> RestartBot(Guid identifier);
Task<bool> DeleteBot(Guid identifier);
Task<bool> UpdateBotConfiguration(Guid identifier, TradingBotConfig newConfig);
Task<IEnumerable<string>> GetActiveBotsNamesAsync();
Task<IEnumerable<Bot>> GetBotsByUser(int id);
Task<IEnumerable<Bot>> GetBotsByIdsAsync(IEnumerable<Guid> botIds);
Task<Bot> GetBotByName(string name);
Task<Bot> GetBotByIdentifier(Guid identifier);
Task<Position> OpenPositionManuallyAsync(Guid identifier, TradeDirection direction);
Task<Position> ClosePositionAsync(Guid identifier, Guid positionId);
Task<TradingBotConfig> GetBotConfig(Guid identifier);
Task<bool> UpdateBotStatisticsAsync(Guid identifier);
Task<bool> SaveBotStatisticsAsync(Bot bot);
/// <summary>
/// Creates a trading bot using the unified TradingBot class
/// Gets paginated bots with filtering and sorting
/// </summary>
/// <param name="config">The trading bot configuration</param>
/// <returns>ITradingBot instance</returns>
Task<ITradingBot> CreateTradingBot(TradingBotConfig config);
/// <summary>
/// Creates a trading bot for backtesting using the unified TradingBot class
/// </summary>
/// <param name="config">The trading bot configuration</param>
/// <returns>ITradingBot instance configured for backtesting</returns>
Task<ITradingBot> CreateBacktestTradingBot(TradingBotConfig config);
IBot CreateSimpleBot(string botName, Workflow workflow);
Task<string> StopBot(string botName);
Task<bool> DeleteBot(string botName);
Task<string> RestartBot(string botName);
Task ToggleIsForWatchingOnly(string botName);
Task<bool> UpdateBotConfiguration(string identifier, TradingBotConfig newConfig);
/// <param name="pageNumber">Page number (1-based)</param>
/// <param name="pageSize">Number of items per page</param>
/// <param name="status">Filter by status (optional)</param>
/// <param name="name">Filter by name (partial match, case-insensitive)</param>
/// <param name="ticker">Filter by ticker (partial match, case-insensitive)</param>
/// <param name="agentName">Filter by agent name (partial match, case-insensitive)</param>
/// <param name="sortBy">Sort field</param>
/// <param name="sortDirection">Sort direction ("Asc" or "Desc")</param>
/// <returns>Tuple containing the bots for the current page and total count</returns>
Task<(IEnumerable<Bot> Bots, int TotalCount)> GetBotsPaginatedAsync(
int pageNumber,
int pageSize,
BotStatus? status = null,
string? name = null,
string? ticker = null,
string? agentName = null,
string sortBy = "CreateDate",
string sortDirection = "Desc");
}

View File

@@ -8,19 +8,7 @@ namespace Managing.Application.Abstractions
public interface IScenarioService
{
Task<Scenario> CreateScenario(string name, List<string> strategies, int? loopbackPeriod = 1);
Task<IEnumerable<Indicator>> GetIndicatorsAsync();
Task<Indicator> CreateStrategy(IndicatorType type,
string name,
int? period = null,
int? fastPeriods = null,
int? slowPeriods = null,
int? signalPeriods = null,
double? multiplier = null,
int? stochPeriods = null,
int? smoothPeriods = null,
int? cyclePeriods = null);
Task<IEnumerable<IndicatorBase>> GetIndicatorsAsync();
Task<bool> UpdateScenario(string name, List<string> strategies, int? loopbackPeriod);
Task<bool> UpdateStrategy(IndicatorType indicatorType, string name, int? period, int? fastPeriods,
@@ -29,12 +17,12 @@ namespace Managing.Application.Abstractions
Task<IEnumerable<Scenario>> GetScenariosByUserAsync(User user);
Task<Scenario> CreateScenarioForUser(User user, string name, List<string> strategies, int? loopbackPeriod = 1);
Task<IEnumerable<Indicator>> GetIndicatorsByUserAsync(User user);
Task<IEnumerable<IndicatorBase>> GetIndicatorsByUserAsync(User user);
Task<bool> DeleteIndicatorByUser(User user, string name);
Task<bool> DeleteScenarioByUser(User user, string name);
Task<Scenario> GetScenarioByUser(User user, string name);
Task<Indicator> CreateIndicatorForUser(User user,
Task<IndicatorBase> CreateIndicatorForUser(User user,
IndicatorType type,
string name,
int? period = null,

View File

@@ -1,37 +1,28 @@
using Managing.Core.FixedSizedQueue;
using Managing.Domain.Accounts;
using Managing.Domain.Accounts;
using Managing.Domain.Bots;
using Managing.Domain.Candles;
using Managing.Domain.Scenarios;
using Managing.Domain.Strategies.Base;
using Managing.Domain.Indicators;
using Managing.Domain.Trades;
using static Managing.Common.Enums;
namespace Managing.Application.Abstractions
{
public interface ITradingBot : IBot
public interface ITradingBot
{
TradingBotConfig Config { get; set; }
Account Account { get; set; }
FixedSizeQueue<Candle> OptimizedCandles { get; set; }
HashSet<Candle> Candles { get; set; }
HashSet<LightSignal> Signals { get; set; }
List<Position> Positions { get; set; }
Dictionary<string, LightSignal> Signals { get; set; }
Dictionary<Guid, Position> Positions { get; set; }
Dictionary<DateTime, decimal> WalletBalances { get; set; }
Dictionary<IndicatorType, IndicatorsResultBase> IndicatorsValues { get; set; }
DateTime StartupTime { get; }
DateTime CreateDate { get; }
DateTime PreloadSince { get; set; }
int PreloadedCandlesCount { get; set; }
long ExecutionCount { get; set; }
Candle LastCandle { get; set; }
Task Run();
Task ToggleIsForWatchOnly();
int GetWinRate();
decimal GetProfitAndLoss();
decimal GetTotalFees();
void LoadScenario(Scenario scenario);
void UpdateIndicatorsValues();
Task LoadAccount();
Task<Position> OpenPositionManually(TradeDirection direction);