
L’idée principale de cette stratégie est d’utiliser la courbe de rupture pour identifier la direction de la tendance et de gérer le risque en combinant des arrêts fixes. La stratégie calcule d’abord le prix le plus élevé et le prix le plus bas d’un certain cycle, formant une courbe de rupture.
La stratégie est principalement composée de quatre parties: la gestion des positions, l’identification des bandes de rupture, le paramétrage des arrêts de perte et le calcul des quantités.
Tout d’abord, la stratégie doit déterminer si la position est actuellement occupée. Si la position est déjà occupée, aucun nouveau signal ne sera généré.
Deuxièmement, la stratégie calcule le prix le plus élevé et le prix le plus bas d’un certain cycle, formant une bande de rupture. Lorsque le prix passe de l’intérieur de la bande de rupture à l’extérieur, un signal de transaction est généré.
En outre, lorsque plusieurs signaux sont générés, la stratégie définit le point médian de la bande de rupture comme un point d’arrêt. Lorsqu’un signal de rupture est généré, un point d’arrêt est également défini. Afin de suivre les arrêts, la stratégie ajuste également le point d’arrêt en temps réel pendant la tenue de la position.
Enfin, la stratégie permet de définir un montant de stop-loss fixe. Lorsque le signal est généré, la stratégie calcule la distance entre le point de stop-loss et le prix actuel, puis, en combinant des facteurs tels que les unités de cotation et le taux de change, elle calcule le montant représenté par la variation de prix entre les points de stop-loss.
C’est l’idée principale de la stratégie: identifier la direction de la tendance par le biais de la bande de rupture et contrôler le risque en utilisant des arrêts fixes.
Cette stratégie de stop-loss fixe à bande de rupture présente les avantages suivants:
L’idée de l’arrêt de la perte est avancée. La stratégie consiste à utiliser un montant fixe de la perte plutôt qu’une distance fixe de la perte. Cela évite le problème du risque non fixe entre les différentes variétés en raison de la différence de valeur du point. Du point de vue de la gestion des risques, le montant fixe de la perte est plus avancé.
La stratégie est capable de calculer intelligemment le nombre de transactions en fonction d’un montant fixe de stop loss, ce qui rend chaque perte contrôlable, ce qui permet un contrôle raisonnable de l’ouverture du risque.
L’identification des bandes de rupture est simple et efficace. L’identification des bandes de rupture est simple et directe et permet d’identifier efficacement la direction de la tendance. Comparée à la simple rupture d’un niveau de prix, cette identification des bandes de rupture évite de nombreux faux signaux qui s’écartent de la direction de la tendance.
Le suivi des arrêts augmente les bénéfices. La stratégie permet d’ajuster la position des arrêts en temps réel, de suivre les arrêts et de localiser plus de bénéfices.
La stratégie s’applique à n’importe quelle variété et permet de contrôler le risque d’arrêt de perte à un montant fixe, ce qui en fait une application très large.
La structure du code est claire. La structure du code de la stratégie est raisonnablement claire, les modules fonctionnels sont bien décomposés, ce qui facilite la compréhension et l’optimisation ultérieure.
Malgré les avantages mentionnés ci-dessus, cette stratégie comporte certains risques à prendre en compte:
La qualité de la forme de la rupture n’a pas pu être déterminée. La stratégie ne peut pas déterminer la qualité de la forme de la rupture, ce qui peut produire des signaux de faible qualité. Le filtrage doit être effectué en combinaison avec d’autres indicateurs.
Les arrêts fixes peuvent être trop mécaniques. Les prix du marché ont souvent des caractéristiques de saut en longueur. Les arrêts fixes peuvent être trop dépendants des règles et ne peuvent pas être ajustés avec souplesse.
Il n’y a pas de limite à la fréquence des transactions. La stratégie n’a pas de limite à la fréquence des transactions.
Le paramètre de fixation du stop-loss dépend des paramètres. La fixation du stop-loss est liée au contrôle de la marge globale et doit être réglée de manière raisonnable en fonction de la taille du capital, des préférences de risque, etc.
La direction de rupture peut générer de faux signaux. Un faux signal de rupture peut être généré en cas de choc ou de reprise des cours. L’optimisation doit être combinée à plusieurs conditions.
Le manque de paramètres de freinage. La stratégie ne dispose pas actuellement de mécanisme de freinage et ne peut pas déterminer de manière proactive les bénéfices. Cela peut entraîner des bénéfices indésirables.
Nous pouvons optimiser les risques en fonction des facteurs suivants:
Ajout d’indicateurs pour juger de la forme et filtrer la qualité du signal. Par exemple MACD, KD, etc.
Évaluation de la qualité de la rupture en combinaison avec des indicateurs de force de rupture. Par exemple, déterminer la force de rupture en fonction de la variation du volume de transaction.
Augmentation des limites de fréquence d’ouverture des positions. Par exemple, une seule transaction par jour ou une règle similaire.
Optimiser la logique de réglage des stop-loss fixes. Par exemple, modifier le stop-loss en pourcentage en fonction d’une valeur de seuil spécifique.
Ajout d’autres conditions de filtrage, telles que l’augmentation du stop loss, la volatilité des prix, etc.
Ajouter des stratégies d’arrêt. Par exemple, s’arrêter à proximité de la résistance.
Selon l’analyse ci-dessus, la stratégie peut être optimisée dans les domaines suivants:
Augmentation des conditions de filtrage, amélioration de la qualité du signal. Plusieurs indicateurs techniques peuvent être ajoutés pour juger de la qualité de la tendance et éviter les signaux de rupture indésirables.
Optimisation de la stratégie de stop-loss pour une plus grande souplesse. Il est possible de changer le stop-loss en stop-loss proportionnel après une certaine distance de réajustement de la rupture. Il est également possible d’optimiser la distance de stop-loss en temps réel en fonction de la volatilité.
Contrôler la fréquence des transactions et éviter les transactions excessives. Vous pouvez définir des conditions de filtrage pour une période de temps ou un nombre de fois, réduisant la fréquence des transactions.
En combinant des indicateurs de jugement de tendance, choisir le moment de l’entrée. Par exemple, l’optimisation est effectuée après la confirmation de la tendance.
Optimiser les stratégies de stop-loss pour améliorer la rentabilité. Vous pouvez définir des objectifs de profit, déplacer des stop-loss, fluctuer des stop-loss, etc.
Optimiser les paramètres de risque. Selon les résultats des tests de retour, il est possible de définir une combinaison de paramètres plus optimale, comme le montant de stop-loss fixe, le cycle de rupture, etc.
Amélioration de la structure du code, augmentation de l’extensibilité. Décomposition des modules tels que la génération de signaux, le filtrage, le contrôle du vent et le gain.
Tester plus d’espaces d’arbitrage. Évaluer les avantages d’arbitrage de différentes combinaisons de variétés.
Ces optimisations multifonctionnelles renforceront la stabilité et la rentabilité de cette stratégie de rupture de pertes. Elles constitueront également une base pour l’expansion à l’avenir vers d’autres combinaisons de stratégies.
Cette stratégie est raisonnable dans son ensemble, en utilisant l’identification de la tendance de la bande de rupture et en utilisant des pertes fixes pour le contrôle des risques. C’est une approche avancée dans la gestion des risques. L’idée de calculer le nombre de transactions est également raisonnable et permet de contrôler chaque perte.
/*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)