Стратегия перекрестного использования двойной EMA

Автор:Чао Чжан, Дата: 2023-12-06 18:22:16
Тэги:

img

Обзор

Стратегия перекрестного использования двойной EMA - это широко используемая стратегия следования тренду. Она использует две линии EMA с разными периодами и генерирует сигналы покупки, когда более короткая EMA пересекает более длинную EMA, и сигналы продажи, когда происходит обратное, для того, чтобы улавливать изменения тренда.

Логика стратегии

Основная логика этой стратегии основана на принципах золотого креста и смертного креста линий EMA. EMA может эффективно сглаживать ценные данные и указывать направление тренда. Короткий период EMA реагирует быстрее на изменения цен, в то время как более длительный период EMA менее чувствителен к шуму и отражает долгосрочную тенденцию. Когда более короткий период EMA пересекает более длительный период EMA, это рассматривается как сигнал о том, что подъемный импульс укрепляется. Когда происходит обратное, это сигнализирует об ускорении нисходящего импульса. Стратегия генерирует торговые сигналы на основе этой логики.

В частности, эта стратегия использует параметры длины1 и длины2 для установки периодов двух линий EMA. demaVal1 - длины1 периода EMA и demaVal2 - длины2 периода EMA. Они рассчитываются как:

demaVal1 = EMA(close, length1)
demaVal2 = EMA(close, length2)  

где EMA() является функцией, которая вычисляет значения EMA. Когда demaVal1 пересекает demaVal2, генерируется сигнал покупки demaCrossover. Когда происходит обратное, генерируется сигнал продажи demaCrossunder. Стратегия отправляет торговые ордера на основе этих двух сигналов.

Преимущества

Преимущества этой стратегии включают:

  1. Простая логика и легко реализовать.
  2. Зрелые теории EMA с широкими применениями.
  3. Гибкая настройка параметров, адаптируемая к различным рыночным условиям.
  4. Дальнейшая оптимизация возможна для улучшения эффективности стратегии.

Риски и улучшения

Существуют также некоторые риски, связанные с этой стратегией:

  1. Частые ложные сигналы могут возникать, когда рынок не имеет тенденции.
  2. Параметры по умолчанию могут не соответствовать всем инструментам, и требуется историческая оптимизация.

Исходя из вышеуказанных рисков, следующие аспекты могут быть оптимизированы:

  1. Корректировка параметров периода EMA для адаптации к рыночным условиям с различными циклами.
  2. Добавление условий фильтрации для предотвращения ложных сигналов, например, показателей физической подготовки, показателей объема.
  3. Включите другие методы, такие как тенденции, уровни поддержки / сопротивления, чтобы улучшить эффективность стратегии.

Заключение

В заключение можно сказать, что стратегия перекрестного использования двойной EMA представляет собой простую, но практичную систему следования трендам.


/*backtest
start: 2022-11-29 00:00:00
end: 2023-12-05 00:00:00
period: 1d
basePeriod: 1h
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/
// © zeguela
//@version=4
strategy(title="ZEGUELA DEMABOT", commission_value=0.063, commission_type=strategy.commission.percent, initial_capital=100, default_qty_value=90, default_qty_type=strategy.percent_of_equity, overlay=true, process_orders_on_close=true)

// Step 1. Script settings

// Input options
srcData = input(title="Source Data", type=input.source, defval=close)

// Length settings
len1 = input(title="Length DEMA #1", type=input.integer, defval=8, minval=1)
len2 = input(title="Length DEMA #2", type=input.integer, defval=24, minval=0)
len3 = input(title="Length DEMA #3", type=input.integer, defval=0, minval=0)

// Step 2. Calculate indicator values
// Function that calculates the DEMA
DEMA(series, length) =>
    if (length > 0)
        emaValue = ema(series, length)
        2 * emaValue - ema(emaValue, length)
    else
        na

// Calculate the DEMA values
demaVal1 = DEMA(srcData, len1)
demaVal2 = DEMA(srcData, len2)
demaVal3 = DEMA(srcData, len3)

// Step 3. Determine indicator signals
// See if there's a DEMA crossover
demaCrossover = if (len2 > 0) and (len3 > 0)
    crossover(demaVal1, demaVal2) and (demaVal3 > demaVal3[1])
else
    if (len2 > 0) and (len3 == 0)
        crossover(demaVal1, demaVal2)
    else
        if (len3 > 0) and (len2 == 0)
            crossover(demaVal1, demaVal3)
        else
            crossover(close, demaVal1)

// Check if there's a DEMA crossunder
demaCrossunder = if (len2 > 0) and (len3 > 0)
    crossunder(demaVal1, demaVal2) and (demaVal3 < demaVal3[1])
else
    if (len2 > 0) and (len3 == 0)
        crossunder(demaVal1, demaVal2)
    else
        if (len3 > 0) and (len2 == 0)
            crossunder(demaVal1, demaVal3)
        else
            crossunder(close, demaVal1)

// Step 4. Output indicator data
// Plot DEMAs on the chart
plot(series=demaVal1, color=color.green, linewidth=2, title="DEMA #1")
plot(series=demaVal2, color=color.red, linewidth=2, title="DEMA #2")
plot(series=demaVal3, color=color.fuchsia, linewidth=2, title="DEMA #3")

//TRAILING STOP CODE
a = input(title="Usar Trailing Stop?", type=input.bool, defval=false)

stopPerlong = input(9.0, title='Stop Loss Long %', type=input.float, group="Stop Loss & Take Profit Settings") / 100
stopPershort = input(6.0, title='Stop Loss Short %', type=input.float, group="Stop Loss & Take Profit Settings") / 100
take1Perlong = input(25.0, title='Take Profit Long % 1', type=input.float, group="Stop Loss & Take Profit Settings") / 100
take1Pershort = input(6.0, title='Take Profit Short % 1', type=input.float, group="Stop Loss & Take Profit Settings") / 100

// Determine stop loss price
longStopPrice  = strategy.position_avg_price * (1 - stopPerlong)
shortStopPrice = strategy.position_avg_price * (1 + stopPershort)
longTake1Price = strategy.position_avg_price * (1 + take1Perlong)
shortTake1Price = strategy.position_avg_price * (1 - take1Pershort)

// Determine trail stop loss prices

longStopPriceTrail = 0.0

longStopPriceTrail := if (strategy.position_size > 0)
    stopValue = close * (1 - stopPerlong)
    max(stopValue, longStopPriceTrail[1])
else
    0

// Determine trailing short price
shortStopPriceTrail = 0.0

shortStopPriceTrail := if (strategy.position_size < 0)
    stopValue = close * (1 + stopPershort)
    min(stopValue, shortStopPriceTrail[1])
else
    999999

//calcular qual stop usar
longStop = a ? longStopPriceTrail : longStopPrice
shortStop = a ? shortStopPriceTrail : shortStopPrice


//calcula o valor do stop e TP pra lançar no alerta
longStopEntrada = close  * (1 - stopPerlong)
shortStopEntrada = close  * (1 + stopPershort) 
longTPEntrada = close * (1 + take1Perlong)
shortTPEntrada = close * (1 - take1Pershort)

//armazena o preço de entrada e valor do SL e TP

price_entryL = 0.0
price_entryL := na(price_entryL) ? na : price_entryL[1]
price_entryS = 0.0
price_entryS := na(price_entryS) ? na : price_entryS[1]
stopL = 0.0
stopL := na(stopL) ? na : stopL[1]
stopS = 0.0
stopS := na(stopS) ? na : stopS[1]
takeL = 0.0
takeL := na(takeL) ? na : takeL[1]
takeS = 0.0
takeS := na(takeS) ? na : takeS[1]

if (demaCrossover)
    price_entryL := close
    stopL := close  * (1 - stopPerlong)
    takeL := close * (1 + take1Perlong)
    
if (demaCrossunder)
    price_entryS := close
    stopS := close  * (1 + stopPershort)
    takeS := close * (1 - take1Pershort)

resultadoL = ((close - price_entryL)/price_entryL) * 100
resultadoLexit = "(SL = 1% e TP = 0,5%)"
resultadoS = ((price_entryS - close)/price_entryS) * 100
resultadoSexit = "(SL = 1% e TP = 0,5)%"
// Make input options that configure backtest date range
_startDate = input(title="Start Date", type=input.integer,
     defval=1, minval=1, maxval=31, group="BackTest Period")
_startMonth = input(title="Start Month", type=input.integer,
     defval=1, minval=1, maxval=12, group="BackTest Period")
_startYear = input(title="Start Year", type=input.integer,
     defval=2018, minval=1800, maxval=2100, group="BackTest Period")

_endDate = input(title="End Date", type=input.integer,
     defval=31, minval=1, maxval=31, group="BackTest Period")
_endMonth = input(title="End Month", type=input.integer,
     defval=12, minval=1, maxval=12, group="BackTest Period")
_endYear = input(title="End Year", type=input.integer,
     defval=2031, minval=1800, maxval=2100, group="BackTest Period")

// Look if the close time of the current bar
// falls inside the date range
_inDateRange = (time >= timestamp(syminfo.timezone, _startYear,
         _startMonth, _startDate, 0, 0)) and
     (time < timestamp(syminfo.timezone, _endYear, _endMonth, _endDate, 0, 0))
  
//Alert configuration     

_alertMessageOpenLong="OpenLong"
_alertMessageCloseLong="CloseLong"
_alertmessageExitLong="ExitLong - TP/SL"

_alertMessageOpenShort="OpenShort"
_alertMessageCloseShort="CloseShort"
_alertMessageExitShort="ExitShort - TP/SL"

if (_inDateRange)
    //ENTER SOME SETUP TRADES FOR TSL EXAMPLE
    if (demaCrossover)
        strategy.entry("LONG", strategy.long, comment = _alertMessageOpenLong)
    if (demaCrossunder)
        strategy.entry("SHORT", strategy.short, comment = _alertMessageOpenShort)
    //EXIT TRADE @ TSL
    if strategy.position_size > 0
        strategy.exit("TP/SL", "LONG", stop=longStop, limit=longTake1Price, comment=_alertmessageExitLong, alert_message=_alertmessageExitLong)
    if strategy.position_size < 0
        strategy.exit("TP/SL", "SHORT", stop=shortStop, limit=shortTake1Price, comment =_alertMessageExitShort, alert_message=_alertMessageExitShort)


//Look & Feel - Plot stop loss and take profit areas
p1=plot(strategy.position_avg_price, color=color.blue, style=plot.style_linebr, linewidth=1, title="Preço de entrada")
p2=plot(series=strategy.position_size > 0 ? longStop : na, color=color.red, style=plot.style_linebr, linewidth=1, title="Long Stop")
p3=plot(series=strategy.position_size > 0 ? longTake1Price : na, color=color.green, style=plot.style_linebr, linewidth=1, title="Long TP")
p4=plot(series=strategy.position_size < 0 ? shortStop : na, color=color.red, style=plot.style_linebr, linewidth=1, title="Short Stop")
p5=plot(series=strategy.position_size < 0 ? shortTake1Price : na, color=color.green, style=plot.style_linebr, linewidth=1, title="Short TP")
fill(p1, p2, color=color.red)
fill(p1, p3, color=color.green)
fill(p1, p4, color=color.red)
fill(p1, p5, color=color.green)

// Insert label with value
stopLossOnLong = "Stop Loss = " + tostring(longStop)
stopLossOnShort = "Stop Loss = " + tostring(shortStop)
takeprofitOnLong = "Take Profit = " + tostring(longTake1Price)
takeprofitOnShort = "Take Profit = " + tostring(shortTake1Price)
precoentrada = "Entrada = " + tostring(strategy.position_avg_price)

var label FinalLabelpriceL = na
var label FinalLabelpriceS = na
var label slFinalLabelL = na
var label slFinalLabelS = na
var label slFinalLabelTPL = na
var label slFinalLabelTPS = na


//Draw entry and stop loss lines and labels

if strategy.position_size > 0   
    
    //write the price above the end of the stoploss line
    slFinalLabelL := label.new(bar_index, longStop, stopLossOnLong, style=label.style_none, size=size.normal, textcolor=color.red)
    slFinalLabelTPL := label.new(bar_index, longTake1Price, takeprofitOnLong, style=label.style_none, size=size.normal, textcolor=color.green)
    FinalLabelpriceL := label.new(bar_index, strategy.position_avg_price, precoentrada, style=label.style_none, size=size.normal, textcolor=color.blue)
    
    // Delete previous label when there is a consecutive new high, as there's no line plot in that case.
    if strategy.position_size > 0[1]
        label.delete(slFinalLabelL[1])
        label.delete(slFinalLabelTPL[1])
        label.delete(FinalLabelpriceL[1])

if strategy.position_size < 0   
    
    //write the price above the end of the stoploss line
    slFinalLabelS := label.new(bar_index, shortStop, stopLossOnShort, style=label.style_none, size=size.normal, textcolor=color.red)
    slFinalLabelTPS := label.new(bar_index, shortTake1Price, takeprofitOnShort, style=label.style_none, size=size.normal, textcolor=color.green)
    FinalLabelpriceS := label.new(bar_index, strategy.position_avg_price, precoentrada, style=label.style_none, size=size.normal, textcolor=color.blue)
    
    // Delete previous label when there is a consecutive new high, as there's no line plot in that case.
    if strategy.position_size < 0[1]
        label.delete(slFinalLabelS[1])
        label.delete(slFinalLabelTPS[1]) 
        label.delete(FinalLabelpriceS[1])

    
// Exit open market position when date range ends
if (not _inDateRange)
    strategy.close_all()

Больше