0bps

Strategy vault / Breakout

Quantitative Trading Strategy Based on Multiple Indicators

This strategy combines multiple technical indicators to make long and short trading decisions. It mainly uses Bollinger Bands, RSI, ADX and other indicators, together with moving averages to determine trend direction.

Author
ChaoZhang
Complexity
Intermediate · 116 lines
Parameters
9
Backtest bar
2h · intraday
Tested on
BTC/USDT · futures

IMG

Overview

This strategy combines multiple technical indicators to make long and short trading decisions. It mainly uses Bollinger Bands, RSI, ADX and other indicators, together with moving averages to determine trend direction.

Strategy Logic

The strategy mainly uses Bollinger Bands to judge price volatility. Narrowing bands represents decreasing volatility which may lead to a breakout. RSI is used to identify overbought and oversold conditions. RSI above 70 is overbought while below 30 is oversold. When bands narrow and RSI approaches its limits, reverse trading is considered.

In addition, ADX is used to assess trend strength. High ADX represents a strong trend, favoring trend trading. Low ADX represents no clear trend, considering mean reversion. Finally, moving averages define long-term trend direction. Uptrend favors long while downtrend favors short.

Specifically, when bands squeeze, RSI nears its limits, and price breaks below lower band, a bounce is expected, go long. When bands squeeze, RSI nears its limits, and price breaks above upper band, a decline is expected, go short. Also, with high ADX, add longs in uptrend. With low ADX, add shorts in downtrend. Combining indicators improves system robustness.

Advantage Analysis

The multi-indicator strategy has these advantages:

  1. Combining indicators improves accuracy and robustness. Single indicator is prone to false signals while multiple indicators verify signals and avoid bad trades.

  2. Considers both trend and range trading, adaptable to different market conditions. Trend trading targets big moves. Range trading aims for small profits.

  3. Longs and shorts lower directional risks and avoid extreme moves.

  4. Stop loss and take profit lock in profits and limit losses when trades go wrong.

  5. Parameter optimization continuously improves strategy by adapting to changing markets.

Risk Analysis

The strategy also has some risks:

  1. More indicators increase complexity. Improper settings may degrade performance. Extensive testing and optimization are needed.

  2. Overreliance on technicals while ignoring fundamentals may cause inaccurate signals. Indicator false signals should be treated with caution.

  3. Markets may have already moved when signals emerge, posing chasing risk. Allowing pullbacks is prudent.

  4. Dual direction trading increases frequency, raising costs and pressure. Position sizing needs control.

  5. Curve fitting risks exist. Robustness should be tested across diverse markets.

Risks can be managed through strict stop loss, prudent position sizing, reasonable leverage etc. Overall, the strategy has strong practical value.

Enhancement Opportunities

Some ways to optimize the strategy:

  1. Test different parameter sets to find optimum values using stepwise, random or genetic algorithms.

  2. Add more indicators like KDJ, Williams to build a robust indicator ensemble.

  3. Optimize position sizing models to dynamically manage risk.

  4. Incorporate machine learning models to predict price trends and movements.

  5. Test across different products, timeframes and markets to improve adaptiveness.

  6. Refine entry and exit timing to capture trends early and exit before reversals.

  7. Employ profit taking, trailing stops to lock in profits and limit losses.

  8. Add fundamental factors and market structure analysis to filter technical signals.

Summary

This strategy automates trading by interpreting multiple indicators. It benefits from indicator cross-validation, dual direction trading, stop loss/take profit etc. Overfitting and false signals require caution. Continuous optimization and testing can transform it into a robust, practical system, representing the future of quant trading strategies.

Parameters

NameDefaultWhat it controls
v_input_int_115length1
v_input_float_12mult1
v_input_114ADX Smoothing
v_input_214DI Length
v_input_int_214(?RSI Settings)RSI Length
v_input_source_1_close0Source: close | high | low | open | hl2 | hlc3 | hlcc4 | ohlc4
v_input_string_10(?MA Settings)MA Type: SMA | Bollinger Bands | EMA | SMMA (RMA) | WMA | VWMA
v_input_int_314MA Length
v_input_float_22BB StdDev

Source Pine Script

