Stratégie de négociation des bandes de pourcentage de Bollinger

Auteur:ChaoZhang est là., Date: 2023-12-11 11h14 et 53 min
Les étiquettes:

img

Résumé

Cette stratégie est basée sur l'indicateur Bollinger Bands, combiné avec des moyennes mobiles et l'indicateur technique ATR, pour mettre en œuvre un système de rupture à court terme.

La logique de la stratégie

  1. Calculer le canal des bandes de Bollinger et la position relative en pourcentage des prix au sein du canal
  2. Calculer les moyennes mobiles séparément pour les prix d'ouverture, de clôture, de haut et de bas
  3. Calculer l'indicateur ATR et définir des lignes de stop-loss combinées à l'ATR
  4. Jugez si les prix sont proches de nouveaux sommets ou de nouveaux bas
  5. Combiner les hauts et les bas de l'année pour juger des tendances à plus long terme
  6. Générer des signaux de négociation basés sur les variations du pourcentage des bandes de Bollinger et de nouveaux sommets/baisses

Cette stratégie utilise le canal des bandes de Bollinger pour juger de la volatilité du marché, la largeur du canal étant déterminée par l'écart type. Les signaux d'achat sont générés lorsque les prix dépassent la bande inférieure et les signaux de vente lorsque les prix dépassent la bande supérieure. Les moyennes mobiles peuvent lisser les fluctuations de Bollinger et réduire les fausses ruptures.

Les avantages

  1. Les filtres de rupture des bandes de Bollinger strictes aident à réduire les faux signaux
  2. Les moyennes mobiles assurent la fluidité des prix et identifient les véritables tendances
  3. L'indicateur ATR suit dynamiquement le stop loss et limite les pertes de transactions uniques
  4. Les nouveaux hauts/baisses et les hauts/baisses annuels rendent les signaux plus fiables
  5. Une combinaison efficace de multiples indicateurs améliore l'efficacité

Risques et solutions

  1. Les paramètres incorrects des bandes de Bollinger peuvent entraîner des faux écarts excessifs, différentes combinaisons de paramètres doivent être testées pour obtenir les meilleurs résultats.
  2. Le prix de référence de clôture peut entraîner des prélèvements supérieurs à la fourchette de stop loss fixée par l'ATR, envisager d'utiliser des prix élevés/faibles plus volatils pour le calcul en pourcentage
  3. Le filtrage strict de Bollinger peut manquer certaines opportunités de tendance à plus long terme, assouplir les filtres et la période de détention de manière appropriée
  4. L'indicateur ATR suit les grandes fluctuations de prix lentement, considérez des mesures de volatilité de fréquence plus élevée comme la vraie plage
  5. Évaluer la signification statistique et la viabilité de la tendance

Directions d'optimisation

  1. Tester différentes combinaisons de paramètres pour déterminer les paramètres de Bollinger optimaux et les longueurs de moyenne mobile
  2. Utiliser une combinaison de modèles incorporant différents paramètres de Bollinger ou moyennes mobiles
  3. Tester la robustesse à travers différents délais et produits, améliorer l'adaptabilité
  4. Incorporer des signaux à plus long terme tels que les signaux Bollinger quotidiens ou les facteurs saisonniers
  5. Évaluer les opportunités de tendance pour élargir la couverture de la stratégie et la rentabilité

Conclusion

Cette stratégie combine efficacement les bandes de pourcentage de Bollinger, les moyennes mobiles, l'indicateur ATR, les nouveaux hauts / bas et les hauts / bas annuels pour construire un système de trading de rupture à court terme relativement strict et efficace. Son avantage exceptionnel réside dans l'utilisation de divers outils pour réduire le bruit et identifier les vrais signaux de tendance. Bien sûr, la stratégie fait également face à certaines difficultés de réglage des paramètres et à des opportunités manquées dans des conditions strictes.


