Intermediate ~20 min Python Build guide

Combine Multiple Indicators

Single indicators give signals — combining them gives confidence. Learn how to build a confluence scoring system that weighs multiple indicators for stronger, more reliable trading signals.

1 sections 1 copy-paste code sample Python
1Guide sections
1Code samples
IntermediateLevel
20 minTime

The Confluence Approach

Instead of relying on a single indicator, score each signal and sum them up. More indicators agreeing = higher confidence in the trade.

01 RSI Momentum
02 MACD Trend + Momentum
03 SMA Cross Trend Direction

Confluence Scoring System

Python Confluence Scoring System
import requests

API_KEY = "YOUR_API_KEY"
BASE = "https://tickatlas.com/v1"
headers = {"X-API-Key": API_KEY}

def confluence_score(symbol, timeframe="H1"):
    """Score a symbol based on multiple indicator signals."""
    params = {
        "symbols": symbol,
        "indicators": "RSI_14,MACD_main,MACD_signal,ADX,SMA_50,SMA_200,BB_upper,BB_lower",
        "timeframe": timeframe
    }
    resp = requests.get(f"{BASE}/multi", headers=headers, params=params).json()
    ind = resp["data"]["data"].get(symbol, {})

    score = 0  # -4 (strong sell) to +4 (strong buy)

    # RSI
    rsi = ind.get("RSI_14", 50)
    if rsi < 30: score += 1    # Oversold = bullish
    elif rsi > 70: score -= 1  # Overbought = bearish

    # MACD
    macd = ind.get("MACD_main", 0)
    signal = ind.get("MACD_signal", 0)
    if macd > signal: score += 1
    elif macd < signal: score -= 1

    # Trend (SMA Golden/Death Cross)
    sma50 = ind.get("SMA_50", 0)
    sma200 = ind.get("SMA_200", 0)
    if sma50 > sma200: score += 1
    elif sma50 < sma200: score -= 1

    # ADX trend strength
    adx = ind.get("ADX", 0)
    if adx > 25: score = int(score * 1.5)  # Amplify in strong trends

    return {
        "symbol": symbol,
        "score": score,
        "signal": "STRONG BUY" if score >= 3 else
                  "BUY" if score >= 1 else
                  "NEUTRAL" if score == 0 else
                  "SELL" if score >= -2 else "STRONG SELL",
        "details": {"rsi": rsi, "macd": macd, "adx": adx,
                     "sma50": sma50, "sma200": sma200}
    }

# Test it
for sym in ["EURUSD", "GBPUSD", "XAUUSD", "USDJPY"]:
    result = confluence_score(sym)
    print(f"{result['symbol']}: {result['signal']} (score: {result['score']})")

Best Indicator Combinations

RSI + MACD + SMA Classic combo: momentum + trend confirmation. Works on all timeframes.
Bollinger Bands + RSI Volatility + momentum. Great for mean-reversion in ranging markets.
ADX + Parabolic SAR + EMA Trend strength + direction + dynamic support/resistance.
Stochastic + CCI + MFI Triple oscillator combo for spotting reversals with volume confirmation.

Production hardening

The code above is the happy path. These are the concerns that decide whether it survives contact with a real deployment.

Keep the key server-side. The API key authenticates with the X-API-Key header and must never reach a browser bundle. Proxy it, or use a public widget key, which is domain-scoped and revocable. Authentication
Handle 429 before you need to. Rate limits are per key and per minute. Back off on 429 rather than retrying immediately, and read the X-RateLimit-* headers on every response. Rate limits
Branch on the error code, not the message. Errors carry a stable machine-readable code; the human-readable text can change. Codes were unified in v3.15. Error handling
Expect gaps, and do not invent values. Markets close, feeds stall, and a retention window can reject a request outright. Surface an explicit unavailable state rather than substituting a zero or the last known price. Troubleshooting
Cache what you poll. Responses are already cached briefly upstream, so polling faster than the data changes spends credits without improving freshness. Cache on your side and poll on the cadence your timeframe actually updates. Pricing and credits
Watch retention per timeframe. History depth is set per timeframe, never per plan, so a request that works on D1 can fall outside the window on M1. Check the published windows before backfilling. Timeframes
Rotate keys and scope them. Issue a separate key per deployment so one can be revoked without taking the others down, and rotate on a schedule rather than after an incident. Authentication
Log the request, not the key. Record endpoint, parameters, status and latency so a failure is reproducible. Never log the key itself, and scrub it from error reports.

Related Guides

Everything this guide touches, linked directly — so it never dead-ends.

Build against live market data

Start with the data layer already solved.

Create an API key, run the first request, then extend one layer at a time. Every account starts pay-as-you-go with $2.50 of credit.