0bps

Strategy vault / Breakout

Multi Indicator Quantitative Trading Strategy

This strategy integrates moving averages, relative strength index (RSI) and moving average convergence divergence (MACD), three major technical indicators, to automatically open and close long and short positions…

Author
ChaoZhang
Complexity
Advanced · 299 lines
Parameters
61
Backtest bar
2h · intraday
Tested on
BTC/USDT · futures

IMG

Overview

This strategy integrates moving averages, relative strength index (RSI) and moving average convergence divergence (MACD), three major technical indicators, to automatically open and close long and short positions. The strategy name contains "Multi Indicator" to highlight the multiple indicators used in this strategy.

Strategy Logic

The strategy mainly judges the trend direction by comparing two moving averages, and combines the RSI indicator to avoid missing reversal opportunities. Specifically, the strategy uses EMA or SMA to calculate the fast line and slow line. The fast line crossing above the slow line is the buy signal, and the fast line crossing below is the sell signal. To filter false breakthroughs, the strategy also sets the logic of the RSI indicator, only when the RSI indicator also meets the condition, the trading signal will be triggered.

In addition, the MACD indicator is also integrated into the strategy for trading decisions. When the difference between MACD indicator crosses above the 0 axis, it is a buy signal, and when it crosses below, it is a sell signal. This can help judge whether the trend has reversed to avoid wrong signals at inflection points.

Advantage Analysis

The biggest advantage of this strategy is to integrate multiple indicators to filter signals, which can effectively reduce false signals and improve signal quality. Specifically, the advantages are as follows:

  1. The fast and slow lines combined with the RSI indicator can avoid false breakthroughs caused by the single use of moving averages.

  2. The integration of the MACD indicator can judge whether the trend has reversed prematurely to avoid wrong signals at the turning point.

  3. Choosing between EMA and SMA allows selecting indicators that are more suitable for different market characteristics.

  4. Choosing money management schemes allows controlling the size of single orders to effectively control risks.

  5. Supporting stop loss and take profit allows locking in profits and avoiding losses enlarging.

Risk Analysis

The main risks of this strategy include:

  1. Improper parameter optimization may lead to poor strategy performance. Need to spend time testing different parameter combinations.

  2. The probability of the indicator issuing wrong signals still exists. When the three indicators issue wrong signals at the same time, it will lead to greater losses.

  3. The performance of a single symbol is unstable, it is necessary to expand to other varieties.

  4. Datenicht zureichen, Strategie effekt wird in der Zukunft abnehmen.

Optimization Directions

The main aspects for optimizing this strategy include:

  1. Test different combinations of indicator parameters to find the optimal parameters.

  2. Increase trailing stop in the stop loss mechanism. After the price runs a certain distance, it can trail stop to lock in profits.

  3. Increase judgment indicators for major trend to avoid trading against the trend. For example, integrate the ADX indicator.

  4. Fügen Sie Moneymanagement Module hinzu für besseres Risikomanagement.

  5. Fügen Sie Filter für fundamentale Faktoren wie Nachrichten hinzu.

Summary

This strategy realizes finding and filtering long and short positions by integrating multiple technical indicators such as moving averages, RSI and MACD. Its advantage is that it can effectively filter out false signals and improve signal quality. The main drawbacks are the parameter selection and the probability of indicators issuing wrong signals still exist. Future optimization directions include parameter optimization, stop loss optimization, trend filtering, etc. Overall, this strategy is effective as a multi-indicator strategy framework, and needs further optimization and verification going forward.

Parameters

