avatar of 发明者量化-小小梦 发明者量化-小小梦
Suivre Messages privés
4
Suivre
1271
Abonnés

« Stratégie magique de moyenne mobile à double EMA » de YouTube Master

Créé le: 2022-10-09 15:56:22, Mis à jour le: 2024-11-29 18:59:45
comments   28
hits   7284

« Stratégie magique de moyenne mobile à double EMA » de YouTube Master

« Stratégie magique de moyenne mobile à double EMA » de YouTube Master

Dans ce numéro, nous discuterons d’une « stratégie magique de moyenne mobile à double EMA » de YouTube, appelée le « tueur du marché des actions et des crypto-monnaies ». Après avoir regardé la vidéo, j’ai appris que cette stratégie est une stratégie de langage pine de vue de trading, qui utilise 2 indicateurs de vue de trading. En voyant que les résultats du backtesting dans la vidéo étaient très bons, et que FMZ prend également en charge le langage Pine de Trading View, je n’ai pas pu m’empêcher de vouloir backtester et tester l’analyse moi-même. Alors commence toute la vie ! Reproduisons la stratégie dans la vidéo.

Indicateurs utilisés par la stratégie

  1. Indicateur EMA

Pour des raisons de simplicité de conception, nous n’utiliserons pas la moyenne mobile exponentielle répertoriée dans la vidéo. Nous utilisons plutôt le ta.ema intégré dans la vue trading (en fait, ils sont identiques).

  1. Indicateur VuManChu Swing Free

Il s’agit d’un indicateur sur Trading View. Nous devons accéder à Trading View et télécharger le code source.

« Stratégie magique de moyenne mobile à double EMA » de YouTube Master

Code gratuit VuManChu Swing :

// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/

// Credits to the original Script - Range Filter DonovanWall https://www.tradingview.com/script/lut7sBgG-Range-Filter-DW/
// This version is the old version of the Range Filter with less settings to tinker with

//@version=4
study(title="Range Filter - B&S Signals", shorttitle="RF - B&S Signals", overlay=true)

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Functions
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------

//Range Size Function
rng_size(x, qty, n)=> 
//    AC       = Cond_EMA(abs(x - x[1]), 1, n)
    wper      = (n*2) - 1
    avrng     = ema(abs(x - x[1]), n)
    AC = ema(avrng, wper)*qty
    rng_size = AC

//Range Filter Function
rng_filt(x, rng_, n)=>
    r          = rng_
    var rfilt  = array.new_float(2, x)
    array.set(rfilt, 1, array.get(rfilt, 0))
    if x - r > array.get(rfilt, 1)
        array.set(rfilt, 0, x - r)
    if x + r < array.get(rfilt, 1)
        array.set(rfilt, 0, x + r)
    rng_filt1 = array.get(rfilt, 0)
    
    hi_band   = rng_filt1 + r
    lo_band   = rng_filt1 - r
    rng_filt  = rng_filt1
    [hi_band, lo_band, rng_filt]
 
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Inputs
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------

//Range Source
rng_src = input(defval=close, type=input.source, title="Swing Source")

//Range Period
rng_per = input(defval=20, minval=1, title="Swing Period")

//Range Size Inputs
rng_qty   = input(defval=3.5, minval=0.0000001, title="Swing Multiplier")

//Bar Colors
use_barcolor = input(defval=false, type=input.bool, title="Bar Colors On/Off")

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Definitions
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------

//Range Filter Values
[h_band, l_band, filt] = rng_filt(rng_src, rng_size(rng_src, rng_qty, rng_per), rng_per)

//Direction Conditions
var fdir = 0.0
fdir    := filt > filt[1] ? 1 : filt < filt[1] ? -1 : fdir
upward   = fdir==1 ? 1 : 0
downward = fdir==-1 ? 1 : 0

//Trading Condition
longCond = rng_src > filt and rng_src > rng_src[1] and upward > 0 or rng_src > filt and rng_src < rng_src[1] and upward > 0 
shortCond = rng_src < filt and rng_src < rng_src[1] and downward > 0 or rng_src < filt and rng_src > rng_src[1] and downward > 0

CondIni = 0
CondIni := longCond ? 1 : shortCond ? -1 : CondIni[1]
longCondition = longCond and CondIni[1] == -1
shortCondition = shortCond and CondIni[1] == 1

