Phase 6 (Stufe 6): MongoDB vollstaendig entfernt
- Legacy-Form stillgelegt: frm_main(.Designer/.resx) + frm_analytics(.Designer/.resx) geloescht, 'Open Legacy'-Menue aus LauncherForm entfernt. - Program.cs: IMongoDatabase-Registrierung + closed_trades-Cleanup weg; Trade-Nummerierung liest jetzt hoechste TradeId aus ICopyTradeLogRepository. - StartupHydrationService: Mongo-/Bson-Fallback entfernt (Settings kommen aus dem Repo; fehlende Accounts erhalten Default-Settings). - Alle Mongo*Repository (Core 4 + Modul 4) geloescht; DI-Zweige auf EF/MySQL reduziert (AddCorePersistence, CopyTradingModule). - ConfigMigrator: Mongo-Pfad (Run/MigrateSettings) entfernt; nur noch RunFromJson + VerifyMySql (kein Mongo-Treiber mehr). - Modelle: [BsonId] entfernt (EF-Keys via HasKey); ObjectId-Defaults -> Guid. - LiteDB-Shim (MongoDbLiteDBShim) geloescht; MongoDB.Driver- + LiteDB-Pakete aus App/Core entfernt; stale usings + user-sichtbare Strings bereinigt. - DatabaseOptions/appsettings.json: Mongo-Provider/Connection-Felder entfernt. - Build gruen; --verify-mysql bestaetigt 3 Accounts/3 Settings/32 Trader/2344 Markets. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
d227d24ca8
commit
b951b912f4
@@ -1,93 +0,0 @@
|
|||||||
using System;
|
|
||||||
using MongoDB.Driver;
|
|
||||||
using PolyTraderSharp.Extensions;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Linq.Expressions;
|
|
||||||
using PolyTraderSharp.Models;
|
|
||||||
|
|
||||||
namespace PolyTraderSharp.Extensions
|
|
||||||
{
|
|
||||||
public static class MongoDbLiteDBShim
|
|
||||||
{
|
|
||||||
// 1. LiteDB: FindOne(predicate) -> MongoDB: Find(predicate).FirstOrDefault()
|
|
||||||
public static T LiteFindOne<T>(this IMongoCollection<T> col, Expression<Func<T, bool>> predicate)
|
|
||||||
{
|
|
||||||
return col.Find(predicate).FirstOrDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. LiteDB: Find(predicate) -> MongoDB: Find(predicate).ToList()
|
|
||||||
// Note: LiteDB returns IEnumerable<T>. ToList() is perfectly fine for iteration.
|
|
||||||
public static List<T> LiteFind<T>(this IMongoCollection<T> col, Expression<Func<T, bool>> predicate)
|
|
||||||
{
|
|
||||||
return col.Find(predicate).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. LiteDB: FindAll() -> MongoDB: Find(_ => true).ToList()
|
|
||||||
public static List<T> LiteFindAll<T>(this IMongoCollection<T> col)
|
|
||||||
{
|
|
||||||
return col.Find(_ => true).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. Upsert extensions mapped to Primary Keys
|
|
||||||
public static void Upsert(this IMongoCollection<AccountState> col, AccountState doc)
|
|
||||||
{
|
|
||||||
col.ReplaceOne(x => x.AccountId == doc.AccountId, doc, new ReplaceOptions { IsUpsert = true });
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Upsert(this IMongoCollection<TrackedTrader> col, TrackedTrader doc)
|
|
||||||
{
|
|
||||||
col.ReplaceOne(x => x.Id == doc.Id, doc, new ReplaceOptions { IsUpsert = true });
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Upsert(this IMongoCollection<Position> col, Position doc)
|
|
||||||
{
|
|
||||||
col.ReplaceOne(x => x.TokenId == doc.TokenId, doc, new ReplaceOptions { IsUpsert = true });
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Upsert(this IMongoCollection<MarketData> col, MarketData doc)
|
|
||||||
{
|
|
||||||
col.ReplaceOne(x => x.Id == doc.Id, doc, new ReplaceOptions { IsUpsert = true });
|
|
||||||
}
|
|
||||||
|
|
||||||
// 5. Update (Updates without upserting if it doesn't exist)
|
|
||||||
public static void Update(this IMongoCollection<TrackedTrader> col, TrackedTrader doc)
|
|
||||||
{
|
|
||||||
col.ReplaceOne(x => x.Id == doc.Id, doc);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Update(this IMongoCollection<AccountState> col, AccountState doc)
|
|
||||||
{
|
|
||||||
col.ReplaceOne(x => x.AccountId == doc.AccountId, doc);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Update(this IMongoCollection<MarketData> col, MarketData doc)
|
|
||||||
{
|
|
||||||
col.ReplaceOne(x => x.Id == doc.Id, doc);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 6. Insert maps perfectly to InsertOne
|
|
||||||
public static void Insert<T>(this IMongoCollection<T> col, T doc)
|
|
||||||
{
|
|
||||||
col.InsertOne(doc);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 7. Delete (by TokenId / String ID)
|
|
||||||
public static void Delete(this IMongoCollection<Position> col, string tokenId)
|
|
||||||
{
|
|
||||||
col.DeleteOne(x => x.TokenId == tokenId);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 8. EnsureIndex shim (MongoDB Index Creation)
|
|
||||||
public static void EnsureIndex<T>(this IMongoCollection<T> col, Expression<Func<T, object>> property)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var indexKeys = Builders<T>.IndexKeys.Ascending(property);
|
|
||||||
var indexModel = new CreateIndexModel<T>(indexKeys);
|
|
||||||
col.Indexes.CreateOne(indexModel);
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -59,8 +59,6 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="LiteDB" Version="5.0.21" />
|
|
||||||
<PackageReference Include="MongoDB.Driver" Version="2.24.0" />
|
|
||||||
<PackageReference Include="Nethereum.Web3" Version="6.1.0" />
|
<PackageReference Include="Nethereum.Web3" Version="6.1.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
|
||||||
|
|||||||
+7
-64
@@ -1,6 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using MongoDB.Driver;
|
using System.Linq;
|
||||||
using PolyTraderSharp.Extensions;
|
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Channels;
|
using System.Threading.Channels;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
@@ -26,13 +25,6 @@ internal static class Program
|
|||||||
[STAThread]
|
[STAThread]
|
||||||
private static void Main(string[] args)
|
private static void Main(string[] args)
|
||||||
{
|
{
|
||||||
// Einmalige Config-Migration Mongo -> MySQL (Phase 6, Stufe 4). Kein UI-Start.
|
|
||||||
if (args.Length > 0 && string.Equals(args[0], "--migrate-config", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
RunConfigMigration();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Config-Migration aus mongoexport-JSON (Ordner, Default "MongoDB") -> MySQL.
|
// Config-Migration aus mongoexport-JSON (Ordner, Default "MongoDB") -> MySQL.
|
||||||
if (args.Length > 0 && string.Equals(args[0], "--migrate-json", StringComparison.OrdinalIgnoreCase))
|
if (args.Length > 0 && string.Equals(args[0], "--migrate-json", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
@@ -59,18 +51,9 @@ internal static class Program
|
|||||||
{
|
{
|
||||||
var databaseOptions = new DatabaseOptions
|
var databaseOptions = new DatabaseOptions
|
||||||
{
|
{
|
||||||
Provider = context.Configuration["Database:Provider"] ?? "Mongo",
|
MySqlConnectionString = context.Configuration["Database:MySqlConnectionString"] ?? string.Empty
|
||||||
MySqlConnectionString = context.Configuration["Database:MySqlConnectionString"] ?? string.Empty,
|
|
||||||
ConnectionString = context.Configuration["Database:ConnectionString"] ?? "mongodb://localhost:27017",
|
|
||||||
DatabaseName = context.Configuration["Database:DatabaseName"] ?? "PolyTraderDB"
|
|
||||||
};
|
};
|
||||||
services.Configure<DatabaseOptions>(context.Configuration.GetSection(DatabaseOptions.SectionName));
|
services.Configure<DatabaseOptions>(context.Configuration.GetSection(DatabaseOptions.SectionName));
|
||||||
services.AddSingleton<IMongoDatabase>((IServiceProvider sp) =>
|
|
||||||
{
|
|
||||||
var dbOptions = sp.GetRequiredService<IOptions<DatabaseOptions>>().Value;
|
|
||||||
var client = new MongoClient(dbOptions.ConnectionString);
|
|
||||||
return client.GetDatabase(dbOptions.DatabaseName);
|
|
||||||
});
|
|
||||||
services.AddCorePersistence(databaseOptions);
|
services.AddCorePersistence(databaseOptions);
|
||||||
services.AddSingleton<IBlockchainWssClientFactory, AlchemyWssClientFactory>();
|
services.AddSingleton<IBlockchainWssClientFactory, AlchemyWssClientFactory>();
|
||||||
services.AddSingleton((IServiceProvider sp) => ServerSettings.Load("server_settings.xml"));
|
services.AddSingleton((IServiceProvider sp) => ServerSettings.Load("server_settings.xml"));
|
||||||
@@ -124,36 +107,18 @@ internal static class Program
|
|||||||
services.AddHostedService<PolymarketWssClient>();
|
services.AddHostedService<PolymarketWssClient>();
|
||||||
services.AddHostedService((IServiceProvider sp) => sp.GetRequiredService<MullvadVpnService>());
|
services.AddHostedService((IServiceProvider sp) => sp.GetRequiredService<MullvadVpnService>());
|
||||||
services.AddHostedService((IServiceProvider sp) => sp.GetRequiredService<ThreemaService>());
|
services.AddHostedService((IServiceProvider sp) => sp.GetRequiredService<ThreemaService>());
|
||||||
services.AddTransient<frm_main>();
|
|
||||||
services.AddSingleton<PolyTraderSharp.Ui.ShellUiHost>();
|
services.AddSingleton<PolyTraderSharp.Ui.ShellUiHost>();
|
||||||
services.AddTransient<PolyTraderSharp.Ui.LauncherForm>();
|
services.AddTransient<PolyTraderSharp.Ui.LauncherForm>();
|
||||||
}).Build();
|
}).Build();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var db = AppHost.Services.GetRequiredService<IMongoDatabase>();
|
// Trade-Nummerierung fortsetzen: höchste bestehende TradeId aus dem Log lesen.
|
||||||
|
|
||||||
// Einmal-Bereinigung (Alt-Bug): entferne closed_trades mit ObjectId-_id.
|
|
||||||
// Das _id muss die int-TradeId sein; fehlerhafte Auto-ObjectIds werden verworfen.
|
|
||||||
// Läuft jetzt über die konfigurierte DB statt über einen hart codierten Client.
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var cleanupCol = db.GetCollection<MongoDB.Bson.BsonDocument>("closed_trades");
|
|
||||||
cleanupCol.DeleteMany(Builders<MongoDB.Bson.BsonDocument>.Filter.Type("_id", MongoDB.Bson.BsonType.ObjectId));
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
|
|
||||||
var copyState = AppHost.Services.GetRequiredService<CopyTradingState>();
|
var copyState = AppHost.Services.GetRequiredService<CopyTradingState>();
|
||||||
var maxTradeDoc = db.GetCollection<MongoDB.Bson.BsonDocument>("closed_trades")
|
var tradeLog = AppHost.Services.GetRequiredService<ICopyTradeLogRepository>();
|
||||||
.Find(Builders<MongoDB.Bson.BsonDocument>.Filter.Empty)
|
var allTrades = tradeLog.Find(_ => true);
|
||||||
.SortByDescending(d => d["_id"])
|
if (allTrades.Count > 0)
|
||||||
.Limit(1)
|
copyState.TotalCopyTrades = allTrades.Max(t => t.TradeId);
|
||||||
.FirstOrDefault();
|
|
||||||
|
|
||||||
if (maxTradeDoc != null && maxTradeDoc.Contains("_id"))
|
|
||||||
{
|
|
||||||
copyState.TotalCopyTrades = maxTradeDoc["_id"].AsInt32;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
|
|
||||||
@@ -232,28 +197,6 @@ internal static class Program
|
|||||||
AppHost.StopAsync().GetAwaiter().GetResult();
|
AppHost.StopAsync().GetAwaiter().GetResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void RunConfigMigration()
|
|
||||||
{
|
|
||||||
var config = new Microsoft.Extensions.Configuration.ConfigurationBuilder()
|
|
||||||
.SetBasePath(System.IO.Directory.GetCurrentDirectory())
|
|
||||||
.AddJsonFile("appsettings.json", optional: true)
|
|
||||||
.AddJsonFile("appsettings.Local.json", optional: true)
|
|
||||||
.AddEnvironmentVariables()
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
var mongoConn = config["Database:ConnectionString"] ?? "mongodb://localhost:27017";
|
|
||||||
var mongoDbName = config["Database:DatabaseName"] ?? "PolyTraderDB";
|
|
||||||
var mySql = config["Database:MySqlConnectionString"] ?? string.Empty;
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(mySql))
|
|
||||||
{
|
|
||||||
Console.WriteLine("FEHLER: Database:MySqlConnectionString fehlt (appsettings.Local.json).");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Services.ConfigMigrator.Run(mongoConn, mongoDbName, mySql);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void RunConfigMigrationFromJson(string folder)
|
private static void RunConfigMigrationFromJson(string folder)
|
||||||
{
|
{
|
||||||
var config = new Microsoft.Extensions.Configuration.ConfigurationBuilder()
|
var config = new Microsoft.Extensions.Configuration.ConfigurationBuilder()
|
||||||
|
|||||||
Generated
+1
-9
@@ -19,7 +19,6 @@ namespace PolyTraderSharp.Ui
|
|||||||
{
|
{
|
||||||
menuStrip = new MenuStrip();
|
menuStrip = new MenuStrip();
|
||||||
miDatei = new ToolStripMenuItem();
|
miDatei = new ToolStripMenuItem();
|
||||||
miLegacy = new ToolStripMenuItem();
|
|
||||||
miBeenden = new ToolStripMenuItem();
|
miBeenden = new ToolStripMenuItem();
|
||||||
toolstrip_windows = new ToolStrip();
|
toolstrip_windows = new ToolStrip();
|
||||||
btn_dashboard = new ToolStripButton();
|
btn_dashboard = new ToolStripButton();
|
||||||
@@ -51,17 +50,11 @@ namespace PolyTraderSharp.Ui
|
|||||||
//
|
//
|
||||||
// miDatei
|
// miDatei
|
||||||
//
|
//
|
||||||
miDatei.DropDownItems.AddRange(new ToolStripItem[] { miLegacy, miBeenden });
|
miDatei.DropDownItems.AddRange(new ToolStripItem[] { miBeenden });
|
||||||
miDatei.Name = "miDatei";
|
miDatei.Name = "miDatei";
|
||||||
miDatei.Size = new Size(69, 29);
|
miDatei.Size = new Size(69, 29);
|
||||||
miDatei.Text = "Datei";
|
miDatei.Text = "Datei";
|
||||||
//
|
//
|
||||||
// miLegacy
|
|
||||||
//
|
|
||||||
miLegacy.Name = "miLegacy";
|
|
||||||
miLegacy.Size = new Size(275, 34);
|
|
||||||
miLegacy.Text = "Legacy-UI (alte Tabs)";
|
|
||||||
//
|
|
||||||
// miBeenden
|
// miBeenden
|
||||||
//
|
//
|
||||||
miBeenden.Name = "miBeenden";
|
miBeenden.Name = "miBeenden";
|
||||||
@@ -202,7 +195,6 @@ namespace PolyTraderSharp.Ui
|
|||||||
|
|
||||||
private System.Windows.Forms.MenuStrip menuStrip;
|
private System.Windows.Forms.MenuStrip menuStrip;
|
||||||
private System.Windows.Forms.ToolStripMenuItem miDatei;
|
private System.Windows.Forms.ToolStripMenuItem miDatei;
|
||||||
private System.Windows.Forms.ToolStripMenuItem miLegacy;
|
|
||||||
private System.Windows.Forms.ToolStripMenuItem miBeenden;
|
private System.Windows.Forms.ToolStripMenuItem miBeenden;
|
||||||
private ToolStrip toolstrip_windows;
|
private ToolStrip toolstrip_windows;
|
||||||
private ToolStripButton btn_settings;
|
private ToolStripButton btn_settings;
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ namespace PolyTraderSharp.Ui
|
|||||||
private readonly TradingState _state;
|
private readonly TradingState _state;
|
||||||
private readonly System.Windows.Forms.Timer _statusTimer = new() { Interval = 1000 };
|
private readonly System.Windows.Forms.Timer _statusTimer = new() { Interval = 1000 };
|
||||||
private readonly Dictionary<string, ToolStripButton> _viewButtons;
|
private readonly Dictionary<string, ToolStripButton> _viewButtons;
|
||||||
private frm_main? _legacyForm;
|
|
||||||
|
|
||||||
public LauncherForm(ShellUiHost uiHost, IServiceProvider services)
|
public LauncherForm(ShellUiHost uiHost, IServiceProvider services)
|
||||||
{
|
{
|
||||||
@@ -47,7 +46,6 @@ namespace PolyTraderSharp.Ui
|
|||||||
|
|
||||||
btn_liveTrading.Click += (_, _) => CycleLiveTrading();
|
btn_liveTrading.Click += (_, _) => CycleLiveTrading();
|
||||||
btn_demoTrading.Click += (_, _) => CycleDemoTrading();
|
btn_demoTrading.Click += (_, _) => CycleDemoTrading();
|
||||||
miLegacy.Click += (_, _) => OpenLegacy();
|
|
||||||
miBeenden.Click += (_, _) => Close();
|
miBeenden.Click += (_, _) => Close();
|
||||||
|
|
||||||
// Offen-Status der Fenster spiegeln (Button „checked", wenn Fenster offen).
|
// Offen-Status der Fenster spiegeln (Button „checked", wenn Fenster offen).
|
||||||
@@ -126,25 +124,8 @@ namespace PolyTraderSharp.Ui
|
|||||||
|
|
||||||
lbl_ratelimit.Text = $"API: {(_state.IsAlchemyHealthy ? "WSS aktiv" : "Polling")}";
|
lbl_ratelimit.Text = $"API: {(_state.IsAlchemyHealthy ? "WSS aktiv" : "Polling")}";
|
||||||
|
|
||||||
// Toggle-Buttons mit externem State synchron halten (z.B. Änderungen aus der Legacy-UI).
|
|
||||||
UpdateTradingToggles();
|
UpdateTradingToggles();
|
||||||
UpdateWindowButtonStates();
|
UpdateWindowButtonStates();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OpenLegacy()
|
|
||||||
{
|
|
||||||
if (_legacyForm != null && !_legacyForm.IsDisposed)
|
|
||||||
{
|
|
||||||
if (_legacyForm.WindowState == FormWindowState.Minimized)
|
|
||||||
_legacyForm.WindowState = FormWindowState.Normal;
|
|
||||||
_legacyForm.BringToFront();
|
|
||||||
_legacyForm.Activate();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_legacyForm = _services.GetRequiredService<frm_main>();
|
|
||||||
_legacyForm.FormClosed += (_, _) => _legacyForm = null;
|
|
||||||
_legacyForm.Show();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-3
@@ -1,7 +1,6 @@
|
|||||||
{
|
{
|
||||||
"Database": {
|
"Database": {
|
||||||
"Provider": "MySql",
|
"_comment": "MySqlConnectionString liegt in der gitignorierten appsettings.Local.json.",
|
||||||
"ConnectionString": "mongodb://localhost:27017",
|
"MySqlConnectionString": ""
|
||||||
"DatabaseName": "PolyTraderDB"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
-111
@@ -1,111 +0,0 @@
|
|||||||
namespace PolyTraderSharp
|
|
||||||
{
|
|
||||||
partial class frm_analytics
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Required designer variable.
|
|
||||||
/// </summary>
|
|
||||||
private System.ComponentModel.IContainer components = null;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Clean up any resources being used.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
|
||||||
protected override void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (disposing && (components != null))
|
|
||||||
{
|
|
||||||
components.Dispose();
|
|
||||||
}
|
|
||||||
base.Dispose(disposing);
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Windows Form Designer generated code
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Required method for Designer support - do not modify
|
|
||||||
/// the contents of this method with the code editor.
|
|
||||||
/// </summary>
|
|
||||||
private void InitializeComponent()
|
|
||||||
{
|
|
||||||
menuStrip1 = new MenuStrip();
|
|
||||||
toolStrip1 = new ToolStrip();
|
|
||||||
tabControl1 = new TabControl();
|
|
||||||
tabPage1 = new TabPage();
|
|
||||||
tabPage2 = new TabPage();
|
|
||||||
tabControl1.SuspendLayout();
|
|
||||||
SuspendLayout();
|
|
||||||
//
|
|
||||||
// menuStrip1
|
|
||||||
//
|
|
||||||
menuStrip1.ImageScalingSize = new Size(24, 24);
|
|
||||||
menuStrip1.Location = new Point(0, 0);
|
|
||||||
menuStrip1.Name = "menuStrip1";
|
|
||||||
menuStrip1.Size = new Size(2229, 24);
|
|
||||||
menuStrip1.TabIndex = 0;
|
|
||||||
menuStrip1.Text = "menuStrip1";
|
|
||||||
//
|
|
||||||
// toolStrip1
|
|
||||||
//
|
|
||||||
toolStrip1.ImageScalingSize = new Size(24, 24);
|
|
||||||
toolStrip1.Location = new Point(0, 24);
|
|
||||||
toolStrip1.Name = "toolStrip1";
|
|
||||||
toolStrip1.Size = new Size(2229, 25);
|
|
||||||
toolStrip1.TabIndex = 1;
|
|
||||||
toolStrip1.Text = "toolStrip1";
|
|
||||||
//
|
|
||||||
// tabControl1
|
|
||||||
//
|
|
||||||
tabControl1.Controls.Add(tabPage1);
|
|
||||||
tabControl1.Controls.Add(tabPage2);
|
|
||||||
tabControl1.Location = new Point(0, 52);
|
|
||||||
tabControl1.Name = "tabControl1";
|
|
||||||
tabControl1.SelectedIndex = 0;
|
|
||||||
tabControl1.Size = new Size(2229, 1115);
|
|
||||||
tabControl1.TabIndex = 2;
|
|
||||||
//
|
|
||||||
// tabPage1
|
|
||||||
//
|
|
||||||
tabPage1.Location = new Point(4, 34);
|
|
||||||
tabPage1.Name = "tabPage1";
|
|
||||||
tabPage1.Padding = new Padding(3);
|
|
||||||
tabPage1.Size = new Size(2221, 1077);
|
|
||||||
tabPage1.TabIndex = 0;
|
|
||||||
tabPage1.Text = "tabPage1";
|
|
||||||
tabPage1.UseVisualStyleBackColor = true;
|
|
||||||
//
|
|
||||||
// tabPage2
|
|
||||||
//
|
|
||||||
tabPage2.Location = new Point(4, 34);
|
|
||||||
tabPage2.Name = "tabPage2";
|
|
||||||
tabPage2.Padding = new Padding(3);
|
|
||||||
tabPage2.Size = new Size(2221, 1077);
|
|
||||||
tabPage2.TabIndex = 1;
|
|
||||||
tabPage2.Text = "tabPage2";
|
|
||||||
tabPage2.UseVisualStyleBackColor = true;
|
|
||||||
//
|
|
||||||
// frm_analytics
|
|
||||||
//
|
|
||||||
AutoScaleDimensions = new SizeF(10F, 25F);
|
|
||||||
AutoScaleMode = AutoScaleMode.Font;
|
|
||||||
ClientSize = new Size(2229, 1169);
|
|
||||||
Controls.Add(tabControl1);
|
|
||||||
Controls.Add(toolStrip1);
|
|
||||||
Controls.Add(menuStrip1);
|
|
||||||
MainMenuStrip = menuStrip1;
|
|
||||||
Name = "frm_analytics";
|
|
||||||
Text = "Analyse";
|
|
||||||
tabControl1.ResumeLayout(false);
|
|
||||||
ResumeLayout(false);
|
|
||||||
PerformLayout();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
private MenuStrip menuStrip1;
|
|
||||||
private ToolStrip toolStrip1;
|
|
||||||
private TabControl tabControl1;
|
|
||||||
private TabPage tabPage1;
|
|
||||||
private TabPage tabPage2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
using System;
|
|
||||||
using MongoDB.Driver;
|
|
||||||
using PolyTraderSharp.Extensions;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Data;
|
|
||||||
using System.Drawing;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
|
|
||||||
namespace PolyTraderSharp
|
|
||||||
{
|
|
||||||
public partial class frm_analytics : Form
|
|
||||||
{
|
|
||||||
public frm_analytics()
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,126 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<root>
|
|
||||||
<!--
|
|
||||||
Microsoft ResX Schema
|
|
||||||
|
|
||||||
Version 2.0
|
|
||||||
|
|
||||||
The primary goals of this format is to allow a simple XML format
|
|
||||||
that is mostly human readable. The generation and parsing of the
|
|
||||||
various data types are done through the TypeConverter classes
|
|
||||||
associated with the data types.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
... ado.net/XML headers & schema ...
|
|
||||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
|
||||||
<resheader name="version">2.0</resheader>
|
|
||||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
|
||||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
|
||||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
|
||||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
|
||||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
|
||||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
|
||||||
</data>
|
|
||||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
|
||||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
|
||||||
<comment>This is a comment</comment>
|
|
||||||
</data>
|
|
||||||
|
|
||||||
There are any number of "resheader" rows that contain simple
|
|
||||||
name/value pairs.
|
|
||||||
|
|
||||||
Each data row contains a name, and value. The row also contains a
|
|
||||||
type or mimetype. Type corresponds to a .NET class that support
|
|
||||||
text/value conversion through the TypeConverter architecture.
|
|
||||||
Classes that don't support this are serialized and stored with the
|
|
||||||
mimetype set.
|
|
||||||
|
|
||||||
The mimetype is used for serialized objects, and tells the
|
|
||||||
ResXResourceReader how to depersist the object. This is currently not
|
|
||||||
extensible. For a given mimetype the value must be set accordingly:
|
|
||||||
|
|
||||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
|
||||||
that the ResXResourceWriter will generate, however the reader can
|
|
||||||
read any of the formats listed below.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.binary.base64
|
|
||||||
value : The object must be serialized with
|
|
||||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.soap.base64
|
|
||||||
value : The object must be serialized with
|
|
||||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
|
||||||
value : The object must be serialized into a byte array
|
|
||||||
: using a System.ComponentModel.TypeConverter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
-->
|
|
||||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
|
||||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
|
||||||
<xsd:element name="root" msdata:IsDataSet="true">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:choice maxOccurs="unbounded">
|
|
||||||
<xsd:element name="metadata">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:sequence>
|
|
||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
|
||||||
</xsd:sequence>
|
|
||||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
|
||||||
<xsd:attribute name="type" type="xsd:string" />
|
|
||||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
|
||||||
<xsd:attribute ref="xml:space" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
<xsd:element name="assembly">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:attribute name="alias" type="xsd:string" />
|
|
||||||
<xsd:attribute name="name" type="xsd:string" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
<xsd:element name="data">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:sequence>
|
|
||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
|
||||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
|
||||||
</xsd:sequence>
|
|
||||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
|
||||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
|
||||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
|
||||||
<xsd:attribute ref="xml:space" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
<xsd:element name="resheader">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:sequence>
|
|
||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
|
||||||
</xsd:sequence>
|
|
||||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
</xsd:choice>
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
</xsd:schema>
|
|
||||||
<resheader name="resmimetype">
|
|
||||||
<value>text/microsoft-resx</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="version">
|
|
||||||
<value>2.0</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="reader">
|
|
||||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="writer">
|
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
|
||||||
</resheader>
|
|
||||||
<metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
|
||||||
<value>17, 17</value>
|
|
||||||
</metadata>
|
|
||||||
<metadata name="toolStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
|
||||||
<value>175, 17</value>
|
|
||||||
</metadata>
|
|
||||||
</root>
|
|
||||||
Generated
-2471
File diff suppressed because it is too large
Load Diff
-1858
File diff suppressed because it is too large
Load Diff
-371
@@ -1,371 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<root>
|
|
||||||
<!--
|
|
||||||
Microsoft ResX Schema
|
|
||||||
|
|
||||||
Version 2.0
|
|
||||||
|
|
||||||
The primary goals of this format is to allow a simple XML format
|
|
||||||
that is mostly human readable. The generation and parsing of the
|
|
||||||
various data types are done through the TypeConverter classes
|
|
||||||
associated with the data types.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
... ado.net/XML headers & schema ...
|
|
||||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
|
||||||
<resheader name="version">2.0</resheader>
|
|
||||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
|
||||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
|
||||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
|
||||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
|
||||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
|
||||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
|
||||||
</data>
|
|
||||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
|
||||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
|
||||||
<comment>This is a comment</comment>
|
|
||||||
</data>
|
|
||||||
|
|
||||||
There are any number of "resheader" rows that contain simple
|
|
||||||
name/value pairs.
|
|
||||||
|
|
||||||
Each data row contains a name, and value. The row also contains a
|
|
||||||
type or mimetype. Type corresponds to a .NET class that support
|
|
||||||
text/value conversion through the TypeConverter architecture.
|
|
||||||
Classes that don't support this are serialized and stored with the
|
|
||||||
mimetype set.
|
|
||||||
|
|
||||||
The mimetype is used for serialized objects, and tells the
|
|
||||||
ResXResourceReader how to depersist the object. This is currently not
|
|
||||||
extensible. For a given mimetype the value must be set accordingly:
|
|
||||||
|
|
||||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
|
||||||
that the ResXResourceWriter will generate, however the reader can
|
|
||||||
read any of the formats listed below.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.binary.base64
|
|
||||||
value : The object must be serialized with
|
|
||||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.soap.base64
|
|
||||||
value : The object must be serialized with
|
|
||||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
|
||||||
value : The object must be serialized into a byte array
|
|
||||||
: using a System.ComponentModel.TypeConverter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
-->
|
|
||||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
|
||||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
|
||||||
<xsd:element name="root" msdata:IsDataSet="true">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:choice maxOccurs="unbounded">
|
|
||||||
<xsd:element name="metadata">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:sequence>
|
|
||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
|
||||||
</xsd:sequence>
|
|
||||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
|
||||||
<xsd:attribute name="type" type="xsd:string" />
|
|
||||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
|
||||||
<xsd:attribute ref="xml:space" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
<xsd:element name="assembly">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:attribute name="alias" type="xsd:string" />
|
|
||||||
<xsd:attribute name="name" type="xsd:string" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
<xsd:element name="data">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:sequence>
|
|
||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
|
||||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
|
||||||
</xsd:sequence>
|
|
||||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
|
||||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
|
||||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
|
||||||
<xsd:attribute ref="xml:space" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
<xsd:element name="resheader">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:sequence>
|
|
||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
|
||||||
</xsd:sequence>
|
|
||||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
</xsd:choice>
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
</xsd:schema>
|
|
||||||
<resheader name="resmimetype">
|
|
||||||
<value>text/microsoft-resx</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="version">
|
|
||||||
<value>2.0</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="reader">
|
|
||||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="writer">
|
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
|
||||||
</resheader>
|
|
||||||
<metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
|
||||||
<value>17, 17</value>
|
|
||||||
</metadata>
|
|
||||||
<metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
|
||||||
<value>175, 17</value>
|
|
||||||
</metadata>
|
|
||||||
<metadata name="toolStrip3.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
|
||||||
<value>1615, 17</value>
|
|
||||||
</metadata>
|
|
||||||
<metadata name="col_mastername.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>True</value>
|
|
||||||
</metadata>
|
|
||||||
<metadata name="col_aktproz.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>True</value>
|
|
||||||
</metadata>
|
|
||||||
<metadata name="col_aktUSD.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>True</value>
|
|
||||||
</metadata>
|
|
||||||
<metadata name="col_name.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>True</value>
|
|
||||||
</metadata>
|
|
||||||
<metadata name="col_Winrate.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>True</value>
|
|
||||||
</metadata>
|
|
||||||
<metadata name="col_pl.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>True</value>
|
|
||||||
</metadata>
|
|
||||||
<metadata name="col_trades.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>True</value>
|
|
||||||
</metadata>
|
|
||||||
<metadata name="dataGridViewLinkColumn1.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>True</value>
|
|
||||||
</metadata>
|
|
||||||
<metadata name="dataGridViewTextBoxColumn1.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>True</value>
|
|
||||||
</metadata>
|
|
||||||
<metadata name="dataGridViewTextBoxColumn2.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>True</value>
|
|
||||||
</metadata>
|
|
||||||
<metadata name="dataGridViewTextBoxColumn3.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>True</value>
|
|
||||||
</metadata>
|
|
||||||
<metadata name="Column_Laufzeit.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>True</value>
|
|
||||||
</metadata>
|
|
||||||
<metadata name="Column_LaufzeitProz.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>True</value>
|
|
||||||
</metadata>
|
|
||||||
<metadata name="Column_laufzeitUSD.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>True</value>
|
|
||||||
</metadata>
|
|
||||||
<metadata name="Column_Aktuellproz.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>True</value>
|
|
||||||
</metadata>
|
|
||||||
<metadata name="Column_aktuellusd.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>True</value>
|
|
||||||
</metadata>
|
|
||||||
<metadata name="toolStrip_openTrades.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
|
||||||
<value>625, 17</value>
|
|
||||||
</metadata>
|
|
||||||
<metadata name="toolStrip_closedtrades.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
|
||||||
<value>770, 17</value>
|
|
||||||
</metadata>
|
|
||||||
<metadata name="toolStrip4.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
|
||||||
<value>1760, 17</value>
|
|
||||||
</metadata>
|
|
||||||
<metadata name="imageList_tabpages.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
|
||||||
<value>1905, 17</value>
|
|
||||||
</metadata>
|
|
||||||
<data name="imageList_tabpages.ImageStream" mimetype="application/x-microsoft.net.object.binary.base64">
|
|
||||||
<value>
|
|
||||||
AAEAAAD/////AQAAAAAAAAAMAgAAAEZTeXN0ZW0uV2luZG93cy5Gb3JtcywgQ3VsdHVyZT1uZXV0cmFs
|
|
||||||
LCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BQEAAAAmU3lzdGVtLldpbmRvd3MuRm9ybXMu
|
|
||||||
SW1hZ2VMaXN0U3RyZWFtZXIBAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAfh0AAAJNU0Z0AUkBTAIBAQUB
|
|
||||||
AAEoAQABKAEAARABAAEQAQAE/wEhAQAI/wFCAU0BNgcAATYDAAEoAwABQAMAASADAAEBAQABIAYAASAS
|
|
||||||
AAMEAQUDIwEzAywBQwMsAUMDLAFDAywBQwMsAUMDLAFDAywBQwMsAUMDLAFDAywBQwMsAUMDLAFDAysB
|
|
||||||
QQMSARjAAAMQARUDyQH/AfcC9gH/AfgC9wH/AfgC9wH/AfgC9wH/AfgC9wH/AfgC9wH/AfgC9wH/AfgC
|
|
||||||
9wH/AfcC9gH/AfYC9QH/AfYC9QH/AfYC9QH/AfkC+AH/A20B38AAAxEBFgH5AvgB/wHzAfIB8QH/AXEB
|
|
||||||
bQFrAf8BcQFtAWsB/wFxAW0BawH/AXEBbQFrAf8BcQFtAWsB/wFxAW0BawH/AXEBbQFrAf8B8wHyAfEB
|
|
||||||
/wHrAeoB6QH/AesB6gHpAf8B6wHqAekB/wHsAesB6gH/A5gB/8AAAxEBFgH6AvkB/wHyAfAB8QH/AW8B
|
|
||||||
bAFqFf8BbwFsAWoB/wHyAvEB/wHnAuUB/wHnAuUB/wHnAuUB/wHnAuUB/wOYAf/AAAMRARYB/AL7Af8B
|
|
||||||
7gLsAf8BaQFmAWQB/wHlAuMB/wHjAuEB/wHjAuEB/wHjAuEB/wHlAuMB/wFpAWYBZAH/Ae4C7QH/AeMC
|
|
||||||
4QH/AeMC4QH/AeMC4QH/AeMC4QH/A5gB/8AAAxEBFgP+Af8B6QHoAecB/wFlAWMBYQH/AeAB3wHeAf8B
|
|
||||||
3gHdAdwB/wHeAd0B3AH/Ad4B3QHcAf8B4AHfAd4B/wFlAWMBYQH/AfIB8QHwAf8B6QHoAecB/wHpAegB
|
|
||||||
5wH/AeYB5QHkAf8B3gHdAdsB/wOYAf/AAAMRARYE/wHlAeQB4wH/AWEBXwFdAf8B3AHbAdoB/wHaAdkB
|
|
||||||
2AH/AdoB2QHYAf8B2gHZAdgB/wHcAdsB2gH/AWIBYAFdAf8BYwFhAV8B/wFeAVwBWgH/AWIBYAFeAf8B
|
|
||||||
YQFfAVwB/wHaAdkB2AH/A5gB/8AAAxEBFgT/AeEB3wHeAf8BXQFbAVkB/wHYAdYB1QH/AdYB1AHTAf8B
|
|
||||||
1gHUAdMB/wHWAdQB0wH/AdgB1gHVAf8BXQFbAVkB/wHhAd8B3gH/AdUB0wHSAf8B4QHfAd4B/wFdAVsB
|
|
||||||
WQH/AdYB1AHTAf8DmAH/wAADEQEWBP8B3QHbAdoB/wFdAVsBWgH/Ab4BvAG7Af8BvQG7AboB/wG9AbsB
|
|
||||||
ugH/Ab0BuwG6Af8BvgG8AbsB/wFdAVsBWgH/Ad0B2wHaAf8B0gHQAc8B/wHdAdsB2gH/AVkBVwFWAf8B
|
|
||||||
0QHPAc4B/wGXApgB/8AAAxEBFgT/AdQB0gHQAf8BUQFPAU4B/wFSAU8BTgH/AVIBUAFPAf8BXAFaAVkB
|
|
||||||
/wFWAVMBUgH/AVIBTwFOAf8BUQFPAU4B/wHVAdMB0QH/Ac4BzAHKAf8B2QHXAdUB/wFVAVMBUgH/Ac0B
|
|
||||||
ygHIAf8BlwKYAf/AAAMRARYE/wHIAcUBxAH/AcgBxQHEAf8ByAHFAcQB/wHKAccBxgH/AVEBTgFNAf8B
|
|
||||||
1AHQAc8B/wHIAcUBxAH/AcgBxQHEAf8ByQHGAcUB/wHKAccBxgH/AdUB0gHRAf8BUgFPAU4B/wHIAcUB
|
|
||||||
xAH/ApcBmAH/wAADEQEWBP8BxQHCAcEB/wHGAcMBwgH/AcYBwwHCAf8ByAHFAcQB/wFOAUsBSgH/AdQB
|
|
||||||
0QHQAf8BygHHAcYB/wHKAccBxgH/AcoBxwHGAf8BygHHAcYB/wHUAdEB0AH/AU4BSwFKAf8BxAHAAb8B
|
|
||||||
/wOXAf/AAAMRARYE/wHAAb4BvAH/AcEBvwG9Af8BwQG/Ab0B/wHDAcEBvwH/AUkCRwH/AU4BTAFLAf8B
|
|
||||||
SwFJAUgB/wFLAUkBSAH/AUsBSQFIAf8BSwFJAUgB/wFOAUwBSwH/AUkCRwH/Ab4BvAG6Af8DlwH/wAAD
|
|
||||||
EQEWBP8BvAG6AbgB/wG9AbsBuQH/Ab0BuwG5Af8BvQG7Abkh/wG4AbYBswH/A5cB/8AAAwwBDwT/AbIB
|
|
||||||
rwGsAf8BswGwAa4B/wGzAbABrgH/AbMBsAGtAf8BsgGvAawB/wGyAa4BrAH/AbIBrgGsAf8BsgGuAawB
|
|
||||||
/wGyAa4BrAH/AbIBrgGsAf8BsgGuAawB/wGyAa8BrAH/AbUBswGxAf8DmAH/xAADagHXA5cB/wOXAf8D
|
|
||||||
lwH/A5cB/wOXAf8DlwH/A5cB/wOXAf8DlwH/A5cB/wOXAf8DlwH/A5gB/wMEAQXAAAMMARADKwFCAywB
|
|
||||||
QwMsAUMDLAFDAywBQwMsAUMDLAFDAywBQwMsAUMDLAFDAywBQwMsAUMDLAFDAywBQwMiATEDBAEFAxEB
|
|
||||||
FgMRARYDEQEWAxEBFgMRARYDEQEWAxEBFgMRARYDEQEWAxEBFgMRARYDEQEWAxEBFgMRARYDCgENBAAD
|
|
||||||
BAEFAxABFQMPARQDAgEDIAADCgENAwoBDSgAAwYBCAMgAS4DKwFCAysBQgMgAS4DBwEJBAADEQEWOP8B
|
|
||||||
jwFxAVYB/wMRARYBtwF/AQ8B/wG2AXwBCQH/AbYBfAEJAf8BtgF8AQkB/wG2AXwBCQH/AbYBfAEJAf8B
|
|
||||||
tgF8AQkB/wG2AXwBCQH/AbYBfAEJAf8BtgF8AQkB/wG2AXwBCQH/AbYBfAEJAf8BtgF8AQkB/wG2AX0B
|
|
||||||
CgH/AWIBXQFVAcQEAAMjATMBtwGDARkB/wG4AYUBHAH/AyMBMgMCAQMYAAMPARQBYQFdAVYBxQFhAV0B
|
|
||||||
VgHFAw8BFAMKAQ0DKgE/AywBQwMsAUMDLAFDAywBQwMsAUMDLAFDAywBQwNEAXkBrwGuAa0B/wHcAdsB
|
|
||||||
3AH/AdwB2wHcAf8BrwGuAa0B/wNEAXcDBwEJAxEBFgT/AWQBxwGTAf8BZwHIAZQB/wFnAcgBlAH/AWcB
|
|
||||||
yAGUAf8BZwHIAZQB/wFnAcgBlAH/AWcByAGUAf8BZgHIAZQB/wFlAcgBkwH/AWUBxwGTAf8BZQHIAZMB
|
|
||||||
/wFmAcgBlAH/AVoBxgGNAf8BjgFtAVMB/wMRARYB3AHiAesB/wPQAf8D0AH/A9AB/wPQAf8D0AH/A9AB
|
|
||||||
/wPQAf8D0AH/A9AB/wPQAf8D0AH/A9AB/wPQAf8BtgF9AQoB/wQAAcABjgEqAf8B5QGsAU4B/wHlAaoB
|
|
||||||
SQH/AbkBhgEdAf8DIQEwBAIQAAMPARQBXgFcAVYBwQHkAaQBPAH/AegBsgFXAf8BXwFbAVYBwAMRARYB
|
|
||||||
UAGFAawB/wFLAYABqgH/AUoBfwGqAf8BSgF/AaoB/wFKAX8BqgH/AUoBfwGqAf8BSgF/AaoB/wFHAX0B
|
|
||||||
qQH/AcYBwgG/Af8BrQGrAagJ/wGtAasBqAH/AcMBwQG/Af8DIAEuAxEBFgT/AVkBuQGFAf8BXAG7AYgB
|
|
||||||
/wFdAbsBiAH/AV0BuwGIAf8BXAG7AYcB/wFaAboBhgH/AVUBuAGCAf8BigHPAasB/wHRAe4B3wH/AdEB
|
|
||||||
6gHbAf8ByQHqAdkB/wGKAc8BqwH/AUgBtAF7Af8BjgFtAVMB/wMRARYE/wFqAWcBZgH/AWwBaAFnAf8B
|
|
||||||
bAFoAWcB/wFsAWgBZwH/AWwBaAFnAf8BbAFoAWcB/wFsAWgBZwH/AWwBaAFnAf8BbAFoAWcB/wFsAWgB
|
|
||||||
ZwH/AWwBaAFnAf8BbAFoAWcB/wFjAmAB/wG0AXoBBwH/BAABugGGAR0B/wHsAboBawH/AeUBrgFRAf8B
|
|
||||||
5QGqAUkB/wG5AYYBHgH/AxwBJwQCCAADDwEUAV4BXAFWAcEB5AGkATsB/wHkAa0BUQL/AecBxAH/AVoB
|
|
||||||
WAFVAbMDEQEWAV0BjQG1Af8BkwGkAa4B/wG5AbMBrQH/AbgBswGsAf8BuAGzAawB/wG4AbMBrAH/AbkB
|
|
||||||
swGtAf8BnQGXAZMB/wGoAaUBowH/Av4B/QP/Af4D/wH+Af8C/gH9Af8BqAGlAaMB/wGPAY4BjQH5AxEB
|
|
||||||
FgT/AakB2AG+Af8BdwHAAZgB/wFmAbgBiwH/AWYBuAGLAf8BgAHFAZ8B/wHNAegB2QH/AZgBugGTAf8B
|
|
||||||
QwGFAU8B/wFCAb0BzAH/AUEBxAHZAf8BQQG3Ab4B/wFDAYUBTwH/AbIB0gG2Af8BjgFuAVMB/wMRARYE
|
|
||||||
/wFxAm4B/wFzAnAB/wFzAnAB/wFzAnAB/wFzAnAB/wFzAnAB/wFzAnAB/wFzAnAB/wFzAnAB/wFzAnAB
|
|
||||||
/wFzAnAB/wFzAnAB/wFlAWMBZQH/AbQBegEHAf8EAAMDAQQB6QHBAYIB/wHsAboBawH/AeUBrgFRAf8B
|
|
||||||
5gGqAUkB/wG3AYQBGwH/AxgBIQQBAwoBDQFeAVwBVgHBAeQBowE7Af8B5AGtAVEC/wHnAcMB/wFXAVYB
|
|
||||||
VAGuBAADEQEWAWkBmQG+Af8BuAGzAawL/wH+A/8B/gX/AZkBlQGTAf8BnwGcAZoB/wNPAf8DVwH/A1oB
|
|
||||||
/wKnAagB/wGgAZ0BmwH/AaIBngGcAf8DEQEWBP8BPQGfAZQB/wFFAYEBQgH/AUUBfAE1Af8BRQF8ATQB
|
|
||||||
/wFEAYcBUAH/AT0BtQHLAf8BOwHNAv8BPQHLAv8BPQHJAv8BPQHJAv8BPQHJAv8BPQHLAv8BKgHKAv8B
|
|
||||||
jwFuAVIB/wMRARYE/wFrAWkBaAH/AW0BawFqAf8BbQFrAWoB/wFtAWsBagH/AW0BawFqAf8BbQFrAWoB
|
|
||||||
/wFtAWsBagH/AW0BawFqAf8BbQFrAWoB/wFtAWsBagH/AW0BawFqAf8BbQFrAWoB/wFfAV0BXgH/AbQB
|
|
||||||
egEHAf8IAAMDAQQB4wG5AXcB/wHsAbsBbAH/AeUBrgFRAf8B5gGqAUkB/wG3AYQBGwH/AxkBIgMjATMB
|
|
||||||
/wHyAcoB/wHjAawBTQL/AecBwwH/AVcBVgFUAa4IAAMRARYBdgGiAccB/wG5AbIBrAH/AQABfwE+Af8B
|
|
||||||
AAGAAUAF/wPCAf8DwAH/AZ8BnQGaAf8BpwGjAaEB/wHyAfEB8AH/AfYB9QH0Af8B9gH1AfQB/wHyAfEB
|
|
||||||
8AH/AacBpAGiAf8BmgKYAfgDEQEWBP8BMwG9Av8BNgG+Av8BNgG+Av8BNgG+Av8BNgG+Av8BNgG9Av8B
|
|
||||||
NgG9Av8BNQG9Av8BNAG8Av8BMwG8Av8BNAG8Av8BNQG9Av8BJAG5Av8BkAFuAVEB/wMRARYE/wFkAWIB
|
|
||||||
YQH/AWcBZQFkAf8BZwFlAWQB/wFnAWUBZAH/AWcBZQFkAf8BZwFlAWQB/wFnAWUBZAH/AWcBZQFkAf8B
|
|
||||||
ZwFlAWQB/wFnAWUBZAH/AWcBZQFkAf8BZwFlAWQB/wFYAlcB/wG0AXoBBwH/DAAEAgHUAaYBVAH/Ae0B
|
|
||||||
uwFtAf8B5QGuAVEB/wHmAaoBSQH/AbwBhQEUAf8BpAGmAawB/wG1AZABSAL/AewBygH/AVcBVgFUAa4M
|
|
||||||
AAMRARYBgwGtAc4B/wG3AbIBqwL/AfoB/AL/AfsB/gH/AfwB+QH6Af8D+AH/A/gB/wH4AfcB+AH/AdgB
|
|
||||||
1wHWAf8BogGgAZ4B/wHwAe8B7gH/AfAB7wHuAf8BogGgAZ4B/wHaAdkB2AH/AwcBCQMRARYE/wEqAbAC
|
|
||||||
/wEuAbIC/wEuAbIC/wEuAbIC/wEuAbIC/wEsAbEC/wElAa8C/wFoAcoC/wHFAewC/wHEAewC/wG6AegC
|
|
||||||
/wFoAcoC/wEVAasC/wGPAW4BUQH/AxEBFgT/AV4BXAFbAf8BYQFfAV4B/wFhAV8BXgH/AWEBXwFeAf8B
|
|
||||||
YQFfAV4B/wFhAV8BXgH/AWEBXwFeAf8BYQFfAV4B/wFhAV8BXgH/AWEBXwFeAf8BYQFfAV4B/wFhAV8B
|
|
||||||
XgH/AVEBUAFRAf8BtAF6AQcB/wgAAwoBDQMKAQ0EAQHFAZMBNAH/Ae4BvAFuAf8B5QGuAVEB/wHmAaoB
|
|
||||||
SAH/AbMBhQEpAf8B2wHeAeMB/wMCAQMQAAMRARYBkAG3AdcB/wG4AbIBqwH/AQABgAE/Af8BAAGCAUIB
|
|
||||||
/wH9AvkB/wLBAcAB/wLAAb8B/wL5AfgB/wG+Ab0BvAH/AdEB0AHOAf8B8wLyAf8B9ALyAf8C1AHRAf8D
|
|
||||||
MQFNBAADEQEWBP8BlgHWAv8BWAG8Av8BRAGyAv8BRAGzAv8BYgHAAv8BwQHnAv8BYQGxAecB/wEAAXUB
|
|
||||||
vwH/AaYBqwGKAf8BuAGxAYcB/wGSAaUBkAH/AQABdAG/Af8BjgHNAfkB/wGPAW8BUgH/AxEBFgT/AVgC
|
|
||||||
VgH/AVICUAH/AVgCVgH/AVsCWQH/AVsCWQH/AVsCWQH/AVsCWQH/AVsCWQH/AVsCWQH/AVsCWQH/AVsC
|
|
||||||
WQH/AVsCWQH/AUsBSQFLAf8BtAF6AQcB/wQAAw8BFANdAcUDXQHFAwYBBwMGAQcBwgGNASQB/wHvAb0B
|
|
||||||
bgH/AeUBrgFRAf8B5wGpAUMB/wMnAToDEAEVAxIBGAMPARQDAwEEBAADEQEWAZsBvwHcAf8BtwGxAaoB
|
|
||||||
/wH4AfIB9AH/Af4B9AH3Af8B9gHxAfMB/wHyAvEB/wHxAvAB/wHxAvAB/wHxAfAB8QX/AUIBhgG9Af8B
|
|
||||||
LAFjAZUB/wwAAxEBFgT/AVcBjgGdAf8BAAFqAc0B/wEAAWoBzAH/AQABagHMAf8BAAF1AcAB/wGhAaUB
|
|
||||||
hQH/AfcBvwFpAf8B7QG8AW0B/wHqAbsBbwH/AekBuwFvAf8B6gG7AW8B/wHtAb0BbQH/AfQBugFfAf8B
|
|
||||||
jgFvAVQB/wMRARYE/wFRAk8B/wGRAo8B/wGPAo0B/wFSAlAB/wFVAlMB/wFVAlMB/wFVAlMB/wFVAlMB
|
|
||||||
/wFVAlMB/wFVAlMB/wFVAlMB/wFVAlMB/wFEAUMBRQH/AbQBewEIAf8DCgENA1wBwQHCAcEBvgH/AZoB
|
|
||||||
lwGVAf8DPQFpAz0BaQGkAaUBqgH/AbYBiAEsAf8B7QG6AWcB/wG7AZcBUAH/AaUCpAH/AXUBcwFxAfYB
|
|
||||||
hAGCAYAB/wF3AXUBcwH/AygBPAMFAQYDEQEWAagByAHjAf8BuAGxAaoB/wEAAYEBQAH/AQABhAFEAf8B
|
|
||||||
9gLxAf8CvgG9Af8B8gHxAfAB/wG+Ab8BvQH/ArwBuwX/AUsBjAHCAf8BPQFtAZkB/wwAAxEBFgH7A/8B
|
|
||||||
5QGzAWMB/wHmAbQBZQH/AecBtAFkAf8B5wG0AWQB/wHmAbQBZQH/AeQBswFmAf8B4wGzAWYB/wHjAbMB
|
|
||||||
ZQH/AeMBsgFkAf8B4wGyAWQB/wHjAbIBZAH/AeMBswFlAf8B4wGuAVoB/wGNAW8BVAH/AxEBFgT/AUsC
|
|
||||||
SQH/AY0CiwH/AYwCiQH/AUwCSgH/AU8CTQH/AU8CTQH/AU8CTQH/AU8CTQH/AU8CTQH/AU8CTQH/AU8C
|
|
||||||
TQH/AU8CTQH/AT4BPAE+Af8BtAF7AQgB/wMKAQ0E/wHAAb4BvQH/AZ4BnQGcAf8BtwG1AbMB/wGwAa0B
|
|
||||||
qwH/AZIBkAGOAf8B3AHeAeAB/wMGAQcBxgHFAcgB/wHDAcEBvwH/AcQBwgHAAf8BzgHMAcoB/wHdAdsB
|
|
||||||
2gH/AcgCxgH/AwwBEAMRARYBswHSAekB/wG2AbABqQH/AfAC6wH/AfYB7gHwAf8B7wLrAf8C6gHpAf8C
|
|
||||||
6gHpAf8B6gHrAekB/wHpAeoB6AX/AU4BkAHIAf8BPgFwAZoB/wwAAxEBFgH7A/8B3QGpAVgB/wHeAasB
|
|
||||||
WwH/Ad4BqwFcAf8B3gGrAVwB/wHeAasBWwH/Ad0BqQFZAf8B3QGnAVQB/wHpAcMBigH/AfkB6QHSAf8B
|
|
||||||
+QHoAdEB/wH4AeUBygH/AekBwwGKAf8B3AGjAUkB/wGNAW8BVAH/AxEBFgT/AUICQAH/ATwCOgH/AUMC
|
|
||||||
QQH/AUYCRAH/AUYCRAH/AUYCRAH/AUYCRAH/AUYCRAH/AUYCRAH/AUYCRAH/AUYCRAH/AUYCRAH/ATQB
|
|
||||||
MwE1Af8BtAF7AQgB/wQAAwIBAwGzAbEBsAH/AdABzgHNAf8BwwHBAcAB/wG2AbQBsgH/Ab8BvQG7Af8D
|
|
||||||
EAEVBAABbQJsAeYBvQG6AbkB/wG4AbYBtAH/AY4BiwGKAf8MAAMRARYBvgHaAe8B/wG3AbABqQH/AQAB
|
|
||||||
gwFCAf8BAAGGAUYB/wHvAuoB/wK7AboB/wKcAZ0B/wK8AbsB/wK6AbkF/wFPAZMBzAH/AT8BcAGcAf8M
|
|
||||||
AAMRARYE/wHwAdIBqgH/AeQBuQF6Af8B3wGvAWoB/wHfAa8BagH/AeYBvQGCAf8B9gHlAc0B/wHNAbIB
|
|
||||||
fgH/AacBfAEpAf8BzgHBAacB/wHRAcgBtAH/AckBuQGaAf8BpgF8ASkB/wHjAc0BpQH/AY0BbwFUAf8D
|
|
||||||
EQEWOP8BtQF8AQoB/wgAA1cBsgT/AdMB0AHPAf8B0AHPAc0B/wGuAa0BrAH/AwMBBAQAAYQBgQF/Af8B
|
|
||||||
qAGlAaIB/wGwAa0BqwH/AY8BjQGLAf8MAAMRARYBygHgAfQB/wG1AbABqAH/AeIB4AHfAf8B6gLlAf8B
|
|
||||||
7wHrAeoB/wHrAeoB6QH/AesB6gHpAf8B6AHnAeYB/wHiAeAB3wX/AVEBlgHPAf8BPgFyAZwB/wwAAxEB
|
|
||||||
FgT/AbsBoAFtAf8BoAFuAQ4B/wGgAW4BDwH/AaABbgEPAf8BqAF8ASkB/wHLAb4BpAH/Ad8B4AHkAf8B
|
|
||||||
3QLcAf8B3ALaAf8B3ALaAf8B3ALaAf8B3QHcAd0B/wLeAeEB/wGNAW4BUwH/AxEBFgH2Ad4BugH/AdIB
|
|
||||||
jwEdAf8B0wGSASQB/wHVAZUBKQH/AdYBlwEvAf8B1wGaATQB/wHZAZ0BOQH/AdoBnwE+Af8B2wGiAUMB
|
|
||||||
/wHrAcUBhgH/AbIBegEKAf8BwgGGAQ8C/wHiAaoB/wEAAQoB/AH/AbgBgQERAf8MAANWAa4E/wHYAdcB
|
|
||||||
1QH/AWkCaAHkAxUBHAMDAQQBcQFwAW8B6AG/AbwBugH/AawBqAGmAf8BjwGMAYoB/wMsAUMDLAFDAw0B
|
|
||||||
EQMQARUB1gHoAfgB/wGVAaoBugH/AbIBrgGoAf8BjAGLAYoB/wK0AbIB/wK1AbMB/wK1AbMB/wKzAbEB
|
|
||||||
/wGyAa8BqgH/AbUBrwGoAf8BVgGaAdMB/wE/AXMBnQH/DAADEAEVBP8B2QHXAdgB/wHZAdgB2QH/A9kB
|
|
||||||
/wPZAf8B2QHYAdkB/wHZAtcB/wHZAdcB1gH/AdkB1wHWAf8B2QHXAdYB/wHZAdcB1gH/AdkB1wHWAf8B
|
|
||||||
2QHXAdYB/wHYAdcB1gH/AY0BbgFTAf8DBAEFAdkBswFqAf8B7QHQAZ4B/wHtAc8BnQH/AewBzwGcAf8B
|
|
||||||
7AHOAZsB/wHsAc4BmgH/AewBzQGZAf8B7AHNAZgB/wHrAcwBlwH/AewBzAGXAf8B7gHOAZkB/wHtAc4B
|
|
||||||
mAH/Ae8BzgGRAf8B9wHTAY0B/wFaAVgBVQGzEAADVgGuA/wB/wHzAfIB8wH/AXcBdQFzAf8DPgFqAxMB
|
|
||||||
GgGvAawBqwH/Ab8BvAG6Af8BqQGmAaQB/wHBAb8BvAH/AuMB4gH/AwYBBwMDAQQBRAF4AaEB/wFBAXYB
|
|
||||||
oAH/AT8BdQGgAf8BsAGsAagB/wHSAdABzgH/Ac4BzAHKAf8BzAHKAckB/wHQAc0BywH/ATkBcgGhAf8B
|
|
||||||
QQF2AaAB/wFCAXYBoAH/AVUBWAFaAbQMAAMDAQQBjwFxAVYB/wGOAW8BUwH/AY4BbwFTAf8BjgFvAVMB
|
|
||||||
/wGOAW8BUwH/AY4BbwFTAf8BjgFvAVMB/wGOAW8BUwH/AY4BbwFTAf8BjgFvAVMB/wGOAW8BUwH/AY4B
|
|
||||||
bwFTAf8BjgFvAVMB/wGOAW8BUwH/AVkBWAFXAbRUAAMMAQ8BeQF1AXMB9wGzAbIBsQH/AcEBwAG/Af8D
|
|
||||||
XAHBBAIBcAFvAW4B5QGZAZYBlAH/AYIBgAF+Af8DGwEmGAADWQGzA6cB/wOoAf8DAwEEHAABQgFNAT4H
|
|
||||||
AAE+AwABKAMAAUADAAEgAwABAQEAAQEGAAEBFgAD/3kAAYALAAGHAfkB/wGBBAABgwHwBgABgQHgBgAB
|
|
||||||
gAHABgABgAEBBgABwAEDBgAB4AEHBgABwAEPAQABAQQAAYABAQEAAQcHAAEHBwABBwQAAYABhwEAAQcE
|
|
||||||
AAHAAYcBAAEHBAAB4AIAAQcEAAHwAgABBwIAAv8B+AEBAfgBfws=
|
|
||||||
</value>
|
|
||||||
</data>
|
|
||||||
<metadata name="toolStrip_terminal.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
|
||||||
<value>1409, 17</value>
|
|
||||||
</metadata>
|
|
||||||
<metadata name="toolStrip_MasterTraders.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
|
||||||
<value>1012, 17</value>
|
|
||||||
</metadata>
|
|
||||||
<metadata name="toolStrip_slaveTraders.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
|
||||||
<value>1264, 17</value>
|
|
||||||
</metadata>
|
|
||||||
<metadata name="toolStrip2.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
|
||||||
<value>480, 17</value>
|
|
||||||
</metadata>
|
|
||||||
<metadata name="toolStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
|
||||||
<value>335, 17</value>
|
|
||||||
</metadata>
|
|
||||||
<metadata name="toolStrip6.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
|
||||||
<value>2273, 17</value>
|
|
||||||
</metadata>
|
|
||||||
<metadata name="toolStrip5.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
|
||||||
<value>2128, 17</value>
|
|
||||||
</metadata>
|
|
||||||
<metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>156</value>
|
|
||||||
</metadata>
|
|
||||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
|
||||||
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
|
||||||
<value>
|
|
||||||
AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAA
|
|
||||||
AADGxsb///////j4+P/4+Pj/+/v7/+/v7//Ly8v/w8PD/8jIyP/CwsL/8fHx//v7+//4+Pj/+Pj4////
|
|
||||||
///FxcX//Pz8//n5+f/5+fn/+fn5//v7+//s7Oz/2NjY/9nZ2f/b29v/2dnZ//Hx8f/6+vr/+fn5//n5
|
|
||||||
+f/5+fn//Pz8//f39//5+fn/+vr6//r6+v/5+fn//v7+//j4+P/8/Pz//f39//j4+P/+/v7/+vr6//r6
|
|
||||||
+v/6+vr/+fn5//j4+P/5+fn/+fn5//r6+v/4+Pj//////5+dnv8mISL/VFBR/1dTVP8kHh//mJWW////
|
|
||||||
///4+Pj/+vr6//r6+v/5+fn/+vr6//r6+v/5+fn//v7+/+vq6v8gGxz/FA4P/xEMDf8QCwz/FQ8Q/xwX
|
|
||||||
GP/m5ub///////n5+f/6+vr/+vr6//r6+v/6+vr/+vn5//z8/P/39/f/ODM0/wMAAP8cFxj/GxYX/wQA
|
|
||||||
AP8zLi//8fHx//v7+//5+fn/+vr6//r6+v/6+vr/+vr6//7+/v/r6+v/4uHh/9bV1f9wbW7/KCMk/ykk
|
|
||||||
Jf9xbm//zs3N///////39/f/+vr6//r6+v/6+vr/+vr6//f39///////fHl6/zMuL//w8PD//////0A7
|
|
||||||
PP9EQEH/4eDh/+Tj5P/r6uv/8fHx//39/f/6+vr/+vr6//v7+//4+Pj//////5OQkf9eWlv/raur/6Og
|
|
||||||
of9FQUL/QTw9/zw4Of9VUVH/eXZ3/56cnP//////+Pj4//r6+v/6+vr/+vr6//39/f/u7e3/8PDw/1dT
|
|
||||||
VP81MDH/RUFC/0hERP+0srL/srCx/yEbHP9jX1////////f39//6+vr/+fn5//r6+v/6+vr/+Pj4////
|
|
||||||
///S0dH/zs3N/z46O/80MDD//////+7u7v8ZFBX/Y19g///////39/f/+vr6//n5+f/6+vr/+vr6//r6
|
|
||||||
+v/6+vr/+fj4//////+Fg4P/gX9////////6+vr/cm9v/6Sio///////+Pj4//n5+f/6+vr/+Pj4//n5
|
|
||||||
+f/6+vr/+fn5//j4+P//////4+Pj/+Pi4//+/v7//v7+/+Tj4//w8PD//f39//n5+f/5+fn/9fX1//v7
|
|
||||||
+//8/Pz/+vr6//z8/P/8/Pz/+vr6//j4+P/4+Pj/+vr6//r6+v/4+Pj/+Pj4//n5+f/5+fn/+Pj4/+Tk
|
|
||||||
5P+4uLj/ysrK/8XFxf/Gxsb/xcXF//T09P/7+/v/+fn5//n5+f/6+vr/+fn5//n5+f/5+fn/+fn5//39
|
|
||||||
/f/CwsL/6enp/+7u7v/09PT/8/Pz//Ly8v/4+Pj/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/9/f3////
|
|
||||||
///Dw8P/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
||||||
AAAAAAAAAAAAAA==
|
|
||||||
</value>
|
|
||||||
</data>
|
|
||||||
</root>
|
|
||||||
+3
-136
@@ -6,100 +6,21 @@ using System.Linq;
|
|||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using MongoDB.Bson;
|
|
||||||
using MongoDB.Driver;
|
|
||||||
using PolyTrader.Core.Persistence;
|
using PolyTrader.Core.Persistence;
|
||||||
using PolyTrader.Core.Persistence.Ef;
|
using PolyTrader.Core.Persistence.Ef;
|
||||||
using PolyTrader.Core.Persistence.Mongo;
|
|
||||||
using PolyTrader.Modules.CopyTrading.Persistence;
|
using PolyTrader.Modules.CopyTrading.Persistence;
|
||||||
using PolyTrader.Modules.CopyTrading.Persistence.Ef;
|
using PolyTrader.Modules.CopyTrading.Persistence.Ef;
|
||||||
using PolyTrader.Modules.CopyTrading.Persistence.Mongo;
|
|
||||||
using PolyTraderSharp.Models;
|
using PolyTraderSharp.Models;
|
||||||
|
|
||||||
namespace PolyTraderSharp.Services
|
namespace PolyTraderSharp.Services
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Einmalige Config-Migration Mongo → MySQL (Phase 6, Stufe 4).
|
/// Einmalige Config-Migration nach MySQL (Phase 6, Stufe 4).
|
||||||
/// Kopiert NUR Konfiguration: Accounts, aktive Markets, Master-Trader,
|
/// Quelle: mongoexport-JSON (<see cref="RunFromJson"/>). <see cref="VerifyMySql"/>
|
||||||
/// Copytrading-Account-Settings (inkl. Fallback auf Alt-Felder im accounts-Dokument)
|
/// liest die migrierte Config zur Kontrolle zurück. Idempotent über Upserts.
|
||||||
/// und Demo-Positionen (reines App-State). Handels-/Master-Trader-Historie startet leer.
|
|
||||||
///
|
|
||||||
/// Aufruf: <c>PolyTraderSharp.exe --migrate-config</c> (kein UI-Start).
|
|
||||||
/// Liest die Mongo-Verbindung aus Database:ConnectionString/DatabaseName, die
|
|
||||||
/// MySQL-Verbindung aus Database:MySqlConnectionString (appsettings[.Local].json).
|
|
||||||
/// Idempotent über Upserts (mehrfacher Aufruf überschreibt, dupliziert nicht).
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class ConfigMigrator
|
public static class ConfigMigrator
|
||||||
{
|
{
|
||||||
public static void Run(string mongoConnection, string mongoDbName, string mySqlConnection)
|
|
||||||
{
|
|
||||||
Console.WriteLine("=== Config-Migration Mongo -> MySQL ===");
|
|
||||||
Console.WriteLine($"Quelle (Mongo): {mongoDbName} @ {mongoConnection}");
|
|
||||||
Console.WriteLine($"Ziel (MySQL): {Redact(mySqlConnection)}");
|
|
||||||
|
|
||||||
// --- Quelle: Mongo ---
|
|
||||||
var mongoDb = new MongoClient(mongoConnection).GetDatabase(mongoDbName);
|
|
||||||
var srcAccounts = new MongoAccountRepository(mongoDb);
|
|
||||||
var srcMarkets = new MongoMarketRepository(mongoDb);
|
|
||||||
var srcPositions = new MongoPositionRepository(mongoDb);
|
|
||||||
var srcTraders = new MongoTrackedTraderRepository(mongoDb);
|
|
||||||
var srcSettings = new MongoCopyTradingAccountSettingsRepository(mongoDb);
|
|
||||||
var rawAccounts = mongoDb.GetCollection<BsonDocument>("accounts");
|
|
||||||
|
|
||||||
// --- Ziel: MySQL/EF (eigene Mini-Container für die DbContext-Factories) ---
|
|
||||||
var target = new ServiceCollection()
|
|
||||||
.AddDbContextFactory<CoreDbContext>(o => o.UseMySql(mySqlConnection, ServerVersion.AutoDetect(mySqlConnection)))
|
|
||||||
.AddDbContextFactory<CopyTradingDbContext>(o => o.UseMySql(mySqlConnection, ServerVersion.AutoDetect(mySqlConnection)))
|
|
||||||
.BuildServiceProvider();
|
|
||||||
|
|
||||||
var coreFactory = target.GetRequiredService<IDbContextFactory<CoreDbContext>>();
|
|
||||||
var ctFactory = target.GetRequiredService<IDbContextFactory<CopyTradingDbContext>>();
|
|
||||||
|
|
||||||
IAccountRepository dstAccounts = new EfAccountRepository(coreFactory);
|
|
||||||
IMarketRepository dstMarkets = new EfMarketRepository(coreFactory);
|
|
||||||
IPositionRepository dstPositions = new EfPositionRepository(coreFactory);
|
|
||||||
ITrackedTraderRepository dstTraders = new EfTrackedTraderRepository(ctFactory);
|
|
||||||
ICopyTradingAccountSettingsRepository dstSettings = new EfCopyTradingAccountSettingsRepository(ctFactory);
|
|
||||||
|
|
||||||
dstMarkets.EnsureIndexes();
|
|
||||||
|
|
||||||
// 1) Accounts
|
|
||||||
var accounts = srcAccounts.GetAll();
|
|
||||||
foreach (var acc in accounts)
|
|
||||||
dstAccounts.Upsert(acc);
|
|
||||||
Console.WriteLine($"[OK] Accounts: {accounts.Count}");
|
|
||||||
|
|
||||||
// 2) Aktive Markets
|
|
||||||
var markets = srcMarkets.GetActive();
|
|
||||||
foreach (var m in markets)
|
|
||||||
dstMarkets.Upsert(m);
|
|
||||||
Console.WriteLine($"[OK] Markets (aktiv): {markets.Count}");
|
|
||||||
|
|
||||||
// 3) Master-Trader
|
|
||||||
var traders = srcTraders.GetAll();
|
|
||||||
foreach (var t in traders)
|
|
||||||
dstTraders.Upsert(t);
|
|
||||||
Console.WriteLine($"[OK] Master-Trader: {traders.Count}");
|
|
||||||
|
|
||||||
// 4) Copytrading-Account-Settings (mit Fallback auf Alt-Felder)
|
|
||||||
int settingsCount = MigrateSettings(accounts, srcSettings, dstSettings, rawAccounts);
|
|
||||||
Console.WriteLine($"[OK] Copytrading-Settings: {settingsCount}");
|
|
||||||
|
|
||||||
// 5) Demo-Positionen (reines App-State; Live-Positionen werden aus der Chain rekonstruiert)
|
|
||||||
int demoPos = 0;
|
|
||||||
foreach (var acc in accounts.Where(a => a.IsDemo))
|
|
||||||
{
|
|
||||||
foreach (var pos in srcPositions.GetDemo(acc.AccountId))
|
|
||||||
{
|
|
||||||
dstPositions.UpsertDemo(acc.AccountId, pos);
|
|
||||||
demoPos++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Console.WriteLine($"[OK] Demo-Positionen: {demoPos}");
|
|
||||||
|
|
||||||
Console.WriteLine("=== Migration abgeschlossen ===");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Config-Migration aus mongoexport-JSON (Ordner mit PolyTraderDB.accounts.json /
|
/// Config-Migration aus mongoexport-JSON (Ordner mit PolyTraderDB.accounts.json /
|
||||||
/// .trackers.json) → MySQL. Markets bleiben aussen vor (bereits migriert und werden
|
/// .trackers.json) → MySQL. Markets bleiben aussen vor (bereits migriert und werden
|
||||||
@@ -321,60 +242,6 @@ namespace PolyTraderSharp.Services
|
|||||||
return set;
|
return set;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int MigrateSettings(
|
|
||||||
List<AccountState> accounts,
|
|
||||||
ICopyTradingAccountSettingsRepository src,
|
|
||||||
ICopyTradingAccountSettingsRepository dst,
|
|
||||||
IMongoCollection<BsonDocument> rawAccounts)
|
|
||||||
{
|
|
||||||
var existing = src.GetAll().ToDictionary(s => s.AccountId);
|
|
||||||
int count = 0;
|
|
||||||
|
|
||||||
foreach (var acc in accounts)
|
|
||||||
{
|
|
||||||
if (existing.TryGetValue(acc.AccountId, out var s))
|
|
||||||
{
|
|
||||||
dst.Upsert(s);
|
|
||||||
count++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var settings = new CopyTradingAccountSettings { AccountId = acc.AccountId };
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var raw = rawAccounts.Find(Builders<BsonDocument>.Filter.Eq("_id", acc.AccountId)).FirstOrDefault();
|
|
||||||
if (raw != null)
|
|
||||||
{
|
|
||||||
settings.PerMarketLimit = Dec(raw, "PerMarketLimit", settings.PerMarketLimit);
|
|
||||||
settings.MaxPriceDifference = Dec(raw, "MaxPriceDifference", settings.MaxPriceDifference);
|
|
||||||
settings.MaxBuyPrice = Dec(raw, "MaxBuyPrice", settings.MaxBuyPrice);
|
|
||||||
settings.ProfitTarget = Dec(raw, "ProfitTarget", settings.ProfitTarget);
|
|
||||||
settings.PreRedeemLimit = Dec(raw, "PreRedeemLimit", settings.PreRedeemLimit);
|
|
||||||
settings.PerMasterLimit = Dec(raw, "PerMasterLimit", settings.PerMasterLimit);
|
|
||||||
settings.perMaxTime6h = Dec(raw, "perMaxTime6h", settings.perMaxTime6h);
|
|
||||||
settings.perMaxTime24h = Dec(raw, "perMaxTime24h", settings.perMaxTime24h);
|
|
||||||
settings.perMaxTime72h = Dec(raw, "perMaxTime72h", settings.perMaxTime72h);
|
|
||||||
settings.perMaxTimeNone = Dec(raw, "perMaxTimeNone", settings.perMaxTimeNone);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
|
|
||||||
dst.Upsert(settings);
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static decimal Dec(BsonDocument doc, string field, decimal fallback)
|
|
||||||
{
|
|
||||||
if (doc.TryGetValue(field, out var v))
|
|
||||||
{
|
|
||||||
try { return v.ToDecimal(); } catch { }
|
|
||||||
}
|
|
||||||
return fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string Redact(string conn) =>
|
private static string Redact(string conn) =>
|
||||||
System.Text.RegularExpressions.Regex.Replace(conn, "(?i)(password=)[^;]*", "$1***");
|
System.Text.RegularExpressions.Regex.Replace(conn, "(?i)(password=)[^;]*", "$1***");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ namespace PolyTraderSharp.Services
|
|||||||
|
|
||||||
_jobStatus = new JobStatusRow
|
_jobStatus = new JobStatusRow
|
||||||
{
|
{
|
||||||
JobName = "MongoDB Transaction Log",
|
JobName = "MySQL Transaction Log",
|
||||||
Description = "Awaits internal signals to write Closed Trades to the database safely.",
|
Description = "Awaits internal signals to write Closed Trades to the database safely.",
|
||||||
StatusText = "Pending Initial Delay..."
|
StatusText = "Pending Initial Delay..."
|
||||||
};
|
};
|
||||||
@@ -97,7 +97,7 @@ namespace PolyTraderSharp.Services
|
|||||||
ExitReason = trade.ExitReason
|
ExitReason = trade.ExitReason
|
||||||
});
|
});
|
||||||
|
|
||||||
_logger.Debug($"Saved ClosedTrade {trade.TradeId} to MongoDB");
|
_logger.Debug($"Saved ClosedTrade {trade.TradeId} to MySQL");
|
||||||
_jobStatus.LastRun = DateTime.Now;
|
_jobStatus.LastRun = DateTime.Now;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace PolyTraderSharp.Services
|
|||||||
|
|
||||||
_jobStatus = new JobStatusRow
|
_jobStatus = new JobStatusRow
|
||||||
{
|
{
|
||||||
JobName = "LiteDB State Snapshot",
|
JobName = "State Snapshot",
|
||||||
Description = "Saves active application state (balances, open pos) to snapshot.json.",
|
Description = "Saves active application state (balances, open pos) to snapshot.json.",
|
||||||
StatusText = "Pending Initial Delay..."
|
StatusText = "Pending Initial Delay..."
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ using System.Linq;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using MongoDB.Bson;
|
|
||||||
using MongoDB.Driver;
|
|
||||||
using PolyTrader.Core.Persistence;
|
using PolyTrader.Core.Persistence;
|
||||||
using PolyTrader.Modules.CopyTrading.Persistence;
|
using PolyTrader.Modules.CopyTrading.Persistence;
|
||||||
using PolyTraderSharp.Models;
|
using PolyTraderSharp.Models;
|
||||||
@@ -26,7 +24,6 @@ namespace PolyTraderSharp.Services
|
|||||||
private readonly IPositionRepository _positionRepo;
|
private readonly IPositionRepository _positionRepo;
|
||||||
private readonly ICopyTradingAccountSettingsRepository _accountSettingsRepo;
|
private readonly ICopyTradingAccountSettingsRepository _accountSettingsRepo;
|
||||||
private readonly ITrackedTraderRepository _traderRepo;
|
private readonly ITrackedTraderRepository _traderRepo;
|
||||||
private readonly IMongoDatabase _db;
|
|
||||||
private readonly TerminalLogger _logger;
|
private readonly TerminalLogger _logger;
|
||||||
|
|
||||||
public StartupHydrationService(
|
public StartupHydrationService(
|
||||||
@@ -36,7 +33,6 @@ namespace PolyTraderSharp.Services
|
|||||||
IPositionRepository positionRepo,
|
IPositionRepository positionRepo,
|
||||||
ICopyTradingAccountSettingsRepository accountSettingsRepo,
|
ICopyTradingAccountSettingsRepository accountSettingsRepo,
|
||||||
ITrackedTraderRepository traderRepo,
|
ITrackedTraderRepository traderRepo,
|
||||||
IMongoDatabase db,
|
|
||||||
TerminalLogger logger)
|
TerminalLogger logger)
|
||||||
{
|
{
|
||||||
_state = state;
|
_state = state;
|
||||||
@@ -45,7 +41,6 @@ namespace PolyTraderSharp.Services
|
|||||||
_positionRepo = positionRepo;
|
_positionRepo = positionRepo;
|
||||||
_accountSettingsRepo = accountSettingsRepo;
|
_accountSettingsRepo = accountSettingsRepo;
|
||||||
_traderRepo = traderRepo;
|
_traderRepo = traderRepo;
|
||||||
_db = db;
|
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,14 +80,12 @@ namespace PolyTraderSharp.Services
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Lädt die Copytrading-Account-Settings in den State. Existiert für einen Account noch
|
/// Lädt die Copytrading-Account-Settings in den State. Existiert für einen Account noch
|
||||||
/// kein Eintrag, werden die Werte einmalig aus den alten AccountState-Feldern des
|
/// kein Eintrag, wird ein Default-Eintrag angelegt und persistiert.
|
||||||
/// Roh-Dokuments migriert (damit konfigurierte Limits nach dem Modell-Split erhalten bleiben).
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void HydrateAccountSettings(List<AccountState> accounts)
|
private void HydrateAccountSettings(List<AccountState> accounts)
|
||||||
{
|
{
|
||||||
var existing = _accountSettingsRepo.GetAll().ToDictionary(s => s.AccountId);
|
var existing = _accountSettingsRepo.GetAll().ToDictionary(s => s.AccountId);
|
||||||
var rawAccounts = _db.GetCollection<BsonDocument>("accounts");
|
int created = 0;
|
||||||
int migrated = 0;
|
|
||||||
|
|
||||||
foreach (var acc in accounts)
|
foreach (var acc in accounts)
|
||||||
{
|
{
|
||||||
@@ -103,41 +96,13 @@ namespace PolyTraderSharp.Services
|
|||||||
}
|
}
|
||||||
|
|
||||||
var settings = new CopyTradingAccountSettings { AccountId = acc.AccountId };
|
var settings = new CopyTradingAccountSettings { AccountId = acc.AccountId };
|
||||||
try
|
|
||||||
{
|
|
||||||
var raw = rawAccounts.Find(Builders<BsonDocument>.Filter.Eq("_id", acc.AccountId)).FirstOrDefault();
|
|
||||||
if (raw != null)
|
|
||||||
{
|
|
||||||
settings.PerMarketLimit = Dec(raw, "PerMarketLimit", settings.PerMarketLimit);
|
|
||||||
settings.MaxPriceDifference = Dec(raw, "MaxPriceDifference", settings.MaxPriceDifference);
|
|
||||||
settings.MaxBuyPrice = Dec(raw, "MaxBuyPrice", settings.MaxBuyPrice);
|
|
||||||
settings.ProfitTarget = Dec(raw, "ProfitTarget", settings.ProfitTarget);
|
|
||||||
settings.PreRedeemLimit = Dec(raw, "PreRedeemLimit", settings.PreRedeemLimit);
|
|
||||||
settings.PerMasterLimit = Dec(raw, "PerMasterLimit", settings.PerMasterLimit);
|
|
||||||
settings.perMaxTime6h = Dec(raw, "perMaxTime6h", settings.perMaxTime6h);
|
|
||||||
settings.perMaxTime24h = Dec(raw, "perMaxTime24h", settings.perMaxTime24h);
|
|
||||||
settings.perMaxTime72h = Dec(raw, "perMaxTime72h", settings.perMaxTime72h);
|
|
||||||
settings.perMaxTimeNone = Dec(raw, "perMaxTimeNone", settings.perMaxTimeNone);
|
|
||||||
migrated++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
|
|
||||||
_accountSettingsRepo.Upsert(settings);
|
_accountSettingsRepo.Upsert(settings);
|
||||||
_copyState.AccountSettings[acc.AccountId] = settings;
|
_copyState.AccountSettings[acc.AccountId] = settings;
|
||||||
|
created++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (migrated > 0)
|
if (created > 0)
|
||||||
_logger.Info($"Copytrading-Account-Settings: {migrated} Account(s) aus Alt-Feldern migriert.");
|
_logger.Info($"Copytrading-Account-Settings: {created} Default-Eintrag/-Einträge angelegt.");
|
||||||
}
|
|
||||||
|
|
||||||
private static decimal Dec(BsonDocument doc, string field, decimal fallback)
|
|
||||||
{
|
|
||||||
if (doc.TryGetValue(field, out var v))
|
|
||||||
{
|
|
||||||
try { return v.ToDecimal(); } catch { }
|
|
||||||
}
|
|
||||||
return fallback;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
||||||
|
|||||||
@@ -8,15 +8,7 @@ namespace PolyTrader.Core.Configuration
|
|||||||
{
|
{
|
||||||
public const string SectionName = "Database";
|
public const string SectionName = "Database";
|
||||||
|
|
||||||
/// <summary>"MySql" (Zielzustand) oder "Mongo" (Übergang/Config-Migration).</summary>
|
|
||||||
public string Provider { get; set; } = "MySql";
|
|
||||||
|
|
||||||
/// <summary>MySQL-Connection-String (aus gitignorierter appsettings.Local.json).</summary>
|
/// <summary>MySQL-Connection-String (aus gitignorierter appsettings.Local.json).</summary>
|
||||||
public string MySqlConnectionString { get; set; } = string.Empty;
|
public string MySqlConnectionString { get; set; } = string.Empty;
|
||||||
|
|
||||||
// --- MongoDB (nur noch für die einmalige Config-Migration nach MySQL) ---
|
|
||||||
public string ConnectionString { get; set; } = "mongodb://localhost:27017";
|
|
||||||
|
|
||||||
public string DatabaseName { get; set; } = "PolyTraderDB";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,37 +4,25 @@ using Microsoft.Extensions.DependencyInjection;
|
|||||||
using PolyTrader.Core.Configuration;
|
using PolyTrader.Core.Configuration;
|
||||||
using PolyTrader.Core.Persistence;
|
using PolyTrader.Core.Persistence;
|
||||||
using PolyTrader.Core.Persistence.Ef;
|
using PolyTrader.Core.Persistence.Ef;
|
||||||
using PolyTrader.Core.Persistence.Mongo;
|
|
||||||
|
|
||||||
namespace PolyTrader.Core.DependencyInjection
|
namespace PolyTrader.Core.DependencyInjection
|
||||||
{
|
{
|
||||||
public static class ServiceCollectionExtensions
|
public static class ServiceCollectionExtensions
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Registriert die Core-Persistenzschicht hinter den Repository-Interfaces.
|
/// Registriert die Core-Persistenzschicht (EF Core / Pomelo / MySQL) hinter den
|
||||||
/// Provider "MySql" -> EF Core (Pomelo) über einen DbContextFactory (thread-safe,
|
/// Repository-Interfaces über einen DbContextFactory (thread-safe, kurzlebiger
|
||||||
/// kurzlebiger Context je Operation). Provider "Mongo" -> Mongo-Implementierungen
|
/// Context je Operation).
|
||||||
/// (Übergang / Config-Migration).
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static IServiceCollection AddCorePersistence(this IServiceCollection services, DatabaseOptions options)
|
public static IServiceCollection AddCorePersistence(this IServiceCollection services, DatabaseOptions options)
|
||||||
{
|
{
|
||||||
if (string.Equals(options.Provider, "MySql", StringComparison.OrdinalIgnoreCase))
|
var conn = options.MySqlConnectionString;
|
||||||
{
|
services.AddDbContextFactory<CoreDbContext>(o => o.UseMySql(conn, ServerVersion.AutoDetect(conn)));
|
||||||
var conn = options.MySqlConnectionString;
|
|
||||||
services.AddDbContextFactory<CoreDbContext>(o => o.UseMySql(conn, ServerVersion.AutoDetect(conn)));
|
|
||||||
|
|
||||||
services.AddSingleton<IAccountRepository, EfAccountRepository>();
|
services.AddSingleton<IAccountRepository, EfAccountRepository>();
|
||||||
services.AddSingleton<IMarketRepository, EfMarketRepository>();
|
services.AddSingleton<IMarketRepository, EfMarketRepository>();
|
||||||
services.AddSingleton<IPositionRepository, EfPositionRepository>();
|
services.AddSingleton<IPositionRepository, EfPositionRepository>();
|
||||||
services.AddSingleton<ITradeLogRepository, EfTradeLogRepository>();
|
services.AddSingleton<ITradeLogRepository, EfTradeLogRepository>();
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
services.AddSingleton<IAccountRepository, MongoAccountRepository>();
|
|
||||||
services.AddSingleton<IMarketRepository, MongoMarketRepository>();
|
|
||||||
services.AddSingleton<IPositionRepository, MongoPositionRepository>();
|
|
||||||
services.AddSingleton<ITradeLogRepository, MongoTradeLogRepository>();
|
|
||||||
}
|
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ namespace PolyTraderSharp.Models
|
|||||||
public class AccountState
|
public class AccountState
|
||||||
{
|
{
|
||||||
[Browsable(false)]
|
[Browsable(false)]
|
||||||
[MongoDB.Bson.Serialization.Attributes.BsonId] public int AccountId { get; set; }
|
public int AccountId { get; set; }
|
||||||
|
|
||||||
[Category("01. General")]
|
[Category("01. General")]
|
||||||
public string Name { get; set; } = string.Empty;
|
public string Name { get; set; } = string.Empty;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ namespace PolyTraderSharp.Models
|
|||||||
{
|
{
|
||||||
public class MarketData
|
public class MarketData
|
||||||
{
|
{
|
||||||
[MongoDB.Bson.Serialization.Attributes.BsonId] public string Id { get; set; } = string.Empty;
|
public string Id { get; set; } = string.Empty;
|
||||||
public string ConditionId { get; set; } = string.Empty;
|
public string ConditionId { get; set; } = string.Empty;
|
||||||
public string Question { get; set; } = string.Empty;
|
public string Question { get; set; } = string.Empty;
|
||||||
public string Slug { get; set; } = string.Empty;
|
public string Slug { get; set; } = string.Empty;
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ namespace PolyTraderSharp.Models
|
|||||||
public int AccountId { get; set; }
|
public int AccountId { get; set; }
|
||||||
public bool IsDemo { get; set; }
|
public bool IsDemo { get; set; }
|
||||||
|
|
||||||
[MongoDB.Bson.Serialization.Attributes.BsonId]
|
|
||||||
public string TokenId { get; set; } = string.Empty;
|
public string TokenId { get; set; } = string.Empty;
|
||||||
public string MarketSlug { get; set; } = string.Empty;
|
public string MarketSlug { get; set; } = string.Empty;
|
||||||
public string ConditionId { get; set; } = string.Empty;
|
public string ConditionId { get; set; } = string.Empty;
|
||||||
|
|||||||
@@ -11,8 +11,7 @@ namespace PolyTraderSharp.Models
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class TradeRecord
|
public class TradeRecord
|
||||||
{
|
{
|
||||||
[MongoDB.Bson.Serialization.Attributes.BsonId]
|
public string Id { get; set; } = Guid.NewGuid().ToString("N");
|
||||||
public string Id { get; set; } = MongoDB.Bson.ObjectId.GenerateNewId().ToString();
|
|
||||||
|
|
||||||
/// <summary>Herkunftsmodul, z.B. "CopyTrading".</summary>
|
/// <summary>Herkunftsmodul, z.B. "CopyTrading".</summary>
|
||||||
public string ModuleName { get; set; } = string.Empty;
|
public string ModuleName { get; set; } = string.Empty;
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using MongoDB.Driver;
|
|
||||||
using PolyTraderSharp.Models;
|
|
||||||
|
|
||||||
namespace PolyTrader.Core.Persistence.Mongo
|
|
||||||
{
|
|
||||||
public class MongoAccountRepository : IAccountRepository
|
|
||||||
{
|
|
||||||
private readonly IMongoCollection<AccountState> _col;
|
|
||||||
|
|
||||||
public MongoAccountRepository(IMongoDatabase db)
|
|
||||||
{
|
|
||||||
_col = db.GetCollection<AccountState>("accounts");
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<AccountState> GetAll() => _col.Find(_ => true).ToList();
|
|
||||||
|
|
||||||
public void Upsert(AccountState account) =>
|
|
||||||
_col.ReplaceOne(x => x.AccountId == account.AccountId, account, new ReplaceOptions { IsUpsert = true });
|
|
||||||
|
|
||||||
public void Delete(int accountId) => _col.DeleteMany(x => x.AccountId == accountId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using MongoDB.Driver;
|
|
||||||
using PolyTraderSharp.Models;
|
|
||||||
|
|
||||||
namespace PolyTrader.Core.Persistence.Mongo
|
|
||||||
{
|
|
||||||
public class MongoMarketRepository : IMarketRepository
|
|
||||||
{
|
|
||||||
private readonly IMongoCollection<MarketData> _col;
|
|
||||||
|
|
||||||
public MongoMarketRepository(IMongoDatabase db)
|
|
||||||
{
|
|
||||||
_col = db.GetCollection<MarketData>("markets");
|
|
||||||
}
|
|
||||||
|
|
||||||
public MarketData? GetById(string id) => _col.Find(x => x.Id == id).FirstOrDefault();
|
|
||||||
|
|
||||||
public MarketData? FindByTokenId(string tokenId) =>
|
|
||||||
_col.Find(x => x.ClobTokenIds != null && x.ClobTokenIds.Contains(tokenId)).FirstOrDefault();
|
|
||||||
|
|
||||||
public List<MarketData> GetActive() => _col.Find(x => !x.Closed).ToList();
|
|
||||||
|
|
||||||
public void Upsert(MarketData market) =>
|
|
||||||
_col.ReplaceOne(x => x.Id == market.Id, market, new ReplaceOptions { IsUpsert = true });
|
|
||||||
|
|
||||||
public void Insert(MarketData market) => _col.InsertOne(market);
|
|
||||||
|
|
||||||
public void Update(MarketData market) => _col.ReplaceOne(x => x.Id == market.Id, market);
|
|
||||||
|
|
||||||
public void EnsureIndexes()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var keys = Builders<MarketData>.IndexKeys.Ascending(x => x.Id);
|
|
||||||
_col.Indexes.CreateOne(new CreateIndexModel<MarketData>(keys));
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using MongoDB.Driver;
|
|
||||||
using PolyTraderSharp.Models;
|
|
||||||
|
|
||||||
namespace PolyTrader.Core.Persistence.Mongo
|
|
||||||
{
|
|
||||||
public class MongoPositionRepository : IPositionRepository
|
|
||||||
{
|
|
||||||
private readonly IMongoDatabase _db;
|
|
||||||
|
|
||||||
public MongoPositionRepository(IMongoDatabase db)
|
|
||||||
{
|
|
||||||
_db = db;
|
|
||||||
}
|
|
||||||
|
|
||||||
private IMongoCollection<Position> Live(int accountId) =>
|
|
||||||
_db.GetCollection<Position>($"open_positions_{accountId}");
|
|
||||||
|
|
||||||
private IMongoCollection<Position> Demo(int accountId) =>
|
|
||||||
_db.GetCollection<Position>($"demo_positions_{accountId}");
|
|
||||||
|
|
||||||
public List<Position> GetLive(int accountId) => Live(accountId).Find(_ => true).ToList();
|
|
||||||
public List<Position> GetDemo(int accountId) => Demo(accountId).Find(_ => true).ToList();
|
|
||||||
|
|
||||||
public Position? FindLive(int accountId, string tokenId) =>
|
|
||||||
Live(accountId).Find(x => x.TokenId == tokenId).FirstOrDefault();
|
|
||||||
|
|
||||||
public Position? FindDemo(int accountId, string tokenId) =>
|
|
||||||
Demo(accountId).Find(x => x.TokenId == tokenId).FirstOrDefault();
|
|
||||||
|
|
||||||
public void UpsertLive(int accountId, Position position) =>
|
|
||||||
Live(accountId).ReplaceOne(x => x.TokenId == position.TokenId, position, new ReplaceOptions { IsUpsert = true });
|
|
||||||
|
|
||||||
public void UpsertDemo(int accountId, Position position) =>
|
|
||||||
Demo(accountId).ReplaceOne(x => x.TokenId == position.TokenId, position, new ReplaceOptions { IsUpsert = true });
|
|
||||||
|
|
||||||
public void DeleteLive(int accountId, string tokenId) =>
|
|
||||||
Live(accountId).DeleteOne(x => x.TokenId == tokenId);
|
|
||||||
|
|
||||||
public void DeleteDemo(int accountId, string tokenId) =>
|
|
||||||
Demo(accountId).DeleteOne(x => x.TokenId == tokenId);
|
|
||||||
|
|
||||||
public void DropDemo(int accountId) => _db.DropCollection($"demo_positions_{accountId}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Linq.Expressions;
|
|
||||||
using MongoDB.Driver;
|
|
||||||
using PolyTraderSharp.Models;
|
|
||||||
|
|
||||||
namespace PolyTrader.Core.Persistence.Mongo
|
|
||||||
{
|
|
||||||
public class MongoTradeLogRepository : ITradeLogRepository
|
|
||||||
{
|
|
||||||
private readonly IMongoCollection<TradeRecord> _col;
|
|
||||||
|
|
||||||
public MongoTradeLogRepository(IMongoDatabase db)
|
|
||||||
{
|
|
||||||
_col = db.GetCollection<TradeRecord>("trade_log");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void EnsureIndexes()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_col.Indexes.CreateOne(new CreateIndexModel<TradeRecord>(
|
|
||||||
Builders<TradeRecord>.IndexKeys.Descending(x => x.ClosedAt)));
|
|
||||||
_col.Indexes.CreateOne(new CreateIndexModel<TradeRecord>(
|
|
||||||
Builders<TradeRecord>.IndexKeys.Ascending(x => x.ModuleName)));
|
|
||||||
_col.Indexes.CreateOne(new CreateIndexModel<TradeRecord>(
|
|
||||||
Builders<TradeRecord>.IndexKeys.Ascending(x => x.AccountId)));
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Insert(TradeRecord record) => _col.InsertOne(record);
|
|
||||||
|
|
||||||
public List<TradeRecord> GetRecent(int limit) =>
|
|
||||||
_col.Find(_ => true).SortByDescending(x => x.ClosedAt).Limit(limit).ToList();
|
|
||||||
|
|
||||||
public List<TradeRecord> Find(Expression<Func<TradeRecord, bool>> predicate) =>
|
|
||||||
_col.Find(predicate).ToList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -10,7 +10,6 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="MongoDB.Driver" Version="2.24.0" />
|
|
||||||
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.3" />
|
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.3" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.11">
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.11">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using MongoDB.Driver;
|
|
||||||
using PolyTrader.Core.Persistence;
|
using PolyTrader.Core.Persistence;
|
||||||
using PolyTraderSharp.Models;
|
using PolyTraderSharp.Models;
|
||||||
using PolyTraderSharp.Services;
|
using PolyTraderSharp.Services;
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ using Microsoft.Extensions.DependencyInjection;
|
|||||||
using PolyTrader.Core.Modularity;
|
using PolyTrader.Core.Modularity;
|
||||||
using PolyTrader.Modules.CopyTrading.Persistence;
|
using PolyTrader.Modules.CopyTrading.Persistence;
|
||||||
using PolyTrader.Modules.CopyTrading.Persistence.Ef;
|
using PolyTrader.Modules.CopyTrading.Persistence.Ef;
|
||||||
using PolyTrader.Modules.CopyTrading.Persistence.Mongo;
|
|
||||||
using PolyTraderSharp;
|
using PolyTraderSharp;
|
||||||
using PolyTraderSharp.Models;
|
using PolyTraderSharp.Models;
|
||||||
using PolyTraderSharp.Services;
|
using PolyTraderSharp.Services;
|
||||||
@@ -37,25 +36,14 @@ namespace PolyTrader.Modules.CopyTrading
|
|||||||
services.AddSingleton(closedTradeChannel.Writer);
|
services.AddSingleton(closedTradeChannel.Writer);
|
||||||
services.AddSingleton(closedTradeChannel.Reader);
|
services.AddSingleton(closedTradeChannel.Reader);
|
||||||
|
|
||||||
// Modul-Persistenz: Provider-Toggle (MySql via EF / Mongo im Übergang).
|
// Modul-Persistenz: EF Core / Pomelo / MySQL (thread-safer DbContextFactory).
|
||||||
var provider = configuration["Database:Provider"] ?? "Mongo";
|
var conn = configuration["Database:MySqlConnectionString"] ?? string.Empty;
|
||||||
if (string.Equals(provider, "MySql", StringComparison.OrdinalIgnoreCase))
|
services.AddDbContextFactory<CopyTradingDbContext>(o => o.UseMySql(conn, ServerVersion.AutoDetect(conn)));
|
||||||
{
|
|
||||||
var conn = configuration["Database:MySqlConnectionString"] ?? string.Empty;
|
|
||||||
services.AddDbContextFactory<CopyTradingDbContext>(o => o.UseMySql(conn, ServerVersion.AutoDetect(conn)));
|
|
||||||
|
|
||||||
services.AddSingleton<ICopyTradeLogRepository, EfCopyTradeLogRepository>();
|
services.AddSingleton<ICopyTradeLogRepository, EfCopyTradeLogRepository>();
|
||||||
services.AddSingleton<ICopyTradingAccountSettingsRepository, EfCopyTradingAccountSettingsRepository>();
|
services.AddSingleton<ICopyTradingAccountSettingsRepository, EfCopyTradingAccountSettingsRepository>();
|
||||||
services.AddSingleton<ITrackedTraderRepository, EfTrackedTraderRepository>();
|
services.AddSingleton<ITrackedTraderRepository, EfTrackedTraderRepository>();
|
||||||
services.AddSingleton<IMasterTraderHistoryRepository, EfMasterTraderHistoryRepository>();
|
services.AddSingleton<IMasterTraderHistoryRepository, EfMasterTraderHistoryRepository>();
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
services.AddSingleton<ICopyTradeLogRepository, MongoCopyTradeLogRepository>();
|
|
||||||
services.AddSingleton<ICopyTradingAccountSettingsRepository, MongoCopyTradingAccountSettingsRepository>();
|
|
||||||
services.AddSingleton<ITrackedTraderRepository, MongoTrackedTraderRepository>();
|
|
||||||
services.AddSingleton<IMasterTraderHistoryRepository, MongoMasterTraderHistoryRepository>();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Modul-Services (Signalquelle, Ausführung, Analytics)
|
// Modul-Services (Signalquelle, Ausführung, Analytics)
|
||||||
services.AddSingleton<TraderMonitorService>();
|
services.AddSingleton<TraderMonitorService>();
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ namespace PolyTraderSharp.Models
|
|||||||
{
|
{
|
||||||
public class ClosedTrade
|
public class ClosedTrade
|
||||||
{
|
{
|
||||||
[MongoDB.Bson.Serialization.Attributes.BsonId] public int TradeId { get; set; }
|
public int TradeId { get; set; }
|
||||||
public int AccountId { get; set; }
|
public int AccountId { get; set; }
|
||||||
public int SourceTraderId { get; set; }
|
public int SourceTraderId { get; set; }
|
||||||
public bool IsDemo { get; set; }
|
public bool IsDemo { get; set; }
|
||||||
|
|||||||
@@ -6,12 +6,11 @@ namespace PolyTraderSharp.Models
|
|||||||
/// Copytrading-spezifische Detail-Einstellungen je Account (Investment-/Zeit-Limits).
|
/// Copytrading-spezifische Detail-Einstellungen je Account (Investment-/Zeit-Limits).
|
||||||
/// Bewusst getrennt vom Core-<see cref="AccountState"/> (allgemeine Account-Daten):
|
/// Bewusst getrennt vom Core-<see cref="AccountState"/> (allgemeine Account-Daten):
|
||||||
/// Diese Werte gehören dem Copytrading-Modul und werden im Modul-View bearbeitet.
|
/// Diese Werte gehören dem Copytrading-Modul und werden im Modul-View bearbeitet.
|
||||||
/// Persistiert in der Collection "ct_account_settings" (BsonId = AccountId).
|
/// Persistiert in Tabelle "mod_copytrading_account_settings" (Key = AccountId).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class CopyTradingAccountSettings
|
public class CopyTradingAccountSettings
|
||||||
{
|
{
|
||||||
[Browsable(false)]
|
[Browsable(false)]
|
||||||
[MongoDB.Bson.Serialization.Attributes.BsonId]
|
|
||||||
public int AccountId { get; set; }
|
public int AccountId { get; set; }
|
||||||
|
|
||||||
[Category("01. Risk Management")]
|
[Category("01. Risk Management")]
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ namespace PolyTraderSharp.Models
|
|||||||
{
|
{
|
||||||
public class MasterTraderHistoryRecord
|
public class MasterTraderHistoryRecord
|
||||||
{
|
{
|
||||||
[MongoDB.Bson.Serialization.Attributes.BsonId] public string Id { get; set; } = MongoDB.Bson.ObjectId.GenerateNewId().ToString();
|
public string Id { get; set; } = Guid.NewGuid().ToString("N");
|
||||||
|
|
||||||
// Verknüpfung zum Master Trader
|
// Verknüpfung zum Master Trader
|
||||||
public int TraderId { get; set; }
|
public int TraderId { get; set; }
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace PolyTraderSharp.Models
|
|||||||
public class TrackedTrader
|
public class TrackedTrader
|
||||||
{
|
{
|
||||||
[Browsable(false)]
|
[Browsable(false)]
|
||||||
[MongoDB.Bson.Serialization.Attributes.BsonId] public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
|
|
||||||
[Category("01. Identification")]
|
[Category("01. Identification")]
|
||||||
public string WalletAddress { get; set; } = string.Empty;
|
public string WalletAddress { get; set; } = string.Empty;
|
||||||
|
|||||||
-39
@@ -1,39 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using MongoDB.Driver;
|
|
||||||
using PolyTraderSharp.Models;
|
|
||||||
|
|
||||||
namespace PolyTrader.Modules.CopyTrading.Persistence.Mongo
|
|
||||||
{
|
|
||||||
public class MongoMasterTraderHistoryRepository : IMasterTraderHistoryRepository
|
|
||||||
{
|
|
||||||
private readonly IMongoCollection<MasterTraderHistoryRecord> _col;
|
|
||||||
|
|
||||||
public MongoMasterTraderHistoryRepository(IMongoDatabase db)
|
|
||||||
{
|
|
||||||
_col = db.GetCollection<MasterTraderHistoryRecord>("mt_history");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void EnsureIndexes()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_col.Indexes.CreateOne(new CreateIndexModel<MasterTraderHistoryRecord>(
|
|
||||||
Builders<MasterTraderHistoryRecord>.IndexKeys.Ascending(x => x.TraderId)));
|
|
||||||
_col.Indexes.CreateOne(new CreateIndexModel<MasterTraderHistoryRecord>(
|
|
||||||
Builders<MasterTraderHistoryRecord>.IndexKeys.Ascending(x => x.ClosedAt)));
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Exists(int traderId, string tokenId, DateTime windowStart, DateTime windowEnd) =>
|
|
||||||
_col.Find(x => x.TraderId == traderId && x.TokenId == tokenId
|
|
||||||
&& x.ClosedAt >= windowStart && x.ClosedAt <= windowEnd).Any();
|
|
||||||
|
|
||||||
public void Insert(MasterTraderHistoryRecord record) => _col.InsertOne(record);
|
|
||||||
|
|
||||||
public List<MasterTraderHistoryRecord> GetByTraderSince(int traderId, DateTime since) =>
|
|
||||||
_col.Find(x => x.TraderId == traderId && x.ClosedAt >= since).ToList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using MongoDB.Driver;
|
|
||||||
using PolyTraderSharp.Models;
|
|
||||||
|
|
||||||
namespace PolyTrader.Modules.CopyTrading.Persistence.Mongo
|
|
||||||
{
|
|
||||||
public class MongoTrackedTraderRepository : ITrackedTraderRepository
|
|
||||||
{
|
|
||||||
private readonly IMongoCollection<TrackedTrader> _col;
|
|
||||||
|
|
||||||
public MongoTrackedTraderRepository(IMongoDatabase db)
|
|
||||||
{
|
|
||||||
_col = db.GetCollection<TrackedTrader>("trackers");
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<TrackedTrader> GetAll() => _col.Find(_ => true).ToList();
|
|
||||||
|
|
||||||
public void Upsert(TrackedTrader trader) =>
|
|
||||||
_col.ReplaceOne(x => x.Id == trader.Id, trader, new ReplaceOptions { IsUpsert = true });
|
|
||||||
|
|
||||||
public void Update(TrackedTrader trader) => _col.ReplaceOne(x => x.Id == trader.Id, trader);
|
|
||||||
|
|
||||||
public void Delete(int id) => _col.DeleteOne(x => x.Id == id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Linq.Expressions;
|
|
||||||
using MongoDB.Driver;
|
|
||||||
using PolyTraderSharp.Models;
|
|
||||||
|
|
||||||
namespace PolyTrader.Modules.CopyTrading.Persistence
|
|
||||||
{
|
|
||||||
public class MongoCopyTradeLogRepository : ICopyTradeLogRepository
|
|
||||||
{
|
|
||||||
private readonly IMongoCollection<ClosedTrade> _col;
|
|
||||||
|
|
||||||
public MongoCopyTradeLogRepository(IMongoDatabase db)
|
|
||||||
{
|
|
||||||
_col = db.GetCollection<ClosedTrade>("closed_trades");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void EnsureIndexes()
|
|
||||||
{
|
|
||||||
CreateIndex(x => x.TradeId);
|
|
||||||
CreateIndex(x => x.AccountId);
|
|
||||||
CreateIndex(x => x.TokenId);
|
|
||||||
CreateIndex(x => x.SourceTraderId);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CreateIndex(Expression<Func<ClosedTrade, object>> field)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var keys = Builders<ClosedTrade>.IndexKeys.Ascending(field);
|
|
||||||
_col.Indexes.CreateOne(new CreateIndexModel<ClosedTrade>(keys));
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Exists(int accountId, string tokenId) =>
|
|
||||||
_col.Find(x => x.AccountId == accountId && x.TokenId == tokenId).Any();
|
|
||||||
|
|
||||||
public void Insert(ClosedTrade trade) => _col.InsertOne(trade);
|
|
||||||
|
|
||||||
public List<ClosedTrade> Find(Expression<Func<ClosedTrade, bool>> predicate) =>
|
|
||||||
_col.Find(predicate).ToList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-27
@@ -1,27 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using MongoDB.Driver;
|
|
||||||
using PolyTraderSharp.Models;
|
|
||||||
|
|
||||||
namespace PolyTrader.Modules.CopyTrading.Persistence
|
|
||||||
{
|
|
||||||
public class MongoCopyTradingAccountSettingsRepository : ICopyTradingAccountSettingsRepository
|
|
||||||
{
|
|
||||||
private readonly IMongoCollection<CopyTradingAccountSettings> _col;
|
|
||||||
|
|
||||||
public MongoCopyTradingAccountSettingsRepository(IMongoDatabase db)
|
|
||||||
{
|
|
||||||
_col = db.GetCollection<CopyTradingAccountSettings>("ct_account_settings");
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<CopyTradingAccountSettings> GetAll() => _col.Find(_ => true).ToList();
|
|
||||||
|
|
||||||
public CopyTradingAccountSettings? Get(int accountId) =>
|
|
||||||
_col.Find(x => x.AccountId == accountId).FirstOrDefault();
|
|
||||||
|
|
||||||
public void Upsert(CopyTradingAccountSettings settings) =>
|
|
||||||
_col.ReplaceOne(x => x.AccountId == settings.AccountId, settings, new ReplaceOptions { IsUpsert = true });
|
|
||||||
|
|
||||||
public void Delete(int accountId) => _col.DeleteOne(x => x.AccountId == accountId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -52,7 +52,7 @@ namespace PolyTraderSharp.Services
|
|||||||
|
|
||||||
public override async Task StartAsync(CancellationToken cancellationToken)
|
public override async Task StartAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
_logger.Info("Starte Preload des MarketCache aus MongoDB um Flaschenhälse zu vermeiden...");
|
_logger.Info("Starte Preload des MarketCache aus der Datenbank um Flaschenhälse zu vermeiden...");
|
||||||
{
|
{
|
||||||
// Initialize cache for EVERYTHING in DB that is not closed!
|
// Initialize cache for EVERYTHING in DB that is not closed!
|
||||||
var activeMarkets = _marketRepo.GetActive();
|
var activeMarkets = _marketRepo.GetActive();
|
||||||
|
|||||||
Reference in New Issue
Block a user