NameDefaultWhat it controls
v_input_10Source: close,op | op | hi | lo | _$10,c3 | c3 | hl
v_input_2false>=< >=< [STRATEGIES] >=< >=<
v_input_30Type Strategy: _L_ | _$17,_L_ | _S_
v_input_4false>=< >=< [BUY/LONG] >=< >=<
v_input_50Pick your poison:: (E)MA 1 > (E)MA 2 | Close above (E)MA 1 | RSI strategy | _$26,mcl | _$28,mcl0 | _$30,sgl0
v_input_6falseif RSI >
v_input_7100if RSI <
v_input_8falseif RSI (HTF) >
v_input_9100if RSI (HTF) <
v_input_100Extra argument: NONE | _$26,mcl | _$28,mcl0 | _$30,sgl0
v_input_110Second argument: NONE | _$32,mcl_HTF | _$34,mcl0HTF | _$36,sgl0HTF | (E)MA 1 (HTF) > (E)MA 2 (HTF) | Close above (E)MA 1 (HTF)
v_input_12false>=< [(E)MA settings (Buy/Long)] >=<
v_input_130(E)MA 1: SMA | _$38,SMA
v_input_1450Length
v_input_150(E)MA 2: SMA | _$38,SMA
v_input_16100Length
v_input_170(E)MA 1 - HTF: SMA | _$38,SMA
v_input_1850Length
v_input_190(E)MA 2 - HTF: SMA | _$38,SMA
v_input_20100Length
v_input_21false>=< >=< [SELL/SHORT] >=< >=<
v_input_220Pick your poison:: (E)MA 3 < (E)MA 4 | Close under (E)MA 3 | RSI strategy | mcl | mcl0 | sgl0
v_input_23falseif RSI >
v_input_24100if RSI <
v_input_25falseif RSI (HTF) >
v_input_26100if RSI (HTF) <
v_input_270Extra argument: NONE | mcl | mcl0 | sgl0
v_input_280Second argument: NONE | mcl_HTF | mcl0HTF | sgl0HTF | (E)MA 3 (HTF) < (E)MA 4 (HTF) | Close under (E)MA 3 (HTF)
v_input_29false>=< [(E)MA settings (Sell/Short)] >=<
v_input_300(E)MA 3: SMA | _$38,SMA
v_input_3150Length
v_input_320(E)MA 4: SMA | _$38,SMA
v_input_33100Length
v_input_340(E)MA 3 - HTF: SMA | _$38,SMA
v_input_3550Length
v_input_360(E)MA 4 - HTF: SMA | _$38,SMA
v_input_37100Length
v_input_38false>=< >=< [RSI]  >=< >=< >=<
v_input_3920RSI Length
v_input_40false>=< >=< [MACD] >=< >=< >=<
v_input_4112Fast Length
v_input_4226Slow Length
v_input_439Signal Smoothing
v_input_44falseSimple MA(Oscillator)
v_input_45falseSimple MA(Signal Line)
v_input_46false>=< >=< [HTF settings] >=< >=<
v_input_47D(E)MA HTF
v_input_48DRSI HTF
v_input_49DMACD HTF
v_input_50false>=< >=< [SL/TP] >=< >=< >=<
v_input_51falseStop Loss?
v_input_5210Stop Loss %
v_input_53falseTake Profit?
v_input_5420Take Profit %
v_input_55false>=< >=< [TIME] >=< >=< >=<
v_input_562010Since Year
v_input_572099Till Year
v_input_58trueSince Month
v_input_5912Till Month
v_input_60trueSince Day
v_input_6131Till Day

Source Pine Script