/*backtest
start: 2022-12-04 00:00:00
end: 2023-12-10 00:00:00
period: 1d
basePeriod: 1h
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/
// © HeWhoMustNotBeNamed

//@version=4
strategy("Bollinger %B Candles Strategy", overlay=false, initial_capital = 1000, default_qty_type = strategy.percent_of_equity, default_qty_value = 100, commission_type = strategy.commission.percent, pyramiding = 1, commission_value = 0.01, calc_on_order_fills = true)

BBLength = input(100, minval=1, step=1)
StdDev = 10
useMovingAverage = input(true)
MAType = input(title="Moving Average Type", defval="rma", options=["ema", "sma", "hma", "rma", "vwma", "wma"])
lookbackPeriod = input(22, minval=10, step=10)
colorByPreviousClose = input(true)

AtrMAType = input(title="Moving Average Type", defval="hma", options=["ema", "sma", "hma", "rma", "vwma", "wma"])
AtrLength = input(10)
AtrMult = input(4)
wicks = input(false)

considerYearlyHighLow = input(false)
considerNewLongTermHighLows = input(false)
shortHighLowPeriod = 100
longHighLowPeriod = 200
tradeDirection = input(title="Trade Direction", defval=strategy.direction.all, options=[strategy.direction.all, strategy.direction.long, strategy.direction.short])

backtestYears = input(10, minval=1, step=1)


//////////////////////////////////// Calculate new high low condition //////////////////////////////////////////////////
f_calculateNewHighLows(shortHighLowPeriod, longHighLowPeriod, considerNewLongTermHighLows)=>
    newHigh = highest(shortHighLowPeriod) == highest(longHighLowPeriod) or not considerNewLongTermHighLows
    newLow = lowest(shortHighLowPeriod) == lowest(longHighLowPeriod) or not considerNewLongTermHighLows
    [newHigh,newLow]

//////////////////////////////////// Calculate Yearly High Low //////////////////////////////////////////////////
f_getYearlyHighLowCondition(considerYearlyHighLow)=>
    yhigh = security(syminfo.tickerid, '12M', high[1]) 
    ylow = security(syminfo.tickerid, '12M', low[1]) 
    yhighlast = yhigh[365]
    ylowlast = ylow[365]
    yhighllast = yhigh[2 * 365]
    ylowllast = ylow[2 * 365]
    
    yearlyTrendUp = na(yhigh)? true : na(yhighlast)? close > yhigh : na(yhighllast)? close > max(yhigh,yhighlast) : close > max(yhigh, min(yhighlast, yhighllast))
    yearlyHighCondition = (  (na(yhigh) or na(yhighlast) ? true : (yhigh > yhighlast) ) and ( na(yhigh) or na(yhighllast) ? true : (yhigh > yhighllast))) or yearlyTrendUp or not considerYearlyHighLow
    yearlyTrendDown = na(ylow)? true : na(ylowlast)? close < ylow : na(ylowllast)? close < min(ylow,ylowlast) : close < min(ylow, max(ylowlast, ylowllast))
    yearlyLowCondition = (  (na(ylow) or na(ylowlast) ? true : (ylow < ylowlast) ) and ( na(ylow) or na(ylowllast) ? true : (ylow < ylowllast))) or yearlyTrendDown or not considerYearlyHighLow
    
    label_x = time+(60*60*24*1000*1)
    [yearlyHighCondition,yearlyLowCondition]

f_getMovingAverage(source, MAType, length)=>
    ma = sma(source, length)
    if(MAType == "ema")
        ma := ema(source,length)
    if(MAType == "hma")
        ma := hma(source,length)
    if(MAType == "rma")
        ma := rma(source,length)
    if(MAType == "vwma")
        ma := vwma(source,length)
    if(MAType == "wma")
        ma := wma(source,length)
    ma

inDateRange = true
[yearlyHighCondition,yearlyLowCondition] = f_getYearlyHighLowCondition(considerYearlyHighLow)
[newHighS,newLowS] = f_calculateNewHighLows(shortHighLowPeriod, longHighLowPeriod, considerNewLongTermHighLows)
[middleclose, upperclose, lowerclose] = bb(close, BBLength, StdDev)
[middleopen, upperopen, loweropen] = bb(open, BBLength, StdDev)
[middlehigh, upperhigh, lowerhigh] = bb(high, BBLength, StdDev)
[middlelow, upperlow, lowerlow] = bb(low, BBLength, StdDev)

percentBClose = (close - lowerclose)*100/(upperclose-lowerclose)
percentBOpen = (open - loweropen)*100/(upperopen-loweropen)
percentBHigh = (high - lowerhigh)*100/(upperhigh-lowerhigh)
percentBLow = (low - lowerlow)*100/(upperlow-lowerlow)

percentBMAClose = f_getMovingAverage(percentBClose, MAType, lookbackPeriod)
percentBMAOpen = f_getMovingAverage(percentBOpen, MAType, lookbackPeriod)
percentBMAHigh = f_getMovingAverage(percentBHigh, MAType, lookbackPeriod)
percentBMALow = f_getMovingAverage(percentBLow, MAType, lookbackPeriod)

newOpen = useMovingAverage? percentBMAOpen : percentBOpen
newClose = useMovingAverage? percentBMAClose : percentBClose
newHigh = useMovingAverage? percentBMAHigh : percentBHigh
newLow = useMovingAverage? percentBMALow : percentBLow

truerange = max(newHigh, newClose[1]) - min(newLow, newClose[1])

averagetruerange = f_getMovingAverage(truerange, AtrMAType, AtrLength)
atr = averagetruerange * AtrMult

longStop = newClose - atr
longStopPrev = nz(longStop[1], longStop)
longStop := (wicks ? newLow[1] : newClose[1]) > longStopPrev ? max(longStop, longStopPrev) : longStop

shortStop = newClose + atr
shortStopPrev = nz(shortStop[1], shortStop)
shortStop := (wicks ? newHigh[1] : newClose[1]) < shortStopPrev ? min(shortStop, shortStopPrev) : shortStop

dir = 1
dir := nz(dir[1], dir)
dir := dir == -1 and (wicks ? newHigh : newClose) > shortStopPrev ? 1 : dir == 1 and (wicks ? newLow : newClose) < longStopPrev ? -1 : dir

trailingStop = dir == 1? longStop : shortStop

candleColor = colorByPreviousClose ?
                 (newClose[1] < newClose ? color.green : newClose[1] > newClose ? color.red : color.silver) : 
                 (newOpen < newClose ? color.green : newOpen > newClose ? color.red : color.silver)
plotcandle(newOpen, newHigh, newLow, newClose, title='PercentBCandle', color = candleColor, wickcolor=candleColor)
plot(trailingStop, title="TrailingStop", style=plot.style_linebr, linewidth=1, color= dir == 1 ? color.green : color.red)

buyCondition = dir==1 and yearlyHighCondition and newHighS
exitBuyCondition = dir == -1
sellCondition = dir == -1 and yearlyLowCondition and newLowS
exitSellCondition = dir == 1
strategy.risk.allow_entry_in(tradeDirection)

barcolor(buyCondition? color.lime : sellCondition ? color.orange : color.silver)
strategy.entry("Buy", strategy.long, when=buyCondition and inDateRange, oca_name="oca_buy")
strategy.close("Buy", when=exitBuyCondition)

strategy.entry("Sell", strategy.short, when=sellCondition and inDateRange, oca_name="oca_sell")
strategy.close("Sell", when=exitSellCondition)

Plus de