Stratégie de négociation d'inversion basée sur un support/résistance généralisé

Auteur:ChaoZhang est là., Date: le 30 octobre 2023 à 11 h 23 min 25 s
Les étiquettes:

img

Résumé

Cette stratégie adopte le trading de renversement basé sur des facteurs haussiers/baissiers, avec des niveaux de prise de profit prédéfinis. Le noyau des facteurs est le modèle étendu Support/Résistance généralisé basé sur le volume de négociation, adapté aux actions à volume et volatilité élevés. Les avantages résident dans la capture de plus grandes opportunités de renversement à moyen et court terme et le profit rapide, tout en supportant le risque d'être piégé.

La logique de la stratégie

  1. Identification des facteurs haussiers/baissiers basés sur Soutien/Résistance généralisé avec volume

    • Utilisation de modèles de chandeliers pour identifier les niveaux classiques de S/R, filtrés par volume significatif

    • La S/R généralisée a une meilleure couverture que les modèles classiques

    • La rupture des signaux de soutien généralisés par le facteur long, la rupture des signaux de résistance généralisés par le facteur court

  2. Opérations de contrepartie

    • Prenez la position inverse lorsque le signal de facteur déclenche

    • Si déjà en position, réduire ou ajouter la position arrière

  3. Définition des niveaux cibles de bénéfice

    • Définition de l'arrêt des pertes basé sur ATR

    • Définir plusieurs niveaux de profit comme 1R, 2R, 3R

    • Profit partiel lors de l'atteinte de différents objectifs

Les avantages

  • Capturez des retours à mi-parcours décents

    Les écarts S/R représentent des signaux d'inversion forts avec une certaine fiabilité, capables de détecter les inversions à moyen terme.

  • Profites rapides, faibles retraits

    En fixant des objectifs de stop loss et de profit multiples, peut réaliser des gains rapides et limiter les retraits

  • Convient pour les titres dont la liquidité institutionnelle et la volatilité sont importantes

    La stratégie repose sur le volume, ce qui nécessite une participation institutionnelle considérable; il faut également de la volatilité pour réaliser des bénéfices

Les risques

  • Être pris au piège dans un marché limité

    Une sortie et une réentrée fréquentes de stop-loss dans la direction opposée peuvent entraîner des coups de fouet.

  • Défaillance du support/résistance

    La S/R généralisée n'est pas absolument fiable, certaines défaillances existent

  • Risque de détention unilatérale

    La logique pure de l' inversion peut manquer de grandes opportunités de tendance

  • Gestion des risques:

    • Conditions de facteur de relâchement, pas d'inversion à chaque rupture

    • Ajouter d'autres filtres, par exemple différence prix/volume

    • Optimiser la stratégie de stop loss pour réduire les pièges

Directions de renforcement

  • Optimiser les paramètres S/R

    Trouvez des facteurs plus fiables en modifiant les paramètres S/R généralisés

  • Optimiser la réalisation des bénéfices

    Ajoutez plus de niveaux de profit ou utilisez des objectifs non fixes

  • Optimiser le stop loss

    Ajustez les paramètres ATR ou utilisez les paramètres stop loss pour réduire les arrêts inutiles

  • Incorporer la tendance et d'autres facteurs

    Ajouter des filtres de tendance comme la moyenne mobile pour éviter les grands conflits de tendance; ajouter également d'autres facteurs d'aide

Résumé

Le noyau de la stratégie est de capturer des oscillations à moyen terme décentes via le trading de renversement. La logique est simple et directe, et peut être pratique avec l'ajustement des paramètres. Mais la nature agressive des renversements conduit à un certain risque de retrait et de piégeage.


