Back to Strategies
EMA Crossover
Code Strategy by 0xsDp5JzBDn·2026-04-24
// EMA Crossover Strategy
// Fast EMA crosses above Slow EMA → LONG
// Fast EMA crosses below Slow EMA → EXIT
const FAST_EMA = 9;
const SLOW_EMA = 21;
const S = await $.Storage.get() || {
prices: []
};
S.prices.push($.Price.price);
// Only keep what we need
if (S.prices.length > SLOW_EMA + 2) {
S.prices = S.prices.slice(-(SLOW_EMA + 2));
}
// Need enough data for the slow EMA
if (S.prices.length < SLOW_EMA + 1) {
await $.Storage.set(S);
return;
}
// Build both EMAs from stored prices
const fastEma = new $.Ta.EMA(FAST_EMA);
const slowEma = new $.Ta.EMA(SLOW_EMA);
// Feed all but the last price (previous candle)
const prevPrices = S.prices.slice(0, -1);
for (const p of prevPrices) {
fastEma.update(p);
slowEma.update(p);
}
// Capture previous crossover state
const prevFast = fastEma.isStable ? fastEma.getResult().valueOf() : null;
const prevSlow = slowEma.isStable ? slowEma.getResult().valueOf() : null;
// Now feed the latest price (current candle)
const lastPrice = S.prices[S.prices.length - 1];
fastEma.update(lastPrice);
slowEma.update(lastPrice);
if (!fastEma.isStable || !slowEma.isStable) {
await $.Storage.set(S);
return;
}
const currFast = fastEma.getResult().valueOf();
const currSlow = slowEma.getResult().valueOf();
const lastAction = $.Strategy.lastTrigger.action;
// Detect crossover: fast crossed ABOVE slow
const crossedUp = prevFast !== null && prevFast <= prevSlow && currFast > currSlow;
// Detect crossunder: fast crossed BELOW slow
const crossedDown = prevFast !== null && prevFast >= prevSlow && currFast < currSlow;
if (crossedUp && lastAction !== $.Action.LONG) {
await $.Strategy.action($.Action.LONG);
} else if (crossedDown && lastAction === $.Action.LONG) {
await $.Strategy.action($.Action.EXIT);
}
await $.Storage.set(S);