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:
@@ -0,0 +1,55 @@
|
||||
using Orleans;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Application.Abstractions.Grains;
|
||||
|
||||
/// <summary>
|
||||
/// A small serializable class to store bot metadata.
|
||||
/// This is a very lean object, perfect for fast storage and retrieval.
|
||||
/// </summary>
|
||||
[GenerateSerializer]
|
||||
public class BotRegistryEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// The unique identifier of the bot
|
||||
/// </summary>
|
||||
[Id(0)]
|
||||
public Guid Identifier { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The unique identifier of the user who owns the bot
|
||||
/// </summary>
|
||||
[Id(1)]
|
||||
public int UserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The current operational status of the bot
|
||||
/// </summary>
|
||||
[Id(2)]
|
||||
public BotStatus Status { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// When the bot was registered in the registry
|
||||
/// </summary>
|
||||
[Id(3)]
|
||||
public DateTime RegisteredAt { get; set; } = DateTime.UtcNow;
|
||||
|
||||
/// <summary>
|
||||
/// When the bot status was last updated
|
||||
/// </summary>
|
||||
[Id(4)]
|
||||
public DateTime LastStatusUpdate { get; set; } = DateTime.UtcNow;
|
||||
|
||||
public BotRegistryEntry()
|
||||
{
|
||||
}
|
||||
|
||||
public BotRegistryEntry(Guid identifier, int userId, BotStatus status = BotStatus.None)
|
||||
{
|
||||
Identifier = identifier;
|
||||
UserId = userId;
|
||||
Status = status;
|
||||
RegisteredAt = DateTime.UtcNow;
|
||||
LastStatusUpdate = DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using Orleans;
|
||||
|
||||
namespace Managing.Application.Abstractions.Grains;
|
||||
|
||||
/// <summary>
|
||||
/// Orleans grain state for BotRegistry.
|
||||
/// This class represents the persistent state of the bot registry grain.
|
||||
/// All properties must be serializable for Orleans state management.
|
||||
/// </summary>
|
||||
[GenerateSerializer]
|
||||
public class BotRegistryState
|
||||
{
|
||||
/// <summary>
|
||||
/// Dictionary containing all registered bots. The key is the identifier.
|
||||
/// </summary>
|
||||
[Id(0)]
|
||||
public Dictionary<Guid, BotRegistryEntry> Bots { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// When the registry was last updated
|
||||
/// </summary>
|
||||
[Id(1)]
|
||||
public DateTime LastUpdated { get; set; } = DateTime.UtcNow;
|
||||
|
||||
/// <summary>
|
||||
/// Total number of bots currently registered
|
||||
/// </summary>
|
||||
[Id(2)]
|
||||
public int TotalBotsCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Number of active bots (status = Up)
|
||||
/// </summary>
|
||||
[Id(3)]
|
||||
public int ActiveBotsCount { get; set; }
|
||||
}
|
||||
@@ -23,23 +23,5 @@ public interface IBacktestTradingBotGrain : IGrainWithGuidKey
|
||||
/// <param name="requestId">The request ID to associate with this backtest</param>
|
||||
/// <param name="metadata">Additional metadata to associate with this backtest</param>
|
||||
/// <returns>The complete backtest result</returns>
|
||||
Task<LightBacktest> RunBacktestAsync(TradingBotConfig config, List<Candle> candles, User user = null, bool save = false, bool withCandles = false, string requestId = null, object metadata = null);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current backtest progress
|
||||
/// </summary>
|
||||
/// <returns>Backtest progress information</returns>
|
||||
Task<BacktestProgress> GetBacktestProgressAsync();
|
||||
Task<LightBacktest> RunBacktestAsync(TradingBotConfig config, HashSet<Candle> candles, User user = null, bool save = false, bool withCandles = false, string requestId = null, object metadata = null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the progress of a backtest
|
||||
/// </summary>
|
||||
public class BacktestProgress
|
||||
{
|
||||
public bool IsInitialized { get; set; }
|
||||
public int TotalCandles { get; set; }
|
||||
public int ProcessedCandles { get; set; }
|
||||
public double ProgressPercentage { get; set; }
|
||||
public bool IsComplete { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using Orleans;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Application.Abstractions.Grains;
|
||||
|
||||
/// <summary>
|
||||
/// Orleans grain interface for LiveBotRegistry operations.
|
||||
/// This interface defines the distributed, async operations available for the bot registry.
|
||||
/// The registry acts as a central, durable directory for all LiveTradingBot grains.
|
||||
/// </summary>
|
||||
public interface ILiveBotRegistryGrain : IGrainWithIntegerKey
|
||||
{
|
||||
/// <summary>
|
||||
/// Registers a new bot with its user ID. This should be called by the LiveTradingBotGrain when it is first initialized.
|
||||
/// The initial status will be BotStatus.Up.
|
||||
/// </summary>
|
||||
/// <param name="identifier">The unique identifier of the bot</param>
|
||||
/// <param name="userId">The unique identifier of the user who owns the bot</param>
|
||||
/// <returns>A task that represents the asynchronous operation</returns>
|
||||
Task RegisterBot(Guid identifier, int userId);
|
||||
|
||||
/// <summary>
|
||||
/// Removes a bot from the registry. This should be a full removal, perhaps called when a user permanently deletes a bot.
|
||||
/// </summary>
|
||||
/// <param name="identifier">The unique identifier of the bot to unregister</param>
|
||||
/// <returns>A task that represents the asynchronous operation</returns>
|
||||
Task UnregisterBot(Guid identifier);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of all bots in the registry. This is for a management dashboard to see all bots in the system.
|
||||
/// </summary>
|
||||
/// <returns>A list of all BotRegistryEntry objects in the registry</returns>
|
||||
Task<List<BotRegistryEntry>> GetAllBots();
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of all bots associated with a specific user. This is the primary method for a user's watchlist.
|
||||
/// </summary>
|
||||
/// <param name="userId">The unique identifier of the user</param>
|
||||
/// <returns>A list of BotRegistryEntry objects for the specified user</returns>
|
||||
Task<List<BotRegistryEntry>> GetBotsForUser(int userId);
|
||||
|
||||
/// <summary>
|
||||
/// A dedicated method for updating only the bot's Status field (Up/Down).
|
||||
/// This will be called by LiveTradingBot's StartAsync and StopAsync methods.
|
||||
/// </summary>
|
||||
/// <param name="identifier">The unique identifier of the bot</param>
|
||||
/// <param name="status">The new status to set for the bot</param>
|
||||
/// <returns>A task that represents the asynchronous operation</returns>
|
||||
Task UpdateBotStatus(Guid identifier, BotStatus status);
|
||||
Task<BotStatus> GetBotStatus(Guid identifier);
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using Managing.Application.Abstractions.Models;
|
||||
using Managing.Domain.Accounts;
|
||||
using Managing.Domain.Bots;
|
||||
using Managing.Domain.Trades;
|
||||
using Managing.Domain.Users;
|
||||
using Orleans;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Application.Abstractions.Grains;
|
||||
|
||||
/// <summary>
|
||||
/// Orleans grain interface for TradingBot operations.
|
||||
/// This interface defines the distributed, async operations available for trading bots.
|
||||
/// </summary>
|
||||
public interface ILiveTradingBotGrain : IGrainWithGuidKey
|
||||
{
|
||||
/// <summary>
|
||||
/// Manually opens a position in the specified direction
|
||||
/// </summary>
|
||||
/// <param name="direction">The direction of the trade (Long/Short)</param>
|
||||
/// <returns>The created Position object</returns>
|
||||
Task<Position> OpenPositionManuallyAsync(TradeDirection direction);
|
||||
|
||||
/// <summary>
|
||||
/// Gets comprehensive bot data including positions, signals, and performance metrics
|
||||
/// </summary>
|
||||
Task<TradingBotResponse> GetBotDataAsync();
|
||||
|
||||
Task CreateAsync(TradingBotConfig config, User user);
|
||||
Task StartAsync();
|
||||
Task StopAsync();
|
||||
|
||||
Task<bool> UpdateConfiguration(TradingBotConfig newConfig);
|
||||
Task<Account> GetAccount();
|
||||
Task<TradingBotConfig> GetConfiguration();
|
||||
Task<Position> ClosePositionAsync(Guid positionId);
|
||||
Task RestartAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the bot and cleans up all associated resources
|
||||
/// </summary>
|
||||
Task DeleteAsync();
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
using Managing.Application.Abstractions.Models;
|
||||
using Managing.Domain.Bots;
|
||||
using Managing.Domain.Trades;
|
||||
using Orleans;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Application.Abstractions.Grains;
|
||||
|
||||
/// <summary>
|
||||
/// Orleans grain interface for TradingBot operations.
|
||||
/// This interface defines the distributed, async operations available for trading bots.
|
||||
/// </summary>
|
||||
public interface ITradingBotGrain : IGrainWithGuidKey
|
||||
{
|
||||
/// <summary>
|
||||
/// Starts the trading bot asynchronously
|
||||
/// </summary>
|
||||
Task StartAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Stops the trading bot asynchronously
|
||||
/// </summary>
|
||||
Task StopAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current status of the trading bot
|
||||
/// </summary>
|
||||
Task<BotStatus> GetStatusAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current configuration of the trading bot
|
||||
/// </summary>
|
||||
Task<TradingBotConfig> GetConfigurationAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Updates the trading bot configuration
|
||||
/// </summary>
|
||||
/// <param name="newConfig">The new configuration to apply</param>
|
||||
/// <returns>True if the configuration was successfully updated</returns>
|
||||
Task<bool> UpdateConfigurationAsync(TradingBotConfig newConfig);
|
||||
|
||||
/// <summary>
|
||||
/// Manually opens a position in the specified direction
|
||||
/// </summary>
|
||||
/// <param name="direction">The direction of the trade (Long/Short)</param>
|
||||
/// <returns>The created Position object</returns>
|
||||
Task<Position> OpenPositionManuallyAsync(TradeDirection direction);
|
||||
|
||||
/// <summary>
|
||||
/// Toggles the bot between watch-only and trading mode
|
||||
/// </summary>
|
||||
Task ToggleIsForWatchOnlyAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Gets comprehensive bot data including positions, signals, and performance metrics
|
||||
/// </summary>
|
||||
Task<TradingBotResponse> GetBotDataAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Loads a bot backup into the grain state
|
||||
/// </summary>
|
||||
/// <param name="backup">The bot backup to load</param>
|
||||
Task LoadBackupAsync(BotBackup backup);
|
||||
|
||||
/// <summary>
|
||||
/// Forces a backup save of the current bot state
|
||||
/// </summary>
|
||||
Task SaveBackupAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current profit and loss for the bot
|
||||
/// </summary>
|
||||
Task<decimal> GetProfitAndLossAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current win rate percentage for the bot
|
||||
/// </summary>
|
||||
Task<int> GetWinRateAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the bot's execution count (number of Run cycles completed)
|
||||
/// </summary>
|
||||
Task<long> GetExecutionCountAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the bot's startup time
|
||||
/// </summary>
|
||||
Task<DateTime> GetStartupTimeAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the bot's creation date
|
||||
/// </summary>
|
||||
Task<DateTime> GetCreateDateAsync();
|
||||
}
|
||||
Reference in New Issue
Block a user