feat: No-Stop-Grid-Variante (--no-stop, --pair) — erstes Edge-Signal auf XRP

XRP-Datenanalyse: nie enge Ranges, breite Bänder → No-Stop-Design.
OOS-PF 2.0-2.74, Volldurchlauf +49% bei 10% MaxDD. Gate formal 
(Worst-Window + Ratio), Tail-Risiko dokumentiert.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-10 07:17:33 +00:00
parent 3d16b76f23
commit f754b91acd
3 changed files with 56 additions and 5 deletions

View File

@@ -13,6 +13,12 @@ export interface GridParams {
adxMax: number; // Grid nur aktiv im Seitwärtsregime (ADX < adxMax)
atrPeriod: number;
tfMs: number; // Entscheidungs-Timeframe (Aktivierung/Deaktivierung, ATR/ADX-Basis)
/**
* true: Range-Breakdown/Ausbruch/Trendbeginn liquidiert alle Lots (harter Stop).
* false: Lots werden nie mit Verlust verkauft (nur TP oder end_of_data);
* Re-Center nur, wenn das Grid leer ist und der Preis die Range verlassen hat.
*/
hardStop: boolean;
}
export const DEFAULT_GRID_PARAMS: GridParams = {
@@ -21,6 +27,7 @@ export const DEFAULT_GRID_PARAMS: GridParams = {
adxMax: 20,
atrPeriod: 14,
tfMs: H4,
hardStop: true,
};
export interface GridConfig {
@@ -136,9 +143,12 @@ export function runGridBacktest(candles15ByPair: Map<Pair, Candle[]>, cfg: GridC
const g = grids.get(pair);
if (g) {
const trendStart = !Number.isNaN(ctx.adx[i]) && ctx.adx[i] >= p.adxMax + 5; // Hysterese
if (bar.close < g.stopPrice || bar.close > g.upperExit || trendStart) {
liquidate(pair, barCloseTs, bar.close, 'grid_stop');
const outOfRange = bar.close < g.stopPrice || bar.close > g.upperExit;
if (p.hardStop) {
const trendStart = !Number.isNaN(ctx.adx[i]) && ctx.adx[i] >= p.adxMax + 5; // Hysterese
if (outOfRange || trendStart) liquidate(pair, barCloseTs, bar.close, 'grid_stop');
} else if (outOfRange && g.lots.every((l) => !l)) {
grids.delete(pair); // leeres Grid folgt dem Preis (Re-Center ohne Verlust)
}
} else if (
!Number.isNaN(ctx.atr[i]) &&
@@ -146,7 +156,7 @@ export function runGridBacktest(candles15ByPair: Map<Pair, Candle[]>, cfg: GridC
ctx.adx[i] < p.adxMax
) {
const spacing = p.spacingAtrMult * ctx.atr[i];
const budgetPerLevel = equity() / PAIRS.length / p.gridLevels;
const budgetPerLevel = equity() / contexts.length / p.gridLevels;
if (spacing > 0 && budgetPerLevel >= cfg.minNotionalUsdt) {
grids.set(pair, {
center: bar.close,