import { BaseStrategy } from './base.js'; export class MartingaleStrategy extends BaseStrategy { constructor(config = {}) { super('martingale', { threshold: config.threshold || 70, baseBet: config.baseBet || 1, maxDoublings: config.maxDoublings || 5, cooldownMs: config.cooldownMs || 60000, ...config }); this.consecutiveLosses = 0; this.currentBetSize = this.config.baseBet; this.lastTradeTime = 0; this.lastTradeTicker = null; } evaluate(state) { if (!state || !this.enabled) return null; const now = Date.now(); if (now - this.lastTradeTime < this.config.cooldownMs) return null; if (state.ticker === this.lastTradeTicker) return null; if (this.consecutiveLosses >= this.config.maxDoublings) return null; const { yesPct, noPct } = state; const threshold = this.config.threshold; let signal = null; // Prevent buying useless contracts at >= 99¢ (which would result in $0 or 0.01¢ profit) if (yesPct >= threshold && noPct < 99) { signal = { strategy: this.name, side: 'no', price: noPct, size: this.currentBetSize, reason: `Yes at ${yesPct}% (≥${threshold}%), betting No at ${noPct}¢`, ticker: state.ticker }; } else if (noPct >= threshold && yesPct < 99) { signal = { strategy: this.name, side: 'yes', price: yesPct, size: this.currentBetSize, reason: `No at ${noPct}% (≥${threshold}%), betting Yes at ${yesPct}¢`, ticker: state.ticker }; } if (signal) { this.lastTradeTime = now; this.lastTradeTicker = state.ticker; } return signal; } onSettlement(result, trade) { if (!trade || trade.strategy !== this.name) return; const won = (trade.side === 'yes' && result === 'yes') || (trade.side === 'no' && result === 'no'); if (won) { console.log(`[Martingale] WIN — resetting to base bet $${this.config.baseBet}`); this.consecutiveLosses = 0; this.currentBetSize = this.config.baseBet; } else { this.consecutiveLosses++; this.currentBetSize = this.config.baseBet * Math.pow(2, this.consecutiveLosses); console.log(`[Martingale] LOSS #${this.consecutiveLosses} — next bet: $${this.currentBetSize}`); if (this.consecutiveLosses >= this.config.maxDoublings) { console.log(`[Martingale] MAX LOSSES REACHED. Strategy paused.`); } } } toJSON() { return { ...super.toJSON(), consecutiveLosses: this.consecutiveLosses, currentBetSize: this.currentBetSize, paused: this.consecutiveLosses >= this.config.maxDoublings }; } }