Multi-Indicator Confluence Strategy

A robust strategy that requires multiple indicator confirmations before entering trades.

Strategy Overview

AspectDetails
TypeConfluence / Multi-Factor
IndicatorsRSI, MACD, ADX, Bollinger Bands
Timeframes1h, 4h, 1d
MarketsAll (Spot & Futures)
DifficultyAdvanced

How It Works

  1. Scoring System: Each indicator contributes a bullish or bearish signal
  2. Confluence Threshold: Only trade when multiple indicators agree
  3. Dynamic Exits: Exit when signals reverse or threshold drops

This approach significantly reduces false signals by requiring multiple confirmations.

Complete Code

// ============================================
// MULTI-INDICATOR CONFLUENCE STRATEGY
// ============================================
// Requires multiple indicator confirmations
// before entering trades. Uses a scoring system
// to measure market conviction.
// ============================================

// ============================================
// PARAMETERS
// ============================================
const MIN_CONFLUENCE = td.config.getNumber('MIN_CONFLUENCE', 3);
const EXIT_CONFLUENCE = td.config.getNumber('EXIT_CONFLUENCE', 2);
const USE_RSI = td.config.getBoolean('USE_RSI', true);
const USE_MACD = td.config.getBoolean('USE_MACD', true);
const USE_ADX = td.config.getBoolean('USE_ADX', true);
const USE_BB = td.config.getBoolean('USE_BB', true);
const USE_EMA = td.config.getBoolean('USE_EMA', true);
const STOP_LOSS_PCT = td.config.getNumber('STOP_LOSS_PCT', 2);
const TAKE_PROFIT_PCT = td.config.getNumber('TAKE_PROFIT_PCT', 6);
const POSITION_SIZE = td.config.getNumber('POSITION_SIZE', 100);
const ENABLE_SHORTS = td.config.getBoolean('ENABLE_SHORTS', false);

// ============================================
// VALIDATION
// ============================================
if (td.market.candles.length < 50) {
    td.utils.log('Waiting for sufficient data');
    return;
}

// Count enabled indicators
const enabledIndicators = [USE_RSI, USE_MACD, USE_ADX, USE_BB, USE_EMA]
    .filter(Boolean).length;

if (MIN_CONFLUENCE > enabledIndicators) {
    td.utils.log('ERROR: MIN_CONFLUENCE exceeds enabled indicators');
    return;
}

// ============================================
// HELPER FUNCTION
// ============================================
function getIndicator(key) {
    const val = td.indicators.custom[key];
    if (val === undefined || val === null) return 0;
    if (Array.isArray(val)) return val[val.length - 1];
    return val;
}

// ============================================
// CALCULATE INDICATORS
// ============================================
const rsi = td.indicators.rsi;
const macd = td.indicators.macd;
const adx = td.indicators.adx;
const bb = td.indicators.bbands;
const ema50 = getIndicator('ema_50');
const ema200 = getIndicator('ema_200');
const price = td.market.price;

// ============================================
// SCORING SYSTEM
// ============================================
let bullScore = 0;
let bearScore = 0;
const signals = [];

// RSI Signals
if (USE_RSI) {
    if (rsi < 35) {
        bullScore++;
        signals.push('RSI oversold');
    } else if (rsi > 65) {
        bearScore++;
        signals.push('RSI overbought');
    }
}

// MACD Signals
if (USE_MACD) {
    if (macd.histogram > 0 && macd.trend === 'bullish') {
        bullScore++;
        signals.push('MACD bullish');
    } else if (macd.histogram < 0 && macd.trend === 'bearish') {
        bearScore++;
        signals.push('MACD bearish');
    }
}

// ADX Trend Strength & Direction
if (USE_ADX) {
    if (adx.value > 25) {
        if (adx.diPlus > adx.diMinus) {
            bullScore++;
            signals.push('ADX bullish trend');
        } else {
            bearScore++;
            signals.push('ADX bearish trend');
        }
    }
}

// Bollinger Band Position
if (USE_BB) {
    if (bb.percentB < 0.2) {
        bullScore++;
        signals.push('BB oversold');
    } else if (bb.percentB > 0.8) {
        bearScore++;
        signals.push('BB overbought');
    }
}

// EMA Trend
if (USE_EMA) {
    if (price > ema50 && ema50 > ema200) {
        bullScore++;
        signals.push('EMA bullish alignment');
    } else if (price < ema50 && ema50 < ema200) {
        bearScore++;
        signals.push('EMA bearish alignment');
    }
}

// ============================================
// ENTRY LOGIC
// ============================================
if (!td.position.hasPosition) {
    // LONG ENTRY
    if (bullScore >= MIN_CONFLUENCE) {
        const stopLoss = td.utils.round(price * (1 - STOP_LOSS_PCT / 100), 2);
        const takeProfit = td.utils.round(price * (1 + TAKE_PROFIT_PCT / 100), 2);

        td.trade.buy({
            amountPercent: POSITION_SIZE,
            stopLoss: stopLoss,
            takeProfit: takeProfit,
            reason: `Bull confluence: ${bullScore}/${enabledIndicators}`
        });

        td.utils.log('LONG ENTRY', {
            bullScore: bullScore,
            signals: signals,
            price: price
        });

        td.state.set('entryScore', bullScore);
        td.state.set('entrySide', 'long');
    }

    // SHORT ENTRY
    if (ENABLE_SHORTS && bearScore >= MIN_CONFLUENCE) {
        const stopLoss = td.utils.round(price * (1 + STOP_LOSS_PCT / 100), 2);
        const takeProfit = td.utils.round(price * (1 - TAKE_PROFIT_PCT / 100), 2);

        td.trade.sell({
            amountPercent: POSITION_SIZE,
            stopLoss: stopLoss,
            takeProfit: takeProfit,
            reason: `Bear confluence: ${bearScore}/${enabledIndicators}`
        });

        td.utils.log('SHORT ENTRY', {
            bearScore: bearScore,
            signals: signals,
            price: price
        });

        td.state.set('entryScore', bearScore);
        td.state.set('entrySide', 'short');
    }
}