//Colors
filt_color = upward ? #05ff9b : downward ? #ff0583 : #cccccc
bar_color  = upward and (rng_src > filt) ? (rng_src > rng_src[1] ? #05ff9b : #00b36b) :
             downward and (rng_src < filt) ? (rng_src < rng_src[1] ? #ff0583 : #b8005d) : #cccccc

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Outputs
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------

//Filter Plot
filt_plot = plot(filt, color=filt_color, transp=67, linewidth=3, title="Filter")

//Band Plots
h_band_plot = plot(h_band, color=color.new(#05ff9b, 100), title="High Band")
l_band_plot = plot(l_band, color=color.new(#ff0583, 100), title="Low Band")

//Band Fills
fill(h_band_plot, filt_plot, color=color.new(#00b36b, 92), title="High Band Fill")
fill(l_band_plot, filt_plot, color=color.new(#b8005d, 92), title="Low Band Fill")

//Bar Color
barcolor(use_barcolor ? bar_color : na)

//Plot Buy and Sell Labels
plotshape(longCondition, title = "Buy Signal", text ="BUY", textcolor = color.white, style=shape.labelup, size = size.normal, location=location.belowbar, color = color.new(color.green, 0))
plotshape(shortCondition, title = "Sell Signal", text ="SELL", textcolor = color.white, style=shape.labeldown, size = size.normal, location=location.abovebar, color = color.new(color.red, 0))

//Alerts
alertcondition(longCondition, title="Buy Alert", message = "BUY")
alertcondition(shortCondition, title="Sell Alert", message = "SELL")

Logique de stratégie

Indicateur EMA : La stratégie utilise deux moyennes mobiles EMA, une ligne rapide (paramètre de petit cycle) et une ligne lente (paramètre de grand cycle). La fonction principale de la moyenne mobile double EMA est de nous aider à déterminer la direction des tendances du marché.

  • Arrangement long La ligne rapide est au-dessus de la ligne lente.

  • Arrangement court La ligne rapide est en dessous de la ligne lente.

Indicateur VuManChu Swing Free : L’indicateur VuManChu Swing Free est utilisé pour envoyer des signaux, puis combiné avec d’autres conditions pour déterminer s’il faut passer un ordre de trading. À partir du code source de l’indicateur VuManChu Swing Free, nous pouvons voir que la variable longCondition représente le signal d’achat et la variable shortCondition représente le signal de vente. Ces deux variables seront utilisées lors de l’écriture des conditions de commande ultérieurement.

Parlons maintenant des conditions spécifiques de déclenchement du signal de trading de la stratégie :

  1. Règles d’entrée en position longue : Le prix de clôture de la ligne K positive doit être supérieur à la ligne rapide EMA, les deux moyennes mobiles EMA doivent être dans une configuration haussière (la ligne rapide est au-dessus de la ligne lente) et l’indicateur VuManChu Swing Free doit afficher un signal d’achat (longCondition est vrai). Si les trois conditions sont remplies, cette ligne K est la ligne K clé pour entrer dans une position longue, et le prix de clôture de cette ligne K est la position d’entrée.

  2. Règles d’entrée en position short (opposée à une position long) : Le prix de clôture du chandelier négatif doit être inférieur à la ligne EMA rapide, les deux moyennes mobiles EMA doivent être en position courte (la ligne rapide est inférieure à la ligne lente) et l’indicateur VuManChu Swing Free doit afficher un signal de vente (shortCondition est vrai). Si les trois conditions sont remplies, le cours de clôture de cette ligne K constitue le point d’entrée pour la vente à découvert.

La logique de trading n’est-elle pas très simple ? Étant donné que la vidéo source ne précise pas le take-profit et le stop-loss, l’éditeur utilisera une méthode de take-profit et de stop-loss plus modérée, en utilisant un stop loss à point fixe et un suivi prendre des bénéfices.

Conception de code

Nous avons placé le code de l’indicateur VuManChu Swing Free directement dans notre code de stratégie intact.

« Stratégie magique de moyenne mobile à double EMA » de YouTube Master

Ensuite, nous écrivons un morceau de code en langage Pine pour implémenter la fonction de transaction :

// extend
fastEmaPeriod = input(50, "fastEmaPeriod")         // 快线周期
slowEmaPeriod = input(200, "slowEmaPeriod")        // 慢线周期
loss = input(30, "loss")                           // 止损点数
trailPoints = input(30, "trailPoints")             // 移动止盈触发点数
trailOffset = input(30, "trailOffset")             // 移动止盈偏移量(点数)
amount = input(1, "amount")                        // 下单量

emaFast = ta.ema(close, fastEmaPeriod)             // 计算快线EMA
emaSlow = ta.ema(close, slowEmaPeriod)             // 计算慢线EMA

buyCondition = longCondition and emaFast > emaSlow and close > open and close > emaFast         // 做多入场条件
sellCondition = shortCondition and emaFast < emaSlow and close < open and close < emaFast       // 做空入场条件

if buyCondition and strategy.position_size == 0
    strategy.entry("long", strategy.long, amount)
    strategy.exit("exit_long", "long", amount, loss=loss, trail_points=trailPoints, trail_offset=trailOffset)
if sellCondition and strategy.position_size == 0
    strategy.entry("short", strategy.short, amount)
    strategy.exit("exit_short", "short", amount, loss=loss, trail_points=trailPoints, trail_offset=trailOffset)

A. Comme vous pouvez le voir, lorsque buyCondition est vrai :

  1. La variable longCondition est vraie (l’indicateur VuManChu Swing Free envoie un signal pour passer en position longue).
  2. emaFast > emaSlow (arrangement haussier EMA).
  3. close > open (indiquant que la BAR actuelle est une ligne positive), close > emaFast (indiquant que le prix de clôture est au-dessus de la ligne rapide EMA).

Les trois conditions pour être long sont réunies.

B. Lorsque sellCondition est vraie, les trois conditions de vente à découvert sont remplies (non décrites ici).

Ensuite, lorsque la condition if détermine que le signal est déclenché, utilisez la fonction strategy.entry pour entrer sur le marché et ouvrir une position, et définissez la fonction strategy.exit pour arrêter la perte et le profit suiveur.

Code complet

/*backtest
start: 2022-01-01 00:00:00
end: 2022-10-08 00:00:00
period: 15m
basePeriod: 5m
exchanges: [{"eid":"Futures_Binance","currency":"ETH_USDT"}]
args: [["ZPrecision",0,358374]]
*/

// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/

// Credits to the original Script - Range Filter DonovanWall https://www.tradingview.com/script/lut7sBgG-Range-Filter-DW/
// This version is the old version of the Range Filter with less settings to tinker with

//@version=4
study(title="Range Filter - B&S Signals", shorttitle="RF - B&S Signals", overlay=true)

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Functions
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------

//Range Size Function
rng_size(x, qty, n)=> 
//    AC       = Cond_EMA(abs(x - x[1]), 1, n)
    wper      = (n*2) - 1
    avrng     = ema(abs(x - x[1]), n)
    AC = ema(avrng, wper)*qty
    rng_size = AC

//Range Filter Function
rng_filt(x, rng_, n)=>
    r          = rng_
    var rfilt  = array.new_float(2, x)
    array.set(rfilt, 1, array.get(rfilt, 0))
    if x - r > array.get(rfilt, 1)
        array.set(rfilt, 0, x - r)
    if x + r < array.get(rfilt, 1)
        array.set(rfilt, 0, x + r)
    rng_filt1 = array.get(rfilt, 0)
    
    hi_band   = rng_filt1 + r
    lo_band   = rng_filt1 - r
    rng_filt  = rng_filt1
    [hi_band, lo_band, rng_filt]
 
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Inputs
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------

//Range Source
rng_src = input(defval=close, type=input.source, title="Swing Source")

//Range Period
rng_per = input(defval=20, minval=1, title="Swing Period")

//Range Size Inputs
rng_qty   = input(defval=3.5, minval=0.0000001, title="Swing Multiplier")

//Bar Colors
use_barcolor = input(defval=false, type=input.bool, title="Bar Colors On/Off")

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Definitions
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------

//Range Filter Values
[h_band, l_band, filt] = rng_filt(rng_src, rng_size(rng_src, rng_qty, rng_per), rng_per)

//Direction Conditions
var fdir = 0.0
fdir    := filt > filt[1] ? 1 : filt < filt[1] ? -1 : fdir
upward   = fdir==1 ? 1 : 0
downward = fdir==-1 ? 1 : 0

//Trading Condition
longCond = rng_src > filt and rng_src > rng_src[1] and upward > 0 or rng_src > filt and rng_src < rng_src[1] and upward > 0 
shortCond = rng_src < filt and rng_src < rng_src[1] and downward > 0 or rng_src < filt and rng_src > rng_src[1] and downward > 0

CondIni = 0
CondIni := longCond ? 1 : shortCond ? -1 : CondIni[1]
longCondition = longCond and CondIni[1] == -1
shortCondition = shortCond and CondIni[1] == 1

//Colors
filt_color = upward ? #05ff9b : downward ? #ff0583 : #cccccc
bar_color  = upward and (rng_src > filt) ? (rng_src > rng_src[1] ? #05ff9b : #00b36b) :
             downward and (rng_src < filt) ? (rng_src < rng_src[1] ? #ff0583 : #b8005d) : #cccccc

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Outputs
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------

//Filter Plot
filt_plot = plot(filt, color=filt_color, transp=67, linewidth=3, title="Filter")

//Band Plots
h_band_plot = plot(h_band, color=color.new(#05ff9b, 100), title="High Band")
l_band_plot = plot(l_band, color=color.new(#ff0583, 100), title="Low Band")

//Band Fills
fill(h_band_plot, filt_plot, color=color.new(#00b36b, 92), title="High Band Fill")
fill(l_band_plot, filt_plot, color=color.new(#b8005d, 92), title="Low Band Fill")

//Bar Color
barcolor(use_barcolor ? bar_color : na)

//Plot Buy and Sell Labels
plotshape(longCondition, title = "Buy Signal", text ="BUY", textcolor = color.white, style=shape.labelup, size = size.normal, location=location.belowbar, color = color.new(color.green, 0))
plotshape(shortCondition, title = "Sell Signal", text ="SELL", textcolor = color.white, style=shape.labeldown, size = size.normal, location=location.abovebar, color = color.new(color.red, 0))

//Alerts
alertcondition(longCondition, title="Buy Alert", message = "BUY")
alertcondition(shortCondition, title="Sell Alert", message = "SELL")


// extend
fastEmaPeriod = input(50, "fastEmaPeriod")
slowEmaPeriod = input(200, "slowEmaPeriod")
loss = input(30, "loss")
trailPoints = input(30, "trailPoints")
trailOffset = input(30, "trailOffset")
amount = input(1, "amount")

emaFast = ta.ema(close, fastEmaPeriod)
emaSlow = ta.ema(close, slowEmaPeriod)

buyCondition = longCondition and emaFast > emaSlow and close > open and close > emaFast
sellCondition = shortCondition and emaFast < emaSlow and close < open and close < emaFast

if buyCondition and strategy.position_size == 0
    strategy.entry("long", strategy.long, amount)
    strategy.exit("exit_long", "long", amount, loss=loss, trail_points=trailPoints, trail_offset=trailOffset)
if sellCondition and strategy.position_size == 0
    strategy.entry("short", strategy.short, amount)
    strategy.exit("exit_short", "short", amount, loss=loss, trail_points=trailPoints, trail_offset=trailOffset)

Backtesting

La plage de temps du backtesting est sélectionnée de janvier 2022 à octobre 2022, la période K-line est de 15 minutes et le modèle de cours de clôture est utilisé pour le backtesting. Le marché choisit le contrat perpétuel ETH_USDT de Binance. Les réglages des paramètres sont ceux indiqués dans la vidéo source : 50 périodes pour la ligne rapide et 200 périodes pour la ligne lente, et les autres paramètres restent inchangés par défaut. Je suis un peu subjectif dans la définition des points de stop loss et de profit suiveur et je les fixe simplement à 30 points.

« Stratégie magique de moyenne mobile à double EMA » de YouTube Master

« Stratégie magique de moyenne mobile à double EMA » de YouTube Master

Les résultats du backtest sont moyens. Après plusieurs backtests, il semble que des paramètres tels que le take-profit et le stop-loss aient un certain impact sur les résultats du backtest. Je pense que cet aspect nécessite une optimisation supplémentaire. Cependant, le taux de gain reste bon après que le signal de stratégie ait déclenché la transaction.

Essayons un contrat perpétuel BTC_USDT :

« Stratégie magique de moyenne mobile à double EMA » de YouTube Master

Les résultats du backtest sur BTC sont également explosifs :

« Stratégie magique de moyenne mobile à double EMA » de YouTube Master

« Stratégie magique de moyenne mobile à double EMA » de YouTube Master

Adresse de la stratégie : https://www.fmz.com/strategy/385745

Il semble que cette méthode de trading soit relativement fiable pour saisir la tendance, et la conception peut être encore optimisée sur la base de cette idée. Dans cet article, nous avons non seulement appris l’idée d’une stratégie de double moyenne mobile, mais nous avons également appris à traiter et à apprendre les stratégies des maîtres sur YouTube. OK, les codes de stratégie ci-dessus ne sont que mes suggestions. Les résultats du backtest ne représentent pas les résultats réels spécifiques. Les codes et conceptions de stratégie sont fournis à titre indicatif uniquement. Merci pour votre soutien, à la prochaine !