Stratégie d'inversion du suivi à double canal

Auteur:ChaoZhang est là., Date: 2023-11-02 16h31 et 50 min
Les étiquettes:

img

Résumé

La stratégie d'inversion de suivi à double canal est une stratégie de trading d'inversion qui combine les bandes de Bollinger, les canaux de Keltner et les indicateurs de momentum.

La logique de la stratégie

  1. Calcul des bandes moyennes, supérieures et inférieures pour les bandes de Bollinger

    • La bande du milieu utilise la SMA de près
    • Les bandes supérieures et inférieures sont les bandes moyennes ± multiple réglable de l'écart-type
  2. Calculer les bandes intermédiaires, supérieures et inférieures pour les canaux de Keltner

    • La bande du milieu utilise la SMA de près
    • Les bandes supérieures et inférieures sont les bandes intermédiaires ± multiples ATR réglables
  3. Déterminer si les bandes de Bollinger sont à l'intérieur des canaux de Keltner

    • Appuyez lorsque BB inférieur > KC inférieur et BB supérieur < KC supérieur
    • S' il vous plaît, dégagez-vous.
  4. Calculer la pente de régression linéaire de la valeur de rapprochement par rapport aux points moyens BB et KC

    • val > 0 indique que la fermeture est en augmentation, val < 0 signifie diminution
  5. Calculer le ROC et l'EMA du ROC pour la clôture

    • Déterminer si le taux de variation dépasse le seuil réglable
    • Au-dessus du seuil indique une tendance existante
  6. Lorsque la pression est supérieure à 0, la valeur est supérieure à 0, et la valeur ROC dépasse le seuil.

    • À l'inverse pour courte
  7. Définir les conditions d'arrêt des pertes et de prise de profit

Les avantages

  1. Amélioration de la précision grâce à la combinaison d'un système à double canal pour l'inversion

  2. Éviter les faux signaux en utilisant la régression linéaire et le taux de changement

  3. Paramètres réglables flexibles pour une optimisation entre produits

  4. Contrôle efficace des risques par transaction avec stop loss/take profit

  5. Données de backtest suffisantes pour valider la viabilité de la stratégie

Risques et solutions

  1. La compression ne conduit pas toujours à un retour effectif

    • Optimiser les paramètres et resserrer les critères de pressage
  2. Les fausses fuites génèrent de mauvais signaux.

    • Ajouter la régression linéaire pour déterminer la direction de la tendance
  3. Stop-loss trop large conduisant à une perte unique excessive

    • Optimiser les points d'arrêt des pertes et le contrôle par perte de transaction
  4. Périodes d'essai insuffisantes

    • Élargir les essais à plus de périodes pour prouver la viabilité à long terme

Des possibilités d'amélioration

  1. Optimisation des paramètres pour plus de produits

  2. Ajouter l'apprentissage automatique pour l'identification du support/résistance

  3. Incorporer une modification de volume pour améliorer la validité de la rupture

  4. Effectuer une analyse sur plusieurs périodes pour déterminer la persistance de la tendance

  5. Optimiser le stop loss/take profit dynamique

Conclusion

La stratégie du double canal de suivi de l'inversion utilise des indicateurs tels que les bandes de Bollinger et les canaux de Keltner pour le trading d'inversion. Avec l'optimisation des paramètres, elle peut être adaptée à différents produits pour identifier la validité de la rupture dans une certaine mesure.


