mirror of
https://github.com/multipleof4/KalBot.git
synced 2026-03-17 14:01:02 +00:00
Delete lib/strategies/martingale-alpha.js
This commit is contained in:
@@ -1,126 +0,0 @@
|
|||||||
import { BaseStrategy } from './base.js';
|
|
||||||
import crypto from 'crypto';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Martingale Alpha Strategy
|
|
||||||
*
|
|
||||||
* When odds are between 40-60% for both sides (a ~coin-flip market):
|
|
||||||
* - Use crypto.randomInt to pick yes/no
|
|
||||||
* - Round 1: bet $1, Round 2: bet $2, Round 3: bet $4
|
|
||||||
* - If any round wins, reset to round 1
|
|
||||||
* - If all 3 lose, reset to round 1 anyway (cap losses at $7 per cycle)
|
|
||||||
*
|
|
||||||
* Probability of losing 3 consecutive 50/50s = 12.5%
|
|
||||||
* Probability of winning at least 1 of 3 = 87.5%
|
|
||||||
*/
|
|
||||||
export class MartingaleAlphaStrategy extends BaseStrategy {
|
|
||||||
constructor(config = {}) {
|
|
||||||
super('martingale-alpha', {
|
|
||||||
minPct: config.minPct || 40,
|
|
||||||
maxPct: config.maxPct || 60,
|
|
||||||
baseBet: config.baseBet || 1,
|
|
||||||
maxRounds: config.maxRounds || 3,
|
|
||||||
slippage: config.slippage || 3,
|
|
||||||
cooldownMs: config.cooldownMs || 20000,
|
|
||||||
...config
|
|
||||||
});
|
|
||||||
|
|
||||||
this.round = 0;
|
|
||||||
this.currentBetSize = this.config.baseBet;
|
|
||||||
this.cycleWins = 0;
|
|
||||||
this.cycleLosses = 0;
|
|
||||||
this.totalCycles = 0;
|
|
||||||
|
|
||||||
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 { minPct, maxPct } = this.config;
|
|
||||||
|
|
||||||
if (yesPct < minPct || yesPct > maxPct) return null;
|
|
||||||
if (noPct < minPct || noPct > maxPct) return null;
|
|
||||||
|
|
||||||
const flip = crypto.randomInt(0, 2);
|
|
||||||
const side = flip === 0 ? 'yes' : 'no';
|
|
||||||
const price = side === 'yes' ? yesPct : noPct;
|
|
||||||
const maxPrice = Math.min(price + this.config.slippage, 95);
|
|
||||||
|
|
||||||
const roundIndex = this.round;
|
|
||||||
const betSize = this.config.baseBet * Math.pow(2, roundIndex);
|
|
||||||
|
|
||||||
const signal = {
|
|
||||||
strategy: this.name,
|
|
||||||
side,
|
|
||||||
price,
|
|
||||||
maxPrice,
|
|
||||||
size: betSize,
|
|
||||||
reason: `R${roundIndex + 1}/${this.config.maxRounds} coin-flip ${side.toUpperCase()} @ ${price}¢ ($${betSize}) | Market: ${yesPct}/${noPct}`,
|
|
||||||
ticker: state.ticker
|
|
||||||
};
|
|
||||||
|
|
||||||
track.time = now;
|
|
||||||
track.ticker = state.ticker;
|
|
||||||
this.currentBetSize = betSize;
|
|
||||||
|
|
||||||
return signal;
|
|
||||||
}
|
|
||||||
|
|
||||||
onSettlement(result, trade) {
|
|
||||||
if (!trade || trade.strategy !== this.name) return;
|
|
||||||
|
|
||||||
const won = trade.side === result;
|
|
||||||
|
|
||||||
if (won) {
|
|
||||||
console.log(`[MartingaleAlpha] WIN on round ${this.round + 1} — cycle complete, resetting`);
|
|
||||||
this.cycleWins++;
|
|
||||||
this.totalCycles++;
|
|
||||||
this._resetCycle();
|
|
||||||
} else {
|
|
||||||
this.round++;
|
|
||||||
if (this.round >= this.config.maxRounds) {
|
|
||||||
console.log(`[MartingaleAlpha] LOST all ${this.config.maxRounds} rounds — cycle failed, resetting`);
|
|
||||||
this.cycleLosses++;
|
|
||||||
this.totalCycles++;
|
|
||||||
this._resetCycle();
|
|
||||||
} else {
|
|
||||||
const nextBet = this.config.baseBet * Math.pow(2, this.round);
|
|
||||||
console.log(`[MartingaleAlpha] LOSS round ${this.round}/${this.config.maxRounds} — next bet: $${nextBet}`);
|
|
||||||
this.currentBetSize = nextBet;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_resetCycle() {
|
|
||||||
this.round = 0;
|
|
||||||
this.currentBetSize = this.config.baseBet;
|
|
||||||
// Reset both callers' ticker locks so new cycle can trade same market
|
|
||||||
this._lastTrade.paper.ticker = null;
|
|
||||||
this._lastTrade.live.ticker = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
toJSON() {
|
|
||||||
return {
|
|
||||||
...super.toJSON(),
|
|
||||||
round: this.round + 1,
|
|
||||||
maxRounds: this.config.maxRounds,
|
|
||||||
currentBetSize: this.currentBetSize,
|
|
||||||
cycleWins: this.cycleWins,
|
|
||||||
cycleLosses: this.cycleLosses,
|
|
||||||
totalCycles: this.totalCycles,
|
|
||||||
cycleWinRate: this.totalCycles > 0
|
|
||||||
? parseFloat(((this.cycleWins / this.totalCycles) * 100).toFixed(1))
|
|
||||||
: 0
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user