Skip to main content

Time Series Forecast & Balance of Power strategy

This strategy uses two indicators, the Time Series Forecast (TSF) and the Balance of Power (BOP), to generate buy and sell signals.

TSF projects a price trend line from recent history to highlight potential direction changes. BOP compares the close to the high/low range to gauge bullish or bearish pressure.

In this example, a TSF cross above price with a positive BOP suggests a buy, while a TSF cross below price with a negative BOP suggests a sell.

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 Time Series Forecast (TSF) indicator
function tsf(period) {
const prices = gb.data.candlesClose.slice(-period);
const sumX = (period * (period + 1)) / 2;
const sumY = prices.reduce((a, b, i) => a + b * (i + 1), 0);
const sumXY = prices.reduce((a, b, i) => a + b * (i + 1) * (period - i), 0);
const sumX2 = (period * (period + 1) * (2 * period + 1)) / 6;
const slope = (period * sumXY - sumX * sumY) / (period * sumX2 - sumX ** 2);
const intercept = (sumY - slope * sumX) / period;
return slope * (period + 1) + intercept;
}

// calculate Balance of Power (BOP) indicator
function bop() {
const high = gb.data.candlesHigh.slice(-1)[0];
const low = gb.data.candlesLow.slice(-1)[0];
const close = gb.data.candlesClose.slice(-1)[0];
const volume = gb.data.candlesVolume.slice(-1)[0];
return (close - low) / (high - low) * volume;
}

// log indicators for debugging purposes
console.log(`TSF: ${tsf(10)}, BOP: ${bop()}`);

if (enoughTimePassed) {
const buyConditions = tsf(10) > gb.data.candlesClose.slice(-1)[0] && bop() > 0 && !gb.data.gotBag;
const sellConditions = tsf(10) < gb.data.candlesClose.slice(-1)[0] && bop() < 0 && gb.data.gotBag;

// fire orders when conditions are met
if (buyConditions) {
const buyAmount = gb.data.baseBalance * 0.95 / gb.data.ask; // use 95% of base balance to avoid dust
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