Combination Trading Strategy Based on Dual EMA and Bandpass Filter

Author: ChaoZhang, Date: 2024-01-17 11:22:30
Tags:

img

Overview

This strategy combines the Dual Exponential Moving Average (DEMA) and Bandpass Filter (BPF) indicators to implement breakout buying and overbought-oversold dual filtering, forming stable trading signals and pursuing maximum profitability.

Strategy Principle

The strategy consists of two sub-strategies:

  1. DEMA Strategy

    It uses the 2-day and 20-day dual exponential moving averages to generate golden cross buying and dead cross selling signals. This indicator filters out some price noise and helps discover trends.

  2. BPF Strategy

    The BPF indicator combines mathematical transforms to detect the cyclical components in prices and forms overbought-oversold zones within a certain period to generate trading signals. This strategy sets it to a 20-day cycle with a 0.5 regularization parameter.

Combining the two provides stronger verification of trend and cyclical factors when concurrent buy/sell signals emerge. Hence the reliability is higher, resulting in more stable entry and exit points.

Advantage Analysis

The biggest advantage of this strategy is the dual indicator filtering that makes the signals more stable and reliable. DEMA smoothes prices and identifies trend directions; BPF recognizes cyclical features and determines overbought-oversold zones. Cross validation between the two can greatly reduce false signals caused by price noise and cyclical adjustments.

In addition, the strategy itself has an infrequent trading frequency, avoiding excessive capital and commission costs from overtrading. Position holding times are mostly mid-to-long term, which helps avoid random fluctuation impacts.

Risk Analysis

The biggest risk of this strategy is misjudging market states. It is prone to wrong signals in ranging markets and could suffer large stop losses when trends reverse. Moreover, parameter settings could also considerably impact strategy performance.

To address these risks, methods like optimizing indicator parameters, setting stop losses/takes profits, combining other indicators etc. can be adopted for control and improvements. When judging the market has entered an ranging, choppy stage, consider suspending the strategy to avoid interference from unfavorable market conditions.

Optimization Directions

The strategy can be optimized in the following aspects:

  1. Time cycle optimization. Test different DEMA and BPF parameter settings to determine the optimal period combinations.

  2. Add stop loss/take profit settings. Reasonably set stop loss amplitudes to avoid loss magnification; take profits appropriately to lock in partial gains.

  3. Add other indicator filters. Such as Volume, MACD etc. to avoid misleading signals from high volume unwinding and position flipping.

  4. Parameter adaptive optimization. Make the DEMA and BPF parameters adaptable based on latest market conditions to keep indicator timeliness.

Conclusion

The strategy integrates the strengths of dual EMA and BPF indicators with dual filtering to improve signal quality and pursue steady mid-to-long term profits. Risks mainly come from market condition misjudgements and inadequate parameter tuning. Methods like multi-indicator validation and dynamic parameter optimization can make the strategy more elastic and adaptive for higher cost-effectiveness.


/*backtest
start: 2023-01-10 00:00:00
end: 2024-01-16 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=5
////////////////////////////////////////////////////////////
//  Copyright by HPotter v1.0 05/04/2022
// This is combo strategies for get a cumulative signal. 
//
// First strategy
// This indicator plots 2/20 exponential moving average. For the Mov 
// Avg X 2/20 Indicator, the EMA bar will be painted when the Alert criteria is met.
//
// Second strategy
// The related article is copyrighted material from
// Stocks & Commodities Mar 2010
//
//
// WARNING:
// - For purpose educate only
// - This script to change bars colors.
////////////////////////////////////////////////////////////
EMA20(Length) =>
    pos = 0.0
    xPrice = close
    xXA = ta.ema(xPrice, Length)
    nHH = math.max(high, high[1])
    nLL = math.min(low, low[1])
    nXS = nLL > xXA or nHH < xXA ? nLL : nHH
    iff_1 = nXS < close[1] ? 1 : nz(pos[1], 0)
    pos := nXS > close[1] ? -1 : iff_1
    pos


BPF(Length,Delta,SellZone,BuyZone) =>
    pos = 0.0
    xPrice = hl2
    beta = math.cos(3.14 * (360 / Length) / 180)
    gamma = 1 / math.cos(3.14 * (720 * Delta / Length) / 180)
    alpha = gamma - math.sqrt(gamma * gamma - 1)
    BP = 0.0
    BP := 0.5 * (1 - alpha) * (xPrice - xPrice[2]) + beta * (1 + alpha) * nz(BP[1]) - alpha * nz(BP[2])
    pos:= BP > SellZone ? 1 :
    	   BP <= BuyZone? -1 : nz(pos[1], 0) 
    pos

strategy(title='Combo 2/20 EMA & Bandpass Filter', shorttitle='Combo', overlay=true)
var I1 = '●═════ 2/20 EMA ═════●'
Length = input.int(14, minval=1, group=I1)
var I2 = '●═════ Bandpass Filter  ═════●'
LengthBPF = input.int(20, minval=1, group=I2)
Delta = input(0.5, group=I2)
SellZone = input.float(5, step = 0.01, group=I2)
BuyZone = input.float(-5, step = 0.01, group=I2)
var misc = '●═════ MISC ═════●'
reverse = input.bool(false, title='Trade reverse', group=misc)
var timePeriodHeader = '●═════ Time Start ═════●'
d = input.int(1, title='From Day', minval=1, maxval=31, group=timePeriodHeader)
m = input.int(1, title='From Month', minval=1, maxval=12, group=timePeriodHeader)
y = input.int(2005, title='From Year', minval=0, group=timePeriodHeader)
StartTrade = time > timestamp(y, m, d, 00, 00) ? true : false
posEMA20 = EMA20(Length)
prePosBPF = BPF(LengthBPF,Delta,SellZone,BuyZone)
iff_1 = posEMA20 == -1 and prePosBPF == -1 and StartTrade ? -1 : 0
pos = posEMA20 == 1 and prePosBPF == 1 and StartTrade ? 1 : iff_1
iff_2 = reverse and pos == -1 ? 1 : pos
possig = reverse and pos == 1 ? -1 : iff_2
if possig == 1
    strategy.entry('Long', strategy.long)
if possig == -1
    strategy.entry('Short', strategy.short)
if possig == 0
    strategy.close_all()
barcolor(possig == -1 ? #b50404 : possig == 1 ? #079605 : #0536b3)

More