Skip to main content

Elder-Ray Index & Zig Zag indicator strategy

This strategy uses two indicators, the Elder-Ray Index and the Zig Zag indicator, to generate entry and exit signals.

The Elder-Ray Index tracks Bull Power and Bear Power by comparing highs and lows to an EMA to gauge buyer and seller strength.

The Zig Zag indicator filters minor price moves by connecting swing highs and lows and only shifting direction after a defined move.

tip

This example strategy is machine generated using Gunbot AI. Review its behavior carefully in a simulated bot instance before using parts of this code in production.

// initialize customStratStore within pairLedger object
gb.data.pairLedger.customStratStore = gb.data.pairLedger.customStratStore || {};

// forced wait time reduces risk of double orders
function checkTime() {
return !gb.data.pairLedger.customStratStore.timeCheck || typeof gb.data.pairLedger.customStratStore.timeCheck !== "number"
? (gb.data.pairLedger.customStratStore.timeCheck = Date.now(), false)
: (Date.now() - gb.data.pairLedger.customStratStore.timeCheck > 8000);
}
const enoughTimePassed = checkTime();

// set timestamp for checkTime in next round
const setTimestamp = () => gb.data.pairLedger.customStratStore.timeCheck = Date.now();

// calculate the Elder-Ray Index
function elderRayIndex() {
const high = gb.data.candlesHigh;
const low = gb.data.candlesLow;
const close = gb.data.candlesClose;
const ema13 = calculateEMA(13, close);
const ema26 = calculateEMA(26, close);
const bullPower = high.map((h, i) => h - ema13[i]);
const bearPower = low.map((l, i) => l - ema13[i]);
const elderRay = close.map((c, i) => {
const diff = ema13[i] - ema26[i];
return diff > 0 ? bullPower[i] / diff : bearPower[i] / Math.abs(diff);
});
return elderRay;
}

// calculate the Zig Zag indicator
function zigZag() {
const deviation = 0.05;
const pivotHigh = [];
const pivotLow = [];
let trend = "up";
let lastPivot = 0;
let currentHigh = 0;
let currentLow = 0;
for (let i = 0; i < gb.data.candlesClose.length; i++) {
if (gb.data.candlesHigh[i] >= currentHigh) {
currentHigh = gb.data.candlesHigh[i];
currentLow = gb.data.candlesLow[i];
if (trend === "down" && (currentHigh - currentLow) > (currentHigh - lastPivot) * deviation) {
pivotLow.push(lastPivot);
trend = "up";
lastPivot = currentLow;
currentHigh = 0;
currentLow = 0;
}
} else if (gb.data.candlesLow[i] <= currentLow) {
currentLow = gb.data.candlesLow[i];
currentHigh = gb.data.candlesHigh[i];
if (trend === "up" && (currentHigh - currentLow) > (lastPivot - currentLow) * deviation) {
pivotHigh.push(lastPivot);
trend = "down";
lastPivot = currentHigh;
currentHigh = 0;
currentLow = 0;
}
}
}
return { pivotHigh, pivotLow };
}

// calculate the Exponential Moving Average
function calculateEMA(period, data) {
const ema = [];
const multiplier = 2 / (period + 1);
let sma = data.slice(0, period).reduce((acc, val) => acc + val, 0) / period;
ema.push(sma);
for (let i = period; i < data.length; i++) {
const currentEMA = (data[i] - ema[i - period]) * multiplier + ema[i - period];
ema.push(currentEMA);
}
return ema;
}

// log all indicators
console.log("Elder-Ray Index:", elderRayIndex());
console.log("Zig Zag:", zigZag());

if (enoughTimePassed) {
const buyConditions = elderRayIndex()[elderRayIndex().length - 1] > 0 && zigZag().pivotLow.length > 0 && !gb.data.gotBag;
const sellConditions = elderRayIndex()[elderRayIndex().length - 1] < 0 && zigZag().pivotHigh.length > 0 && gb.data.gotBag;

// fire orders when conditions are met
if (buyConditions) {
const buyAmount = parseFloat(gb.data.pairLedger.whatstrat.TRADING_LIMIT) / gb.data.bid;
gb.method.buyMarket(buyAmount, gb.data.pairName);
setTimestamp();
} else if (sellConditions) {
gb.method.sellMarket(gb.data.quoteBalance, gb.data.pairName);
setTimestamp();
}
}

// Code is machine generated, review it and run in simulator mode first