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

@@ -3,6 +3,7 @@ using Managing.Domain.Accounts;
using Managing.Domain.Backtests;
using Managing.Domain.Bots;
using Managing.Domain.Candles;
using Managing.Domain.Indicators;
using Managing.Domain.MoneyManagements;
using Managing.Domain.Scenarios;
using Managing.Domain.Statistics;
@@ -13,7 +14,6 @@ using Managing.Domain.Workers;
using Managing.Infrastructure.Databases.PostgreSql.Entities;
using Newtonsoft.Json;
using static Managing.Common.Enums;
using SystemJsonSerializer = System.Text.Json.JsonSerializer;
namespace Managing.Infrastructure.Databases.PostgreSql;
@@ -125,7 +125,8 @@ public static class PostgreSqlMappers
Name = entity.Name,
AgentName = entity.AgentName,
AvatarUrl = entity.AvatarUrl,
TelegramChannel = entity.TelegramChannel
TelegramChannel = entity.TelegramChannel,
Id = entity.Id // Assuming Id is the primary key for UserEntity
};
}
@@ -183,7 +184,9 @@ public static class PostgreSqlMappers
{
try
{
geneticRequest.EligibleIndicators = SystemJsonSerializer.Deserialize<List<IndicatorType>>(entity.EligibleIndicatorsJson) ?? new List<IndicatorType>();
geneticRequest.EligibleIndicators =
SystemJsonSerializer.Deserialize<List<IndicatorType>>(entity.EligibleIndicatorsJson) ??
new List<IndicatorType>();
}
catch
{
@@ -263,10 +266,12 @@ public static class PostgreSqlMappers
// Deserialize JSON fields using MongoMappers for compatibility
var config = JsonConvert.DeserializeObject<TradingBotConfig>(entity.ConfigJson);
var positions = JsonConvert.DeserializeObject<List<Position>>(entity.PositionsJson) ?? new List<Position>();
var signals = JsonConvert.DeserializeObject<List<LightSignal>>(entity.SignalsJson) ?? new List<LightSignal>();
var statistics = !string.IsNullOrEmpty(entity.StatisticsJson)
? JsonConvert.DeserializeObject<PerformanceMetrics>(entity.StatisticsJson)
var positionsList = JsonConvert.DeserializeObject<List<Position>>(entity.PositionsJson) ?? new List<Position>();
var positions = positionsList.ToDictionary(p => p.Identifier, p => p);
var signalsList = JsonConvert.DeserializeObject<List<LightSignal>>(entity.SignalsJson) ?? new List<LightSignal>();
var signals = signalsList.ToDictionary(s => s.Identifier, s => s);
var statistics = !string.IsNullOrEmpty(entity.StatisticsJson)
? JsonConvert.DeserializeObject<PerformanceMetrics>(entity.StatisticsJson)
: null;
var backtest = new Backtest(config, positions, signals)
@@ -303,8 +308,8 @@ public static class PostgreSqlMappers
GrowthPercentage = backtest.GrowthPercentage,
HodlPercentage = backtest.HodlPercentage,
ConfigJson = JsonConvert.SerializeObject(backtest.Config),
PositionsJson = JsonConvert.SerializeObject(backtest.Positions),
SignalsJson = JsonConvert.SerializeObject(backtest.Signals),
PositionsJson = JsonConvert.SerializeObject(backtest.Positions.Values.ToList()),
SignalsJson = JsonConvert.SerializeObject(backtest.Signals.Values.ToList()),
StartDate = backtest.StartDate,
EndDate = backtest.EndDate,
MoneyManagementJson = JsonConvert.SerializeObject(backtest.Config?.MoneyManagement),
@@ -354,7 +359,8 @@ public static class PostgreSqlMappers
{
try
{
bundleRequest.Results = JsonConvert.DeserializeObject<List<string>>(entity.ResultsJson) ?? new List<string>();
bundleRequest.Results = JsonConvert.DeserializeObject<List<string>>(entity.ResultsJson) ??
new List<string>();
}
catch
{
@@ -426,7 +432,7 @@ public static class PostgreSqlMappers
return new Scenario(entity.Name, entity.LoopbackPeriod)
{
User = entity.UserName != null ? new User { Name = entity.UserName } : null,
Indicators = new List<Indicator>() // Will be populated separately when needed
Indicators = new List<IndicatorBase>() // Will be populated separately when needed
};
}
@@ -443,11 +449,11 @@ public static class PostgreSqlMappers
}
// Indicator mappings
public static Indicator Map(IndicatorEntity entity)
public static IndicatorBase Map(IndicatorEntity entity)
{
if (entity == null) return null;
return new Indicator(entity.Name, entity.Type)
return new IndicatorBase(entity.Name, entity.Type)
{
SignalType = entity.SignalType,
MinimumHistory = entity.MinimumHistory,
@@ -463,26 +469,26 @@ public static class PostgreSqlMappers
};
}
public static IndicatorEntity Map(Indicator indicator)
public static IndicatorEntity Map(IndicatorBase indicatorBase)
{
if (indicator == null) return null;
if (indicatorBase == null) return null;
return new IndicatorEntity
{
Name = indicator.Name,
Type = indicator.Type,
Name = indicatorBase.Name,
Type = indicatorBase.Type,
Timeframe = Timeframe.FifteenMinutes, // Default timeframe
SignalType = indicator.SignalType,
MinimumHistory = indicator.MinimumHistory,
Period = indicator.Period,
FastPeriods = indicator.FastPeriods,
SlowPeriods = indicator.SlowPeriods,
SignalPeriods = indicator.SignalPeriods,
Multiplier = indicator.Multiplier,
SmoothPeriods = indicator.SmoothPeriods,
StochPeriods = indicator.StochPeriods,
CyclePeriods = indicator.CyclePeriods,
UserName = indicator.User?.Name
SignalType = indicatorBase.SignalType,
MinimumHistory = indicatorBase.MinimumHistory,
Period = indicatorBase.Period,
FastPeriods = indicatorBase.FastPeriods,
SlowPeriods = indicatorBase.SlowPeriods,
SignalPeriods = indicatorBase.SignalPeriods,
Multiplier = indicatorBase.Multiplier,
SmoothPeriods = indicatorBase.SmoothPeriods,
StochPeriods = indicatorBase.StochPeriods,
CyclePeriods = indicatorBase.CyclePeriods,
UserName = indicatorBase.User?.Name
};
}
@@ -491,8 +497,8 @@ public static class PostgreSqlMappers
{
if (entity == null) return null;
var candle = !string.IsNullOrEmpty(entity.CandleJson)
? JsonConvert.DeserializeObject<Candle>(entity.CandleJson)
var candle = !string.IsNullOrEmpty(entity.CandleJson)
? JsonConvert.DeserializeObject<Candle>(entity.CandleJson)
: null;
return new Signal(
@@ -541,7 +547,8 @@ public static class PostgreSqlMappers
var moneyManagement = new MoneyManagement(); // Default money management
if (!string.IsNullOrEmpty(entity.MoneyManagementJson))
{
moneyManagement = JsonConvert.DeserializeObject<MoneyManagement>(entity.MoneyManagementJson) ?? new MoneyManagement();
moneyManagement = JsonConvert.DeserializeObject<MoneyManagement>(entity.MoneyManagementJson) ??
new MoneyManagement();
}
var position = new Position(
@@ -590,7 +597,9 @@ public static class PostgreSqlMappers
SignalIdentifier = position.SignalIdentifier,
AccountName = position.AccountName,
UserName = position.User?.Name,
MoneyManagementJson = position.MoneyManagement != null ? JsonConvert.SerializeObject(position.MoneyManagement) : null
MoneyManagementJson = position.MoneyManagement != null
? JsonConvert.SerializeObject(position.MoneyManagement)
: null
};
}
@@ -636,16 +645,15 @@ public static class PostgreSqlMappers
}
// Collection mappings
public static IEnumerable<Scenario> Map(IEnumerable<ScenarioEntity> entities)
{
return entities?.Select(Map) ?? Enumerable.Empty<Scenario>();
}
public static IEnumerable<Indicator> Map(IEnumerable<IndicatorEntity> entities)
public static IEnumerable<IndicatorBase> Map(IEnumerable<IndicatorEntity> entities)
{
return entities?.Select(Map) ?? Enumerable.Empty<Indicator>();
return entities?.Select(Map) ?? Enumerable.Empty<IndicatorBase>();
}
public static IEnumerable<Signal> Map(IEnumerable<SignalEntity> entities)
@@ -663,48 +671,57 @@ public static class PostgreSqlMappers
#region Bot Mappings
// BotBackup mappings
public static BotBackup Map(BotBackupEntity entity)
public static Bot Map(BotEntity entity)
{
if (entity == null) return null;
var botBackup = new BotBackup
var bot = new Bot
{
Identifier = entity.Identifier,
User = entity.User != null ? Map(entity.User) : null,
LastStatus = entity.LastStatus,
CreateDate = entity.CreateDate
Status = entity.Status,
CreateDate = entity.CreateDate,
Name = entity.Name,
Ticker = entity.Ticker,
StartupTime = entity.StartupTime,
TradeWins = entity.TradeWins,
TradeLosses = entity.TradeLosses,
Pnl = entity.Pnl,
Roi = entity.Roi,
Volume = entity.Volume,
Fees = entity.Fees
};
// Deserialize the JSON data using the helper method
botBackup.DeserializeData(entity.Data);
return botBackup;
return bot;
}
public static BotBackupEntity Map(BotBackup botBackup)
public static BotEntity Map(Bot bot)
{
if (botBackup == null) return null;
if (bot == null) return null;
return new BotBackupEntity
return new BotEntity
{
Identifier = botBackup.Identifier,
UserName = botBackup.User?.Name,
User = botBackup.User != null ? Map(botBackup.User) : null,
Data = botBackup.SerializeData(), // Serialize the data using the helper method
LastStatus = botBackup.LastStatus,
CreateDate = botBackup.CreateDate,
Identifier = bot.Identifier,
UserId = bot.User.Id,
User = bot.User != null ? Map(bot.User) : null,
Status = bot.Status,
CreateDate = bot.CreateDate,
Name = bot.Name,
Ticker = bot.Ticker,
StartupTime = bot.StartupTime,
TradeWins = bot.TradeWins,
TradeLosses = bot.TradeLosses,
Pnl = bot.Pnl,
Roi = bot.Roi,
Volume = bot.Volume,
Fees = bot.Fees,
UpdatedAt = DateTime.UtcNow
};
}
public static IEnumerable<BotBackup> Map(IEnumerable<BotBackupEntity> entities)
public static IEnumerable<Bot> Map(IEnumerable<BotEntity> entities)
{
return entities?.Select(Map) ?? Enumerable.Empty<BotBackup>();
}
public static IEnumerable<BotBackupEntity> Map(IEnumerable<BotBackup> botBackups)
{
return botBackups?.Select(Map) ?? Enumerable.Empty<BotBackupEntity>();
return entities?.Select(Map) ?? Enumerable.Empty<Bot>();
}
#endregion
@@ -763,7 +780,8 @@ public static class PostgreSqlMappers
{
try
{
overview.Spotlights = SystemJsonSerializer.Deserialize<List<Spotlight>>(entity.SpotlightsJson) ?? new List<Spotlight>();
overview.Spotlights = SystemJsonSerializer.Deserialize<List<Spotlight>>(entity.SpotlightsJson) ??
new List<Spotlight>();
}
catch (JsonException)
{
@@ -913,4 +931,4 @@ public static class PostgreSqlMappers
}
#endregion
}
}