/*backtest
start: 2023-11-04 00:00:00
end: 2023-12-04 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/
// © fikira
//@version=4
strategy("Strategy Tester EMA-SMA-RSI-MACD", shorttitle="Strat-test", overlay=true, max_bars_back=5000, 
 default_qty_type= strategy.percent_of_equity, calc_on_order_fills=false, calc_on_every_tick=false, 
 pyramiding=0, default_qty_value=100, initial_capital=100)

Tiny     = "Tiny"
Small    = "Small"
Normal   = "Normal"
Large    = "Large"

cl      = "close" , op  = "open" , hi  = "high" , lo  = "low"
c4      = "ohlc4" , c3  = "hlc3" , hl  = "hl2"

co      = "(E)MA 1 > (E)MA 2" 
cu      = "(E)MA 3 < (E)MA 4"

co_HTF  = "(E)MA 1 (HTF) > (E)MA 2 (HTF)" 
cu_HTF  = "(E)MA 3 (HTF) < (E)MA 4 (HTF)"

L_S     = "Long & Short"                , _L_  = "Long Only"                , _S_ = "Short Only"

cla     = "Close above (E)MA 1"         
clu     = "Close under (E)MA 3"

cla_HTF = "Close above (E)MA 1 (HTF)"
clu_HTF = "Close under (E)MA 3 (HTF)"

rsi     = "RSI strategy"

none    = "NONE"
mch     = "macd > signal"               , mcl     = "macd < signal"
mch0    = "macd > 0"                    , mcl0    = "macd < 0"
sgh0    = "signal > 0"                  , sgl0    = "signal < 0"

mch_HTF = "macd (HTF) > signal (HTF)"   , mcl_HTF = "macd (HTF) < signal (HTF)"
mch0HTF = "macd (HTF) > 0"              , mcl0HTF = "macd (HTF) < 0"
sgh0HTF = "signal (HTF) > 0"            , sgl0HTF = "signal (HTF) < 0"

EMA     = "EMA"                         , SMA = "SMA"       

s       = input(cl,   "Source" , options=[cl, op, hi, lo, c4, c3, hl])

src     =
 s  == cl ? close :
 s  == op ? open  :
 s  == hi ? high  :
 s  == lo ? low   :
 s  == c4 ? ohlc4 :
 s  == c3 ? hlc3  : 
 s  == hl ? hl2   :
 close

__1_    = input(false, ">=< >=< [STRATEGIES] >=< >=<")

Type    = input(_L_,  "Type Strategy", options=[L_S, _L_, _S_])

_1a_    = input(false, ">=< >=< [BUY/LONG] >=< >=<")

ENT     = input(co,   "Pick your poison:", options=[co, cla, rsi, mch, mch0, sgh0])
EH      = input(0,    " if RSI >")
EL      = input(100,  " if RSI <")
EH_HTF  = input(0,    " if RSI (HTF) >")
EL_HTF  = input(100,  " if RSI (HTF) <")

EX      = input(none, " Extra argument", options=[none, mch, mch0, sgh0])
EX2     = input(none, " Second argument", options=[none, mch_HTF, mch0HTF, sgh0HTF, co_HTF, cla_HTF])

_1b_    = input(false, ">=< [(E)MA settings (Buy/Long)] >=<")

ma1     = input(SMA,  "  (E)MA 1", options=[EMA, SMA])
len1    = input(50,   "     Length"  )
ma2     = input(SMA,  "  (E)MA 2", options=[EMA, SMA])
len2    = input(100,  "     Length"  )
ma1HTF  = input(SMA,  "  (E)MA 1 - HTF", options=[EMA, SMA])
len1HTF = input(50,   "     Length"  )
ma2HTF  = input(SMA,  "  (E)MA 2 - HTF", options=[EMA, SMA])
len2HTF = input(100,  "     Length"  )

_2a_    = input(false, ">=< >=< [SELL/SHORT] >=< >=<")

CLO     = input(cu,   "Pick your poison:", options=[cu, clu, rsi, mcl, mcl0, sgl0])
CH      = input(0,    " if RSI >")
CL      = input(100,  " if RSI <")
CH_HTF  = input(0,    " if RSI (HTF) >")
CL_HTF  = input(100,  " if RSI (HTF) <")

CX      = input(none, " Extra argument", options=[none, mcl, mcl0, sgl0])
CX2     = input(none, " Second argument", options=[none, mcl_HTF, mcl0HTF, sgl0HTF, cu_HTF, clu_HTF])

_2b_    = input(false, ">=< [(E)MA settings (Sell/Short)] >=<")

ma3     = input(SMA,  "  (E)MA 3", options=[EMA, SMA])
len3    = input(50,   "     Length"  )
ma4     = input(SMA,  "  (E)MA 4", options=[EMA, SMA])
len4    = input(100,  "     Length"  )
ma3HTF  = input(SMA,  "  (E)MA 3 - HTF", options=[EMA, SMA])
len3HTF = input(50,   "     Length"  )
ma4HTF  = input(SMA,  "  (E)MA 4 - HTF", options=[EMA, SMA])
len4HTF = input(100,  "     Length"  )

__3_    = input(false, ">=< >=< [RSI]  >=< >=< >=<")

ler     = input(20 , "  RSI Length")

__4_    = input(false, ">=< >=< [MACD] >=< >=< >=<")

fst     = input(12, "  Fast Length")
slw     = input(26, "  Slow Length")
sgn     = input(9 , "  Signal Smoothing")
sma_source = input(false, "Simple MA(Oscillator)")
sma_signal = input(false, "Simple MA(Signal Line)")

__5_    = input(false, ">=< >=< [HTF settings] >=< >=<")

MA_HTF  = input("D", "  (E)MA HTF", type = input.resolution)
RSI_HTF = input("D", "  RSI HTF"  , type = input.resolution)
MACD_HTF= input("D", "  MACD HTF" , type = input.resolution)

__6_    = input(false, ">=< >=< [SL/TP] >=< >=< >=<")

sl      = input(false, "Stop Loss?")
SL      = input(10.0, title="  Stop Loss %"  ) / 100
tp      = input(false, "Take Profit?")
TP      = input(20.0, title="  Take Profit %") / 100
 
SL_     = strategy.position_avg_price * (1 - SL)
TP_     = strategy.position_avg_price * (1 + TP)

// Limitation in time
// (= inspired from a script of "Che_Trader")

xox     = input(false, ">=< >=< [TIME] >=< >=< >=<")

ystr1   = input(2010, "  Since Year" )
ystp1   = input(2099, "  Till Year"  )
mstr1   = input(1   , "  Since Month")
mstp1   = input(12  , "  Till Month" )
dstr1   = input(1   , "  Since Day"  )
dstp1   = input(31  , "  Till Day"   )
 
_Str1   = timestamp(ystr1, mstr1, dstr1,  1,  1)
Stp1_   = timestamp(ystp1, mstp1, dstp1, 23, 59)

TIME    = time >= _Str1 and time <= Stp1_ ? true : false

////////////////////////////////////////////////////////////////////////////////////////////

_1      = 
 ma1 == SMA ? sma(src, len1) : 
 ma1 == EMA ? ema(src, len1) : 
 na
_2      = 
 ma2 == SMA ? sma(src, len2) :
 ma2 == EMA ? ema(src, len2) :
 na
_3      = 
 ma3 == SMA ? sma(src, len3) :
 ma3 == EMA ? ema(src, len3) :
 na
_4      = 
 ma4 == SMA ? sma(src, len4) :
 ma4 == EMA ? ema(src, len4) :
 na

_1b  = 
 ma1HTF == SMA ? sma(src, len1HTF) :
 ma1HTF == EMA ? ema(src, len1HTF) :
 na
_2b  = 
 ma2HTF == SMA ? sma(src, len2HTF) :
 ma2HTF == EMA ? ema(src, len2HTF) :
 na
_3b  = 
 ma3HTF == SMA ? sma(src, len3HTF) :
 ma3HTF == EMA ? ema(src, len3HTF) :
 na
_4b  = 
 ma4HTF == SMA ? sma(src, len4HTF) :
 ma4HTF == EMA ? ema(src, len4HTF) :
 na

_1_HTF = security(syminfo.tickerid, MA_HTF,  _1b)
_2_HTF = security(syminfo.tickerid, MA_HTF,  _2b)
_3_HTF = security(syminfo.tickerid, MA_HTF,  _3b)
_4_HTF = security(syminfo.tickerid, MA_HTF,  _4b)
cl_HTF = security(syminfo.tickerid, MA_HTF,  close)

////////////////////////////////////////////////////////////////////////////////////////////

plot(ENT == co or ENT == cla ? _1 : na            , title="(E)MA 1", color=color.lime                           )
plot(ENT == co               ? _2 : na            , title="(E)MA 2", color=color.red                            )
plot(CLO == cu or CLO == clu ? _3 : na            , title="(E)MA 3", color= _3 == _1 ? color.lime : color.yellow)
plot(CLO == cu               ? _4 : na            , title="(E)MA 4", color= _4 == _2 ? color.red  : color.blue  )
plot(EX2 == co_HTF or EX2 == cla_HTF ? _1_HTF : na, title="(E)MA 1 HTF", color=color.lime, linewidth=2, transp=50)
plot(EX2 == co_HTF                   ? _2_HTF : na, title="(E)MA 2 HTF", color=color.red , linewidth=2, transp=50)
plot(CX2 == cu_HTF or CX2 == clu_HTF ? _3_HTF : na, title="(E)MA 3 HTF", color= _3_HTF == _1_HTF ? color.lime : color.yellow, linewidth=2, transp=50)
plot(CX2 == cu_HTF                   ? _4_HTF : na, title="(E)MA 4 HTF", color= _4_HTF == _2_HTF ? color.red  : color.blue  , linewidth=2, transp=50)

////////////////////////////////////////////////////////////////////////////////////////////

// RSI

rsi_       = rsi(src, ler)
rsi_HTF    = security(syminfo.tickerid, RSI_HTF,  rsi_)

////////////////////////////////////////////////////////////////////////////////////////////

// MACD

fast_ma    = sma_source ? sma(src, fst) : ema(src, fst)
slow_ma    = sma_source ? sma(src, slw) : ema(src, slw)
macd       = fast_ma - slow_ma
signal     = sma_signal ? sma(macd, sgn) : ema(macd, sgn)
hist       = macd - signal

macd_HTF   = security(syminfo.tickerid, MACD_HTF, macd  )
signal_HTF = security(syminfo.tickerid, MACD_HTF, signal)

////////////////////////////////////////////////////////////////////////////////////////////

extra = 
 EX  == none    ? true                   :
 EX  == mch     ? macd >  signal         :
 EX  == mch0    ? macd >  0              :
 EX  == sgh0    ? signal >  0            :
 false

cxtra = 
 CX  == none    ? true                   :
 CX  == mcl     ? macd <= signal         :
 CX  == mcl0    ? macd <= 0              :
 CX  == sgl0    ? signal <= 0            :
 false

EXTRA = 
 EX2 == none    ? true                   :
 EX2 == mch_HTF ? macd_HTF >  signal_HTF :
 EX2 == mch0HTF ? macd_HTF >  0          :
 EX2 == sgh0HTF ? signal_HTF >  0        :
 EX2 == co_HTF  ? _1_HTF >  _2_HTF       :
 EX2 == cla_HTF ? cl_HTF >  _1_HTF       : 
 false
 
CXTRA =
 CX2 == none    ? true                   :
 CX2 == mcl_HTF ? macd_HTF <= signal_HTF :
 CX2 == mcl0HTF ? macd_HTF <= 0          :
 CX2 == sgl0HTF ? signal_HTF <= 0        :
 CX2 == cu_HTF  ? _3_HTF <= _4_HTF       :
 CX2 == clu_HTF ? cl_HTF <= _3_HTF       : 
 false

RSI = rsi_ > EH and rsi_ <= EL and rsi_HTF > EH_HTF and rsi_HTF <= EL_HTF

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

BUY = 
 ENT == co    and TIME and extra and EXTRA and RSI ? _1 > _2        : 
 ENT == cla   and TIME and extra and EXTRA and RSI ? src > _1       : 
 ENT == rsi   and TIME and extra and EXTRA         ? RSI            : 
 ENT == mch   and TIME and extra and EXTRA and RSI ? macd > signal  : 
 ENT == mch0  and TIME and extra and EXTRA and RSI ? macd > 0       : 
 ENT == sgh0  and TIME and extra and EXTRA and RSI ? signal > 0     : 
 na

SELL = 
 CLO == cu    and TIME and cxtra and CXTRA and RSI ? _3 <= _4       : 
 CLO == clu   and TIME and cxtra and CXTRA and RSI ? src <= _3      : 
 CLO == rsi   and TIME and cxtra and CXTRA         ? RSI            :
 CLO == mcl   and TIME and cxtra and CXTRA and RSI ? macd <= signal : 
 CLO == mcl0  and TIME and cxtra and CXTRA and RSI ? macd <= 0      : 
 CLO == sgl0  and TIME and cxtra and CXTRA and RSI ? signal <= 0    : 
 na

if BUY
    if (Type == _S_)
        strategy.close("[S]")
    else
        strategy.entry("[B]", strategy.long)

if SELL
    if (Type == _L_)
        strategy.close("[B]")
    else
        strategy.entry("[S]", strategy.short)

strategy.exit("[SL/TP]", "[B]", stop= sl ? SL_ : na, limit= tp ? TP_ : na)

Published by ChaoZhang on the FMZ strategy square · last modified 2023-12-05. 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/Multi-Indicator-Quantitative-Trading-Strategy.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