Sostituisci le euristiche a soglia con regime e anticipo adattivi; un solo archivio per asta

Le strategie a numero fisso (calore, ritiro morbido, anti-bot, avversari aggressivi,
puntata probabilistica, velocità del prezzo, esaurimento, concorrenza) e le impostazioni
morte (cadenze di polling, finestra critica, database, log avanzati, suggerimenti
sull'anticipo, schede dettagliate) non ci sono più: rigiocate sui dossier non fermavano
una puntata sbagliata senza fermarne anche di giuste, e i loro numeri andavano tarati a
mano. Restano i paletti dell'utente (tetti, budget, fascia oraria) e il duello.

Al loro posto due componenti che imparano dalla sessione in corso, dentro i paletti:
- CompetitionRegime per asta (Calmo / Sfogo / Sondaggio) guidato dal valore atteso
  appreso: tre negativi di fila e si lascia sfogare gli altri, si rientra con una
  puntata di prova dopo abbastanza cicli buoni, e se viene coperta subito la pazienza
  raddoppia. È il "capire da soli quando tornare a puntare".
- LatencyModel per l'anticipo: margine + p99 della latenza misurata adesso, tenuto fra
  LeadMinMs e LeadMaxMs; una puntata tardiva alza il margine subito, venti in tempo lo
  abbassano piano. Un anticipo scritto a mano su un'asta vince sempre (BidLeadIsManual).

Archiviazione: l'archivio mensile aste-AAAA-MM.jsonl (95 MB) duplicava il riepilogo che
ogni dossier ha già in coda. AuctionDetailStore ora legge testa e coda dei dossier, con
cache: 6349 file in 6 s la prima volta. Pulsanti per svuotare le esportazioni e per
azzerare le statistiche voce per voce (lo storico passa dalla copia di sicurezza).

Scheda Apprendimento: sezione "Autonomia sul momento" con il modello di latenza e il
regime di ogni asta seguita. Ml/LEGGIMI.md descrive l'algoritmo per intero.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
2026-09-08 00:11:49 +02:00
co-authored by Claude Fable 5.1
parent afb778ea26
commit 8b7c39c9e3
36 changed files with 2111 additions and 1155 deletions
+6 -7
View File
@@ -96,12 +96,11 @@ namespace AutoBidder.Engine.Backtest
{
if (string.IsNullOrEmpty(reason)) return "altro";
if (reason.StartsWith("Anti-bot", StringComparison.OrdinalIgnoreCase)) return "anti-bot";
if (reason.StartsWith("Soft retreat", StringComparison.OrdinalIgnoreCase)) return "soft-retreat";
if (reason.StartsWith("Asta troppo calda", StringComparison.OrdinalIgnoreCase)) return "asta-calda";
if (reason.StartsWith("Bidder aggressivi", StringComparison.OrdinalIgnoreCase)) return "avversari-aggressivi";
if (reason.StartsWith("Skip probabilistico", StringComparison.OrdinalIgnoreCase)) return "probabilistico";
if (reason.StartsWith("Prezzo sale", StringComparison.OrdinalIgnoreCase)) return "velocita-prezzo";
if (reason.StartsWith("autopuntata avversaria", StringComparison.OrdinalIgnoreCase)) return "duello";
if (reason.StartsWith("puntata saltata: fascia", StringComparison.OrdinalIgnoreCase)) return "fascia-oraria";
if (reason.StartsWith("valore atteso", StringComparison.OrdinalIgnoreCase)) return "valore-atteso";
if (reason.StartsWith("lascio sfogare", StringComparison.OrdinalIgnoreCase)) return "sfogo";
if (reason.StartsWith("puntata di prova", StringComparison.OrdinalIgnoreCase)) return "sondaggio";
if (reason.StartsWith("Limite puntate", StringComparison.OrdinalIgnoreCase)) return "limite-puntate";
if (reason.StartsWith("Budget", StringComparison.OrdinalIgnoreCase)) return "budget";
@@ -181,7 +180,6 @@ namespace AutoBidder.Engine.Backtest
continue;
}
strategy.UpdateHeatMetric(auction, options.EffectiveSettings, options.Username);
var decision = strategy.ShouldPlaceBid(auction, state, options.EffectiveSettings, options.Username);
if (!decision.ShouldBid)
@@ -312,6 +310,7 @@ namespace AutoBidder.Engine.Backtest
Name = header?.Name ?? "",
BuyNowPrice = header?.BuyNowPrice,
BidBeforeDeadlineMs = options.LeadMs,
BidLeadIsManual = true, // la rigiocata prova un anticipo preciso, non quello adattivo
BidsUsedOnThisAuction = 0
};