CopyTrading Slice 1: Settings-Fundament + detaillierte Erklärungen

Umsetzung des Fable-Plans, Start mit dem risikoarmen Settings-Fundament
(kein Hot-Path/CLOB-Verhalten geändert):

- Alle Copytrading-Settings (alt + neu) haben jetzt [Description]/[DisplayName] ->
  im PropertyGrid als Erklärung sichtbar (Richards Vorgabe). Test erzwingt, dass
  jede einstellbare Option eine Beschreibung trägt.
- ProfitTarget-Default -> 9999 (praktisch deaktiviert); Migration setzt zusätzlich
  bestehende Zeilen per SQL auf 9999 (Entscheidung 2). Take-Profit-LOGIK folgt.
- Neue Account-Settings (noch nicht verdrahtet, für Phase 0.1/1.3/2):
  SellFloorPct (15), MaxSpreadPct (5), MinSellRatioPct (10).
- Neue Master-Trader-Settings: AutoPauseEnabled (Default AN, per Master abschaltbar,
  Entscheidung 3) + MakerEntry (Default aus, Entscheidung 4).
- EF-Migration AddCopytradingBehaviorSettings (neue Spalten + sinnvolle Defaults
  fuer Bestandszeilen) erstellt und auf MySQL angewendet.
- Erklärung dokumentiert einen gefundenen Skalen-Verdacht: PreRedeemLimit wird
  gegen den 0-1-Preis verglichen; Alt-Werte 99.5 triggern nie (-> ggf. 0.995).