/*backtest
start: 2023-09-29 00:00:00
end: 2023-10-29 00:00:00
period: 1h
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/
// © DojiEmoji

//@version=5
strategy("Fractal Strat [KL] ", overlay=true, pyramiding=1, initial_capital=1000000000)
var string ENUM_LONG = "Long"
var string GROUP_ENTRY = "Entry"
var string GROUP_TSL = "Stop loss"
var string GROUP_TREND = "Trend prediction"
var string GROUP_ORDER = "Order size and Profit taking"

// backtest_timeframe_start = input.time(defval=timestamp("01 Apr 2000 13:30 +0000"), title="Backtest Start Time")
within_timeframe = true

// TSL: calculate the stop loss price. {
_multiple       = input(2.0, title="ATR Multiplier for trailing stop loss", group=GROUP_TSL)
ATR_TSL         = ta.atr(input(14, title="Length of ATR for trailing stop loss", group=GROUP_TSL, tooltip="Initial risk amount = atr(this length) x multiplier")) * _multiple
TSL_source      = low
TSL_line_color  = color.green
TSL_transp      = 100
var stop_loss_price = float(0)

var float initial_entry_p    = float(0)
var float risk_amt           = float(0)
var float initial_order_size = float(0)

if strategy.position_size == 0 or not within_timeframe
    TSL_line_color := color.black
    stop_loss_price := TSL_source - ATR_TSL
else if strategy.position_size > 0
    stop_loss_price := math.max(stop_loss_price, TSL_source - ATR_TSL)
    TSL_transp := 0

plot(stop_loss_price, color=color.new(TSL_line_color, TSL_transp))
// } end of "TSL" block


// Order size and profit taking {
pcnt_alloc = input.int(5, title="Allocation (%) of portfolio into this security", tooltip="Size of positions is based on this % of undrawn capital. This is fixed throughout the backtest period.", minval=0, maxval=100, group=GROUP_ORDER) / 100

// Taking profits at user defined target levels relative to risked amount (i.e 1R, 2R, 3R)
var bool  tp_mode = input(true, title="Take profit and different levels", group=GROUP_ORDER)
var float FIRST_LVL_PROFIT = input.float(1, title="First level profit", tooltip="Relative to risk. Example: entry at $10 and inital stop loss at $9. Taking first level profit at 1R means taking profits at $11", group=GROUP_ORDER)
var float SECOND_LVL_PROFIT = input.float(2, title="Second level profit", tooltip="Relative to risk. Example: entry at $10 and inital stop loss at $9. Taking second level profit at 2R means taking profits at $12", group=GROUP_ORDER)
var float THIRD_LVL_PROFIT = input.float(3, title="Third level profit", tooltip="Relative to risk. Example: entry at $10 and inital stop loss at $9. Taking third level profit at 3R means taking profits at $13", group=GROUP_ORDER)

// }

// Fractals {
// Modified from synapticEx's implementation: https://www.tradingview.com/script/cDCNneRP-Fractal-Support-Resistance-Fixed-Volume-2/

rel_vol_len = 6 // Relative volume is used; the middle candle has to have volume above the average (say sma over prior 6 bars)
rel_vol = ta.sma(volume, rel_vol_len)
_up = high[3]>high[4] and high[4]>high[5] and high[2]<high[3] and high[1]<high[2] and volume[3]>rel_vol[3]
_down = low[3]<low[4] and low[4]<low[5] and low[2]>low[3] and low[1]>low[2] and volume[3]>rel_vol[3]

fractal_resistance = high[3], fractal_support = low[3]   // initialize

fractal_resistance :=  _up ? high[3] : fractal_resistance[1]
fractal_support := _down ? low[3] : fractal_support[1]

plot(fractal_resistance, "fractal_resistance", color=color.new(color.red,50), linewidth=2, style=plot.style_cross, offset =-3, join=false)
plot(fractal_support, "fractal_support", color=color.new(color.lime,50), linewidth=2, style=plot.style_cross, offset=-3, join=false)
// }

// ATR diversion test {
// Hypothesis testing (2-tailed):
//
// Null hypothesis (H0) and Alternative hypothesis (Ha):
//     H0 : atr_fast equals atr_slow
//     Ha : atr_fast not equals to atr_slow; implies atr_fast is either too low or too high
len_fast    = input(5,title="Length of ATR (fast) for diversion test", group=GROUP_ENTRY)
atr_fast    = ta.atr(len_fast)
atr_slow    = ta.atr(input(50,title="Length of ATR (slow) for diversion test", group=GROUP_ENTRY, tooltip="This needs to be larger than Fast"))

// Calculate test statistic (test_stat)
std_error   = ta.stdev(ta.tr, len_fast) / math.pow(len_fast, 0.5)
test_stat = (atr_fast - atr_slow) / std_error

// Compare test_stat against critical value defined by user in settings
//critical_value = input.float(1.645,title="Critical value", tooltip="Strategy uses 2-tailed test to compare atr_fast vs atr_slow. Null hypothesis (H0) is that both should equal. Based on the computed test statistic value, if absolute value of it is +/- this critical value, then H0 will be rejected.", group=GROUP_ENTRY)
conf_interval = input.string(title="Confidence Interval", defval="95%", options=["90%","95%","99%"], tooltip="Critical values of 1.645, 1.96, 2.58, for CI=90%/95%/99%, respectively; Under 2-tailed test to compare atr_fast vs atr_slow. Null hypothesis (H0) is that both should equal. Based on the computed test statistic value, if absolute value of it is +/- critical value, then H0 will be rejected.")
critical_value = conf_interval == "90%" ? 1.645 : conf_interval == "95%" ? 1.96 : 2.58
reject_H0_lefttail = test_stat < -critical_value
reject_H0_righttail = test_stat > critical_value

// } end of "ATR diversion test" block

// Entry Signals
entry_signal_long = close >= fractal_support and reject_H0_lefttail

// MAIN {
// Update the stop limit if strategy holds a position.
if strategy.position_size > 0
    strategy.exit(ENUM_LONG, comment="SL", stop=stop_loss_price)

// Entry
if within_timeframe and entry_signal_long and strategy.position_size == 0
    initial_entry_p := close
    risk_amt := ATR_TSL
    initial_order_size := math.floor(pcnt_alloc * strategy.equity / close)
    strategy.entry(ENUM_LONG, strategy.long, qty=initial_order_size)

var int TP_taken_count = 0
if tp_mode and close > strategy.position_avg_price
    if close >= initial_entry_p + THIRD_LVL_PROFIT * risk_amt and TP_taken_count == 2
        strategy.close(ENUM_LONG, comment="TP Lvl3", qty=math.floor(initial_order_size / 3))
        TP_taken_count := TP_taken_count + 1
    else if close >= initial_entry_p + SECOND_LVL_PROFIT * risk_amt and TP_taken_count == 1
        strategy.close(ENUM_LONG, comment="TP Lvl2", qty=math.floor(initial_order_size / 3))
        TP_taken_count := TP_taken_count + 1
    else if close >= initial_entry_p + FIRST_LVL_PROFIT * risk_amt and TP_taken_count == 0
        strategy.close(ENUM_LONG, comment="TP Lvl1", qty=math.floor(initial_order_size / 3))
        TP_taken_count := TP_taken_count + 1
    
// Alerts
_atr = ta.atr(14)
alert_helper(msg) =>
    prefix = "[" + syminfo.root + "] "
    suffix = "(P=" + str.tostring(close, "#.##") + "; atr=" + str.tostring(_atr, "#.##") + ")"
    alert(str.tostring(prefix) + str.tostring(msg) + str.tostring(suffix), alert.freq_once_per_bar)

if strategy.position_size > 0 and ta.change(strategy.position_size)
    if strategy.position_size > strategy.position_size[1]
        alert_helper("BUY")
    else if strategy.position_size < strategy.position_size[1]
        alert_helper("SELL")

// Clean up - set the variables back to default values once no longer in use
if ta.change(strategy.position_size) and strategy.position_size == 0
    TP_taken_count := 0
    initial_entry_p := float(0)
    risk_amt := float(0)
    initial_order_size := float(0)
    stop_loss_price := float(0)
// } end of MAIN block


Plus de