Skip to main content

Klinger & Mass Index

The Mass Index is a technical indicator that is used to identify trend reversals by analyzing the range between high and low prices. It calculates the difference between two moving averages of the range, and when this difference increases beyond a certain threshold, it indicates that a trend reversal is likely to occur.

The Klinger Oscillator, on the other hand, is a volume-based indicator that compares the volume flow of money into and out of a security over a given period of time. It combines a short-term and long-term volume moving average to generate signals for potential trend changes.

By using these two indicators together, the trading strategy can generate entry and exit signals. When the Mass Index indicates a potential trend reversal, the Klinger Oscillator can confirm this signal with its volume-based analysis. The strategy may buy when both indicators signal a trend reversal and sell when the indicators show a potential downturn in the market.

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 Mass Index
function massIndex(highs, lows) {
const nineEMA = ema(9, highs, lows);
const twentySixEMA = ema(26, highs, lows);
const diff = nineEMA.map((val, i) => val - twentySixEMA[i]);
const ratio = diff.map((val, i) => val / twentySixEMA[i]);
const emaRatio = ema(9, ratio, ratio);
const sum = emaRatio.reduce((acc, val) => acc + val, 0);
return 25 / sum;
}

// calculate Klinger Oscillator
function klingerOscillator() {
const volumeEMA = ema(34, gb.data.candlesVolume, gb.data.candlesVolume);
const moneyFlow = gb.data.candlesClose.map((val, i) => val * gb.data.candlesVolume[i]);
const cmf = moneyFlow.map((val, i) => {
if (i === 0) return 0;
const prevClose = gb.data.candlesClose[i - 1];
const prevVolume = gb.data.candlesVolume[i - 1];
const moneyFlowMultiplier = (val > (prevClose * prevVolume)) ? 1 : (val < (prevClose * prevVolume)) ? -1 : 0;
return moneyFlowMultiplier * gb.data.candlesVolume[i];
});
const cmfEMA = ema(13, cmf, cmf);
const klinger = cmfEMA.map((val, i) => val - volumeEMA[i]);
return klinger;
}

// calculate exponential moving average
function ema(period, highs, lows) {
const emaArr = [];
const multiplier = 2 / (period + 1);
let ema = highs[0];
for (let i = 1; i < highs.length; i++) {
ema = (highs[i] - ema) * multiplier + ema;
emaArr.push(ema);
}
return emaArr;
}

if (enoughTimePassed) {
// calculate indicators
const massIndexValue = massIndex(gb.data.candlesHigh, gb.data.candlesLow);
const klingerOscillatorValue = klingerOscillator();

// log indicators
console.log("Mass Index:", massIndexValue);
console.log("Klinger Oscillator:", klingerOscillatorValue[klingerOscillatorValue.length - 1]);

// set buy and sell conditions
const buyConditions = massIndexValue < 26 && klingerOscillatorValue[klingerOscillatorValue.length - 1] > 0 && !gb.data.gotBag;
const sellConditions = massIndexValue > 27 && klingerOscillatorValue[klingerOscillatorValue.length - 1] < 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");
} else if (sellConditions) {
gb.method.sellMarket(gb.data.quoteBalance, gb.data.pairName);
setTimestamp();
console.log("Sell order placed");
}
}

// end of strategy code

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