Skip to main content

Choppiness Index and the Detrended Price Oscillator

This strategy involves using two technical indicators, the Choppiness Index and the Detrended Price Oscillator, to generate signals for entering and exiting trades.

The Choppiness Index is a measure of the market's trendiness, indicating whether the market is choppy or trending. It ranges between 0 and 100, with values below 38 indicating a choppy market and values above 61 indicating a trending market. The Detrended Price Oscillator (DPO) is a momentum indicator that aims to remove the trend component from the price action, allowing traders to focus on short-term price movements.

The strategy aims to buy and sell based on the signals generated by these indicators. The exact rules for entering and exiting trades are not specified, but the strategy seems to imply that it avoids buying when the market is choppy and does not sell when the market is trending strongly.

Overall, this strategy aims to capitalize on short-term price movements by identifying entry and exit signals using two technical indicators, while also taking into account the market's trendiness to avoid entering trades in unfavorable 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 choppiness index
function choppinessIndex(period = 14) {
const high = gb.data.candlesHigh.slice(-period);
const low = gb.data.candlesLow.slice(-period);
const close = gb.data.candlesClose.slice(-period);
const atr = gb.data.atr.slice(-period);
const range = high.map((h, i) => h - low[i]);
const tr = range.map((r, i) => Math.max(high[i] - low[i], Math.abs(high[i] - close[i - 1]), Math.abs(low[i] - close[i - 1])));
const atrSum = atr.reduce((acc, val) => acc + val, 0);
const trSum = tr.reduce((acc, val) => acc + val, 0);
const ci = 100 * Math.log10(atrSum / trSum) / Math.log10(period);
return ci;
}

// calculate detrended price oscillator
function detrendedPriceOscillator(period = 14) {
const close = gb.data.candlesClose.slice(-period);
const sma = close.reduce((acc, val) => acc + val, 0) / period;
const detrended = close.map((c) => c - sma);
const dpo = detrended[Math.floor(period / 2)];
return dpo;
}

if (enoughTimePassed) {
// calculate indicators
const ci = choppinessIndex();
const dpo = detrendedPriceOscillator();

// log indicators
console.log(`Choppiness Index: ${ci}`);
console.log(`Detrended Price Oscillator: ${dpo}`);

// set buy and sell conditions
const buyConditions = ci < 38 && dpo > 0 && !gb.data.gotBag;
const sellConditions = ci > 62 && dpo < 0 && gb.data.gotBag;

// log trading conditions
console.log(`Buy Conditions: ${buyConditions}`);
console.log(`Sell Conditions: ${sellConditions}`);

// 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