Un riavvio, una sospensione del PC o un container fermo lasciavano i basket aperti senza che nessuno applicasse le regole di uscita per il tempo perso. Ora un heartbeat ogni 30 s misura l'inattività; oltre la soglia il bot blocca le entrate, risolve gli ordini senza esito, riconcilia, riscalda le serie con le barre perse e rivaluta ogni basket aperto come a una chiusura di barra ordinaria (chiudi o tieni), chiude le orfane, riporta le esterne, scrive reports/recupero_<run_id>.csv e riapre le entrate dopo il riscaldamento; a mercato chiuso aspetta. Un lock tenuto in esclusiva impedisce due istanze sulla stessa cartella dati. Sezione recovery in strategy.json. Test (r). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
98 lines
6.1 KiB
JSON
98 lines
6.1 KiB
JSON
{
|
||
"_comment": "Encelado — strategia Correlation Baskets su eToro. Cinque basket di due coppie forex correlate: si entra quando il cross sintetico diverge (z-score), si esce quando converge o al take-profit di basket in pip; lo stop di basket è obbligatorio. Ogni chiave con '_' davanti è documentazione.",
|
||
|
||
"_preset": "Conservative | Moderate | Aggressive. Fissa zIn, riskPerBasketPct, maxBaskets, tpPips, maxAdds, zStop; si cambia a caldo dalla finestra senza toccare i basket aperti. Le chiavi omonime qui sotto, se presenti, sovrascrivono il preset.",
|
||
"preset": "Moderate",
|
||
|
||
"_signalMode": "ZScoreSynthetic (default, |z| >= zIn sul cross sintetico) oppure PipDivergence (fedele all'interfaccia Titany: divergenza in pip dall'ancora, dIn).",
|
||
"signalMode": "ZScoreSynthetic",
|
||
"_exitMode": "First = la prima fra TP in pip e rientro dello z; FixedPips = solo TP in pip lordi; ZReturn = solo |z| <= zOut.",
|
||
"exitMode": "First",
|
||
"_averagingMode": "Off | AddOnce | Grid. Off in live; AddOnce in paper. Moltiplicatore di lotto sempre 1,0 (niente martingala).",
|
||
"averagingMode": "Off",
|
||
"tpMode": "Pips",
|
||
"_sameCrossPolicy": "I basket 4 e 5 sono entrambi EURCAD: Exclusive = uno solo aperto per volta; Half = entrambi a metà size.",
|
||
"sameCrossPolicy": "Exclusive",
|
||
"preferDirectCross": false,
|
||
|
||
"_indicatori": "Correlazione di Pearson rolling dei rendimenti M15 su window (ρ_W) e windowShort (ρ_20); z-score del cross sintetico su window; half-life OLS ricalcolata ogni halfLifeRecalcHours.",
|
||
"window": 100,
|
||
"windowShort": 20,
|
||
"rhoMin": 0.60,
|
||
"rhoShortMin": 0.40,
|
||
"halfLifeMinBars": 4,
|
||
"halfLifeMaxBars": 96,
|
||
"halfLifeRecalcHours": 4,
|
||
"atrPeriod": 14,
|
||
"ewmaSpan": 100,
|
||
"trendPeriod": 14,
|
||
|
||
"zOut": 0.25,
|
||
"dIn": 15,
|
||
"anchorBars": 32,
|
||
"gridStepZ": 0.75,
|
||
"lotMultiplier": 1.0,
|
||
|
||
"_uscite": "Stop di basket: |z| >= zStop, oppure perdita netta >= maxLossPerBasketPct dell'equity, oppure |ρ_20| < rhoBreak per rhoBreakBars barre, oppure maxHoldingBars barre (96 = 24 h).",
|
||
"maxLossPerBasketPct": 1.5,
|
||
"rhoBreak": 0.20,
|
||
"rhoBreakBars": 8,
|
||
"maxHoldingBars": 96,
|
||
"tpAtrMultiple": 1.0,
|
||
|
||
"_costGate": "Costo = spread_A + spread_B (in pip-equivalenti di A) + markup e commissioni dell'API + overnight stimato per maxHoldingBars. Entrata solo se TP >= costMultiple × costo e ogni spread <= spreadMedianMultiple × la sua mediana delle ultime 24 h; spread oltre spreadAnomalyMultiple × mediana = chiusura forzata.",
|
||
"costMultiple": 3,
|
||
"spreadMedianMultiple": 2,
|
||
"spreadAnomalyMultiple": 3,
|
||
"slippagePipsPerLeg": 0.3,
|
||
"overnightPipsPerDay": 0.3,
|
||
|
||
"_calendario": "Nessuna entrata nei blackoutBeforeMin minuti prima e blackoutAfterMin dopo un evento ad alto impatto sulle valute del basket; niente entrate dal venerdì fridayCutoffUtcHour UTC alla riapertura né nei primi openDelayMinutes dopo l'apertura settimanale; sessions = fasce orarie UTC ammesse (vuoto = sempre).",
|
||
"blackoutBeforeMin": 45,
|
||
"blackoutAfterMin": 30,
|
||
"fridayCutoffUtcHour": 20,
|
||
"openDelayMinutes": 30,
|
||
"sessions": [],
|
||
|
||
"_sizing": "Lotto B = lotto A × (ATR_A × pipValue_A) / (ATR_B × pipValue_B); lotto A tale che la perdita allo stop valga riskPerBasketPct dell'equity; leva effettiva <= maxEffectiveLeverage sul nozionale complessivo; orderLeverage è la leva dichiarata a eToro per ogni gamba (1, 2, 5, 10, 20, 30).",
|
||
"maxEffectiveLeverage": 10,
|
||
"orderLeverage": 10,
|
||
"_volScale": "zIn effettivo = zIn × clamp(σ_prevista / σ_media_30g, volScaleMin, volScaleMax).",
|
||
"volScaleMin": 0.8,
|
||
"volScaleMax": 1.5,
|
||
"volAverageDays": 30,
|
||
"mlMinProbability": 0.55,
|
||
|
||
"_sicurezza": "equityStopPct: perdita dal picco di equity (al netto dei movimenti di cassa) oltre la quale il bot chiude tutto e si blocca (reset manuale con motivazione). dailyLossPct: perdita giornaliera oltre la quale niente nuove entrate fino al giorno dopo.",
|
||
"equityStopPct": 9,
|
||
"dailyLossPct": 3,
|
||
"legTimeoutSec": 5,
|
||
"clockSkewMaxSeconds": 5,
|
||
|
||
"_risk": "Margine (5.0, §10). La size di un basket è il minimo fra la size a rischio e quella a margine. maxMarginUsePct: margine totale impegnato dopo l'apertura, in % dell'equity. maxMarginPerBasketPct: margine delle due gambe di un basket, in % dell'equity. marginBufferPct: il disponibile deve superare il margine richiesto di questa percentuale prima di inviare A e, ricontrollato, prima di inviare B (altrimenti A viene richiusa). closeForeignOnKill: il kill-switch chiude anche le posizioni non aperte dal bot. marginCallBlockRatio / marginCallCloseRatio: sotto equity/margine usato = 1,5 niente entrate; sotto 1,2 si chiude il basket con il P&L peggiore.",
|
||
"risk": {
|
||
"maxMarginUsePct": 40,
|
||
"maxMarginPerBasketPct": 12,
|
||
"marginBufferPct": 25,
|
||
"closeForeignOnKill": false,
|
||
"marginCallBlockRatio": 1.5,
|
||
"marginCallCloseRatio": 1.2
|
||
},
|
||
|
||
"_recovery": "Recupero dopo inattività (5.0, §6). Il bot scrive data/state/heartbeat.json ogni heartbeatSeconds; se all'avvio o fra due cicli passano più di thresholdMinutes (riavvio, sospensione del PC, aggiornamento, container fermo) blocca le entrate, risolve gli ordini senza esito, riconcilia, riscalda le serie con le barre perse e rivaluta ogni basket aperto come a una chiusura di barra ordinaria (chiudi o tieni; le orfane si chiudono, le esterne si riportano); scrive reports/recupero_<run_id>.csv e riapre le entrate dopo warmupMinutes di quotazioni. A mercato chiuso aspetta la riapertura.",
|
||
"recovery": {
|
||
"thresholdMinutes": 10,
|
||
"warmupMinutes": 15,
|
||
"heartbeatSeconds": 30
|
||
},
|
||
|
||
"_baskets": "I cinque basket della specifica. Il cross sintetico e il verso delle gambe sono derivati dai codici delle valute, non configurati.",
|
||
"baskets": [
|
||
{ "a": "EURUSD", "b": "USDCHF", "enabled": true, "note": "cross sintetico EURCHF" },
|
||
{ "a": "AUDUSD", "b": "USDCAD", "enabled": true, "note": "cross sintetico AUDCAD" },
|
||
{ "a": "NZDUSD", "b": "EURNZD", "enabled": true, "note": "cross sintetico EURUSD: replica EURUSD pagando due spread" },
|
||
{ "a": "USDCAD", "b": "EURUSD", "enabled": true, "note": "cross sintetico EURCAD (stessa esposizione del basket 5)" },
|
||
{ "a": "EURAUD", "b": "AUDCAD", "enabled": true, "note": "cross sintetico EURCAD (stessa esposizione del basket 4)" }
|
||
]
|
||
}
|