/*backtest
start: 2023-10-02 00:00:00
end: 2023-11-01 00:00:00
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=4
// Credit for the initial Squeeze Momentum code to LazyBear, rate of change code is from Kiasaki
strategy("Squeeze X BF 🚀", overlay=false, initial_capital=10000, default_qty_type=strategy.percent_of_equity, default_qty_value=100, commission_type=strategy.commission.percent, commission_value=0.0)

/////////////// Time Frame ///////////////
testStartYear = input(2012, "Backtest Start Year") 
testStartMonth = input(1, "Backtest Start Month")
testStartDay = input(1, "Backtest Start Day")
testPeriodStart = timestamp(testStartYear,testStartMonth,testStartDay, 0, 0)

testStopYear = input(2019, "Backtest Stop Year")
testStopMonth = input(12, "Backtest Stop Month")
testStopDay = input(31, "Backtest Stop Day")
testPeriodStop = timestamp(testStopYear,testStopMonth,testStopDay, 0, 0)

testPeriod() => true

/////////////// Squeeeeze ///////////////
length = input(20, title="BB Length")
mult = input(2.0,title="BB MultFactor")
lengthKC=input(22, title="KC Length")
multKC = input(1.5, title="KC MultFactor")
 
useTrueRange = input(true, title="Use TrueRange (KC)")
 
// Calculate BB
source = close
basis = sma(source, length)
dev = mult * stdev(source, length)
upperBB = basis + dev
lowerBB = basis - dev

// Calculate KC
ma = sma(source, lengthKC)
range = useTrueRange ? tr : (high - low)
rangema = sma(range, lengthKC)
upperKC = ma + rangema * multKC
lowerKC = ma - rangema * multKC

sqzOn  = (lowerBB > lowerKC) and (upperBB < upperKC)
sqzOff = (lowerBB < lowerKC) and (upperBB > upperKC)
noSqz  = (sqzOn == false) and (sqzOff == false)

val = linreg(source - avg(avg(highest(high, lengthKC), lowest(low, lengthKC)),sma(close,lengthKC)), lengthKC,0)

///////////// Rate Of Change ///////////// 
roclength = input(30, minval=1), pcntChange = input(7, minval=1)
roc = 100 * (source - source[roclength]) / source[roclength]
emaroc = ema(roc, roclength / 2)
isMoving() => emaroc > (pcntChange / 2) or emaroc < (0 - (pcntChange / 2))

/////////////// Strategy ///////////////
long = val > 0 and isMoving()
short = val < 0 and isMoving()

last_long = 0.0
last_short = 0.0
last_long := long ? time : nz(last_long[1])
last_short := short ? time : nz(last_short[1])

long_signal = crossover(last_long, last_short)
short_signal = crossover(last_short, last_long)

last_open_long_signal = 0.0
last_open_short_signal = 0.0
last_open_long_signal := long_signal ? open : nz(last_open_long_signal[1])
last_open_short_signal := short_signal ? open : nz(last_open_short_signal[1])

last_long_signal = 0.0
last_short_signal = 0.0
last_long_signal := long_signal ? time : nz(last_long_signal[1])
last_short_signal := short_signal ? time : nz(last_short_signal[1])

in_long_signal = last_long_signal > last_short_signal
in_short_signal = last_short_signal > last_long_signal

last_high = 0.0
last_low = 0.0
last_high := not in_long_signal ? na : in_long_signal and (na(last_high[1]) or high > nz(last_high[1])) ? high : nz(last_high[1])
last_low := not in_short_signal ? na : in_short_signal and (na(last_low[1]) or low < nz(last_low[1])) ? low : nz(last_low[1])

sl_inp = input(100.0, title='Stop Loss %') / 100
tp_inp = input(5000.0, title='Take Profit %') / 100
 
take_level_l = strategy.position_avg_price * (1 + tp_inp)
take_level_s = strategy.position_avg_price * (1 - tp_inp)

since_longEntry = barssince(last_open_long_signal != last_open_long_signal[1]) 
since_shortEntry = barssince(last_open_short_signal != last_open_short_signal[1]) 

slLong = in_long_signal ? strategy.position_avg_price * (1 - sl_inp) : na
slShort = strategy.position_avg_price * (1 + sl_inp)
long_sl = in_long_signal ? slLong : na
short_sl = in_short_signal ? slShort : na

/////////////// Execution ///////////////
if testPeriod()
    strategy.entry("Long",  strategy.long, when=long)
    strategy.entry("Short", strategy.short, when=short)
    strategy.exit("Long Ex", "Long", stop=long_sl, limit=take_level_l, when=since_longEntry > 0)
    strategy.exit("Short Ex", "Short", stop=short_sl, limit=take_level_s, when=since_shortEntry > 0)
    
/////////////// Plotting ///////////////
bcolor = iff(val > 0, iff(val > nz(val[1]), color.lime, color.green), iff(val < nz(val[1]), color.red, color.maroon))
plot(val, color=bcolor, linewidth=4)
bgcolor(not isMoving() ? color.white : long ? color.lime : short ? color.red : na, transp=70)
bgcolor(long_signal ? color.lime : short_signal ? color.red : na, transp=50)
hline(0, color = color.white)

Plus de