La stratégie Twin Range Filter est une stratégie de trading basée sur la volatilité des prix. Elle utilise deux indicateurs de gamme moyenne avec des paramètres différents, combinés avec la relation entre prix et gamme, pour générer des signaux de trading.
Cette stratégie utilise deux indicateurs de fourchette lisse avec des durées de période différentes: un indicateur de fourchette rapide (période par défaut 27) et un indicateur de fourchette lente (période par défaut 55).
La stratégie Twin Range Filter compare le prix avec les deux indicateurs de gamme pour déterminer s'il se trouve actuellement dans une certaine plage d'oscillation.
Plus précisément, la stratégie utilise une ligne médiane comme référence, qui est la moyenne des deux indicateurs de fourchette. Un signal long est généré lorsque le prix est au-dessus de la ligne médiane d'une fourchette rapide; un signal court est généré lorsque le prix tombe en dessous de la ligne médiane d'une fourchette rapide.
Pour filtrer les faux signaux, il ajoute également une condition: un signal n'est généré que lorsque le mouvement du prix actuel est cohérent avec la période précédente.
En résumé, cette stratégie identifie la gamme d'oscillation avec des indicateurs de gamme jumelles et génère des ordres lorsque le prix franchit la gamme.
Les avantages de la stratégie de filtrage à double portée:
Utilise des caractéristiques de volatilité des prix, adaptables à des actifs très volatils comme le Bitcoin.
Les indicateurs jumeaux contiennent des délais différents: le plus rapide capte les opportunités à court terme, tandis que le plus lent tient compte des tendances à long terme.
L'ajout de filtres de direction des prix réduit les faux signaux des fluctuations à court terme.
Une logique simple et claire, facile à comprendre et à mettre en œuvre, adaptée au trading d'algo.
Quelques risques de la stratégie à noter:
Il s'appuie sur des indicateurs de volatilité et peut être moins performant dans des environnements à faible volatilité.
Les paramètres de gamme doivent être optimisés pour différents produits, sinon les opportunités de négociation peuvent être manquées ou de faux signaux peuvent se produire.
La divergence entre le prix et la volatilité n'est pas prise en compte.
Les niveaux de stop-loss peuvent nécessiter un ajustement dans des environnements à forte volatilité.
La stratégie peut être améliorée sous plusieurs aspects:
Tester et optimiser les paramètres de gamme pour trouver des combinaisons optimales pour différents produits et délais.
Ajouter des mécanismes de stop loss dynamiques basés sur la volatilité récente, pour optimiser la stratégie de stop loss.
Ajouter des filtres basés sur la divergence de volatilité des prix pour éviter de faux signaux.
Incorporer d'autres indicateurs tels que les variations de volume pour augmenter la certitude d'entrée.
Tester et ajouter des mécanismes de sortie de profit appropriés adaptés à la stratégie.
Dans l'ensemble, le Twin Range Filter est une stratégie de trading efficace pour les actifs très volatils. Il utilise bien les caractéristiques de volatilité des prix et génère une logique de trading simple et claire. Avec d'autres améliorations telles que l'optimisation des paramètres et la gestion des risques, il peut devenir un composant précieux dans un système de trading quantitatif. Il fournit également un aperçu du trading algorithmique basé sur les caractéristiques de volatilité du marché.
/*backtest start: 2023-11-05 00:00:00 end: 2023-11-12 00:00:00 period: 30m 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/ // © colinmck, greenmask9 //@version=4 strategy(title="Twin Range Filter Algo", overlay=true) source = input(defval=close, title="Source") // Smooth Average Range per1 = input(defval=27, minval=1, title="Fast period") mult1 = input(defval=1.6, minval=0.1, title="Fast range") per2 = input(defval=55, minval=1, title="Slow period") mult2 = input(defval=2, minval=0.1, title="Slow range") smoothrng(x, t, m) => wper = t * 2 - 1 avrng = ema(abs(x - x[1]), t) smoothrng = ema(avrng, wper) * m smoothrng smrng1 = smoothrng(source, per1, mult1) smrng2 = smoothrng(source, per2, mult2) smrng = (smrng1 + smrng2) / 2 // Range Filter rngfilt(x, r) => rngfilt = x rngfilt := x > nz(rngfilt[1]) ? x - r < nz(rngfilt[1]) ? nz(rngfilt[1]) : x - r : x + r > nz(rngfilt[1]) ? nz(rngfilt[1]) : x + r rngfilt filt = rngfilt(source, smrng) upward = 0.0 upward := filt > filt[1] ? nz(upward[1]) + 1 : filt < filt[1] ? 0 : nz(upward[1]) downward = 0.0 downward := filt < filt[1] ? nz(downward[1]) + 1 : filt > filt[1] ? 0 : nz(downward[1]) hband = filt + smrng lband = filt - smrng longCond = bool(na) shortCond = bool(na) longCond := source > filt and source > source[1] and upward > 0 or source > filt and source < source[1] and upward > 0 shortCond := source < filt and source < source[1] and downward > 0 or source < filt and source > source[1] and downward > 0 CondIni = 0 CondIni := longCond ? 1 : shortCond ? -1 : CondIni[1] long = longCond and CondIni[1] == -1 short = shortCond and CondIni[1] == 1 // Plotting // Strategy // From this part on, programmer is greenmaks9 // Separator = input(title="Following conditions and backtest algorithm are added by @greenmask9 🎯, original script is written by @colinmck 👍. Read both of their's release notes for more info on how this script works.", type=input.bool, defval=false) disabler = input(title="Disable greenmask9's ATR conditions", type=input.bool, defval=false) //second l2 = input(title="ATR1", defval=32, minval=1) s2 = input(title="Smoothing", defval="SMA", options=["RMA", "SMA", "EMA", "WMA"]) atr2(source, l2) => if s2 == "SMA" sma(source, l2) else if s2 == "RMA" rma(source, l2) else if s2 == "EMA" ema(source, l2) else wma(source, l2) //third l3 = input(title="ATR2", defval=64, minval=1) s3 = input(title="Smoothing", defval="RMA", options=["RMA", "SMA", "EMA", "WMA"]) atr3(source, l3) => if s3 == "RMA" rma(source, l3) else if s3 == "SMA" sma(source, l3) else if s3 == "EMA" ema(source, l3) else wma(source, l3) atr20=atr2(tr(true), l2) atr30=atr3(tr(true), l3) strategy.initial_capital = 50000 ordersize=floor(strategy.initial_capital/close) profit = input(title="Ticks profit", type=input.integer, defval=900) stop = input(title="Ticks stoploss", type=input.integer, defval=300) maxcandles_till_close = input(title="Time stoploss", type=input.integer, defval=17) bull = long and (atr20<atr30 or disabler) bear = short and (atr20<atr30 or disabler) bullclock = barssince(bull) bearclock = barssince(bear) if (bull) strategy.entry("Twin Long", strategy.long, ordersize) strategy.exit("Exit", from_entry = "Twin Long", profit = profit, loss = stop) if (bear) strategy.entry("Twin Short", strategy.short, ordersize) strategy.exit("Exit", from_entry = "Twin Short", profit = profit, loss = stop) //time stoploss strategy.close("Twin Long", when = bullclock == maxcandles_till_close, comment = "Timed out") strategy.close("Twin Short", when = bearclock == maxcandles_till_close, comment = "Timed out")