Initial commit: Predictalytics solution
Clean Architecture .NET 8 solution (Domain/Application/Infrastructure/Api/Worker/WinFormsHost) for analyzing Polymarket traders for copytrading/strategy-replication candidates. Includes EF Core InitialBaseline migration and DB secrets removed from source/config in preparation for version control.
This commit is contained in:
@@ -0,0 +1,157 @@
|
||||
using Predictalytics.Domain.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Predictalytics.Infrastructure.Data;
|
||||
|
||||
public class AppDbContext : DbContext
|
||||
{
|
||||
public DbSet<Trader> Traders => Set<Trader>();
|
||||
public DbSet<Trade> Trades => Set<Trade>();
|
||||
public DbSet<Market> Markets => Set<Market>();
|
||||
public DbSet<MarketOutcome> MarketOutcomes => Set<MarketOutcome>();
|
||||
public DbSet<TraderScore> TraderScores => Set<TraderScore>();
|
||||
public DbSet<WatchlistEntry> WatchlistEntries => Set<WatchlistEntry>();
|
||||
public DbSet<Alert> Alerts => Set<Alert>();
|
||||
public DbSet<PlatformConfig> PlatformConfigs => Set<PlatformConfig>();
|
||||
public DbSet<TraderAnalytics> TraderAnalytics => Set<TraderAnalytics>();
|
||||
public DbSet<MarketAnalytics> MarketAnalytics => Set<MarketAnalytics>();
|
||||
|
||||
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder mb)
|
||||
{
|
||||
// Trader
|
||||
mb.Entity<Trader>(e =>
|
||||
{
|
||||
e.HasKey(t => t.Id);
|
||||
e.HasIndex(t => new { t.Platform, t.PlatformUserId }).IsUnique();
|
||||
e.Property(t => t.PlatformUserId).HasMaxLength(128);
|
||||
e.Property(t => t.DisplayName).HasMaxLength(256);
|
||||
e.Property(t => t.TotalPnl).HasPrecision(18, 4);
|
||||
e.Property(t => t.WinRate).HasPrecision(8, 4);
|
||||
e.HasOne(t => t.CurrentScore).WithOne(s => s.Trader)
|
||||
.HasForeignKey<TraderScore>(s => s.TraderId).OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
// Trade
|
||||
mb.Entity<Trade>(e =>
|
||||
{
|
||||
e.HasKey(t => t.Id);
|
||||
e.HasIndex(t => new { t.Platform, t.PlatformTradeId }).IsUnique();
|
||||
e.HasIndex(t => t.TraderId);
|
||||
e.HasIndex(t => t.ExecutedAt);
|
||||
e.HasIndex(t => t.AssetId);
|
||||
e.HasIndex(t => t.DbMarketId);
|
||||
// PlatformTradeId: legacy data up to 256 chars; new trades use shorter format
|
||||
e.Property(t => t.PlatformTradeId).HasMaxLength(256);
|
||||
// MarketId: Polymarket ConditionId is always 66 hex chars
|
||||
e.Property(t => t.MarketId).HasMaxLength(66);
|
||||
// AssetId: clobTokenId; Polymarket uses decimal strings up to 78 chars
|
||||
e.Property(t => t.AssetId).HasMaxLength(80);
|
||||
// Outcome: labels can be long (e.g. anime titles or sports match descriptions)
|
||||
e.Property(t => t.Outcome).HasMaxLength(128);
|
||||
// Price: 0.00–1.00 on prediction markets, 6 decimals sufficient
|
||||
e.Property(t => t.Price).HasPrecision(10, 6);
|
||||
// Size: number of shares, needs more integer digits
|
||||
e.Property(t => t.Size).HasPrecision(14, 6);
|
||||
e.Property(t => t.Amount).HasPrecision(18, 4);
|
||||
// TransactionHash: 0x + 64 hex = 66 chars
|
||||
e.Property(t => t.TransactionHash).HasMaxLength(66);
|
||||
e.HasOne(t => t.Trader).WithMany(tr => tr.Trades).HasForeignKey(t => t.TraderId);
|
||||
e.HasOne(t => t.MarketOutcome).WithMany().HasForeignKey(t => t.MarketOutcomeId)
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
e.HasOne(t => t.DbMarket).WithMany().HasForeignKey(t => t.DbMarketId)
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
});
|
||||
|
||||
// Market
|
||||
mb.Entity<Market>(e =>
|
||||
{
|
||||
e.HasKey(m => m.Id);
|
||||
e.HasIndex(m => new { m.Platform, m.PlatformMarketId }).IsUnique();
|
||||
e.Property(m => m.PlatformMarketId).HasMaxLength(256);
|
||||
e.Property(m => m.MarketSlug).HasMaxLength(512);
|
||||
e.Property(m => m.EventSlug).HasMaxLength(512);
|
||||
e.Property(m => m.Question).HasMaxLength(1024);
|
||||
e.Property(m => m.Description).HasMaxLength(4096);
|
||||
e.Property(m => m.ImageUrl).HasMaxLength(1024);
|
||||
e.Property(m => m.Category).HasMaxLength(128);
|
||||
e.Property(m => m.Volume).HasPrecision(18, 4);
|
||||
e.Property(m => m.Liquidity).HasPrecision(18, 4);
|
||||
e.HasMany(m => m.Outcomes).WithOne(o => o.Market).HasForeignKey(o => o.MarketId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
// MarketOutcome
|
||||
mb.Entity<MarketOutcome>(e =>
|
||||
{
|
||||
e.HasKey(o => o.Id);
|
||||
e.HasIndex(o => o.TokenId);
|
||||
e.HasIndex(o => new { o.MarketId, o.OutcomeIndex }).IsUnique();
|
||||
e.Property(o => o.Label).HasMaxLength(256);
|
||||
e.Property(o => o.TokenId).HasMaxLength(256);
|
||||
e.Property(o => o.CurrentPrice).HasPrecision(18, 8);
|
||||
});
|
||||
|
||||
// TraderScore
|
||||
mb.Entity<TraderScore>(e =>
|
||||
{
|
||||
e.HasKey(s => s.Id);
|
||||
e.Property(s => s.ActivityScore).HasPrecision(8, 4);
|
||||
e.Property(s => s.QualityScore).HasPrecision(8, 4);
|
||||
e.Property(s => s.CombinedScore).HasPrecision(8, 4);
|
||||
e.Property(s => s.VolumeScore).HasPrecision(8, 4);
|
||||
e.Property(s => s.TimingScore).HasPrecision(8, 4);
|
||||
});
|
||||
|
||||
// WatchlistEntry
|
||||
mb.Entity<WatchlistEntry>(e =>
|
||||
{
|
||||
e.HasKey(w => w.Id);
|
||||
e.HasIndex(w => w.TraderId).IsUnique();
|
||||
e.Property(w => w.Label).HasMaxLength(256);
|
||||
e.HasOne(w => w.Trader).WithMany(t => t.WatchlistEntries).HasForeignKey(w => w.TraderId);
|
||||
});
|
||||
|
||||
// Alert
|
||||
mb.Entity<Alert>(e =>
|
||||
{
|
||||
e.HasKey(a => a.Id);
|
||||
e.HasIndex(a => a.CreatedAt);
|
||||
e.Property(a => a.Title).HasMaxLength(512);
|
||||
e.Property(a => a.Message).HasMaxLength(4096);
|
||||
e.HasOne(a => a.Trader).WithMany().HasForeignKey(a => a.TraderId).OnDelete(DeleteBehavior.SetNull);
|
||||
});
|
||||
|
||||
// PlatformConfig
|
||||
mb.Entity<PlatformConfig>(e =>
|
||||
{
|
||||
e.HasKey(p => p.Id);
|
||||
e.Property(p => p.Name).HasMaxLength(128);
|
||||
e.Property(p => p.DisplayName).HasMaxLength(256);
|
||||
e.Property(p => p.BaseUrl).HasMaxLength(1024);
|
||||
});
|
||||
|
||||
// TraderAnalytics
|
||||
mb.Entity<TraderAnalytics>(e =>
|
||||
{
|
||||
e.HasKey(a => a.TraderId);
|
||||
e.Property(a => a.OverallPnL).HasPrecision(18, 4);
|
||||
e.Property(a => a.OverallWinRate).HasPrecision(8, 4);
|
||||
e.Property(a => a.PnL30d).HasPrecision(18, 4);
|
||||
e.Property(a => a.WinRate30d).HasPrecision(8, 4);
|
||||
e.Property(a => a.PnL7d).HasPrecision(18, 4);
|
||||
e.Property(a => a.WinRate7d).HasPrecision(8, 4);
|
||||
e.Property(a => a.PnL24h).HasPrecision(18, 4);
|
||||
e.Property(a => a.WinRate24h).HasPrecision(8, 4);
|
||||
});
|
||||
|
||||
// MarketAnalytics
|
||||
mb.Entity<MarketAnalytics>(e =>
|
||||
{
|
||||
e.HasKey(a => a.MarketId);
|
||||
e.Property(a => a.BotActivityScore).HasPrecision(8, 4);
|
||||
e.Property(a => a.AverageTradeSize).HasPrecision(18, 4);
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user