Skip to main content

Chaikin

A mean reversion strategy that uses Moving Average Envelopes and Chaikin Oscillator as indicators for entry and exit signals.

The Moving Average Envelopes are two lines that are drawn above and below the moving average of the price of the asset. These lines create a channel that helps to identify the overbought and oversold levels of the asset's price. The strategy is based on the assumption that when the price of the asset moves too far away from the moving average, it will eventually revert back to the mean.

The Chaikin Oscillator is another technical indicator that measures the accumulation or distribution of the asset. It is calculated by subtracting a 10-period exponential moving average of the Accumulation Distribution Line (ADL) from a 3-period exponential moving average of the ADL. The oscillator moves above and below a zero line and helps to identify the momentum of the asset's price.

The strategy calculates these indicators without using built-in methods and logs every indicator and trading condition. It avoids buying when there is a "bag," which likely refers to a negative trend or signal, and avoids selling when there is no "bag," which likely refers to a positive trend or signal.

Overall, the strategy is a mean reversion strategy that uses technical indicators to identify potential entry and exit points for trades, and seeks to avoid buying or selling during unfavorable market conditions.

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 moving average envelopes
const maPeriod = 20;
const maMultiplier = 0.025;
const maUpper = gb.data.candlesClose.map((close, i) => {
const ma = gb.data.candlesClose.slice(i - maPeriod + 1, i + 1).reduce((a, b) => a + b, 0) / maPeriod;
return ma + ma * maMultiplier;
});
const maLower = gb.data.candlesClose.map((close, i) => {
const ma = gb.data.candlesClose.slice(i - maPeriod + 1, i + 1).reduce((a, b) => a + b, 0) / maPeriod;
return ma - ma * maMultiplier;
});

// calculate chaikin oscillator
const adl = gb.data.candlesClose.reduce((acc, close, i) => {
const clv = ((close - gb.data.candlesLow[i]) - (gb.data.candlesHigh[i] - close)) / (gb.data.candlesHigh[i] - gb.data.candlesLow[i]) * gb.data.candlesVolume[i];
return acc + clv;
}, 0);
const adlEma1 = gb.data.ema1 ? gb.data.ema1 * (maPeriod - 1) / (maPeriod + 1) + adl * 2 / (maPeriod + 1) : adl;
const adlEma2 = gb.data.ema2 ? gb.data.ema2 * (maPeriod - 1) / (maPeriod + 1) + adl * 2 / (maPeriod + 1) : adl;
const chaikin = adlEma1 - adlEma2;

// log indicators
console.log(`MA Upper: ${maUpper[maUpper.length - 1]}`);
console.log(`MA Lower: ${maLower[maLower.length - 1]}`);
console.log(`Chaikin Oscillator: ${chaikin}`);

if (enoughTimePassed) {
const buyConditions = gb.data.candlesClose[gb.data.candlesClose.length - 1] < maLower[maLower.length - 1] && chaikin > 0 && !gb.data.gotBag;
const sellConditions = gb.data.candlesClose[gb.data.candlesClose.length - 1] > maUpper[maUpper.length - 1] && chaikin < 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();
console.log(`Buy order placed at ${gb.data.bid}`);
} else if (sellConditions) {
gb.method.sellMarket(gb.data.quoteBalance, gb.data.pairName);
setTimestamp();
console.log(`Sell order placed at ${gb.data.ask}`);
}
}

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