diff --git a/src/Predictalytics.Infrastructure/Migrations/20260708183009_AddCopytradingScores.Designer.cs b/src/Predictalytics.Infrastructure/Migrations/20260708183009_AddCopytradingScores.Designer.cs
new file mode 100644
index 0000000..88bc21e
--- /dev/null
+++ b/src/Predictalytics.Infrastructure/Migrations/20260708183009_AddCopytradingScores.Designer.cs
@@ -0,0 +1,1097 @@
+//
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Predictalytics.Infrastructure.Data;
+
+#nullable disable
+
+namespace Predictalytics.Infrastructure.Migrations
+{
+ [DbContext(typeof(AppDbContext))]
+ [Migration("20260708183009_AddCopytradingScores")]
+ partial class AddCopytradingScores
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "8.0.11")
+ .HasAnnotation("Relational:MaxIdentifierLength", 64);
+
+ MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);
+
+ modelBuilder.Entity("Predictalytics.Domain.Entities.Alert", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("CreatedAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("IsRead")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("Message")
+ .IsRequired()
+ .HasMaxLength(4096)
+ .HasColumnType("varchar(4096)");
+
+ b.Property("Platform")
+ .HasColumnType("int");
+
+ b.Property("Severity")
+ .HasColumnType("int");
+
+ b.Property("Title")
+ .IsRequired()
+ .HasMaxLength(512)
+ .HasColumnType("varchar(512)");
+
+ b.Property("TraderId")
+ .HasColumnType("int");
+
+ b.Property("Type")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CreatedAt");
+
+ b.HasIndex("TraderId");
+
+ b.ToTable("Alerts");
+ });
+
+ modelBuilder.Entity("Predictalytics.Domain.Entities.BackgroundJob", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("CompletedAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("CreatedAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("ErrorMessage")
+ .HasMaxLength(4096)
+ .HasColumnType("varchar(4096)");
+
+ b.Property("JobType")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("varchar(64)");
+
+ b.Property("StartedAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Status")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("varchar(64)");
+
+ b.Property("TraderId")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("JobType");
+
+ b.HasIndex("Status");
+
+ b.HasIndex("TraderId");
+
+ b.ToTable("BackgroundJobs");
+ });
+
+ modelBuilder.Entity("Predictalytics.Domain.Entities.Event", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("CreatedAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("DbCreatedAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Description")
+ .HasMaxLength(4096)
+ .HasColumnType("varchar(4096)");
+
+ b.Property("EndDate")
+ .HasColumnType("datetime(6)");
+
+ b.Property("ImageUrl")
+ .HasMaxLength(1024)
+ .HasColumnType("varchar(1024)");
+
+ b.Property("IsActive")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("IsClosed")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("LastUpdatedAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Platform")
+ .HasColumnType("int");
+
+ b.Property("PlatformEventId")
+ .HasColumnType("bigint");
+
+ b.Property("Slug")
+ .IsRequired()
+ .HasMaxLength(512)
+ .HasColumnType("varchar(512)");
+
+ b.Property("StartDate")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Tags")
+ .IsRequired()
+ .HasMaxLength(1024)
+ .HasColumnType("varchar(1024)");
+
+ b.Property("Title")
+ .IsRequired()
+ .HasMaxLength(1024)
+ .HasColumnType("varchar(1024)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Platform", "PlatformEventId")
+ .IsUnique();
+
+ b.ToTable("Events");
+ });
+
+ modelBuilder.Entity("Predictalytics.Domain.Entities.Market", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("Category")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("varchar(64)");
+
+ b.Property("ClosedAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("ConditionId")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.Property("CreatedAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("DbCreatedAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Description")
+ .HasMaxLength(4096)
+ .HasColumnType("varchar(4096)");
+
+ b.Property("EndDate")
+ .HasColumnType("datetime(6)");
+
+ b.Property("EventId")
+ .HasColumnType("int");
+
+ b.Property("FeeRateBps")
+ .HasColumnType("decimal(65,30)");
+
+ b.Property("ImageUrl")
+ .HasMaxLength(1024)
+ .HasColumnType("varchar(1024)");
+
+ b.Property("IsNegRisk")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("IsResolved")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("LastTradesUpdatedAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("LastUpdatedAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Liquidity")
+ .HasPrecision(18, 4)
+ .HasColumnType("decimal(18,4)");
+
+ b.Property("MarketSlug")
+ .IsRequired()
+ .HasMaxLength(512)
+ .HasColumnType("varchar(512)");
+
+ b.Property("Platform")
+ .HasColumnType("int");
+
+ b.Property("PlatformMarketId")
+ .HasColumnType("bigint");
+
+ b.Property("Question")
+ .IsRequired()
+ .HasMaxLength(1024)
+ .HasColumnType("varchar(1024)");
+
+ b.Property("QuestionId")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.Property("ResolutionOutcome")
+ .HasColumnType("longtext");
+
+ b.Property("StartDate")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Subcategory")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("varchar(128)");
+
+ b.Property("Volume")
+ .HasPrecision(18, 4)
+ .HasColumnType("decimal(18,4)");
+
+ b.Property("Volume24h")
+ .HasPrecision(18, 4)
+ .HasColumnType("decimal(18,4)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("EventId");
+
+ b.HasIndex("Platform", "PlatformMarketId")
+ .IsUnique();
+
+ b.ToTable("Markets");
+ });
+
+ modelBuilder.Entity("Predictalytics.Domain.Entities.MarketAnalytics", b =>
+ {
+ b.Property("MarketId")
+ .HasColumnType("int");
+
+ b.Property("AverageTradeSize")
+ .HasPrecision(18, 4)
+ .HasColumnType("decimal(18,4)");
+
+ b.Property("BotActivityScore")
+ .HasPrecision(8, 4)
+ .HasColumnType("decimal(8,4)");
+
+ b.Property("LastCalculatedAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("UniqueTradersCount")
+ .HasColumnType("int");
+
+ b.HasKey("MarketId");
+
+ b.ToTable("MarketAnalytics");
+ });
+
+ modelBuilder.Entity("Predictalytics.Domain.Entities.MarketOutcome", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("CurrentPrice")
+ .HasPrecision(18, 8)
+ .HasColumnType("decimal(18,8)");
+
+ b.Property("Label")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.Property("MarketId")
+ .HasColumnType("int");
+
+ b.Property("OutcomeIndex")
+ .HasColumnType("int");
+
+ b.Property("TokenId")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TokenId");
+
+ b.HasIndex("MarketId", "OutcomeIndex")
+ .IsUnique();
+
+ b.ToTable("MarketOutcomes");
+ });
+
+ modelBuilder.Entity("Predictalytics.Domain.Entities.MarketOutcomePriceSnapshot", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("MarketOutcomeId")
+ .HasColumnType("int");
+
+ b.Property("Price")
+ .HasPrecision(10, 6)
+ .HasColumnType("decimal(10,6)");
+
+ b.Property("Timestamp")
+ .HasColumnType("datetime(6)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("MarketOutcomeId", "Timestamp");
+
+ b.ToTable("MarketOutcomePriceSnapshots");
+ });
+
+ modelBuilder.Entity("Predictalytics.Domain.Entities.PlatformConfig", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("int");
+
+ b.Property("BaseUrl")
+ .HasMaxLength(1024)
+ .HasColumnType("varchar(1024)");
+
+ b.Property("CreatedAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("DisplayName")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.Property("IsActive")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("varchar(128)");
+
+ b.Property("SettingsJson")
+ .HasColumnType("longtext");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("datetime(6)");
+
+ b.HasKey("Id");
+
+ b.ToTable("PlatformConfigs");
+ });
+
+ modelBuilder.Entity("Predictalytics.Domain.Entities.Trade", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("Amount")
+ .HasPrecision(18, 4)
+ .HasColumnType("decimal(18,4)");
+
+ b.Property("AssetId")
+ .IsRequired()
+ .HasMaxLength(80)
+ .HasColumnType("varchar(80)");
+
+ b.Property("DbMarketId")
+ .HasColumnType("int");
+
+ b.Property("ExecutedAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("IsContextEnriched")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("MarketId")
+ .IsRequired()
+ .HasMaxLength(66)
+ .HasColumnType("varchar(66)");
+
+ b.Property("MarketOutcomeId")
+ .HasColumnType("int");
+
+ b.Property("Outcome")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("varchar(128)");
+
+ b.Property("Platform")
+ .HasColumnType("int");
+
+ b.Property("PlatformTradeId")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.Property("PostTradePrice1m")
+ .HasColumnType("decimal(18,4)");
+
+ b.Property("PreTradePrice1m")
+ .HasColumnType("decimal(18,4)");
+
+ b.Property("Price")
+ .HasPrecision(18, 6)
+ .HasColumnType("decimal(18,6)");
+
+ b.Property("Side")
+ .HasColumnType("int");
+
+ b.Property("Size")
+ .HasPrecision(14, 6)
+ .HasColumnType("decimal(14,6)");
+
+ b.Property("TraderId")
+ .HasColumnType("int");
+
+ b.Property("TransactionHash")
+ .HasMaxLength(66)
+ .HasColumnType("varchar(66)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AssetId");
+
+ b.HasIndex("DbMarketId");
+
+ b.HasIndex("ExecutedAt");
+
+ b.HasIndex("MarketOutcomeId");
+
+ b.HasIndex("TraderId");
+
+ b.HasIndex("Platform", "PlatformTradeId")
+ .IsUnique();
+
+ b.ToTable("Trades");
+ });
+
+ modelBuilder.Entity("Predictalytics.Domain.Entities.TradeContext", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("EstimatedOrderType")
+ .IsRequired()
+ .HasMaxLength(32)
+ .HasColumnType("varchar(32)");
+
+ b.Property("EstimatedSlippage")
+ .HasPrecision(18, 4)
+ .HasColumnType("decimal(18,4)");
+
+ b.Property("FollowerFillPrice10s")
+ .HasColumnType("decimal(65,30)");
+
+ b.Property("FollowerFillPrice60s")
+ .HasColumnType("decimal(65,30)");
+
+ b.Property("PriceAfter1m")
+ .HasPrecision(18, 4)
+ .HasColumnType("decimal(18,4)");
+
+ b.Property("PriceBefore1m")
+ .HasPrecision(18, 4)
+ .HasColumnType("decimal(18,4)");
+
+ b.Property("TradeId")
+ .HasColumnType("bigint");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TradeId")
+ .IsUnique();
+
+ b.ToTable("TradeContexts");
+ });
+
+ modelBuilder.Entity("Predictalytics.Domain.Entities.Trader", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("AiStrategySummary")
+ .HasColumnType("longtext");
+
+ b.Property("AiStrategyUpdatedAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("CreatedAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("DisplayName")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.Property("IsAutoDiscovered")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("IsInitialImportComplete")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("IsSuspectedBot")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("LastAnalyzedAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("LastApiErrorAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("LastPolledAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("LastTradesUpdatedAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("ManualPriorityOverride")
+ .HasColumnType("int");
+
+ b.Property("Notes")
+ .HasColumnType("longtext");
+
+ b.Property("Platform")
+ .HasColumnType("int");
+
+ b.Property("PlatformUserId")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("varchar(128)");
+
+ b.Property("Strategy")
+ .HasColumnType("int");
+
+ b.Property("Tier")
+ .HasColumnType("int");
+
+ b.Property("TotalPnl")
+ .HasPrecision(18, 4)
+ .HasColumnType("decimal(18,4)");
+
+ b.Property("TotalTrades")
+ .HasColumnType("int");
+
+ b.Property("WinRate")
+ .HasPrecision(8, 4)
+ .HasColumnType("decimal(8,4)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Platform", "PlatformUserId")
+ .IsUnique();
+
+ b.ToTable("Traders");
+ });
+
+ modelBuilder.Entity("Predictalytics.Domain.Entities.TraderAnalytics", b =>
+ {
+ b.Property("TraderId")
+ .HasColumnType("int");
+
+ b.Property("CopytradingCopyabilityScore")
+ .HasColumnType("decimal(65,30)");
+
+ b.Property("CopytradingQualityScore")
+ .HasColumnType("decimal(65,30)");
+
+ b.Property("CopytradingScore")
+ .HasColumnType("decimal(65,30)");
+
+ b.Property("CurrentBalance")
+ .HasColumnType("decimal(65,30)");
+
+ b.Property("EstimatedBankroll")
+ .HasColumnType("decimal(65,30)");
+
+ b.Property("LastCalculatedAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("OverallPnL")
+ .HasPrecision(18, 4)
+ .HasColumnType("decimal(18,4)");
+
+ b.Property("OverallWinRate")
+ .HasPrecision(8, 4)
+ .HasColumnType("decimal(8,4)");
+
+ b.Property("PnL24h")
+ .HasPrecision(18, 4)
+ .HasColumnType("decimal(18,4)");
+
+ b.Property("PnL30d")
+ .HasPrecision(18, 4)
+ .HasColumnType("decimal(18,4)");
+
+ b.Property("PnL7d")
+ .HasPrecision(18, 4)
+ .HasColumnType("decimal(18,4)");
+
+ b.Property("WinRate24h")
+ .HasPrecision(8, 4)
+ .HasColumnType("decimal(8,4)");
+
+ b.Property("WinRate30d")
+ .HasPrecision(8, 4)
+ .HasColumnType("decimal(8,4)");
+
+ b.Property("WinRate7d")
+ .HasPrecision(8, 4)
+ .HasColumnType("decimal(8,4)");
+
+ b.HasKey("TraderId");
+
+ b.ToTable("TraderAnalytics");
+ });
+
+ modelBuilder.Entity("Predictalytics.Domain.Entities.TraderCategoryPerformance", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("Category")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("varchar(64)");
+
+ b.Property("Subcategory")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("varchar(128)");
+
+ b.Property("TotalPnL")
+ .HasPrecision(18, 4)
+ .HasColumnType("decimal(18,4)");
+
+ b.Property("TotalTrades")
+ .HasColumnType("int");
+
+ b.Property("TotalVolume")
+ .HasPrecision(18, 4)
+ .HasColumnType("decimal(18,4)");
+
+ b.Property("TraderId")
+ .HasColumnType("int");
+
+ b.Property("WinningTrades")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TraderId", "Category", "Subcategory")
+ .IsUnique();
+
+ b.ToTable("TraderCategoryPerformances");
+ });
+
+ modelBuilder.Entity("Predictalytics.Domain.Entities.TraderDailySnapshot", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("CurrentBalance")
+ .HasPrecision(18, 4)
+ .HasColumnType("decimal(18,4)");
+
+ b.Property("Date")
+ .HasColumnType("datetime(6)");
+
+ b.Property("TotalPnl")
+ .HasPrecision(18, 4)
+ .HasColumnType("decimal(18,4)");
+
+ b.Property("TraderId")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TraderId", "Date")
+ .IsUnique();
+
+ b.ToTable("TraderDailySnapshots");
+ });
+
+ modelBuilder.Entity("Predictalytics.Domain.Entities.TraderPosition", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("AvgCost")
+ .HasPrecision(10, 6)
+ .HasColumnType("decimal(10,6)");
+
+ b.Property("IsHistoryPruned")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("LastAppliedTradeId")
+ .HasColumnType("bigint");
+
+ b.Property("LastTradeExecutedAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("LastUpdatedAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("MarketOutcomeId")
+ .HasColumnType("int");
+
+ b.Property("RealizedPnl")
+ .HasPrecision(18, 4)
+ .HasColumnType("decimal(18,4)");
+
+ b.Property("SharesHeld")
+ .HasPrecision(14, 6)
+ .HasColumnType("decimal(14,6)");
+
+ b.Property("TraderId")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("MarketOutcomeId");
+
+ b.HasIndex("TraderId", "MarketOutcomeId")
+ .IsUnique();
+
+ b.ToTable("TraderPositions");
+ });
+
+ modelBuilder.Entity("Predictalytics.Domain.Entities.TraderScore", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("ActivityScore")
+ .HasPrecision(5, 2)
+ .HasColumnType("decimal(5,2)");
+
+ b.Property("CalculatedAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("CombinedScore")
+ .HasPrecision(5, 2)
+ .HasColumnType("decimal(5,2)");
+
+ b.Property("QualityScore")
+ .HasPrecision(5, 2)
+ .HasColumnType("decimal(5,2)");
+
+ b.Property("Rank")
+ .HasColumnType("int");
+
+ b.Property("TimingScore")
+ .HasPrecision(5, 2)
+ .HasColumnType("decimal(5,2)");
+
+ b.Property("TraderId")
+ .HasColumnType("int");
+
+ b.Property("VolumeScore")
+ .HasPrecision(5, 2)
+ .HasColumnType("decimal(5,2)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TraderId")
+ .IsUnique();
+
+ b.ToTable("TraderScores");
+ });
+
+ modelBuilder.Entity("Predictalytics.Domain.Entities.WatchlistEntry", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("AddedAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("AlertsEnabled")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("Label")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.Property("Notes")
+ .HasColumnType("longtext");
+
+ b.Property("TraderId")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TraderId")
+ .IsUnique();
+
+ b.ToTable("WatchlistEntries");
+ });
+
+ modelBuilder.Entity("Predictalytics.Domain.Entities.Alert", b =>
+ {
+ b.HasOne("Predictalytics.Domain.Entities.Trader", "Trader")
+ .WithMany()
+ .HasForeignKey("TraderId")
+ .OnDelete(DeleteBehavior.SetNull);
+
+ b.Navigation("Trader");
+ });
+
+ modelBuilder.Entity("Predictalytics.Domain.Entities.BackgroundJob", b =>
+ {
+ b.HasOne("Predictalytics.Domain.Entities.Trader", "Trader")
+ .WithMany()
+ .HasForeignKey("TraderId")
+ .OnDelete(DeleteBehavior.SetNull);
+
+ b.Navigation("Trader");
+ });
+
+ modelBuilder.Entity("Predictalytics.Domain.Entities.Market", b =>
+ {
+ b.HasOne("Predictalytics.Domain.Entities.Event", "Event")
+ .WithMany("Markets")
+ .HasForeignKey("EventId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Event");
+ });
+
+ modelBuilder.Entity("Predictalytics.Domain.Entities.MarketAnalytics", b =>
+ {
+ b.HasOne("Predictalytics.Domain.Entities.Market", "Market")
+ .WithOne("Analytics")
+ .HasForeignKey("Predictalytics.Domain.Entities.MarketAnalytics", "MarketId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Market");
+ });
+
+ modelBuilder.Entity("Predictalytics.Domain.Entities.MarketOutcome", b =>
+ {
+ b.HasOne("Predictalytics.Domain.Entities.Market", "Market")
+ .WithMany("Outcomes")
+ .HasForeignKey("MarketId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Market");
+ });
+
+ modelBuilder.Entity("Predictalytics.Domain.Entities.MarketOutcomePriceSnapshot", b =>
+ {
+ b.HasOne("Predictalytics.Domain.Entities.MarketOutcome", "MarketOutcome")
+ .WithMany()
+ .HasForeignKey("MarketOutcomeId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("MarketOutcome");
+ });
+
+ modelBuilder.Entity("Predictalytics.Domain.Entities.Trade", b =>
+ {
+ b.HasOne("Predictalytics.Domain.Entities.Market", "DbMarket")
+ .WithMany()
+ .HasForeignKey("DbMarketId")
+ .OnDelete(DeleteBehavior.SetNull);
+
+ b.HasOne("Predictalytics.Domain.Entities.MarketOutcome", "MarketOutcome")
+ .WithMany()
+ .HasForeignKey("MarketOutcomeId")
+ .OnDelete(DeleteBehavior.SetNull);
+
+ b.HasOne("Predictalytics.Domain.Entities.Trader", "Trader")
+ .WithMany("Trades")
+ .HasForeignKey("TraderId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("DbMarket");
+
+ b.Navigation("MarketOutcome");
+
+ b.Navigation("Trader");
+ });
+
+ modelBuilder.Entity("Predictalytics.Domain.Entities.TradeContext", b =>
+ {
+ b.HasOne("Predictalytics.Domain.Entities.Trade", "Trade")
+ .WithOne("Context")
+ .HasForeignKey("Predictalytics.Domain.Entities.TradeContext", "TradeId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Trade");
+ });
+
+ modelBuilder.Entity("Predictalytics.Domain.Entities.TraderAnalytics", b =>
+ {
+ b.HasOne("Predictalytics.Domain.Entities.Trader", "Trader")
+ .WithOne("Analytics")
+ .HasForeignKey("Predictalytics.Domain.Entities.TraderAnalytics", "TraderId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Trader");
+ });
+
+ modelBuilder.Entity("Predictalytics.Domain.Entities.TraderCategoryPerformance", b =>
+ {
+ b.HasOne("Predictalytics.Domain.Entities.Trader", "Trader")
+ .WithMany("CategoryPerformances")
+ .HasForeignKey("TraderId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Trader");
+ });
+
+ modelBuilder.Entity("Predictalytics.Domain.Entities.TraderDailySnapshot", b =>
+ {
+ b.HasOne("Predictalytics.Domain.Entities.Trader", "Trader")
+ .WithMany()
+ .HasForeignKey("TraderId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Trader");
+ });
+
+ modelBuilder.Entity("Predictalytics.Domain.Entities.TraderPosition", b =>
+ {
+ b.HasOne("Predictalytics.Domain.Entities.MarketOutcome", "MarketOutcome")
+ .WithMany()
+ .HasForeignKey("MarketOutcomeId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("Predictalytics.Domain.Entities.Trader", "Trader")
+ .WithMany("Positions")
+ .HasForeignKey("TraderId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("MarketOutcome");
+
+ b.Navigation("Trader");
+ });
+
+ modelBuilder.Entity("Predictalytics.Domain.Entities.TraderScore", b =>
+ {
+ b.HasOne("Predictalytics.Domain.Entities.Trader", "Trader")
+ .WithOne("CurrentScore")
+ .HasForeignKey("Predictalytics.Domain.Entities.TraderScore", "TraderId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Trader");
+ });
+
+ modelBuilder.Entity("Predictalytics.Domain.Entities.WatchlistEntry", b =>
+ {
+ b.HasOne("Predictalytics.Domain.Entities.Trader", "Trader")
+ .WithMany("WatchlistEntries")
+ .HasForeignKey("TraderId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Trader");
+ });
+
+ modelBuilder.Entity("Predictalytics.Domain.Entities.Event", b =>
+ {
+ b.Navigation("Markets");
+ });
+
+ modelBuilder.Entity("Predictalytics.Domain.Entities.Market", b =>
+ {
+ b.Navigation("Analytics");
+
+ b.Navigation("Outcomes");
+ });
+
+ modelBuilder.Entity("Predictalytics.Domain.Entities.Trade", b =>
+ {
+ b.Navigation("Context");
+ });
+
+ modelBuilder.Entity("Predictalytics.Domain.Entities.Trader", b =>
+ {
+ b.Navigation("Analytics");
+
+ b.Navigation("CategoryPerformances");
+
+ b.Navigation("CurrentScore");
+
+ b.Navigation("Positions");
+
+ b.Navigation("Trades");
+
+ b.Navigation("WatchlistEntries");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/src/Predictalytics.Infrastructure/Migrations/20260708183009_AddCopytradingScores.cs b/src/Predictalytics.Infrastructure/Migrations/20260708183009_AddCopytradingScores.cs
new file mode 100644
index 0000000..a6c0881
--- /dev/null
+++ b/src/Predictalytics.Infrastructure/Migrations/20260708183009_AddCopytradingScores.cs
@@ -0,0 +1,206 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace Predictalytics.Infrastructure.Migrations
+{
+ ///
+ public partial class AddCopytradingScores : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropColumn(
+ name: "CopytradingCopyabilityScore",
+ table: "TraderScores");
+
+ migrationBuilder.DropColumn(
+ name: "CopytradingQualityScore",
+ table: "TraderScores");
+
+ migrationBuilder.DropColumn(
+ name: "CopytradingScore",
+ table: "TraderScores");
+
+ migrationBuilder.AlterColumn(
+ name: "VolumeScore",
+ table: "TraderScores",
+ type: "decimal(5,2)",
+ precision: 5,
+ scale: 2,
+ nullable: false,
+ oldClrType: typeof(decimal),
+ oldType: "decimal(8,4)",
+ oldPrecision: 8,
+ oldScale: 4);
+
+ migrationBuilder.AlterColumn(
+ name: "TimingScore",
+ table: "TraderScores",
+ type: "decimal(5,2)",
+ precision: 5,
+ scale: 2,
+ nullable: false,
+ oldClrType: typeof(decimal),
+ oldType: "decimal(8,4)",
+ oldPrecision: 8,
+ oldScale: 4);
+
+ migrationBuilder.AlterColumn(
+ name: "QualityScore",
+ table: "TraderScores",
+ type: "decimal(5,2)",
+ precision: 5,
+ scale: 2,
+ nullable: false,
+ oldClrType: typeof(decimal),
+ oldType: "decimal(8,4)",
+ oldPrecision: 8,
+ oldScale: 4);
+
+ migrationBuilder.AlterColumn(
+ name: "CombinedScore",
+ table: "TraderScores",
+ type: "decimal(5,2)",
+ precision: 5,
+ scale: 2,
+ nullable: false,
+ oldClrType: typeof(decimal),
+ oldType: "decimal(8,4)",
+ oldPrecision: 8,
+ oldScale: 4);
+
+ migrationBuilder.AlterColumn(
+ name: "ActivityScore",
+ table: "TraderScores",
+ type: "decimal(5,2)",
+ precision: 5,
+ scale: 2,
+ nullable: false,
+ oldClrType: typeof(decimal),
+ oldType: "decimal(8,4)",
+ oldPrecision: 8,
+ oldScale: 4);
+
+ migrationBuilder.AddColumn(
+ name: "CopytradingCopyabilityScore",
+ table: "TraderAnalytics",
+ type: "decimal(65,30)",
+ nullable: false,
+ defaultValue: 0m);
+
+ migrationBuilder.AddColumn(
+ name: "CopytradingQualityScore",
+ table: "TraderAnalytics",
+ type: "decimal(65,30)",
+ nullable: false,
+ defaultValue: 0m);
+
+ migrationBuilder.AddColumn(
+ name: "CopytradingScore",
+ table: "TraderAnalytics",
+ type: "decimal(65,30)",
+ nullable: false,
+ defaultValue: 0m);
+ }
+
+ ///
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropColumn(
+ name: "CopytradingCopyabilityScore",
+ table: "TraderAnalytics");
+
+ migrationBuilder.DropColumn(
+ name: "CopytradingQualityScore",
+ table: "TraderAnalytics");
+
+ migrationBuilder.DropColumn(
+ name: "CopytradingScore",
+ table: "TraderAnalytics");
+
+ migrationBuilder.AlterColumn(
+ name: "VolumeScore",
+ table: "TraderScores",
+ type: "decimal(8,4)",
+ precision: 8,
+ scale: 4,
+ nullable: false,
+ oldClrType: typeof(decimal),
+ oldType: "decimal(5,2)",
+ oldPrecision: 5,
+ oldScale: 2);
+
+ migrationBuilder.AlterColumn(
+ name: "TimingScore",
+ table: "TraderScores",
+ type: "decimal(8,4)",
+ precision: 8,
+ scale: 4,
+ nullable: false,
+ oldClrType: typeof(decimal),
+ oldType: "decimal(5,2)",
+ oldPrecision: 5,
+ oldScale: 2);
+
+ migrationBuilder.AlterColumn(
+ name: "QualityScore",
+ table: "TraderScores",
+ type: "decimal(8,4)",
+ precision: 8,
+ scale: 4,
+ nullable: false,
+ oldClrType: typeof(decimal),
+ oldType: "decimal(5,2)",
+ oldPrecision: 5,
+ oldScale: 2);
+
+ migrationBuilder.AlterColumn(
+ name: "CombinedScore",
+ table: "TraderScores",
+ type: "decimal(8,4)",
+ precision: 8,
+ scale: 4,
+ nullable: false,
+ oldClrType: typeof(decimal),
+ oldType: "decimal(5,2)",
+ oldPrecision: 5,
+ oldScale: 2);
+
+ migrationBuilder.AlterColumn(
+ name: "ActivityScore",
+ table: "TraderScores",
+ type: "decimal(8,4)",
+ precision: 8,
+ scale: 4,
+ nullable: false,
+ oldClrType: typeof(decimal),
+ oldType: "decimal(5,2)",
+ oldPrecision: 5,
+ oldScale: 2);
+
+ migrationBuilder.AddColumn(
+ name: "CopytradingCopyabilityScore",
+ table: "TraderScores",
+ type: "decimal(65,30)",
+ nullable: false,
+ defaultValue: 0m);
+
+ migrationBuilder.AddColumn(
+ name: "CopytradingQualityScore",
+ table: "TraderScores",
+ type: "decimal(65,30)",
+ nullable: false,
+ defaultValue: 0m);
+
+ migrationBuilder.AddColumn(
+ name: "CopytradingScore",
+ table: "TraderScores",
+ type: "decimal(8,4)",
+ precision: 8,
+ scale: 4,
+ nullable: false,
+ defaultValue: 0m);
+ }
+ }
+}
diff --git a/src/Predictalytics.Infrastructure/Migrations/AppDbContextModelSnapshot.cs b/src/Predictalytics.Infrastructure/Migrations/AppDbContextModelSnapshot.cs
index 6659991..eac4f5b 100644
--- a/src/Predictalytics.Infrastructure/Migrations/AppDbContextModelSnapshot.cs
+++ b/src/Predictalytics.Infrastructure/Migrations/AppDbContextModelSnapshot.cs
@@ -629,6 +629,15 @@ namespace Predictalytics.Infrastructure.Migrations
b.Property("TraderId")
.HasColumnType("int");
+ b.Property("CopytradingCopyabilityScore")
+ .HasColumnType("decimal(65,30)");
+
+ b.Property("CopytradingQualityScore")
+ .HasColumnType("decimal(65,30)");
+
+ b.Property("CopytradingScore")
+ .HasColumnType("decimal(65,30)");
+
b.Property("CurrentBalance")
.HasColumnType("decimal(65,30)");
@@ -805,43 +814,33 @@ namespace Predictalytics.Infrastructure.Migrations
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
b.Property("ActivityScore")
- .HasPrecision(8, 4)
- .HasColumnType("decimal(8,4)");
+ .HasPrecision(5, 2)
+ .HasColumnType("decimal(5,2)");
b.Property("CalculatedAt")
.HasColumnType("datetime(6)");
b.Property("CombinedScore")
- .HasPrecision(8, 4)
- .HasColumnType("decimal(8,4)");
-
- b.Property("CopytradingCopyabilityScore")
- .HasColumnType("decimal(65,30)");
-
- b.Property("CopytradingQualityScore")
- .HasColumnType("decimal(65,30)");
-
- b.Property("CopytradingScore")
- .HasPrecision(8, 4)
- .HasColumnType("decimal(8,4)");
+ .HasPrecision(5, 2)
+ .HasColumnType("decimal(5,2)");
b.Property("QualityScore")
- .HasPrecision(8, 4)
- .HasColumnType("decimal(8,4)");
+ .HasPrecision(5, 2)
+ .HasColumnType("decimal(5,2)");
b.Property("Rank")
.HasColumnType("int");
b.Property("TimingScore")
- .HasPrecision(8, 4)
- .HasColumnType("decimal(8,4)");
+ .HasPrecision(5, 2)
+ .HasColumnType("decimal(5,2)");
b.Property("TraderId")
.HasColumnType("int");
b.Property("VolumeScore")
- .HasPrecision(8, 4)
- .HasColumnType("decimal(8,4)");
+ .HasPrecision(5, 2)
+ .HasColumnType("decimal(5,2)");
b.HasKey("Id");