/*backtest
start: 2023-09-24 00:00:00
end: 2023-10-24 00:00:00
period: 2h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © The_Bigger_Bull
//@version=5
strategy("Best TradingView Strategy", overlay=true, margin_long=0, margin_short=0)
//Bollinger Bands
source1 = close
length1 = input.int(15, minval=1)
mult1 = input.float(2.0, minval=0.001, maxval=50)
basis1 = ta.sma(source1, length1)
dev1 = mult1 * ta.stdev(source1, length1)
upper1 = basis1 + dev1
lower1 = basis1 - dev1
//buyEntry = ta.crossover(source1, lower1)
//sellEntry = ta.crossunder(source1, upper1)

//RSI
ma(source, length, type) =>
    switch type
        "SMA" => ta.sma(source, length)
        "Bollinger Bands" => ta.sma(source, length)
        "EMA" => ta.ema(source, length)
        "SMMA (RMA)" => ta.rma(source, length)
        "WMA" => ta.wma(source, length)
        "VWMA" => ta.vwma(source, length)

rsiLengthInput = input.int(14, minval=1, title="RSI Length", group="RSI Settings")
rsiSourceInput = input.source(close, "Source", group="RSI Settings")
maTypeInput = input.string("SMA", title="MA Type", options=["SMA", "Bollinger Bands", "EMA", "SMMA (RMA)", "WMA", "VWMA"], group="MA Settings")
maLengthInput = input.int(14, title="MA Length", group="MA Settings")
bbMultInput = input.float(2.0, minval=0.001, maxval=50, title="BB StdDev", group="MA Settings")

up = ta.rma(math.max(ta.change(rsiSourceInput), 0), rsiLengthInput)
down = ta.rma(-math.min(ta.change(rsiSourceInput), 0), rsiLengthInput)
rsi = down == 0 ? 100 : up == 0 ? 0 : 100 - (100 / (1 + up / down))
rsiMA = ma(rsi, maLengthInput, maTypeInput)
isBB = maTypeInput == "Bollinger Bands"

//plot(rsi, "RSI", color=#7E57C2)
//plot(rsiMA, "RSI-based MA", color=color.yellow)
rsiUpperBand = hline(70, "RSI Upper Band", color=#787B86)
hline(50, "RSI Middle Band", color=color.new(#787B86, 50))
rsiLowerBand = hline(30, "RSI Lower Band", color=#787B86)
fill(rsiUpperBand, rsiLowerBand, color=color.rgb(126, 87, 194, 90), title="RSI Background Fill")
bbUpperBand = plot(isBB ? rsiMA + ta.stdev(rsi, maLengthInput) * bbMultInput : na, title = "Upper Bollinger Band", color=color.green)
bbLowerBand = plot(isBB ? rsiMA - ta.stdev(rsi, maLengthInput) * bbMultInput : na, title = "Lower Bollinger Band", color=color.green)
fill(bbUpperBand, bbLowerBand, color= isBB ? color.new(color.green, 90) : na, title="Bollinger Bands Background Fill")

//ADX

adxlen = input(14, title="ADX Smoothing")
dilen = input(14, title="DI Length")
dirmov(len) =>
	up1 = ta.change(high)
	down1 = -ta.change(low)
	plusDM = na(up1) ? na : (up1 > down1 and up1 > 0 ? up1 : 0)
	minusDM = na(down1) ? na : (down1 > up1 and down1 > 0 ? down1 : 0)
	truerange = ta.rma(ta.tr, len)
	plus = fixnan(100 * ta.rma(plusDM, len) / truerange)
	minus = fixnan(100 * ta.rma(minusDM, len) / truerange)
	[plus, minus]
adx(dilen, adxlen) =>
	[plus, minus] = dirmov(dilen)
	sum = plus + minus
	adx = 100 * ta.rma(math.abs(plus - minus) / (sum == 0 ? 1 : sum), adxlen)
sig = adx(dilen, adxlen)




out = ta.sma(close, 14)

sma1=ta.sma(close,55)

ema200=ta.ema(close,200)



longCondition = (out>sma1) and ta.crossover(source1, lower1)

if (longCondition )
    strategy.entry("long", strategy.long)
    
shortCondition = (out<sma1) and ta.crossunder(source1, lower1)

if (shortCondition )
    strategy.entry("short", strategy.short)
    
    
stopl=strategy.position_avg_price-50
tptgt=strategy.position_avg_price+100
stopshort=strategy.position_avg_price+50
tptgtshort=strategy.position_avg_price-100

strategy.exit("longclose","long",trail_offset=5,trail_points=45,when=ta.crossover(sma1,out))
strategy.exit("shortclose","short",trail_offset=5,trail_points=45,when=ta.crossover(out,sma1))

    
//if strategy.position_avg_price<0
    
    
plot(sma1 , color=color.blue)
plot(out, color=color.green)
//plot(ema200,color=color.red)


    
    

Published by ChaoZhang on the FMZ strategy square · last modified 2023-10-25. Collected in the Quant Trading Vault. Unvalidated research: re-test with your own data and costs before trusting it.

Build this with AgenKit

A spec is not a trading system. Paste this into your coding agent and AgenKit runs a specialist team — architecture, test-first build, risk gates, review — with paper trading on by default.

in Claude Code, Cursor, Codex & 4 more
/agenkit build a production-grade trading bot with a backtest engine, risk controls and paper trading by default from strategies/Quantitative-Trading-Strategy-Based-on-Multiple-Indicators.md
  1. npx agenkit install engineering-kit in your project
  2. Paste the command into your agent and approve each phase
  3. Get tests, backtest, risk controls and a paper-trading switch

Understand it first

Before you run this, read the lesson behind the idea and how to backtest it honestly. Specs like this one are the survivors of an unknown number of trials; deflate their results accordingly.

Related specs

esc

Try , , or .

↑↓ move↵ open