diff --git a/src/Managing.Api/Controllers/BotController.cs b/src/Managing.Api/Controllers/BotController.cs
index 444bcee3..aabacfac 100644
--- a/src/Managing.Api/Controllers/BotController.cs
+++ b/src/Managing.Api/Controllers/BotController.cs
@@ -441,6 +441,8 @@ public class BotController : BaseController
string? name = null,
string? ticker = null,
string? agentName = null,
+ decimal? minBalance = null,
+ decimal? maxBalance = null,
BotSortableColumn sortBy = BotSortableColumn.CreateDate,
SortDirection sortDirection = SortDirection.Desc)
{
@@ -468,6 +470,8 @@ public class BotController : BaseController
name,
ticker,
agentName,
+ minBalance,
+ maxBalance,
sortBy,
sortDirection,
showOnlyProfitable);
@@ -545,6 +549,7 @@ public class BotController : BaseController
Name = item.Name,
Ticker = item.Ticker,
TradingType = item.TradingType,
+ BotTradingBalance = item.BotTradingBalance,
});
}
diff --git a/src/Managing.Api/Controllers/DataController.cs b/src/Managing.Api/Controllers/DataController.cs
index 8b59bfe7..3f082106 100644
--- a/src/Managing.Api/Controllers/DataController.cs
+++ b/src/Managing.Api/Controllers/DataController.cs
@@ -908,6 +908,8 @@ public class DataController : ControllerBase
/// Filter by name (partial match, case-insensitive)
/// Filter by ticker (partial match, case-insensitive)
/// Filter by agent name (partial match, case-insensitive)
+ /// Filter by minimum BotTradingBalance (optional)
+ /// Filter by maximum BotTradingBalance (optional)
/// Sort field (defaults to CreateDate)
/// Sort direction - Asc or Desc (defaults to Desc)
/// A paginated list of strategies excluding Saved status bots
@@ -918,6 +920,8 @@ public class DataController : ControllerBase
string? name = null,
string? ticker = null,
string? agentName = null,
+ decimal? minBalance = null,
+ decimal? maxBalance = null,
BotSortableColumn sortBy = BotSortableColumn.CreateDate,
SortDirection sortDirection = SortDirection.Desc)
{
@@ -946,6 +950,8 @@ public class DataController : ControllerBase
name,
ticker,
agentName,
+ minBalance,
+ maxBalance,
sortBy,
sortDirection,
showOnlyProfitable);
@@ -1031,6 +1037,7 @@ public class DataController : ControllerBase
Ticker = item.Ticker,
TradingType = item.TradingType,
MasterAgentName = item.MasterBotUser?.AgentName,
+ BotTradingBalance = item.BotTradingBalance,
});
}
diff --git a/src/Managing.Api/Models/Responses/TradingBotResponse.cs b/src/Managing.Api/Models/Responses/TradingBotResponse.cs
index eaf15aa2..60d880df 100644
--- a/src/Managing.Api/Models/Responses/TradingBotResponse.cs
+++ b/src/Managing.Api/Models/Responses/TradingBotResponse.cs
@@ -92,5 +92,11 @@ namespace Managing.Api.Models.Responses
/// The agent name of the master bot's owner (for copy trading bots)
///
public string MasterAgentName { get; set; }
+
+ ///
+ /// The trading balance configured for this bot
+ ///
+ [Required]
+ public decimal BotTradingBalance { get; internal set; }
}
}
\ No newline at end of file
diff --git a/src/Managing.AppHost/Properties/launchSettings.json.task-TASK-4485 b/src/Managing.AppHost/Properties/launchSettings.json.task-TASK-4485
deleted file mode 100644
index f98a41b8..00000000
--- a/src/Managing.AppHost/Properties/launchSettings.json.task-TASK-4485
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "$schema": "https://json.schemastore.org/launchsettings.json",
- "profiles": {
- "http": {
- "commandName": "Project",
- "dotnetRunMessages": true,
- "launchBrowser": true,
- "applicationUrl": "http://localhost:15000",
- "environmentVariables": {
- "ASPNETCORE_ENVIRONMENT": "Development",
- "DOTNET_ENVIRONMENT": "Development",
- "DOTNET_DASHBOARD_OTLP_HTTP_ENDPOINT_URL": "http://localhost:19000",
- "ASPIRE_ALLOW_UNSECURED_TRANSPORT": "true"
- }
- }
- }
-}
diff --git a/src/Managing.Application.Abstractions/Repositories/IBotRepository.cs b/src/Managing.Application.Abstractions/Repositories/IBotRepository.cs
index 100c7ab6..916e9c6d 100644
--- a/src/Managing.Application.Abstractions/Repositories/IBotRepository.cs
+++ b/src/Managing.Application.Abstractions/Repositories/IBotRepository.cs
@@ -25,6 +25,8 @@ public interface IBotRepository
/// Filter by name (partial match, case-insensitive)
/// Filter by ticker (partial match, case-insensitive)
/// Filter by agent name (partial match, case-insensitive)
+ /// Filter by minimum BotTradingBalance (optional)
+ /// Filter by maximum BotTradingBalance (optional)
/// Sort field
/// Sort direction ("Asc" or "Desc")
/// Whether to show only profitable bots (ROI > 0)
@@ -36,6 +38,8 @@ public interface IBotRepository
string? name = null,
string? ticker = null,
string? agentName = null,
+ decimal? minBalance = null,
+ decimal? maxBalance = null,
BotSortableColumn sortBy = BotSortableColumn.CreateDate,
SortDirection sortDirection = SortDirection.Desc,
bool showOnlyProfitable = false);
diff --git a/src/Managing.Application/Abstractions/IBotService.cs b/src/Managing.Application/Abstractions/IBotService.cs
index f0d211a2..8fb478fa 100644
--- a/src/Managing.Application/Abstractions/IBotService.cs
+++ b/src/Managing.Application/Abstractions/IBotService.cs
@@ -46,6 +46,8 @@ public interface IBotService
/// Filter by name (partial match, case-insensitive)
/// Filter by ticker (partial match, case-insensitive)
/// Filter by agent name (partial match, case-insensitive)
+ /// Filter by minimum BotTradingBalance (optional)
+ /// Filter by maximum BotTradingBalance (optional)
/// Sort field
/// Sort direction
/// Whether to show only profitable bots (ROI > 0)
@@ -57,6 +59,8 @@ public interface IBotService
string? name = null,
string? ticker = null,
string? agentName = null,
+ decimal? minBalance = null,
+ decimal? maxBalance = null,
BotSortableColumn sortBy = BotSortableColumn.CreateDate,
SortDirection sortDirection = SortDirection.Desc,
bool showOnlyProfitable = false);
diff --git a/src/Managing.Application/Bots/Grains/LiveTradingBotGrain.cs b/src/Managing.Application/Bots/Grains/LiveTradingBotGrain.cs
index 3dc090d8..5d4821bc 100644
--- a/src/Managing.Application/Bots/Grains/LiveTradingBotGrain.cs
+++ b/src/Managing.Application/Bots/Grains/LiveTradingBotGrain.cs
@@ -1062,6 +1062,7 @@ public class LiveTradingBotGrain : Grain, ILiveTradingBotGrain, IRemindable
Roi = 0,
Volume = 0,
Fees = 0,
+ BotTradingBalance = _state.State.Config.BotTradingBalance,
MasterBotUserId = _state.State.Config.MasterBotUserId
};
}
@@ -1127,6 +1128,7 @@ public class LiveTradingBotGrain : Grain, ILiveTradingBotGrain, IRemindable
Fees = agentMetrics.TotalFees,
LongPositionCount = longPositionCount,
ShortPositionCount = shortPositionCount,
+ BotTradingBalance = _state.State.Config.BotTradingBalance,
MasterBotUserId = _state.State.Config.MasterBotUserId
};
}
diff --git a/src/Managing.Application/ManageBot/BotService.cs b/src/Managing.Application/ManageBot/BotService.cs
index 82fa965f..31b519f5 100644
--- a/src/Managing.Application/ManageBot/BotService.cs
+++ b/src/Managing.Application/ManageBot/BotService.cs
@@ -375,7 +375,8 @@ namespace Managing.Application.ManageBot
|| existingBot.LastStartTime != bot.LastStartTime
|| existingBot.LastStopTime != bot.LastStopTime
|| existingBot.Ticker != bot.Ticker
- || existingBot.TradingType != bot.TradingType)
+ || existingBot.TradingType != bot.TradingType
+ || existingBot.BotTradingBalance != Math.Round(bot.BotTradingBalance, 8))
{
_tradingBotLogger.LogInformation("Update bot statistics for bot {BotId}",
bot.Identifier);
@@ -486,6 +487,8 @@ namespace Managing.Application.ManageBot
string? name = null,
string? ticker = null,
string? agentName = null,
+ decimal? minBalance = null,
+ decimal? maxBalance = null,
BotSortableColumn sortBy = BotSortableColumn.CreateDate,
SortDirection sortDirection = SortDirection.Desc,
bool showOnlyProfitable = false)
@@ -501,6 +504,8 @@ namespace Managing.Application.ManageBot
name,
ticker,
agentName,
+ minBalance,
+ maxBalance,
sortBy,
sortDirection,
showOnlyProfitable);
diff --git a/src/Managing.Common/Enums.cs b/src/Managing.Common/Enums.cs
index a8d0c4ef..c7ee91aa 100644
--- a/src/Managing.Common/Enums.cs
+++ b/src/Managing.Common/Enums.cs
@@ -98,7 +98,8 @@ public static class Enums
Roi,
Pnl,
WinRate,
- AgentName
+ AgentName,
+ BotTradingBalance
}
///
diff --git a/src/Managing.Domain/Bots/Bot.cs b/src/Managing.Domain/Bots/Bot.cs
index dbaba6cd..4b2bb0f8 100644
--- a/src/Managing.Domain/Bots/Bot.cs
+++ b/src/Managing.Domain/Bots/Bot.cs
@@ -28,6 +28,8 @@ namespace Managing.Domain.Bots
public decimal Fees { get; set; }
public int LongPositionCount { get; set; }
public int ShortPositionCount { get; set; }
+
+ public decimal BotTradingBalance { get; set; }
///
/// The user ID of the master bot's owner when this bot is for copy trading
diff --git a/src/Managing.Infrastructure.Database/Migrations/20260101142151_AddBotTradingBalanceToBots.Designer.cs b/src/Managing.Infrastructure.Database/Migrations/20260101142151_AddBotTradingBalanceToBots.Designer.cs
new file mode 100644
index 00000000..c6f465c9
--- /dev/null
+++ b/src/Managing.Infrastructure.Database/Migrations/20260101142151_AddBotTradingBalanceToBots.Designer.cs
@@ -0,0 +1,1791 @@
+//
+using System;
+using Managing.Infrastructure.Databases.PostgreSql;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+#nullable disable
+
+namespace Managing.Infrastructure.Databases.Migrations
+{
+ [DbContext(typeof(ManagingDbContext))]
+ [Migration("20260101142151_AddBotTradingBalanceToBots")]
+ partial class AddBotTradingBalanceToBots
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "8.0.11")
+ .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+ NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+ modelBuilder.Entity("Managing.Infrastructure.Databases.PostgreSql.Entities.AccountEntity", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Exchange")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("IsGmxInitialized")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("boolean")
+ .HasDefaultValue(false);
+
+ b.Property("Key")
+ .IsRequired()
+ .HasMaxLength(500)
+ .HasColumnType("character varying(500)");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(255)
+ .HasColumnType("character varying(255)");
+
+ b.Property("Secret")
+ .HasMaxLength(500)
+ .HasColumnType("character varying(500)");
+
+ b.Property("Type")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("UserId")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Name")
+ .IsUnique();
+
+ b.HasIndex("UserId");
+
+ b.ToTable("Accounts");
+ });
+
+ modelBuilder.Entity("Managing.Infrastructure.Databases.PostgreSql.Entities.AgentSummaryEntity", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("ActiveStrategiesCount")
+ .HasColumnType("integer");
+
+ b.Property("AgentName")
+ .IsRequired()
+ .HasMaxLength(255)
+ .HasColumnType("character varying(255)");
+
+ b.Property("BacktestCount")
+ .HasColumnType("integer");
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("Losses")
+ .HasColumnType("integer");
+
+ b.Property("NetPnL")
+ .HasPrecision(18, 8)
+ .HasColumnType("numeric(18,8)");
+
+ b.Property("Runtime")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("TotalBalance")
+ .HasPrecision(18, 8)
+ .HasColumnType("numeric(18,8)");
+
+ b.Property("TotalFees")
+ .HasPrecision(18, 8)
+ .HasColumnType("numeric(18,8)");
+
+ b.Property("TotalPnL")
+ .HasColumnType("decimal(18,8)");
+
+ b.Property("TotalROI")
+ .HasColumnType("decimal(18,8)");
+
+ b.Property("TotalVolume")
+ .HasPrecision(18, 8)
+ .HasColumnType("numeric(18,8)");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("UserId")
+ .HasColumnType("integer");
+
+ b.Property("Wins")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AgentName")
+ .IsUnique();
+
+ b.HasIndex("TotalPnL");
+
+ b.HasIndex("UserId")
+ .IsUnique();
+
+ b.ToTable("AgentSummaries");
+ });
+
+ modelBuilder.Entity("Managing.Infrastructure.Databases.PostgreSql.Entities.BacktestEntity", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("ConfigJson")
+ .IsRequired()
+ .HasColumnType("jsonb");
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("Duration")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("interval")
+ .HasDefaultValue(new TimeSpan(0, 0, 0, 0, 0));
+
+ b.Property("EndDate")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("Fees")
+ .HasColumnType("decimal(18,8)");
+
+ b.Property("FinalPnl")
+ .HasColumnType("decimal(18,8)");
+
+ b.Property("GrowthPercentage")
+ .HasColumnType("decimal(18,8)");
+
+ b.Property("HodlPercentage")
+ .HasColumnType("decimal(18,8)");
+
+ b.Property("Identifier")
+ .IsRequired()
+ .HasMaxLength(255)
+ .HasColumnType("character varying(255)");
+
+ b.Property("IndicatorsCount")
+ .HasColumnType("integer");
+
+ b.Property("IndicatorsCsv")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("InitialBalance")
+ .HasColumnType("decimal(18,8)");
+
+ b.Property("MaxDrawdown")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("decimal(18,8)")
+ .HasDefaultValue(0m);
+
+ b.Property("MaxDrawdownRecoveryTime")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("interval")
+ .HasDefaultValue(new TimeSpan(0, 0, 0, 0, 0));
+
+ b.Property("Metadata")
+ .HasColumnType("text");
+
+ b.Property("MoneyManagementJson")
+ .IsRequired()
+ .HasColumnType("jsonb");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(255)
+ .HasColumnType("character varying(255)");
+
+ b.Property("NetPnl")
+ .HasColumnType("decimal(18,8)");
+
+ b.Property("PositionCount")
+ .HasColumnType("integer");
+
+ b.Property("PositionsJson")
+ .IsRequired()
+ .HasColumnType("jsonb");
+
+ b.Property("RequestId")
+ .HasMaxLength(255)
+ .HasColumnType("uuid");
+
+ b.Property("Score")
+ .HasColumnType("double precision");
+
+ b.Property("ScoreMessage")
+ .IsRequired()
+ .HasMaxLength(1000)
+ .HasColumnType("text");
+
+ b.Property("SharpeRatio")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("decimal(18,8)")
+ .HasDefaultValue(0m);
+
+ b.Property("SignalsJson")
+ .IsRequired()
+ .HasColumnType("jsonb");
+
+ b.Property("StartDate")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("StatisticsJson")
+ .HasColumnType("jsonb");
+
+ b.Property("Ticker")
+ .IsRequired()
+ .HasMaxLength(32)
+ .HasColumnType("character varying(32)");
+
+ b.Property("Timeframe")
+ .HasColumnType("integer");
+
+ b.Property("TradingType")
+ .HasColumnType("integer");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("UserId")
+ .HasColumnType("integer");
+
+ b.Property("WinRate")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Identifier")
+ .IsUnique();
+
+ b.HasIndex("RequestId");
+
+ b.HasIndex("Score");
+
+ b.HasIndex("UserId");
+
+ b.HasIndex("RequestId", "Score");
+
+ b.HasIndex("UserId", "Name");
+
+ b.HasIndex("UserId", "Score");
+
+ b.HasIndex("UserId", "Ticker");
+
+ b.HasIndex("UserId", "Timeframe");
+
+ b.ToTable("Backtests");
+ });
+
+ modelBuilder.Entity("Managing.Infrastructure.Databases.PostgreSql.Entities.BotEntity", b =>
+ {
+ b.Property("Identifier")
+ .ValueGeneratedOnAdd()
+ .HasMaxLength(255)
+ .HasColumnType("uuid");
+
+ b.Property("AccumulatedRunTimeSeconds")
+ .HasColumnType("bigint");
+
+ b.Property("BotTradingBalance")
+ .HasColumnType("numeric");
+
+ b.Property("CreateDate")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("Fees")
+ .HasPrecision(18, 8)
+ .HasColumnType("numeric(18,8)");
+
+ b.Property("LastStartTime")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("LastStopTime")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("LongPositionCount")
+ .HasColumnType("integer");
+
+ b.Property("MasterBotUserId")
+ .HasColumnType("integer");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(255)
+ .HasColumnType("character varying(255)");
+
+ b.Property("NetPnL")
+ .HasPrecision(18, 8)
+ .HasColumnType("numeric(18,8)");
+
+ b.Property("Pnl")
+ .HasPrecision(18, 8)
+ .HasColumnType("numeric(18,8)");
+
+ b.Property("Roi")
+ .HasPrecision(18, 8)
+ .HasColumnType("numeric(18,8)");
+
+ b.Property("ShortPositionCount")
+ .HasColumnType("integer");
+
+ b.Property("StartupTime")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("Status")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Ticker")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("TradeLosses")
+ .HasColumnType("integer");
+
+ b.Property("TradeWins")
+ .HasColumnType("integer");
+
+ b.Property("TradingType")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("UserId")
+ .HasColumnType("integer");
+
+ b.Property("Volume")
+ .HasPrecision(18, 8)
+ .HasColumnType("numeric(18,8)");
+
+ b.HasKey("Identifier");
+
+ b.HasIndex("Identifier")
+ .IsUnique();
+
+ b.HasIndex("MasterBotUserId");
+
+ b.HasIndex("Status");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("Bots");
+ });
+
+ modelBuilder.Entity("Managing.Infrastructure.Databases.PostgreSql.Entities.BundleBacktestRequestEntity", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("CompletedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("CompletedBacktests")
+ .HasColumnType("integer");
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("CurrentBacktest")
+ .HasMaxLength(500)
+ .HasColumnType("character varying(500)");
+
+ b.Property("DateTimeRangesJson")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("ErrorMessage")
+ .HasColumnType("text");
+
+ b.Property("EstimatedTimeRemainingSeconds")
+ .HasColumnType("integer");
+
+ b.Property("FailedBacktests")
+ .HasColumnType("integer");
+
+ b.Property("MoneyManagementVariantsJson")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(255)
+ .HasColumnType("character varying(255)");
+
+ b.Property("ProgressInfo")
+ .HasColumnType("text");
+
+ b.Property("RequestId")
+ .HasMaxLength(255)
+ .HasColumnType("uuid");
+
+ b.Property("ResultsJson")
+ .IsRequired()
+ .HasColumnType("jsonb");
+
+ b.Property("Status")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("TickerVariantsJson")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("TotalBacktests")
+ .HasColumnType("integer");
+
+ b.Property("UniversalConfigJson")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("UserId")
+ .HasColumnType("integer");
+
+ b.Property("Version")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasDefaultValue(1);
+
+ b.HasKey("Id");
+
+ b.HasIndex("RequestId")
+ .IsUnique();
+
+ b.HasIndex("Status");
+
+ b.HasIndex("UserId");
+
+ b.HasIndex("UserId", "CreatedAt");
+
+ b.HasIndex("UserId", "Name", "Version");
+
+ b.ToTable("BundleBacktestRequests");
+ });
+
+ modelBuilder.Entity("Managing.Infrastructure.Databases.PostgreSql.Entities.FundingRateEntity", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("Date")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("Direction")
+ .HasColumnType("integer");
+
+ b.Property("Exchange")
+ .HasColumnType("integer");
+
+ b.Property("OpenInterest")
+ .HasPrecision(18, 8)
+ .HasColumnType("decimal(18,8)");
+
+ b.Property("Rate")
+ .HasPrecision(18, 8)
+ .HasColumnType("decimal(18,8)");
+
+ b.Property("Ticker")
+ .HasColumnType("integer");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Date");
+
+ b.HasIndex("Exchange");
+
+ b.HasIndex("Ticker");
+
+ b.HasIndex("Exchange", "Date");
+
+ b.HasIndex("Ticker", "Exchange");
+
+ b.HasIndex("Ticker", "Exchange", "Date")
+ .IsUnique();
+
+ b.ToTable("FundingRates");
+ });
+
+ modelBuilder.Entity("Managing.Infrastructure.Databases.PostgreSql.Entities.GeneticRequestEntity", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Balance")
+ .HasColumnType("decimal(18,8)");
+
+ b.Property("BestChromosome")
+ .HasMaxLength(4000)
+ .HasColumnType("character varying(4000)");
+
+ b.Property("BestFitness")
+ .HasColumnType("double precision");
+
+ b.Property("BestFitnessSoFar")
+ .HasColumnType("double precision");
+
+ b.Property("BestIndividual")
+ .HasMaxLength(4000)
+ .HasColumnType("character varying(4000)");
+
+ b.Property("CompletedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("CrossoverMethod")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("CurrentGeneration")
+ .HasColumnType("integer");
+
+ b.Property("EligibleIndicatorsJson")
+ .HasMaxLength(2000)
+ .HasColumnType("character varying(2000)");
+
+ b.Property("ElitismPercentage")
+ .HasColumnType("integer");
+
+ b.Property("EndDate")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("ErrorMessage")
+ .HasMaxLength(2000)
+ .HasColumnType("character varying(2000)");
+
+ b.Property("Generations")
+ .HasColumnType("integer");
+
+ b.Property("MaxTakeProfit")
+ .HasColumnType("double precision");
+
+ b.Property("MutationMethod")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("MutationRate")
+ .HasColumnType("double precision");
+
+ b.Property("PopulationSize")
+ .HasColumnType("integer");
+
+ b.Property("ProgressInfo")
+ .HasMaxLength(4000)
+ .HasColumnType("character varying(4000)");
+
+ b.Property("RequestId")
+ .IsRequired()
+ .HasMaxLength(255)
+ .HasColumnType("character varying(255)");
+
+ b.Property("SelectionMethod")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("StartDate")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("Status")
+ .IsRequired()
+ .HasMaxLength(50)
+ .HasColumnType("character varying(50)");
+
+ b.Property("Ticker")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Timeframe")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("UserId")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.HasIndex("RequestId")
+ .IsUnique();
+
+ b.HasIndex("Status");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("GeneticRequests");
+ });
+
+ modelBuilder.Entity("Managing.Infrastructure.Databases.PostgreSql.Entities.IndicatorEntity", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("CyclePeriods")
+ .HasColumnType("integer");
+
+ b.Property("FastPeriods")
+ .HasColumnType("integer");
+
+ b.Property("MinimumHistory")
+ .HasColumnType("integer");
+
+ b.Property("Multiplier")
+ .HasColumnType("double precision");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(255)
+ .HasColumnType("character varying(255)");
+
+ b.Property("Period")
+ .HasColumnType("integer");
+
+ b.Property("SignalPeriods")
+ .HasColumnType("integer");
+
+ b.Property("SignalType")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("SlowPeriods")
+ .HasColumnType("integer");
+
+ b.Property("SmoothPeriods")
+ .HasColumnType("integer");
+
+ b.Property("StochPeriods")
+ .HasColumnType("integer");
+
+ b.Property("Timeframe")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Type")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("UserId")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId");
+
+ b.HasIndex("UserId", "Name");
+
+ b.ToTable("Indicators");
+ });
+
+ modelBuilder.Entity("Managing.Infrastructure.Databases.PostgreSql.Entities.JobEntity", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uuid");
+
+ b.Property("AssignedWorkerId")
+ .HasMaxLength(255)
+ .HasColumnType("character varying(255)");
+
+ b.Property("BundleRequestId")
+ .HasColumnType("uuid");
+
+ b.Property("CompletedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("ConfigJson")
+ .IsRequired()
+ .HasColumnType("jsonb");
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("EndDate")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("ErrorMessage")
+ .HasColumnType("text");
+
+ b.Property("FailureCategory")
+ .HasColumnType("integer");
+
+ b.Property("GeneticRequestId")
+ .HasMaxLength(255)
+ .HasColumnType("character varying(255)");
+
+ b.Property("IsRetryable")
+ .HasColumnType("boolean");
+
+ b.Property("JobType")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasDefaultValue(0);
+
+ b.Property("LastHeartbeat")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("MaxRetries")
+ .HasColumnType("integer");
+
+ b.Property("Priority")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasDefaultValue(0);
+
+ b.Property("ProgressPercentage")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasDefaultValue(0);
+
+ b.Property("RequestId")
+ .HasMaxLength(255)
+ .HasColumnType("character varying(255)");
+
+ b.Property("ResultJson")
+ .HasColumnType("jsonb");
+
+ b.Property("RetryAfter")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("RetryCount")
+ .HasColumnType("integer");
+
+ b.Property("StartDate")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("StartedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("Status")
+ .HasColumnType("integer");
+
+ b.Property("UserId")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.HasIndex("BundleRequestId")
+ .HasDatabaseName("idx_bundle_request");
+
+ b.HasIndex("GeneticRequestId")
+ .HasDatabaseName("idx_genetic_request");
+
+ b.HasIndex("AssignedWorkerId", "Status")
+ .HasDatabaseName("idx_assigned_worker");
+
+ b.HasIndex("UserId", "Status")
+ .HasDatabaseName("idx_user_status");
+
+ b.HasIndex("Status", "JobType", "Priority", "CreatedAt")
+ .HasDatabaseName("idx_status_jobtype_priority_created");
+
+ b.ToTable("Jobs", (string)null);
+ });
+
+ modelBuilder.Entity("Managing.Infrastructure.Databases.PostgreSql.Entities.MoneyManagementEntity", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("Leverage")
+ .HasColumnType("decimal(18,8)");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(255)
+ .HasColumnType("character varying(255)");
+
+ b.Property("StopLoss")
+ .HasColumnType("decimal(18,8)");
+
+ b.Property("TakeProfit")
+ .HasColumnType("decimal(18,8)");
+
+ b.Property("Timeframe")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("UserId")
+ .HasColumnType("integer");
+
+ b.Property("UserName")
+ .HasMaxLength(255)
+ .HasColumnType("character varying(255)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId");
+
+ b.HasIndex("UserName");
+
+ b.HasIndex("UserName", "Name");
+
+ b.ToTable("MoneyManagements");
+ });
+
+ modelBuilder.Entity("Managing.Infrastructure.Databases.PostgreSql.Entities.PositionEntity", b =>
+ {
+ b.Property("Identifier")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("AccountId")
+ .HasColumnType("integer");
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("Date")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("GasFees")
+ .HasColumnType("decimal(18,8)");
+
+ b.Property("Initiator")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("InitiatorIdentifier")
+ .HasColumnType("uuid");
+
+ b.Property("MoneyManagementJson")
+ .HasColumnType("text");
+
+ b.Property("NetPnL")
+ .HasColumnType("decimal(18,8)");
+
+ b.Property("OpenTradeId")
+ .HasColumnType("integer");
+
+ b.Property("OriginDirection")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("ProfitAndLoss")
+ .HasColumnType("decimal(18,8)");
+
+ b.Property("SignalIdentifier")
+ .IsRequired()
+ .HasMaxLength(255)
+ .HasColumnType("character varying(255)");
+
+ b.Property("Status")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("StopLossTradeId")
+ .HasColumnType("integer");
+
+ b.Property("TakeProfit1TradeId")
+ .HasColumnType("integer");
+
+ b.Property("TakeProfit2TradeId")
+ .HasColumnType("integer");
+
+ b.Property("Ticker")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("TradingType")
+ .HasColumnType("integer");
+
+ b.Property("UiFees")
+ .HasColumnType("decimal(18,8)");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("UserId")
+ .HasColumnType("integer");
+
+ b.HasKey("Identifier");
+
+ b.HasIndex("Identifier")
+ .IsUnique();
+
+ b.HasIndex("InitiatorIdentifier");
+
+ b.HasIndex("OpenTradeId");
+
+ b.HasIndex("Status");
+
+ b.HasIndex("StopLossTradeId");
+
+ b.HasIndex("TakeProfit1TradeId");
+
+ b.HasIndex("TakeProfit2TradeId");
+
+ b.HasIndex("UserId");
+
+ b.HasIndex("UserId", "Identifier");
+
+ b.ToTable("Positions");
+ });
+
+ modelBuilder.Entity("Managing.Infrastructure.Databases.PostgreSql.Entities.ScenarioEntity", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("LoopbackPeriod")
+ .HasColumnType("integer");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(255)
+ .HasColumnType("character varying(255)");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("UserId")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId");
+
+ b.HasIndex("UserId", "Name");
+
+ b.ToTable("Scenarios");
+ });
+
+ modelBuilder.Entity("Managing.Infrastructure.Databases.PostgreSql.Entities.ScenarioIndicatorEntity", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("IndicatorId")
+ .HasColumnType("integer");
+
+ b.Property("ScenarioId")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.HasIndex("IndicatorId");
+
+ b.HasIndex("ScenarioId", "IndicatorId")
+ .IsUnique();
+
+ b.ToTable("ScenarioIndicators");
+ });
+
+ modelBuilder.Entity("Managing.Infrastructure.Databases.PostgreSql.Entities.SignalEntity", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("CandleJson")
+ .HasColumnType("text");
+
+ b.Property("Confidence")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("Date")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("Direction")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Identifier")
+ .IsRequired()
+ .HasMaxLength(255)
+ .HasColumnType("character varying(255)");
+
+ b.Property("IndicatorName")
+ .IsRequired()
+ .HasMaxLength(255)
+ .HasColumnType("character varying(255)");
+
+ b.Property("SignalType")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Status")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Ticker")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Timeframe")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Type")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("UserId")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Date");
+
+ b.HasIndex("Identifier");
+
+ b.HasIndex("Status");
+
+ b.HasIndex("Ticker");
+
+ b.HasIndex("UserId");
+
+ b.HasIndex("UserId", "Date");
+
+ b.HasIndex("Identifier", "Date", "UserId")
+ .IsUnique();
+
+ b.ToTable("Signals");
+ });
+
+ modelBuilder.Entity("Managing.Infrastructure.Databases.PostgreSql.Entities.SpotlightOverviewEntity", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("DateTime")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property