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:
co-authored by
Claude Opus 4.8
parent
92a88e8be8
commit
38f609ed31
@@ -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 (0–1)")]
|
||||
[Description("Absolute Preis-Obergrenze pro Share auf der 0–1-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 6–24h 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 24–72h 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 (0–1)")]
|
||||
[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 0–1-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 =>
|
||||
|
||||
+270
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
+83
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user