// ============================================
// EXIT LOGIC
// ============================================
if (td.position.hasPosition) {
    const entrySide = td.state.get('entrySide');

    // Exit long when bear signals strengthen
    if (entrySide === 'long' && bearScore >= EXIT_CONFLUENCE) {
        td.trade.close(`Bear confluence reached: ${bearScore}`);
        td.utils.log('EXIT LONG', {
            bearScore: bearScore,
            pnl: td.position.pnl,
            signals: signals
        });
    }

    // Exit short when bull signals strengthen
    if (entrySide === 'short' && bullScore >= EXIT_CONFLUENCE) {
        td.trade.close(`Bull confluence reached: ${bullScore}`);
        td.utils.log('EXIT SHORT', {
            bullScore: bullScore,
            pnl: td.position.pnl,
            signals: signals
        });
    }

    // Trailing stop based on score degradation
    const entryScore = td.state.get('entryScore', MIN_CONFLUENCE);
    const currentScore = entrySide === 'long' ? bullScore : bearScore;

    if (currentScore < entryScore - 1 && td.position.pnlPercent > 0) {
        td.trade.close('Confluence weakening with profit');
        td.utils.log('EXIT - Score degradation', {
            entryScore: entryScore,
            currentScore: currentScore,
            pnl: td.position.pnl
        });
    }
}

// ============================================
// DEBUG LOGGING
// ============================================
const DEBUG = td.config.getBoolean('DEBUG_MODE', false);
if (DEBUG) {
    td.utils.log('Confluence Scores', {
        bullScore: bullScore,
        bearScore: bearScore,
        minRequired: MIN_CONFLUENCE,
        signals: signals,
        indicators: {
            rsi: rsi.toFixed(2),
            macdHistogram: macd.histogram.toFixed(4),
            adx: adx.value.toFixed(2),
            bbPercentB: bb.percentB.toFixed(3),
            priceVsEma50: price > ema50 ? 'above' : 'below'
        }
    });
}

Parameters

ParameterTypeDefaultDescription
MIN_CONFLUENCENumber3Minimum signals to enter
EXIT_CONFLUENCENumber2Opposite signals to exit
USE_RSIBooleantrueInclude RSI signals
USE_MACDBooleantrueInclude MACD signals
USE_ADXBooleantrueInclude ADX signals
USE_BBBooleantrueInclude Bollinger Band signals
USE_EMABooleantrueInclude EMA trend signals
STOP_LOSS_PCTNumber2Stop loss percentage
TAKE_PROFIT_PCTNumber6Take profit percentage
ENABLE_SHORTSBooleanfalseAllow short positions

Scoring System Explained

Each indicator can add one point to bull or bear score:

IndicatorBullish SignalBearish Signal
RSIRSI < 35RSI > 65
MACDHistogram > 0, bullishHistogram < 0, bearish
ADXDI+ > DI- (trending up)DI- > DI+ (trending down)
BB%B < 0.2 (near lower)%B > 0.8 (near upper)
EMAPrice > EMA50 > EMA200Price < EMA50 < EMA200

Maximum score: 5 (if all indicators enabled)

Recommended Settings

Conservative (High Confluence)

MIN_CONFLUENCE: 4
EXIT_CONFLUENCE: 2
STOP_LOSS_PCT: 1.5
TAKE_PROFIT_PCT: 4
ENABLE_SHORTS: false

Moderate

MIN_CONFLUENCE: 3
EXIT_CONFLUENCE: 2
STOP_LOSS_PCT: 2
TAKE_PROFIT_PCT: 6

Aggressive (More Trades)

MIN_CONFLUENCE: 2
EXIT_CONFLUENCE: 2
ENABLE_SHORTS: true

Performance Tips

  1. Higher confluence = fewer trades but higher quality
  2. Lower confluence = more trades but more noise
  3. ADX filter is crucial - prevents trading in choppy markets
  4. EMA alignment - ensures you trade with the major trend
  5. Test on higher timeframes first (4h, 1d)

Customization Ideas

Add Volume Confirmation

// Add volume to scoring
const avgVolume = td.market.candles.slice(-20)
    .reduce((s, c) => s + c.volume, 0) / 20;
const currentVol = td.market.candles.slice(-1)[0].volume;

if (currentVol > avgVolume * 1.5) {
    // High volume confirms the move
    if (bullScore > 0) bullScore++;
    if (bearScore > 0) bearScore++;
    signals.push('High volume confirmation');
}

Weighted Scoring

// Give more weight to certain indicators
const weights = {
    rsi: 1,
    macd: 1.5,  // MACD is more important
    adx: 2,     // Trend confirmation is critical
    bb: 1,
    ema: 1.5
    openGraph: { title: 'Multi-Indicator Example', description: 'Example multi-indicator custom trading strategy.' },
};

// In RSI section:
if (rsi < 35) bullScore += weights.rsi;

// In MACD section:
if (macd.histogram > 0) bullScore += weights.macd;

// Adjust MIN_CONFLUENCE accordingly (e.g., 4.5 instead of 3)

Next Steps