import { BaseStrategy } from './base.js'; export class ThresholdStrategy extends BaseStrategy { constructor(config = {}) { super('threshold', { triggerPct: config.triggerPct || 65, betSize: config.betSize || 1, slippage: config.slippage || 3, cooldownMs: config.cooldownMs || 30000, ...config }); this._lastTrade = { paper: { time: 0, ticker: null }, live: { time: 0, ticker: null } }; } evaluate(state, caller = 'paper') { if (!state || !this.enabled) return null; const track = this._lastTrade[caller] || this._lastTrade.paper; const now = Date.now(); if (now - track.time < this.config.cooldownMs) return null; if (state.ticker === track.ticker) return null; const { yesPct, noPct } = state; const trigger = this.config.triggerPct; let signal = null; if (yesPct >= trigger && noPct < 99) { signal = { strategy: this.name, side: 'no', price: noPct, maxPrice: Math.min(noPct + this.config.slippage, 95), size: this.config.betSize, reason: `Yes at ${yesPct}% (≥${trigger}%), contrarian No at ${noPct}¢`, ticker: state.ticker }; } else if (noPct >= trigger && yesPct < 99) { signal = { strategy: this.name, side: 'yes', price: yesPct, maxPrice: Math.min(yesPct + this.config.slippage, 95), size: this.config.betSize, reason: `No at ${noPct}% (≥${trigger}%), contrarian Yes at ${yesPct}¢`, ticker: state.ticker }; } if (signal) { track.time = now; track.ticker = state.ticker; } return signal; } toJSON() { return { ...super.toJSON(), lastTradeTicker: this._lastTrade.live.ticker || this._lastTrade.paper.ticker }; } }