L'idée principale de cette stratégie est d'utiliser la bande de rupture pour identifier la direction de la tendance et combiner le stop loss fixe pour la gestion des risques. La stratégie calcule d'abord les prix les plus élevés et les plus bas sur une certaine période pour former une bande de rupture. Lorsque le prix traverse la bande de rupture, un signal de trading est généré. En outre, la stratégie permet aux traders de définir un montant de stop loss fixe. Chaque fois qu'un trade est placé, le système calculera la taille de la position en fonction du montant de stop loss fixe, de sorte que chaque perte soit fixe.
La stratégie est composée de quatre parties principales: gestion des positions, identification de la bande de rupture, réglage des stop-loss et dimensionnement des positions.
En premier lieu, la stratégie vérifie s'il existe une position ouverte, si elle existe, aucun nouveau signal ne sera généré.
Deuxièmement, la stratégie calcule les prix les plus élevés et les plus bas au cours d'une période pour former une bande de rupture. Lorsque le prix sort de la bande, un signal de trading est généré. Plus précisément, si le prix dépasse la bande supérieure, un signal long est généré. Si le prix dépasse la bande inférieure, un signal court est généré.
En outre, lorsqu'un signal long est généré, la stratégie définit le point médian de la bande de rupture comme le stop loss.
Enfin, la stratégie permet de définir un montant de stop loss fixe. Lorsqu'un signal est généré, la stratégie calcule le nombre de pips du stop loss au prix actuel, et combine des facteurs tels que la taille du tick et le taux de change, pour déterminer le changement de prix entre le stop loss et le prix actuel en termes monétaires. La taille de la position est ensuite calculée sur la base du montant de stop loss fixe.
Les principaux principes de la stratégie sont l'identification de la direction de la tendance avec des bandes de rupture et le contrôle du risque avec un stop loss fixe.
Cette stratégie d'arrêt-perte fixe à bande de rupture présente les avantages suivants:
Concept de stop loss avancé. La stratégie utilise un montant de stop loss fixe au lieu d'une distance de stop loss fixe. Cela évite le problème de l'impossibilité de fixer le risque sur les produits avec des valeurs de tick différentes.
La stratégie peut calculer intelligemment la taille de la position en fonction du montant fixe de stop loss, de sorte que la perte par transaction soit contrôlée, gérant ainsi raisonnablement l'exposition au risque.
Identification de rupture simple et efficace. L'identification de rupture avec des bandes est simple et directe, et peut identifier efficacement la direction de la tendance. Par rapport à la rupture d'un seul niveau de prix, cette identification de bande de rupture peut éviter plus de faux signaux loin de la tendance.
La capacité de la stratégie à ajuster le stop loss en temps réel pour le stop loss de suivi aide à verrouiller plus de profits.
La stratégie est applicable à tous les produits. Tant que les paramètres sont correctement définis, un contrôle du risque de stop-loss de montant fixe peut être réalisé, ce qui rend la stratégie très polyvalente.
La structure du code est claire et modulaire, ce qui le rend facile à comprendre et à optimiser.
Malgré les avantages, la stratégie présente certains risques:
La stratégie ne juge pas la qualité du schéma de rupture et peut générer des signaux de faible qualité. D'autres indicateurs sont nécessaires pour filtrer les signaux.
Le stop loss fixe peut être trop mécanique. Les prix du marché sont souvent différents. Le stop loss fixe peut trop dépendre des règles et manquer de flexibilité dans l'ajustement.
La stratégie ne limite pas la fréquence des échanges et peut être trop fréquente.
La fixation du montant du stop loss est cruciale pour le contrôle global du risque et doit tenir compte de la taille du capital, de l'appétit pour le risque, etc.
La direction de la rupture peut donner de mauvais signaux. Des signaux de rupture erronés peuvent se produire lors d'oscillations de prix ou de retraits. Plus de conditions sont nécessaires pour optimiser la stratégie.
Aucun mécanisme de prise de profit. La stratégie n'a actuellement aucune capacité de prise de profit pour verrouiller activement les bénéfices. Cela peut entraîner des bénéfices insatisfaisants.
Pour faire face à ces risques, certaines façons d'optimiser la stratégie comprennent:
Ajout d'indicateurs pour filtrer la qualité du signal, par exemple MACD, KD, etc.
Incorporation d'indicateurs de résistance de rupture pour évaluer la qualité. Par exemple, le jugement de la résistance par des changements de volume.
Ajout de limites de fréquence des transactions ouvertes, par exemple une transaction par jour.
Optimisation de la logique de stop loss fixe, par exemple le stop loss basé sur le pourcentage au-dessus d'un seuil.
L'établissement doit fournir des informations détaillées sur les risques liés à l'utilisation de l'instrument.
Incorporation de stratégies de prise de profit, par exemple prise de profit près de la résistance.
Sur la base de l'analyse, la stratégie peut être optimisée dans les aspects suivants:
Ajout de filtres pour améliorer la qualité du signal en utilisant plusieurs indicateurs techniques et en évaluant la qualité de la tendance.
Optimisation du stop loss pour plus de flexibilité. Peut passer à un stop de trailing basé sur le pourcentage après un certain retracement. Peut également optimiser dynamiquement en fonction de la volatilité.
Contrôler la fréquence des transactions afin d'éviter une survente en ajoutant des filtres sur les périodes ou la fréquence.
Incorporation d'indicateurs de tendance pour améliorer le calendrier, par exemple en attendant la confirmation de la tendance.
Optimisation des stratégies de prise de bénéfices pour améliorer la rentabilité par le biais de l'objectif de profit, de l'arrêt des bénéfices, de l'arrêt de la volatilité, etc.
Optimisation des paramètres de risque basés sur les backtests, tels que le montant fixe de l'arrêt, la période de rupture, etc.
Refactoring de code pour une meilleure extensibilité en découplant davantage les modules de signal, de filtre, de risque et de profit.
Tester plus de produits pour des opportunités d'arbitrage. Évaluer l'avantage sur différentes combinaisons de produits.
Grâce à ces dimensions d'optimisation, la stratégie d'arrêt de perte de rupture peut devenir plus robuste et rentable.
Dans l'ensemble, la stratégie est raisonnable en utilisant des bandes de rupture pour identifier les tendances et les arrêts de montant fixe pour le contrôle des risques. Les concepts sont progressifs pour la gestion des risques. La logique de dimensionnement des positions est également bonne pour contrôler la perte par transaction. Mais la stratégie peut être améliorée grâce à diverses optimisations pour améliorer la qualité du signal, la flexibilité du stop loss, la rentabilité, etc. En incorporant des filtres de tendance, en améliorant la prise de profit et en contrôlant strictement la fréquence des transactions, une amélioration significative peut être obtenue. En conclusion, la stratégie fournit un cadre pour apprendre les techniques de gestion des risques et de dimensionnement des positions, jetant les bases de la recherche sur des systèmes d'arbitrage et de multi-stratégie plus complexes.
/*backtest start: 2023-10-26 00:00:00 end: 2023-10-28 03:00:00 period: 10m basePeriod: 1m 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/ //@version=4 //@author=Takazudo strategy("Fixed price SL", overlay=true, default_qty_type=strategy.fixed, initial_capital=0, currency=currency.USD) var COLOR_TRANSPARENT = color.new(#000000, 100) var COLOR_ENTRY_BAND = color.new(#43A6F5, 30) //============================================================================ // config //============================================================================ // Money management _g1 = 'Money management' var config_riskPrice = input(100, minval=1, title="Risk price for each entry", group=_g1) var config_depositCurrency = input(title="Deposit currency", type=input.string, defval="USD", options=["USD"], group=_g1) // Entry strategy _g2 = 'Entry strategy' var config_entryBandBars = input(defval = 100, title = "Entry band bar count", minval=1, group=_g2) // Backtesting range _g3 = 'Backtesting range' fromYear = input(defval = 2018, title = "From Year", minval = 1970, group=_g3) fromMonth = input(defval = 1, title = "From Month", minval = 1, maxval = 12, group=_g3) fromDay = input(defval = 1, title = "From Day", minval = 1, maxval = 31, group=_g3) toYear = input(defval = 2020, title = "To Year", minval = 1970, group=_g3) toMonth = input(defval = 12, title = "To Month", minval = 1, maxval = 12, group=_g3) toDay = input(defval = 31, title = "To Day", minval = 1, maxval = 31, group=_g3) //============================================================================ // exchange caliculations //============================================================================ // mico pip size caliculation // ex1: AUDCAD -> 0.0001 // ex2: USDJPY -> 0.01 f_calcMicroPipSize() => _base = syminfo.basecurrency _quote = syminfo.currency _result = 0.0001 if _quote == 'JPY' _result := _result * 100 if _base == 'BTC' _result := _result * 100 _result // convert price to pips f_convertPriceToPips(_price) => _microPipSize = f_calcMicroPipSize() _price / _microPipSize // caliculate exchange rate between deposit and quote currency f_calcDepositExchangeSymbolId() => _result = '' _deposit = config_depositCurrency _quote = syminfo.currency if (_deposit == 'USD') and (_quote == 'USD') _result := na if (_deposit == 'USD') and (_quote == 'AUD') _result := 'OANDA:AUDUSD' if (_deposit == 'EUR') and (_quote == 'USD') _result := 'OANDA:EURUSD' if (_deposit == 'USD') and (_quote == 'GBP') _result := 'OANDA:GBPUSD' if (_deposit == 'USD') and (_quote == 'NZD') _result := 'OANDA:NZDUSD' if (_deposit == 'USD') and (_quote == 'CAD') _result := 'OANDA:USDCAD' if (_deposit == 'USD') and (_quote == 'CHF') _result := 'OANDA:USDCHF' if (_deposit == 'USD') and (_quote == 'JPY') _result := 'OANDA:USDJPY' _result // Let's say we need CAD to USD exchange // However there's only "OANDA:USDCAD" symbol. // Then we need to invert the exhchange rate. // this function tells us whether we should invert the rate or not f_calcShouldInvert() => _result = false _deposit = config_depositCurrency _quote = syminfo.currency if (_deposit == 'USD') and (_quote == 'CAD') _result := true if (_deposit == 'USD') and (_quote == 'CHF') _result := true if (_deposit == 'USD') and (_quote == 'JPY') _result := true _result // caliculate how much quantity should I buy or sell f_calcQuantitiesForEntry(_depositExchangeRate, _slPips) => _microPipSize = f_calcMicroPipSize() _priceForEachPipAsDeposit = _microPipSize * _depositExchangeRate _losePriceOnSl = _priceForEachPipAsDeposit * _slPips floor(config_riskPrice / _losePriceOnSl) //============================================================================ // Quantity caliculation //============================================================================ depositExchangeSymbolId = f_calcDepositExchangeSymbolId() // caliculate deposit exchange rate rate = security(depositExchangeSymbolId, timeframe.period, hl2) shouldInvert = f_calcShouldInvert() depositExchangeRate = if config_depositCurrency == syminfo.currency // if USDUSD, no exchange of course 1 else // else, USDCAD to CADUSD invert if we need shouldInvert ? (1 / rate) : rate //============================================================================ // Range Edge caliculation //============================================================================ f_calcEntryBand_high() => _highest = max(open[3], close[3]) for i = 4 to (config_entryBandBars - 1) _highest := max(_highest, open[i], close[i]) _highest f_calcEntryBand_low() => _lowest = min(open[3], close[3]) for i = 4 to (config_entryBandBars - 1) _lowest := min(_lowest, open[i], close[i]) _lowest entryBand_high = f_calcEntryBand_high() entryBand_low = f_calcEntryBand_low() entryBand_height = entryBand_high - entryBand_low plot(entryBand_high, color=COLOR_ENTRY_BAND, linewidth=1) plot(entryBand_low, color=COLOR_ENTRY_BAND, linewidth=1) rangeBreakDetected_long = entryBand_high < close rangeBreakDetected_short = entryBand_low > close shouldMakeEntryLong = (strategy.position_size == 0) and rangeBreakDetected_long shouldMakeEntryShort = (strategy.position_size == 0) and rangeBreakDetected_short //============================================================================ // SL & Quantity //============================================================================ var sl_long = hl2 var sl_short = hl2 entryQty = 0 slPips = 0.0 // just show info bubble f_showEntryInfo(_isLong) => _str = 'SL pips: ' + tostring(slPips) + '\n' + 'Qty: ' + tostring(entryQty) _bandHeight = entryBand_high - entryBand_low _y = _isLong ? (entryBand_low + _bandHeight * 1/4) : (entryBand_high - _bandHeight * 1/4) _style = _isLong ? label.style_label_up : label.style_label_down label.new(bar_index, _y, _str, size=size.large, style=_style) if shouldMakeEntryLong sl_long := (entryBand_high + entryBand_low) / 2 slPips := f_convertPriceToPips(close - sl_long) entryQty := f_calcQuantitiesForEntry(depositExchangeRate, slPips) if shouldMakeEntryShort sl_short := (entryBand_high + entryBand_low) / 2 slPips := f_convertPriceToPips(sl_short - close) entryQty := f_calcQuantitiesForEntry(depositExchangeRate, slPips) // trailing SL if strategy.position_size > 0 sl_long := max(sl_long, entryBand_low) if strategy.position_size < 0 sl_short := min(sl_short, entryBand_high) //============================================================================ // backtest duration //============================================================================ // Calculate start/end date and time condition startDate = timestamp(fromYear, fromMonth, fromDay, 00, 00) finishDate = timestamp(toYear, toMonth, toDay, 00, 00) //============================================================================ // make entries //============================================================================ if (true) if shouldMakeEntryLong strategy.entry(id="Long", long=true, stop=close, qty=entryQty) f_showEntryInfo(true) if shouldMakeEntryShort strategy.entry(id="Short", long=false, stop=close, qty=entryQty) f_showEntryInfo(false) strategy.exit('Long-SL/TP', 'Long', stop=sl_long) strategy.exit('Short-SL/TP', 'Short', stop=sl_short) //============================================================================ // plot misc //============================================================================ sl = strategy.position_size > 0 ? sl_long : strategy.position_size < 0 ? sl_short : na plot(sl, color=color.red, style=plot.style_cross, linewidth=2, title="SL") value_bgcolor = rangeBreakDetected_long ? color.green : rangeBreakDetected_short ? color.red : COLOR_TRANSPARENT bgcolor(value_bgcolor, transp=95)