Phase 6 (Stufe 3): CopyTrading-Modul auf EF/MySQL umschaltbar
- CopyTradingDbContext (mod_copytrading_* Tabellen) + Design-Time-Factory - EF-Repos: CopyTradeLog, AccountSettings, TrackedTrader, MasterTraderHistory - Neue Repo-Contracts ITrackedTraderRepository + IMasterTraderHistoryRepository (loest die Collection-Inkonsistenz trackers/tracked_traders auf eine Quelle auf) - Mongo-Impls der neuen Contracts (Uebergang) - CopyTradingModule.RegisterServices: Provider-Toggle (MySql via EF / Mongo) - StartupHydrationService + MasterTraderAnalyticsJob nutzen die Repos statt _db - InitialCopyTrading-Migration erstellt und auf MySQL angewendet Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
d8cfdbf6be
commit
8101b79cfb
@@ -0,0 +1,103 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.ChangeTracking;
|
||||
using PolyTraderSharp.Models;
|
||||
|
||||
namespace PolyTrader.Modules.CopyTrading.Persistence.Ef
|
||||
{
|
||||
/// <summary>
|
||||
/// EF-Core-Kontext für die Entitäten des Copytrading-Moduls (gleiche MySQL-DB wie der
|
||||
/// Core, eigene Tabellen mit Präfix mod_copytrading_).
|
||||
/// </summary>
|
||||
public class CopyTradingDbContext : DbContext
|
||||
{
|
||||
public CopyTradingDbContext(DbContextOptions<CopyTradingDbContext> options) : base(options) { }
|
||||
|
||||
public DbSet<ClosedTrade> ClosedTrades => Set<ClosedTrade>();
|
||||
public DbSet<TrackedTrader> Traders => Set<TrackedTrader>();
|
||||
public DbSet<CopyTradingAccountSettings> AccountSettings => Set<CopyTradingAccountSettings>();
|
||||
public DbSet<MasterTraderHistoryRecord> History => Set<MasterTraderHistoryRecord>();
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder b)
|
||||
{
|
||||
b.Ignore<ClosedTradeRow>(); // reine UI-Anzeige-Klasse
|
||||
|
||||
b.Entity<ClosedTrade>(e =>
|
||||
{
|
||||
e.ToTable("mod_copytrading_closed_trades");
|
||||
e.HasKey(x => x.TradeId);
|
||||
e.Property(x => x.TradeId).ValueGeneratedNever();
|
||||
e.Property(x => x.TokenId).HasMaxLength(120);
|
||||
e.Property(x => x.MarketSlug).HasMaxLength(300);
|
||||
e.Property(x => x.MarketQuestion).HasMaxLength(1000);
|
||||
e.Property(x => x.Outcome).HasMaxLength(200);
|
||||
e.Property(x => x.Side).HasMaxLength(10);
|
||||
e.Property(x => x.ExitReason).HasMaxLength(200);
|
||||
e.Property(x => x.EntryPrice).HasPrecision(18, 6);
|
||||
e.Property(x => x.ExitPrice).HasPrecision(18, 6);
|
||||
e.Property(x => x.Size).HasPrecision(18, 6);
|
||||
e.Property(x => x.RealizedPnl).HasPrecision(18, 6);
|
||||
e.Property(x => x.PnlPercent).HasPrecision(18, 6);
|
||||
e.Property(x => x.TotalFees).HasPrecision(18, 6);
|
||||
e.HasIndex(x => x.AccountId);
|
||||
e.HasIndex(x => x.TokenId);
|
||||
e.HasIndex(x => x.SourceTraderId);
|
||||
});
|
||||
|
||||
b.Entity<TrackedTrader>(e =>
|
||||
{
|
||||
e.ToTable("mod_copytrading_traders");
|
||||
e.HasKey(x => x.Id);
|
||||
e.Property(x => x.Id).ValueGeneratedNever();
|
||||
e.Property(x => x.WalletAddress).HasMaxLength(128);
|
||||
e.Property(x => x.DisplayName).HasMaxLength(200);
|
||||
e.Property(x => x.Category).HasMaxLength(64);
|
||||
e.Property(x => x.Description).HasMaxLength(1000);
|
||||
e.Property(x => x.Reasoning).HasMaxLength(1000);
|
||||
|
||||
var comparer = new ValueComparer<HashSet<int>>(
|
||||
(a, c) => (a == null && c == null) || (a != null && c != null && a.SetEquals(c)),
|
||||
v => v.Aggregate(0, (h, i) => HashCode.Combine(h, i)),
|
||||
v => new HashSet<int>(v));
|
||||
|
||||
e.Property(x => x.AssignedAccountIds)
|
||||
.HasConversion(
|
||||
v => JsonSerializer.Serialize(v, (JsonSerializerOptions?)null),
|
||||
v => string.IsNullOrEmpty(v) ? new HashSet<int>() : (JsonSerializer.Deserialize<HashSet<int>>(v, (JsonSerializerOptions?)null) ?? new HashSet<int>()))
|
||||
.HasColumnType("text");
|
||||
e.Property(x => x.AssignedAccountIds).Metadata.SetValueComparer(comparer);
|
||||
});
|
||||
|
||||
b.Entity<CopyTradingAccountSettings>(e =>
|
||||
{
|
||||
e.ToTable("mod_copytrading_account_settings");
|
||||
e.HasKey(x => x.AccountId);
|
||||
e.Property(x => x.AccountId).ValueGeneratedNever();
|
||||
e.Property(x => x.PerMarketLimit).HasPrecision(18, 6);
|
||||
e.Property(x => x.MaxPriceDifference).HasPrecision(18, 6);
|
||||
e.Property(x => x.MaxBuyPrice).HasPrecision(18, 6);
|
||||
e.Property(x => x.ProfitTarget).HasPrecision(18, 6);
|
||||
e.Property(x => x.PreRedeemLimit).HasPrecision(18, 6);
|
||||
e.Property(x => x.PerMasterLimit).HasPrecision(18, 6);
|
||||
e.Property(x => x.perMaxTime6h).HasPrecision(18, 6);
|
||||
e.Property(x => x.perMaxTime24h).HasPrecision(18, 6);
|
||||
e.Property(x => x.perMaxTime72h).HasPrecision(18, 6);
|
||||
e.Property(x => x.perMaxTimeNone).HasPrecision(18, 6);
|
||||
});
|
||||
|
||||
b.Entity<MasterTraderHistoryRecord>(e =>
|
||||
{
|
||||
e.ToTable("mod_copytrading_mt_history");
|
||||
e.HasKey(x => x.Id);
|
||||
e.Property(x => x.Id).HasMaxLength(64);
|
||||
e.Property(x => x.TokenId).HasMaxLength(120);
|
||||
e.Property(x => x.RealizedPnl).HasPrecision(18, 6);
|
||||
e.HasIndex(x => x.TraderId);
|
||||
e.HasIndex(x => x.ClosedAt);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Design;
|
||||
|
||||
namespace PolyTrader.Modules.CopyTrading.Persistence.Ef
|
||||
{
|
||||
/// <summary>
|
||||
/// Design-Time-Factory für EF-Tooling. Connection über Umgebungsvariable POLYTRADER_MYSQL
|
||||
/// (keine Zugangsdaten im Code/Repo).
|
||||
/// </summary>
|
||||
public class CopyTradingDbContextFactory : IDesignTimeDbContextFactory<CopyTradingDbContext>
|
||||
{
|
||||
public CopyTradingDbContext CreateDbContext(string[] args)
|
||||
{
|
||||
var conn = Environment.GetEnvironmentVariable("POLYTRADER_MYSQL")
|
||||
?? "Server=localhost;Port=3306;Database=polytrader;User ID=root;Password=;";
|
||||
|
||||
var options = new DbContextOptionsBuilder<CopyTradingDbContext>()
|
||||
.UseMySql(conn, ServerVersion.AutoDetect(conn))
|
||||
.Options;
|
||||
|
||||
return new CopyTradingDbContext(options);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using PolyTraderSharp.Models;
|
||||
|
||||
namespace PolyTrader.Modules.CopyTrading.Persistence.Ef
|
||||
{
|
||||
public class EfCopyTradeLogRepository : ICopyTradeLogRepository
|
||||
{
|
||||
private readonly IDbContextFactory<CopyTradingDbContext> _factory;
|
||||
|
||||
public EfCopyTradeLogRepository(IDbContextFactory<CopyTradingDbContext> factory) => _factory = factory;
|
||||
|
||||
public void EnsureIndexes() { }
|
||||
|
||||
public bool Exists(int accountId, string tokenId)
|
||||
{
|
||||
using var ctx = _factory.CreateDbContext();
|
||||
return ctx.ClosedTrades.AsNoTracking().Any(x => x.AccountId == accountId && x.TokenId == tokenId);
|
||||
}
|
||||
|
||||
public void Insert(ClosedTrade trade)
|
||||
{
|
||||
using var ctx = _factory.CreateDbContext();
|
||||
ctx.ClosedTrades.Add(trade);
|
||||
ctx.SaveChanges();
|
||||
}
|
||||
|
||||
public List<ClosedTrade> Find(Expression<Func<ClosedTrade, bool>> predicate)
|
||||
{
|
||||
using var ctx = _factory.CreateDbContext();
|
||||
return ctx.ClosedTrades.AsNoTracking().Where(predicate).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using PolyTraderSharp.Models;
|
||||
|
||||
namespace PolyTrader.Modules.CopyTrading.Persistence.Ef
|
||||
{
|
||||
public class EfCopyTradingAccountSettingsRepository : ICopyTradingAccountSettingsRepository
|
||||
{
|
||||
private readonly IDbContextFactory<CopyTradingDbContext> _factory;
|
||||
|
||||
public EfCopyTradingAccountSettingsRepository(IDbContextFactory<CopyTradingDbContext> factory) => _factory = factory;
|
||||
|
||||
public List<CopyTradingAccountSettings> GetAll()
|
||||
{
|
||||
using var ctx = _factory.CreateDbContext();
|
||||
return ctx.AccountSettings.AsNoTracking().ToList();
|
||||
}
|
||||
|
||||
public CopyTradingAccountSettings? Get(int accountId)
|
||||
{
|
||||
using var ctx = _factory.CreateDbContext();
|
||||
return ctx.AccountSettings.AsNoTracking().FirstOrDefault(x => x.AccountId == accountId);
|
||||
}
|
||||
|
||||
public void Upsert(CopyTradingAccountSettings settings)
|
||||
{
|
||||
using var ctx = _factory.CreateDbContext();
|
||||
var existing = ctx.AccountSettings.Find(settings.AccountId);
|
||||
if (existing == null)
|
||||
ctx.AccountSettings.Add(settings);
|
||||
else
|
||||
ctx.Entry(existing).CurrentValues.SetValues(settings);
|
||||
ctx.SaveChanges();
|
||||
}
|
||||
|
||||
public void Delete(int accountId)
|
||||
{
|
||||
using var ctx = _factory.CreateDbContext();
|
||||
var existing = ctx.AccountSettings.Find(accountId);
|
||||
if (existing != null)
|
||||
{
|
||||
ctx.AccountSettings.Remove(existing);
|
||||
ctx.SaveChanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using PolyTraderSharp.Models;
|
||||
|
||||
namespace PolyTrader.Modules.CopyTrading.Persistence.Ef
|
||||
{
|
||||
public class EfMasterTraderHistoryRepository : IMasterTraderHistoryRepository
|
||||
{
|
||||
private readonly IDbContextFactory<CopyTradingDbContext> _factory;
|
||||
|
||||
public EfMasterTraderHistoryRepository(IDbContextFactory<CopyTradingDbContext> factory) => _factory = factory;
|
||||
|
||||
public void EnsureIndexes() { }
|
||||
|
||||
public bool Exists(int traderId, string tokenId, DateTime windowStart, DateTime windowEnd)
|
||||
{
|
||||
using var ctx = _factory.CreateDbContext();
|
||||
return ctx.History.AsNoTracking().Any(x => x.TraderId == traderId && x.TokenId == tokenId
|
||||
&& x.ClosedAt >= windowStart && x.ClosedAt <= windowEnd);
|
||||
}
|
||||
|
||||
public void Insert(MasterTraderHistoryRecord record)
|
||||
{
|
||||
using var ctx = _factory.CreateDbContext();
|
||||
ctx.History.Add(record);
|
||||
ctx.SaveChanges();
|
||||
}
|
||||
|
||||
public List<MasterTraderHistoryRecord> GetByTraderSince(int traderId, DateTime since)
|
||||
{
|
||||
using var ctx = _factory.CreateDbContext();
|
||||
return ctx.History.AsNoTracking().Where(x => x.TraderId == traderId && x.ClosedAt >= since).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using PolyTraderSharp.Models;
|
||||
|
||||
namespace PolyTrader.Modules.CopyTrading.Persistence.Ef
|
||||
{
|
||||
public class EfTrackedTraderRepository : ITrackedTraderRepository
|
||||
{
|
||||
private readonly IDbContextFactory<CopyTradingDbContext> _factory;
|
||||
|
||||
public EfTrackedTraderRepository(IDbContextFactory<CopyTradingDbContext> factory) => _factory = factory;
|
||||
|
||||
public List<TrackedTrader> GetAll()
|
||||
{
|
||||
using var ctx = _factory.CreateDbContext();
|
||||
return ctx.Traders.AsNoTracking().ToList();
|
||||
}
|
||||
|
||||
public void Upsert(TrackedTrader trader)
|
||||
{
|
||||
using var ctx = _factory.CreateDbContext();
|
||||
var existing = ctx.Traders.Find(trader.Id);
|
||||
if (existing == null)
|
||||
ctx.Traders.Add(trader);
|
||||
else
|
||||
ctx.Entry(existing).CurrentValues.SetValues(trader);
|
||||
ctx.SaveChanges();
|
||||
}
|
||||
|
||||
public void Update(TrackedTrader trader) => Upsert(trader);
|
||||
|
||||
public void Delete(int id)
|
||||
{
|
||||
using var ctx = _factory.CreateDbContext();
|
||||
var existing = ctx.Traders.Find(id);
|
||||
if (existing != null)
|
||||
{
|
||||
ctx.Traders.Remove(existing);
|
||||
ctx.SaveChanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+252
@@ -0,0 +1,252 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using PolyTrader.Modules.CopyTrading.Persistence.Ef;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace PolyTrader.Modules.CopyTrading.Persistence.Ef.Migrations
|
||||
{
|
||||
[DbContext(typeof(CopyTradingDbContext))]
|
||||
[Migration("20260705120059_InitialCopyTrading")]
|
||||
partial class InitialCopyTrading
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "8.0.13")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||
|
||||
MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("PolyTraderSharp.Models.ClosedTrade", b =>
|
||||
{
|
||||
b.Property<int>("TradeId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("AccountId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<DateTime>("ClosedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<decimal>("EntryPrice")
|
||||
.HasPrecision(18, 6)
|
||||
.HasColumnType("decimal(18,6)");
|
||||
|
||||
b.Property<decimal>("ExitPrice")
|
||||
.HasPrecision(18, 6)
|
||||
.HasColumnType("decimal(18,6)");
|
||||
|
||||
b.Property<string>("ExitReason")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("varchar(200)");
|
||||
|
||||
b.Property<bool>("IsDemo")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("MarketQuestion")
|
||||
.IsRequired()
|
||||
.HasMaxLength(1000)
|
||||
.HasColumnType("varchar(1000)");
|
||||
|
||||
b.Property<string>("MarketSlug")
|
||||
.IsRequired()
|
||||
.HasMaxLength(300)
|
||||
.HasColumnType("varchar(300)");
|
||||
|
||||
b.Property<DateTime>("OpenedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("Outcome")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("varchar(200)");
|
||||
|
||||
b.Property<decimal>("PnlPercent")
|
||||
.HasPrecision(18, 6)
|
||||
.HasColumnType("decimal(18,6)");
|
||||
|
||||
b.Property<decimal>("RealizedPnl")
|
||||
.HasPrecision(18, 6)
|
||||
.HasColumnType("decimal(18,6)");
|
||||
|
||||
b.Property<string>("Side")
|
||||
.IsRequired()
|
||||
.HasMaxLength(10)
|
||||
.HasColumnType("varchar(10)");
|
||||
|
||||
b.Property<decimal>("Size")
|
||||
.HasPrecision(18, 6)
|
||||
.HasColumnType("decimal(18,6)");
|
||||
|
||||
b.Property<int>("SourceTraderId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("TokenId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(120)
|
||||
.HasColumnType("varchar(120)");
|
||||
|
||||
b.Property<decimal>("TotalFees")
|
||||
.HasPrecision(18, 6)
|
||||
.HasColumnType("decimal(18,6)");
|
||||
|
||||
b.HasKey("TradeId");
|
||||
|
||||
b.HasIndex("AccountId");
|
||||
|
||||
b.HasIndex("SourceTraderId");
|
||||
|
||||
b.HasIndex("TokenId");
|
||||
|
||||
b.ToTable("mod_copytrading_closed_trades", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PolyTraderSharp.Models.CopyTradingAccountSettings", b =>
|
||||
{
|
||||
b.Property<int>("AccountId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<decimal>("MaxBuyPrice")
|
||||
.HasPrecision(18, 6)
|
||||
.HasColumnType("decimal(18,6)");
|
||||
|
||||
b.Property<decimal>("MaxPriceDifference")
|
||||
.HasPrecision(18, 6)
|
||||
.HasColumnType("decimal(18,6)");
|
||||
|
||||
b.Property<decimal>("PerMarketLimit")
|
||||
.HasPrecision(18, 6)
|
||||
.HasColumnType("decimal(18,6)");
|
||||
|
||||
b.Property<decimal>("PerMasterLimit")
|
||||
.HasPrecision(18, 6)
|
||||
.HasColumnType("decimal(18,6)");
|
||||
|
||||
b.Property<decimal>("PreRedeemLimit")
|
||||
.HasPrecision(18, 6)
|
||||
.HasColumnType("decimal(18,6)");
|
||||
|
||||
b.Property<decimal>("ProfitTarget")
|
||||
.HasPrecision(18, 6)
|
||||
.HasColumnType("decimal(18,6)");
|
||||
|
||||
b.Property<decimal>("perMaxTime24h")
|
||||
.HasPrecision(18, 6)
|
||||
.HasColumnType("decimal(18,6)");
|
||||
|
||||
b.Property<decimal>("perMaxTime6h")
|
||||
.HasPrecision(18, 6)
|
||||
.HasColumnType("decimal(18,6)");
|
||||
|
||||
b.Property<decimal>("perMaxTime72h")
|
||||
.HasPrecision(18, 6)
|
||||
.HasColumnType("decimal(18,6)");
|
||||
|
||||
b.Property<decimal>("perMaxTimeNone")
|
||||
.HasPrecision(18, 6)
|
||||
.HasColumnType("decimal(18,6)");
|
||||
|
||||
b.HasKey("AccountId");
|
||||
|
||||
b.ToTable("mod_copytrading_account_settings", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PolyTraderSharp.Models.MasterTraderHistoryRecord", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("varchar(64)");
|
||||
|
||||
b.Property<DateTime>("ClosedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<decimal>("RealizedPnl")
|
||||
.HasPrecision(18, 6)
|
||||
.HasColumnType("decimal(18,6)");
|
||||
|
||||
b.Property<string>("TokenId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(120)
|
||||
.HasColumnType("varchar(120)");
|
||||
|
||||
b.Property<int>("TraderId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ClosedAt");
|
||||
|
||||
b.HasIndex("TraderId");
|
||||
|
||||
b.ToTable("mod_copytrading_mt_history", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PolyTraderSharp.Models.TrackedTrader", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("AssignedAccountIds")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Category")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("varchar(64)");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasMaxLength(1000)
|
||||
.HasColumnType("varchar(1000)");
|
||||
|
||||
b.Property<string>("DisplayName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("varchar(200)");
|
||||
|
||||
b.Property<bool>("IsActive")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("IsHidden")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("Reasoning")
|
||||
.IsRequired()
|
||||
.HasMaxLength(1000)
|
||||
.HasColumnType("varchar(1000)");
|
||||
|
||||
b.Property<double>("TotalPnl")
|
||||
.HasColumnType("double");
|
||||
|
||||
b.Property<int>("TotalTrades")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("WalletAddress")
|
||||
.IsRequired()
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("varchar(128)");
|
||||
|
||||
b.Property<int>("WinningTrades")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<double>("Winrate30t")
|
||||
.HasColumnType("double");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("mod_copytrading_traders", (string)null);
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
+164
@@ -0,0 +1,164 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace PolyTrader.Modules.CopyTrading.Persistence.Ef.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class InitialCopyTrading : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AlterDatabase()
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "mod_copytrading_account_settings",
|
||||
columns: table => new
|
||||
{
|
||||
AccountId = table.Column<int>(type: "int", nullable: false),
|
||||
PerMarketLimit = table.Column<decimal>(type: "decimal(18,6)", precision: 18, scale: 6, nullable: false),
|
||||
MaxPriceDifference = table.Column<decimal>(type: "decimal(18,6)", precision: 18, scale: 6, nullable: false),
|
||||
MaxBuyPrice = table.Column<decimal>(type: "decimal(18,6)", precision: 18, scale: 6, nullable: false),
|
||||
ProfitTarget = table.Column<decimal>(type: "decimal(18,6)", precision: 18, scale: 6, nullable: false),
|
||||
PreRedeemLimit = table.Column<decimal>(type: "decimal(18,6)", precision: 18, scale: 6, nullable: false),
|
||||
PerMasterLimit = table.Column<decimal>(type: "decimal(18,6)", precision: 18, scale: 6, nullable: false),
|
||||
perMaxTime6h = table.Column<decimal>(type: "decimal(18,6)", precision: 18, scale: 6, nullable: false),
|
||||
perMaxTime24h = table.Column<decimal>(type: "decimal(18,6)", precision: 18, scale: 6, nullable: false),
|
||||
perMaxTime72h = table.Column<decimal>(type: "decimal(18,6)", precision: 18, scale: 6, nullable: false),
|
||||
perMaxTimeNone = table.Column<decimal>(type: "decimal(18,6)", precision: 18, scale: 6, nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_mod_copytrading_account_settings", x => x.AccountId);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "mod_copytrading_closed_trades",
|
||||
columns: table => new
|
||||
{
|
||||
TradeId = table.Column<int>(type: "int", nullable: false),
|
||||
AccountId = table.Column<int>(type: "int", nullable: false),
|
||||
SourceTraderId = table.Column<int>(type: "int", nullable: false),
|
||||
IsDemo = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||
TokenId = table.Column<string>(type: "varchar(120)", maxLength: 120, nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
MarketSlug = table.Column<string>(type: "varchar(300)", maxLength: 300, nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
MarketQuestion = table.Column<string>(type: "varchar(1000)", maxLength: 1000, nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Outcome = table.Column<string>(type: "varchar(200)", maxLength: 200, nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Side = table.Column<string>(type: "varchar(10)", maxLength: 10, nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
EntryPrice = table.Column<decimal>(type: "decimal(18,6)", precision: 18, scale: 6, nullable: false),
|
||||
ExitPrice = table.Column<decimal>(type: "decimal(18,6)", precision: 18, scale: 6, nullable: false),
|
||||
Size = table.Column<decimal>(type: "decimal(18,6)", precision: 18, scale: 6, nullable: false),
|
||||
RealizedPnl = table.Column<decimal>(type: "decimal(18,6)", precision: 18, scale: 6, nullable: false),
|
||||
PnlPercent = table.Column<decimal>(type: "decimal(18,6)", precision: 18, scale: 6, nullable: false),
|
||||
TotalFees = table.Column<decimal>(type: "decimal(18,6)", precision: 18, scale: 6, nullable: false),
|
||||
OpenedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
||||
ClosedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
||||
ExitReason = table.Column<string>(type: "varchar(200)", maxLength: 200, nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_mod_copytrading_closed_trades", x => x.TradeId);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "mod_copytrading_mt_history",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(type: "varchar(64)", maxLength: 64, nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
TraderId = table.Column<int>(type: "int", nullable: false),
|
||||
TokenId = table.Column<string>(type: "varchar(120)", maxLength: 120, nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
RealizedPnl = table.Column<decimal>(type: "decimal(18,6)", precision: 18, scale: 6, nullable: false),
|
||||
ClosedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_mod_copytrading_mt_history", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "mod_copytrading_traders",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false),
|
||||
WalletAddress = table.Column<string>(type: "varchar(128)", maxLength: 128, nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
DisplayName = table.Column<string>(type: "varchar(200)", maxLength: 200, nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Category = table.Column<string>(type: "varchar(64)", maxLength: 64, nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Description = table.Column<string>(type: "varchar(1000)", maxLength: 1000, nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Reasoning = table.Column<string>(type: "varchar(1000)", maxLength: 1000, nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
IsActive = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||
IsHidden = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||
TotalTrades = table.Column<int>(type: "int", nullable: false),
|
||||
WinningTrades = table.Column<int>(type: "int", nullable: false),
|
||||
Winrate30t = table.Column<double>(type: "double", nullable: false),
|
||||
TotalPnl = table.Column<double>(type: "double", nullable: false),
|
||||
AssignedAccountIds = table.Column<string>(type: "text", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_mod_copytrading_traders", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_mod_copytrading_closed_trades_AccountId",
|
||||
table: "mod_copytrading_closed_trades",
|
||||
column: "AccountId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_mod_copytrading_closed_trades_SourceTraderId",
|
||||
table: "mod_copytrading_closed_trades",
|
||||
column: "SourceTraderId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_mod_copytrading_closed_trades_TokenId",
|
||||
table: "mod_copytrading_closed_trades",
|
||||
column: "TokenId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_mod_copytrading_mt_history_ClosedAt",
|
||||
table: "mod_copytrading_mt_history",
|
||||
column: "ClosedAt");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_mod_copytrading_mt_history_TraderId",
|
||||
table: "mod_copytrading_mt_history",
|
||||
column: "TraderId");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "mod_copytrading_account_settings");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "mod_copytrading_closed_trades");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "mod_copytrading_mt_history");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "mod_copytrading_traders");
|
||||
}
|
||||
}
|
||||
}
|
||||
+249
@@ -0,0 +1,249 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using PolyTrader.Modules.CopyTrading.Persistence.Ef;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace PolyTrader.Modules.CopyTrading.Persistence.Ef.Migrations
|
||||
{
|
||||
[DbContext(typeof(CopyTradingDbContext))]
|
||||
partial class CopyTradingDbContextModelSnapshot : ModelSnapshot
|
||||
{
|
||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "8.0.13")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||
|
||||
MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("PolyTraderSharp.Models.ClosedTrade", b =>
|
||||
{
|
||||
b.Property<int>("TradeId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("AccountId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<DateTime>("ClosedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<decimal>("EntryPrice")
|
||||
.HasPrecision(18, 6)
|
||||
.HasColumnType("decimal(18,6)");
|
||||
|
||||
b.Property<decimal>("ExitPrice")
|
||||
.HasPrecision(18, 6)
|
||||
.HasColumnType("decimal(18,6)");
|
||||
|
||||
b.Property<string>("ExitReason")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("varchar(200)");
|
||||
|
||||
b.Property<bool>("IsDemo")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("MarketQuestion")
|
||||
.IsRequired()
|
||||
.HasMaxLength(1000)
|
||||
.HasColumnType("varchar(1000)");
|
||||
|
||||
b.Property<string>("MarketSlug")
|
||||
.IsRequired()
|
||||
.HasMaxLength(300)
|
||||
.HasColumnType("varchar(300)");
|
||||
|
||||
b.Property<DateTime>("OpenedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("Outcome")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("varchar(200)");
|
||||
|
||||
b.Property<decimal>("PnlPercent")
|
||||
.HasPrecision(18, 6)
|
||||
.HasColumnType("decimal(18,6)");
|
||||
|
||||
b.Property<decimal>("RealizedPnl")
|
||||
.HasPrecision(18, 6)
|
||||
.HasColumnType("decimal(18,6)");
|
||||
|
||||
b.Property<string>("Side")
|
||||
.IsRequired()
|
||||
.HasMaxLength(10)
|
||||
.HasColumnType("varchar(10)");
|
||||
|
||||
b.Property<decimal>("Size")
|
||||
.HasPrecision(18, 6)
|
||||
.HasColumnType("decimal(18,6)");
|
||||
|
||||
b.Property<int>("SourceTraderId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("TokenId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(120)
|
||||
.HasColumnType("varchar(120)");
|
||||
|
||||
b.Property<decimal>("TotalFees")
|
||||
.HasPrecision(18, 6)
|
||||
.HasColumnType("decimal(18,6)");
|
||||
|
||||
b.HasKey("TradeId");
|
||||
|
||||
b.HasIndex("AccountId");
|
||||
|
||||
b.HasIndex("SourceTraderId");
|
||||
|
||||
b.HasIndex("TokenId");
|
||||
|
||||
b.ToTable("mod_copytrading_closed_trades", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PolyTraderSharp.Models.CopyTradingAccountSettings", b =>
|
||||
{
|
||||
b.Property<int>("AccountId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<decimal>("MaxBuyPrice")
|
||||
.HasPrecision(18, 6)
|
||||
.HasColumnType("decimal(18,6)");
|
||||
|
||||
b.Property<decimal>("MaxPriceDifference")
|
||||
.HasPrecision(18, 6)
|
||||
.HasColumnType("decimal(18,6)");
|
||||
|
||||
b.Property<decimal>("PerMarketLimit")
|
||||
.HasPrecision(18, 6)
|
||||
.HasColumnType("decimal(18,6)");
|
||||
|
||||
b.Property<decimal>("PerMasterLimit")
|
||||
.HasPrecision(18, 6)
|
||||
.HasColumnType("decimal(18,6)");
|
||||
|
||||
b.Property<decimal>("PreRedeemLimit")
|
||||
.HasPrecision(18, 6)
|
||||
.HasColumnType("decimal(18,6)");
|
||||
|
||||
b.Property<decimal>("ProfitTarget")
|
||||
.HasPrecision(18, 6)
|
||||
.HasColumnType("decimal(18,6)");
|
||||
|
||||
b.Property<decimal>("perMaxTime24h")
|
||||
.HasPrecision(18, 6)
|
||||
.HasColumnType("decimal(18,6)");
|
||||
|
||||
b.Property<decimal>("perMaxTime6h")
|
||||
.HasPrecision(18, 6)
|
||||
.HasColumnType("decimal(18,6)");
|
||||
|
||||
b.Property<decimal>("perMaxTime72h")
|
||||
.HasPrecision(18, 6)
|
||||
.HasColumnType("decimal(18,6)");
|
||||
|
||||
b.Property<decimal>("perMaxTimeNone")
|
||||
.HasPrecision(18, 6)
|
||||
.HasColumnType("decimal(18,6)");
|
||||
|
||||
b.HasKey("AccountId");
|
||||
|
||||
b.ToTable("mod_copytrading_account_settings", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PolyTraderSharp.Models.MasterTraderHistoryRecord", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("varchar(64)");
|
||||
|
||||
b.Property<DateTime>("ClosedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<decimal>("RealizedPnl")
|
||||
.HasPrecision(18, 6)
|
||||
.HasColumnType("decimal(18,6)");
|
||||
|
||||
b.Property<string>("TokenId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(120)
|
||||
.HasColumnType("varchar(120)");
|
||||
|
||||
b.Property<int>("TraderId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ClosedAt");
|
||||
|
||||
b.HasIndex("TraderId");
|
||||
|
||||
b.ToTable("mod_copytrading_mt_history", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PolyTraderSharp.Models.TrackedTrader", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("AssignedAccountIds")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Category")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("varchar(64)");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasMaxLength(1000)
|
||||
.HasColumnType("varchar(1000)");
|
||||
|
||||
b.Property<string>("DisplayName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("varchar(200)");
|
||||
|
||||
b.Property<bool>("IsActive")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("IsHidden")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("Reasoning")
|
||||
.IsRequired()
|
||||
.HasMaxLength(1000)
|
||||
.HasColumnType("varchar(1000)");
|
||||
|
||||
b.Property<double>("TotalPnl")
|
||||
.HasColumnType("double");
|
||||
|
||||
b.Property<int>("TotalTrades")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("WalletAddress")
|
||||
.IsRequired()
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("varchar(128)");
|
||||
|
||||
b.Property<int>("WinningTrades")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<double>("Winrate30t")
|
||||
.HasColumnType("double");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("mod_copytrading_traders", (string)null);
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user