From 7993ca44a0b23fa12155c860b2f1edac40202df5 Mon Sep 17 00:00:00 2001 From: Alberto Balbo Date: Tue, 8 Sep 2026 11:00:49 +0200 Subject: [PATCH] Database SQLite al posto dei dossier, gestore del rischio, decisioni in shadow, rete neurale, bandit e simulatore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le aste non si salvano più in un file JSON per asta più tre archivi da tenere allineati: un solo database SQLite (winsqlite3.dll di Windows via P/Invoke, nessun pacchetto) con prodotti, aste, puntate, interrogazioni coalescenti, reset con profondità del ciclo, nostre puntate, decisioni del motore, misure di rete, puntatori, sessioni e contabilità. Scrittura in coda su un thread dedicato, letture in WAL. Per scelta dell'utente si parte da zero: il database si riempie man mano che si osservano le aste; i vecchi dossier restano leggibili per un'importazione futura ma non si scrivono più. Storico, schede, apprendimento, rigiocata ed esportazioni leggono tutti da lì. Il documento di progetto (Modifiche.txt) tradotto in C# senza librerie: - RiskManager: kill-switch (file KILL_SWITCH, anche dalla barra), HALT persistente per stop-loss e drawdown, tetto del giorno, aste in gioco insieme, contabilità in euro. - Theory: valore atteso con fee, spedizione, valore reale per prodotto (nuova colonna nella scheda Prodotti) e copertura «Compralo Ora»; null-model; sopravvivenza empirica e Kaplan-Meier dai reset; arrivi di Poisson. - Shadow per asta: in Osserva il cecchino arriva allo stesso istante, registra cosa avrebbe fatto e non punta; alla chiusura ogni decisione riceve l'esito, e ShadowReport confronta le policy sugli stessi istanti con intervallo di confidenza sul ROI. - NeuralNet (MLP, Adam) come sfidante del logistico, scelto dal Brier prequenziale; ThompsonBandit come seconda policy che impara dagli esiti delle decisioni; PennyAuctionEnv con avversari tarati sul database e QLearningAgent conservativo; SimulationLab per il confronto fra policy; esportazione CSV delle decisioni con reason_detail. Tutto nella scheda Apprendimento. Ml/LEGGIMI.md riscritto con le avvertenze su termini d'uso, quadro legale e realtà economica, lo schema del database e lo stato delle milestone. Co-Authored-By: Claude Fable 5.1 --- Mimante/App.xaml.cs | 27 +- Mimante/Controls/AuctionMonitorControl.xaml | 13 + .../Controls/AuctionMonitorControl.xaml.cs | 14 + Mimante/Controls/LearningControl.xaml | 61 ++ Mimante/Controls/LearningControl.xaml.cs | 78 ++ Mimante/Controls/ProductsControl.xaml | 5 + Mimante/Controls/SettingsControl.xaml | 103 ++- Mimante/Controls/SettingsControl.xaml.cs | 74 ++ .../MainWindow.EventHandlers.Settings.cs | 38 + .../MainWindow.EventHandlers.Stats.cs | 13 +- Mimante/Core/MainWindow.DataSettings.cs | 2 +- Mimante/Core/MainWindow.Risk.cs | 63 ++ Mimante/Data/AuctionDatabase.cs | 731 ++++++++++++++++++ Mimante/Data/AuctionRecorder.cs | 521 +++++++++++++ Mimante/Data/Sqlite.cs | 495 ++++++++++++ Mimante/Dialogs/WipeStatsDialog.xaml | 6 +- Mimante/Dialogs/WipeStatsDialog.xaml.cs | 4 +- Mimante/Engine/AuctionRunner.cs | 13 +- Mimante/Engine/Backtest/BacktestReport.cs | 57 +- Mimante/Engine/Backtest/BacktestRunner.cs | 2 +- Mimante/Engine/Backtest/DossierReader.cs | 95 ++- Mimante/MainWindow.xaml | 6 +- Mimante/MainWindow.xaml.cs | 1 + Mimante/Ml/DossierTrainingReader.cs | 123 ++- Mimante/Ml/LEGGIMI.md | 324 +++++--- Mimante/Ml/LearningEvaluator.cs | 63 +- Mimante/Ml/LearningService.cs | 370 +++++---- Mimante/Ml/NeuralNet.cs | 274 +++++++ Mimante/Ml/PennyAuctionEnv.cs | 303 ++++++++ Mimante/Ml/QLearningAgent.cs | 214 +++++ Mimante/Ml/ShadowReport.cs | 165 ++++ Mimante/Ml/SimulationLab.cs | 193 +++++ Mimante/Ml/Theory.cs | 217 ++++++ Mimante/Ml/ThompsonBandit.cs | 210 +++++ Mimante/Models/AuctionInfo.cs | 7 + Mimante/Models/WatchedProduct.cs | 8 + Mimante/Modifiche.txt | 203 +++++ Mimante/Services/AuctionMonitor.cs | 76 +- Mimante/Services/BidStrategyService.cs | 198 +++-- Mimante/Services/RiskManager.cs | 278 +++++++ Mimante/Tests/AuctionDossierTests.cs | 302 -------- Mimante/Tests/AuctionRecorderTests.cs | 254 ++++++ Mimante/Tests/CompletedAuctionsStoreTests.cs | 16 +- Mimante/Tests/DossierSummaryTests.cs | 102 --- Mimante/Tests/MlModelBacktest.cs | 15 +- Mimante/Tests/MlModelsTests.cs | 225 ++++++ Mimante/Tests/RealDossierBacktest.cs | 11 +- Mimante/Tests/RealDossierSummaries.cs | 53 -- Mimante/Tests/RiskManagerTests.cs | 138 ++++ Mimante/Tests/SqliteTests.cs | 159 ++++ Mimante/Tests/StatsWipeTests.cs | 3 +- Mimante/Tests/TestEnvironment.cs | 3 +- Mimante/Tests/TheoryTests.cs | 127 +++ Mimante/Utilities/AppPaths.cs | 33 +- Mimante/Utilities/AuctionDetailStore.cs | 295 ++----- Mimante/Utilities/AuctionDossier.cs | 571 -------------- Mimante/Utilities/AuctionExporter.cs | 196 ++--- Mimante/Utilities/CompletedAuctionsStore.cs | 380 ++++----- Mimante/Utilities/DecisionExporter.cs | 93 +++ Mimante/Utilities/ProductStatsStore.cs | 18 + Mimante/Utilities/SettingsManager.cs | 29 + Mimante/Utilities/StatsWipe.cs | 59 +- Mimante/Utilities/TextLogService.cs | 3 +- Mimante/ViewModels/ProductViewModel.cs | 13 + Mimante/build/Release.proj | 22 +- 65 files changed, 6645 insertions(+), 2123 deletions(-) create mode 100644 Mimante/Core/MainWindow.Risk.cs create mode 100644 Mimante/Data/AuctionDatabase.cs create mode 100644 Mimante/Data/AuctionRecorder.cs create mode 100644 Mimante/Data/Sqlite.cs create mode 100644 Mimante/Ml/NeuralNet.cs create mode 100644 Mimante/Ml/PennyAuctionEnv.cs create mode 100644 Mimante/Ml/QLearningAgent.cs create mode 100644 Mimante/Ml/ShadowReport.cs create mode 100644 Mimante/Ml/SimulationLab.cs create mode 100644 Mimante/Ml/Theory.cs create mode 100644 Mimante/Ml/ThompsonBandit.cs create mode 100644 Mimante/Services/RiskManager.cs delete mode 100644 Mimante/Tests/AuctionDossierTests.cs create mode 100644 Mimante/Tests/AuctionRecorderTests.cs delete mode 100644 Mimante/Tests/DossierSummaryTests.cs create mode 100644 Mimante/Tests/MlModelsTests.cs delete mode 100644 Mimante/Tests/RealDossierSummaries.cs create mode 100644 Mimante/Tests/RiskManagerTests.cs create mode 100644 Mimante/Tests/SqliteTests.cs create mode 100644 Mimante/Tests/TheoryTests.cs delete mode 100644 Mimante/Utilities/AuctionDossier.cs create mode 100644 Mimante/Utilities/DecisionExporter.cs diff --git a/Mimante/App.xaml.cs b/Mimante/App.xaml.cs index 36a83a7..71252a8 100644 --- a/Mimante/App.xaml.cs +++ b/Mimante/App.xaml.cs @@ -23,7 +23,7 @@ namespace AutoBidder // Le impostazioni stanno nella radice fissa, quindi si possono leggere anche // prima di sapere dove finiranno gli altri dati. var settings = SettingsManager.Load(); - AppPaths.Configure(settings.DataFolder, settings.StatsFolder, settings.LogFolder); + AppPaths.Configure(settings.DataFolder, settings.StatsFolder, settings.LogFolder, settings.DatabasePath); AppPaths.EnsureFolders(); // Le versioni precedenti scrivevano parte dei dati in Roaming e parte in Local, @@ -36,8 +36,21 @@ namespace AutoBidder TextLogService.PurgeOldLogs(); TextLogService.App("INFO", $"[PERCORSI] configurazione in {AppPaths.ConfigRoot}, dati in {AppPaths.DataFolder}"); - // Le righe di registro delle aste confluiscono nei rispettivi dossier. - AuctionDossier.CaptureAuctionLogs(); + // Il database si apre per primo: da qui in poi ogni archivio ci scrive. + Data.AuctionDatabase.OnLog += m => TextLogService.App("INFO", m); + try + { + var db = Data.AuctionDatabase.Instance; + TextLogService.App("INFO", $"[DATABASE] {db.Path} (SQLite {Data.AuctionDatabase.LibraryVersion}, {db.SizeBytes / 1024:N0} KB)"); + db.Enqueue("INSERT INTO sessions(started_at, app_version) VALUES(?1, ?2)", Data.AuctionDatabase.Now(), AppInfo.Version); + } + catch (Exception ex) + { + TextLogService.App("ERROR", $"[DATABASE] Apertura non riuscita: {ex.Message}"); + } + + // Le righe di registro delle aste confluiscono nel database. + Data.AuctionRecorder.CaptureAuctionLogs(); // Lo storico e' cresciuto per mesi con versioni diverse dell'applicazione: // alcuni record hanno campi che allora non esistevano. Quelli deducibili si @@ -74,6 +87,14 @@ namespace AutoBidder TextLogService.SessionEnded(); FileLogWriter.DisposeAll(); + try + { + var db = Data.AuctionDatabase.Instance; + db.Enqueue("UPDATE sessions SET ended_at = ?1 WHERE session_id = (SELECT MAX(session_id) FROM sessions)", Data.AuctionDatabase.Now()); + Data.AuctionDatabase.CloseInstance(); + } + catch { /* all'uscita non c'è più nessuno a cui dirlo */ } + // L'icona di notifica sopravvive al processo se non la si rimuove: // resterebbe nell'area di notifica come icona fantasma. WindowsNotifier.Dispose(); diff --git a/Mimante/Controls/AuctionMonitorControl.xaml b/Mimante/Controls/AuctionMonitorControl.xaml index 39df607..ed86b24 100644 --- a/Mimante/Controls/AuctionMonitorControl.xaml +++ b/Mimante/Controls/AuctionMonitorControl.xaml @@ -66,6 +66,19 @@ + + + + + + + diff --git a/Mimante/Controls/AuctionMonitorControl.xaml.cs b/Mimante/Controls/AuctionMonitorControl.xaml.cs index 8a73e5c..4f82bc6 100644 --- a/Mimante/Controls/AuctionMonitorControl.xaml.cs +++ b/Mimante/Controls/AuctionMonitorControl.xaml.cs @@ -67,6 +67,20 @@ namespace AutoBidder.Controls RaiseEvent(new RoutedEventArgs(StopClickedEvent, this)); } + private void KillSwitchToggle_Changed(object sender, RoutedEventArgs e) + { + RaiseEvent(new RoutedEventArgs(KillSwitchChangedEvent, this)); + } + + public static readonly RoutedEvent KillSwitchChangedEvent = EventManager.RegisterRoutedEvent( + "KillSwitchChanged", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AuctionMonitorControl)); + + public event RoutedEventHandler KillSwitchChanged + { + add { AddHandler(KillSwitchChangedEvent, value); } + remove { RemoveHandler(KillSwitchChangedEvent, value); } + } + private void AddUrlButton_Click(object sender, RoutedEventArgs e) { RaiseEvent(new RoutedEventArgs(AddUrlClickedEvent, this)); diff --git a/Mimante/Controls/LearningControl.xaml b/Mimante/Controls/LearningControl.xaml index 69ca0c7..35e8b9a 100644 --- a/Mimante/Controls/LearningControl.xaml +++ b/Mimante/Controls/LearningControl.xaml @@ -84,6 +84,12 @@ Content="Apri cartella" Margin="0,0,8,0" ToolTip="La cartella con modello, profilo, elenco dei dossier letti e ultima valutazione" Click="OpenFolderButton_Click"/> + + + + + + + + + + + + @@ -577,9 +600,9 @@ Dalla rigiocata di 2.095 aste concluse: con anticipo sotto il secondo serve in m + Content="Registra ogni asta seguita nel database (puntate di ogni utente, reset, mie puntate, decisioni)"/> @@ -671,6 +694,80 @@ Se il valore è maggiore di zero, il sistema non punta quando le puntate residue + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +