La "Magic Double EMA Strategy" des anciens combattants de YouTube

Auteur:Je ne sais pas., Créé: 2022-11-07 12:02:31, Mis à jour: 2023-09-15 20:51:23

img

La Magic Double EMA Strategy des anciens combattants de YouTube

Dans ce numéro, nous allons discuter d'une Magic Double EMA Strategy de YouTube, qui est connue sous le nom de the Killer of Stock and Cryptocurrency Market. J'ai regardé la vidéo et j'ai appris que cette stratégie est une stratégie de langage de trading Pine qui utilise 2 indicateurs de trading. L'effet de backtesting dans la vidéo est très bon, et FMZ prend également en charge le langage Pine de Trading View, donc je ne peux pas m'empêcher de vouloir faire le backtest et l'analyse par moi-même. Alors commençons le travail!

Indicateurs utilisés par la stratégie

  1. Indicateurs de l'EMA

Pour des raisons de simplicité de conception, nous n'utiliserons pas l'exponentiel de moyenne mobile indiqué dans la vidéo, nous utiliserons le ta.ema intégré de la vue de trading à la place (c'est en fait la même chose).

  1. Indicateurs de dégagement de VuManChu

Ceci est un indicateur sur Trading View, nous devons aller à Trading View et ramasser le code source.

img

Le code de VuManChu Swing Free:

// 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")

La logique de la stratégie

L'indicateur EMA: la stratégie utilise deux EMA, l'un est la ligne rapide (paramètre de petite période) et l'autre est la ligne lente (paramètre de grande période).

  • accord de position longue La ligne rapide est au-dessus de la ligne lente.

  • accord de position courte La ligne rapide est sous la ligne lente.

VuManChu Swing Free Indicator: L'indicateur VuManChu Swing Free est utilisé pour envoyer des signaux et juger si une commande doit être passée en combinaison avec d'autres conditions.

Maintenant, parlons des conditions de déclenchement spécifiques du signal de trading:

  1. Règles d'entrée en position longue: Le prix de clôture de la ligne K positive devrait être au-dessus de la ligne rapide de l'EMA, les deux EMA devraient être une position longue (ligne rapide au-dessus de la ligne lente), et l'indicateur VuManChu Swing Free devrait afficher un signal d'achat (longCondition est vraie).

  2. Règles d'entrée en position courte (contrairement à la position longue): Le prix de clôture de la ligne K négative devrait être inférieur à la ligne rapide de l'EMA, les deux EMA devraient être une position courte (ligne rapide en dessous de la ligne lente) et l'indicateur VuManChu Swing Free devrait afficher un signal de vente (shortCondition est vraie). Si les trois conditions sont remplies, le prix de clôture de la ligne K est la position d'entrée courte.

Est-ce que la logique de trading est très simple? puisque la vidéo source ne spécifie pas l'arrêt de profit et l'arrêt de perte, je vais utiliser une méthode d'arrêt de profit et d'arrêt de perte modérée librement, en utilisant des points fixes pour arrêter la perte et suivre l'arrêt de profit.

Conception du code

Le code de l'indicateur VuManChu Swing Free, on le met dans notre code de stratégie directement sans aucun changement.

img

Ensuite, immédiatement après, nous écrivons un morceau de code de la langue Pine qui implémente la fonction de trading:

// extend
fastEmaPeriod = input(50, "fastEmaPeriod")         // fast line period
slowEmaPeriod = input(200, "slowEmaPeriod")        // slow line period
loss = input(30, "loss")                           // stop loss points
trailPoints = input(30, "trailPoints")             // number of trigger points for moving stop loss
trailOffset = input(30, "trailOffset")             // moving stop profit offset (points)
amount = input(1, "amount")                        // order amount

emaFast = ta.ema(close, fastEmaPeriod)             // calculate the fast line EMA
emaSlow = ta.ema(close, slowEmaPeriod)             // calculate the slow line EMA

buyCondition = longCondition and emaFast > emaSlow and close > open and close > emaFast         // entry conditions for long positions
sellCondition = shortCondition and emaFast < emaSlow and close < open and close < emaFast       // entry conditions for short positions

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.ItOn peut voir que lorsque buyCondition est vrai, c'est:

  1. Variable longCondition est vraie (l'indicateur VuManChu Swing Free envoie un signal de position longue).
  2. EmaFast > emaSlow (alignement de la position longue de l'EMA).
  3. close > open (signifie que le BAR actuel est positif), close > emaFast (signifie que le prix de clôture est supérieur à la ligne rapide de l'EMA).

Les trois conditions pour rester longtemps.

B.Lorsque la condition de vente est vraie, les trois conditions de création d'une position courte sont valables (non répétées ici).

Ensuite, nous utilisons la fonction strategy.entry pour entrer et ouvrir une position dans le cas d'un si condition jugement signal déclencheur, et de définir lestrategy.exitfonction de stopper les pertes et de suivre les bénéfices en même temps.

Le 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)

Test de retour

L'intervalle de temps du backtest est de janvier 2022 à octobre 2022. La période de la ligne K est de 15 minutes et le modèle de prix de clôture est utilisé pour le backtest. Le marché choisit le contrat perpétuel Binance ETH_USDT. Les paramètres sont définis en fonction des 50 périodes de ligne rapide et des 200 périodes de ligne lente dans la vidéo source. Les autres paramètres restent inchangés par défaut. J'ai défini les points de stop loss et de suivi des points de stop profit à 30 points de manière subjective.

img

img

img

Les résultats du backtesting sont ordinaires et il semble que les paramètres de stop-loss aient une certaine influence sur les résultats du backtesting. Je pense que cet aspect doit encore être optimisé et conçu. Cependant, après que le signal stratégique ait déclenché le trading, le taux de gain est toujours OK.

Essayons un autre contrat perpétuel BTC_USDT:

img

Le résultat du backtest sur BTC a également été très rentable:

img

img

Stratégie de:https://www.fmz.com/strategy/385745

Il semble que cette méthode de trading soit relativement fiable pour saisir la tendance, vous pouvez continuer à optimiser la conception en fonction de cette idée. Dans cet article, nous avons non seulement appris l'idée d'une stratégie de moyenne mobile double, mais nous avons également appris à traiter et à apprendre la stratégie des vétérans sur YouTube. OK, le code de stratégie ci-dessus n'est que mon brique et mortier, les résultats des backtests ne représentent pas les résultats spécifiques du réel bot, le code de stratégie, la conception sont uniquement à titre de référence. Merci pour votre soutien, nous vous verrons la prochaine fois!


Relationnée

Plus de