Tests: 86 gruen. Build/Smoke gruen.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-07-07 09:44:50 +02:00
co-authored by Claude Opus 4.8
parent 92a88e8be8
commit 38f609ed31
8 changed files with 546 additions and 13 deletions
@@ -7,6 +7,9 @@ namespace PolyTraderSharp.Models
/// Bewusst getrennt vom Core-<see cref="AccountState"/> (allgemeine Account-Daten):
/// Diese Werte gehören dem Copytrading-Modul und werden im Modul-View bearbeitet.
/// Persistiert in Tabelle "mod_copytrading_account_settings" (Key = AccountId).
///
/// Die [Description]-Attribute erscheinen im PropertyGrid als Erklärung bitte bei
/// jeder Verhaltensänderung mitpflegen, damit die Bedeutung nachvollziehbar bleibt.
/// </summary>
public class CopyTradingAccountSettings
{
@@ -14,33 +17,86 @@ namespace PolyTraderSharp.Models
public int AccountId { get; set; }
[Category("01. Risk Management")]
[DisplayName("Limit pro Markt (%)")]
[Description("Maximaler Einsatz in EINEN einzelnen Markt, als Prozent des Account-Guthabens (TotalBalance). " +
"Beispiel: 5 = höchstens 5 % des Guthabens in einem Markt. Begrenzt das Klumpenrisiko pro Markt.")]
public decimal PerMarketLimit { get; set; } = 5.0m;
[Category("01. Risk Management")]
public decimal MaxPriceDifference { get; set; } = 2.0m;
[DisplayName("Limit pro Master (%)")]
[Description("Maximaler gleichzeitiger Gesamteinsatz in Trades EINES Master-Traders, als Prozent des Guthabens. " +
"Beispiel: 10 = höchstens 10 % des Guthabens gleichzeitig einem Master folgen. Begrenzt den Schaden, " +
"wenn ein einzelner Master schlecht läuft.")]
public decimal PerMasterLimit { get; set; } = 10.0m;
[Category("01. Risk Management")]
[DisplayName("Max. Kaufpreis (01)")]
[Description("Absolute Preis-Obergrenze pro Share auf der 01-Skala (1.00 = 100 ¢). Kauf wird übersprungen, wenn der " +
"Master über diesem Preis kauft; zusätzlich wird unser Limitpreis hierauf gedeckelt. " +
"Beispiel: 0.98 = nichts über 98 ¢ kaufen (nahe 1.00 ist das Aufwärtspotenzial gering, das Risiko asymmetrisch).")]
public decimal MaxBuyPrice { get; set; } = 0.98m;
[Category("01. Risk Management")]
public decimal ProfitTarget { get; set; } = 50.0m;
[DisplayName("Max. Preisaufschlag BUY (%)")]
[Description("Wie viel Prozent ÜBER dem Einstiegspreis des Masters wir beim BUY maximal limitieren, um einen Fill zu " +
"bekommen (gedeckelt durch 'Max. Kaufpreis'). Beispiel: 2 = unser Limit liegt 2 % über dem Master-Preis. " +
"Höher = mehr/schnellere Fills, aber schlechtere Einstiegspreise (mehr Slippage).")]
public decimal MaxPriceDifference { get; set; } = 2.0m;
[Category("01. Risk Management")]
public decimal PreRedeemLimit { get; set; } = 0.0m;
[Category("01. Risk Management")]
public decimal PerMasterLimit { get; set; } = 10.0m;
[Category("02. Time Limits")]
[Category("02. Time Limits (Exposure nach Restlaufzeit)")]
[DisplayName("Limit < 6h Restlaufzeit (%)")]
[Description("Exposure-Deckel für Märkte, die in WENIGER als 6 Stunden auflaufen (Zeit bis Marktschluss), als Prozent " +
"des Guthabens. Die Summe aller offenen Positionen in dieser Zeitklasse darf diesen Anteil nicht übersteigen. " +
"Schnell auflaufende Märkte sind binärer/riskanter daher meist niedriger.")]
public decimal perMaxTime6h { get; set; } = 20.0m;
[Category("02. Time Limits")]
[Category("02. Time Limits (Exposure nach Restlaufzeit)")]
[DisplayName("Limit 624h Restlaufzeit (%)")]
[Description("Exposure-Deckel für Märkte, die in 6 bis 24 Stunden auflaufen, als Prozent des Guthabens.")]
public decimal perMaxTime24h { get; set; } = 20.0m;
[Category("02. Time Limits")]
[Category("02. Time Limits (Exposure nach Restlaufzeit)")]
[DisplayName("Limit 2472h Restlaufzeit (%)")]
[Description("Exposure-Deckel für Märkte, die in 24 bis 72 Stunden auflaufen, als Prozent des Guthabens.")]
public decimal perMaxTime72h { get; set; } = 20.0m;
[Category("02. Time Limits")]
[Category("02. Time Limits (Exposure nach Restlaufzeit)")]
[DisplayName("Limit > 72h / kein Enddatum (%)")]
[Description("Exposure-Deckel für Märkte, die in MEHR als 72 Stunden auflaufen oder kein Enddatum haben, als Prozent " +
"des Guthabens. Meist höher, da mehr Zeit zur Erholung bleibt.")]
public decimal perMaxTimeNone { get; set; } = 40.0m;
[Category("03. Exit / Take-Profit")]
[DisplayName("Take-Profit (% Gewinn)")]
[Description("Take-Profit-Schwelle in Prozent Gewinn: erreicht der aktuelle Preis >= Einstiegspreis × (1 + Wert/100), " +
"wird verkauft. AKTUELL PROJEKTWEIT AUF 9999 = praktisch deaktiviert (Entscheidung: erst implementieren, " +
"dann bewusst scharf schalten). Die Verkaufslogik folgt in Phase 0.3 (über die SELL-Eskalationsleiter).")]
public decimal ProfitTarget { get; set; } = 9999m;
[Category("03. Exit / Take-Profit")]
[DisplayName("Pre-Redeem-Schwelle (01)")]
[Description("Auto-Redeem: erreicht der Marktpreis diesen Wert, wird die Position vorzeitig glattgestellt (near-resolution, " +
"spart das Warten bis zur Auflösung). 0 = deaktiviert. WICHTIG: Der Code vergleicht gegen den 01-Preis " +
"(z. B. 0.995 = 99,5 ¢). Migrierte Alt-Werte wie 99.5 triggern NIE und sollten auf z. B. 0.995 korrigiert werden.")]
public decimal PreRedeemLimit { get; set; } = 0.0m;
[Category("03. Exit / Take-Profit")]
[DisplayName("SELL-Floor (%) [Phase 0.1]")]
[Description("Untergrenze der SELL-Eskalationsleiter: absoluter Mindest-Verkaufspreis = Master-Exit-Preis × (1 Wert/100). " +
"Unterhalb wird NICHT mehr verkauft, sondern die Position gehalten + Benachrichtigung. Schützt davor, in ein " +
"leergeräumtes Orderbuch als 'Exit-Liquidity' zu verkaufen. NOCH NICHT VERDRAHTET (Phase 0.1).")]
public decimal SellFloorPct { get; set; } = 15.0m;
[Category("04. Orderbuch / Ausführung")]
[DisplayName("Max. Spread BUY (%) [Phase 1.3]")]
[Description("Pre-Trade-Orderbuch-Check: ist der Spread (Ask Bid) breiter als dieser Prozentsatz, wird der BUY " +
"übersprungen (illiquider/riskanter Markt, Sniping-Verdacht). NOCH NICHT VERDRAHTET (Phase 1.3).")]
public decimal MaxSpreadPct { get; set; } = 5.0m;
[Category("04. Orderbuch / Ausführung")]
[DisplayName("Min. Verkaufsquote (%) [Phase 2]")]
[Description("Mindest-Verkaufsquote des Masters, ab der wir einen Teilverkauf spiegeln. Verkäufe unter dieser Quote gelten " +
"als Rauschen (Day-Trader-Zappeln) und werden ignoriert. NOCH NICHT VERDRAHTET (Phase 2).")]
public decimal MinSellRatioPct { get; set; } = 10.0m;
}
}
@@ -4,49 +4,96 @@ using System.Collections.Generic;
namespace PolyTraderSharp.Models
{
/// <summary>
/// Ein überwachter Master-Trader, dessen Trades kopiert werden. Neben Identifikation und
/// Statistik enthält er per-Master-Verhaltenseinstellungen (Auto-Pause, Maker-Einstieg).
/// Die [Description]-Attribute erscheinen im PropertyGrid als Erklärung.
/// </summary>
public class TrackedTrader
{
[Browsable(false)]
public int Id { get; set; }
[Category("01. Identification")]
[DisplayName("Wallet-Adresse")]
[Description("Polygon-Wallet des Master-Traders. Diese Adresse wird on-chain (Alchemy-WSS) auf Käufe/Verkäufe überwacht.")]
public string WalletAddress { get; set; } = string.Empty;
[Category("01. Identification")]
[DisplayName("Anzeigename")]
[Description("Frei wählbarer Name zur Wiedererkennung in UI und Logs.")]
public string DisplayName { get; set; } = string.Empty;
[Category("02. Categorization")]
[DisplayName("Kategorie")]
[Description("Einordnung des Master-Typs (z. B. HF, INSIDER, SNIPER, HOLDER). Beeinflusst teils das Verhalten " +
"(z. B. engere SELL-Limits für 'HF'). Frei setzbar; für Verhaltensregeln bitte konsistente Werte verwenden.")]
public string Category { get; set; } = "NEW_BIG_BET";
[Category("02. Categorization")]
[DisplayName("Beschreibung")]
[Description("Freitext-Notiz zum Master (z. B. Herkunft, beobachtete Stärken/Schwächen).")]
public string Description { get; set; } = string.Empty;
[Category("02. Categorization")]
[DisplayName("Begründung / Reasoning")]
[Description("Warum kopieren wir diesen Master? Wird auch vom Auto-Kill-Switch mit Zeitstempel befüllt, wenn er " +
"automatisch pausiert wird (Phase 3.3).")]
public string Reasoning { get; set; } = string.Empty;
[Category("03. General")]
[DisplayName("Aktiv")]
[Description("Nur aktive Master werden kopiert und on-chain überwacht. Wird bei ausgelöster Auto-Pause automatisch " +
"auf 'false' gesetzt; Reaktivierung erfolgt bewusst nur manuell.")]
public bool IsActive { get; set; } = true;
[Category("03. General")]
[DisplayName("Ausgeblendet")]
[Description("Blendet den Master in der Standard-Ansicht aus, ohne ihn zu löschen (Archiv). Kopiert wird trotzdem nur, " +
"wenn 'Aktiv' gesetzt ist.")]
public bool IsHidden { get; set; } = false;
[Category("05. Copytrading-Verhalten")]
[DisplayName("Auto-Pause aktiv")]
[Description("Kill-Switch für diesen Master: Läuft die Copy-Performance der letzten Trades unter die Schwelle, wird der " +
"Master automatisch deaktiviert (Aktiv = false) samt Benachrichtigung, damit nachts nicht weiter Verlust " +
"aufläuft. STANDARDMÄSSIG AN; für einzelne Master bewusst abschaltbar, wenn du trotz Schwäche dranbleiben " +
"willst. Reaktivierung immer manuell. (Auslöse-Logik: Phase 3.3.)")]
public bool AutoPauseEnabled { get; set; } = true;
[Category("05. Copytrading-Verhalten")]
[DisplayName("Maker-Einstieg")]
[Description("Wenn aktiv, werden BUYs als GTC-Limit AUF dem Best-Bid platziert (Maker) statt teuer über dem Ask (Taker). " +
"Sinnvoll für langsame Master (Haltedauer Stunden/Tage): spart Taker-Fees und Spread. Kein Fill nach der " +
"konfigurierten Zeit → Eskalation auf Taker oder Verwerfen. (Ausführungs-Logik: Phase 4.)")]
public bool MakerEntry { get; set; } = false;
// Stats
[Category("04. Statistics")]
[ReadOnly(true)]
[DisplayName("Trades (7 Tage)")]
[Description("Anzahl der vom Analytics-Job erfassten Master-Trades der letzten 7 Tage (Kennzahl, kein Einstellwert).")]
public int TotalTrades { get; set; } = 0;
[Category("04. Statistics")]
[ReadOnly(true)]
[DisplayName("Gewinner-Trades")]
[Description("Anzahl profitabler Master-Trades im Auswertungsfenster (Kennzahl).")]
public int WinningTrades { get; set; } = 0;
[Category("04. Statistics")]
[ReadOnly(true)]
[DisplayName("Winrate (%)")]
[Description("Anteil profitabler Trades. ACHTUNG: allein irreführend Favoriten-Käufer haben hohe Winrate und können " +
"trotzdem negativ sein. Profit-Faktor/Ø-PnL sind aussagekräftiger (Phase 3).")]
public double Winrate30t { get; set; } = 0.0;
[Category("04. Statistics")]
[ReadOnly(true)]
[DisplayName("PnL (7 Tage)")]
[Description("Realisierter Gewinn/Verlust des MASTERS im Fenster (nicht unser Copy-Ergebnis). Copy-PnL folgt in Phase 3.")]
public double TotalPnl { get; set; } = 0.0;
[Browsable(false)]
public HashSet<int> AssignedAccountIds { get; set; } = new();
}
@@ -86,6 +86,9 @@ namespace PolyTrader.Modules.CopyTrading.Persistence.Ef
e.Property(x => x.perMaxTime24h).HasPrecision(18, 6);
e.Property(x => x.perMaxTime72h).HasPrecision(18, 6);
e.Property(x => x.perMaxTimeNone).HasPrecision(18, 6);
e.Property(x => x.SellFloorPct).HasPrecision(18, 6);
e.Property(x => x.MaxSpreadPct).HasPrecision(18, 6);
e.Property(x => x.MinSellRatioPct).HasPrecision(18, 6);
});
b.Entity<MasterTraderHistoryRecord>(e =>
@@ -0,0 +1,270 @@
// <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("20260707073736_AddCopytradingBehaviorSettings")]
partial class AddCopytradingBehaviorSettings
{
/// <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>("MaxSpreadPct")
.HasPrecision(18, 6)
.HasColumnType("decimal(18,6)");
b.Property<decimal>("MinSellRatioPct")
.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>("SellFloorPct")
.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<bool>("AutoPauseEnabled")
.HasColumnType("tinyint(1)");
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<bool>("MakerEntry")
.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
}
}
}
@@ -0,0 +1,83 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace PolyTrader.Modules.CopyTrading.Persistence.Ef.Migrations
{
/// <inheritdoc />
public partial class AddCopytradingBehaviorSettings : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "AutoPauseEnabled",
table: "mod_copytrading_traders",
type: "tinyint(1)",
nullable: false,
defaultValue: true);
migrationBuilder.AddColumn<bool>(
name: "MakerEntry",
table: "mod_copytrading_traders",
type: "tinyint(1)",
nullable: false,
defaultValue: false);
migrationBuilder.AddColumn<decimal>(
name: "MaxSpreadPct",
table: "mod_copytrading_account_settings",
type: "decimal(18,6)",
precision: 18,
scale: 6,
nullable: false,
defaultValue: 5m);
migrationBuilder.AddColumn<decimal>(
name: "MinSellRatioPct",
table: "mod_copytrading_account_settings",
type: "decimal(18,6)",
precision: 18,
scale: 6,
nullable: false,
defaultValue: 10m);
migrationBuilder.AddColumn<decimal>(
name: "SellFloorPct",
table: "mod_copytrading_account_settings",
type: "decimal(18,6)",
precision: 18,
scale: 6,
nullable: false,
defaultValue: 15m);
// Entscheidung Richard: ProfitTarget zunächst überall auf 9999 (praktisch deaktiviert),
// bis die Take-Profit-Logik (Phase 0.3) scharf geschaltet wird.
migrationBuilder.Sql("UPDATE mod_copytrading_account_settings SET ProfitTarget = 9999;");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "AutoPauseEnabled",
table: "mod_copytrading_traders");
migrationBuilder.DropColumn(
name: "MakerEntry",
table: "mod_copytrading_traders");
migrationBuilder.DropColumn(
name: "MaxSpreadPct",
table: "mod_copytrading_account_settings");
migrationBuilder.DropColumn(
name: "MinSellRatioPct",
table: "mod_copytrading_account_settings");
migrationBuilder.DropColumn(
name: "SellFloorPct",
table: "mod_copytrading_account_settings");
}
}
}
@@ -120,6 +120,14 @@ namespace PolyTrader.Modules.CopyTrading.Persistence.Ef.Migrations
.HasPrecision(18, 6)
.HasColumnType("decimal(18,6)");
b.Property<decimal>("MaxSpreadPct")
.HasPrecision(18, 6)
.HasColumnType("decimal(18,6)");
b.Property<decimal>("MinSellRatioPct")
.HasPrecision(18, 6)
.HasColumnType("decimal(18,6)");
b.Property<decimal>("PerMarketLimit")
.HasPrecision(18, 6)
.HasColumnType("decimal(18,6)");
@@ -136,6 +144,10 @@ namespace PolyTrader.Modules.CopyTrading.Persistence.Ef.Migrations
.HasPrecision(18, 6)
.HasColumnType("decimal(18,6)");
b.Property<decimal>("SellFloorPct")
.HasPrecision(18, 6)
.HasColumnType("decimal(18,6)");
b.Property<decimal>("perMaxTime24h")
.HasPrecision(18, 6)
.HasColumnType("decimal(18,6)");
@@ -196,6 +208,9 @@ namespace PolyTrader.Modules.CopyTrading.Persistence.Ef.Migrations
.IsRequired()
.HasColumnType("text");
b.Property<bool>("AutoPauseEnabled")
.HasColumnType("tinyint(1)");
b.Property<string>("Category")
.IsRequired()
.HasMaxLength(64)
@@ -217,6 +232,9 @@ namespace PolyTrader.Modules.CopyTrading.Persistence.Ef.Migrations
b.Property<bool>("IsHidden")
.HasColumnType("tinyint(1)");
b.Property<bool>("MakerEntry")
.HasColumnType("tinyint(1)");
b.Property<string>("Reasoning")
.IsRequired()
.HasMaxLength(1000)