Volume-Based Strategy with Custom Indicator
This strategy uses a custom indicator to calculate the ratio between buy and sell volume over a period. It demonstrates:
- How to create a custom indicator that maintains state per token
- How to handle rolling windows of data
- How to use volume data for trading decisions
The VolumeRatio indicator:
- Maintains a rolling window of buy and sell volumes for each token
- Calculates the ratio of total buy volume to total sell volume
- Returns values > 1 when buying pressure is stronger, < 1 when selling pressure is stronger
The strategy:
- Buys when the ratio > 1.5 (50% more buying than selling)
- Sells when the ratio < 0.67 (50% more selling than buying)
class VolumeRatio extends BaseIndicator {
constructor(id, params) {
super(id, params);
this.tokenState = new Map();
this.period = params.period || 20;
}
onNewBar(candle, barIndex) {
const token = candle.token_address;
let state = this.tokenState.get(token);
if (!state) {
state = { buyVols: [], sellVols: [] };
this.tokenState.set(token, state);
}
state.buyVols.push(candle.buy_volume);
state.sellVols.push(candle.sell_volume);
if (state.buyVols.length > this.period) {
state.buyVols.shift();
state.sellVols.shift();
}
}
getValue(token) {
const state = this.tokenState.get(token);
if (!state || state.buyVols.length < this.period) return NaN;
const totalBuy = state.buyVols.reduce((a, b) => a + b, 0);
const totalSell = state.sellVols.reduce((a, b) => a + b, 0);
return totalBuy / totalSell;
}
}
// Register the custom indicator
registerIndicator(
"VOLUME_RATIO", // Name for this type of indicator
VolumeRatio, // Class reference
{ period: 20 }, // Parameters
"VOL_RATIO_20" // Custom ID for this instance
);
function onBar(data, indicators, positions, trades) {
const rowCount = data.close.length;
const signals = new Array(rowCount).fill("HOLD");
for (let i = 0; i < rowCount; i++) {
const token = data.token_address[i];
const ratio = indicators.getValue("VOL_RATIO_20", token);
if (ratio > 1.5) { // 50% more buying than selling
signals[i] = "BUY";
} else if (ratio < 0.67) { // 50% more selling than buying
signals[i] = "SELL";
}
}
return signals;
}