Estratégia de média móvel estocástica

Autora:ChaoZhang, Data: 2023-12-19 11:41:40
Tags:

img

Resumo

Esta estratégia combina a média móvel exponencial (EMA) com o oscilador estocástico de uma forma de tendência e continuação, juntamente com algumas funcionalidades interessantes.

Estratégia lógica

A estratégia tem 4 condições obrigatórias para desbloquear um sinal de negociação.

  • A EMA rápida deve ser superior à EMA lenta
  • A linha estocástica K% deve estar no território de sobrecompra
  • A linha estocástica K% deve atravessar a linha estocástica D%
  • Preço de fechamento entre a EMA lenta e a EMA rápida Uma vez que todas as condições são verdadeiras, uma negociação começará na abertura da próxima vela.

Análise das vantagens

A estratégia combina as vantagens da EMA e do Estocástico para capturar efetivamente o início e a continuação das tendências, adequado para operações de médio e longo prazo.

Em especial, as vantagens da estratégia incluem:

  1. As passagens da EMA julgam a direcção da tendência e aumentam a estabilidade e a fiabilidade do sinal
  2. Os juízes estocásticos sobrecompraram e sobrevenderam níveis para encontrar oportunidades de reversão
  3. Combinando dois indicadores, tem tanto a tendência seguindo como a reversão média
  4. ATR calcula automaticamente a distância de stop loss, ajustando as paradas com base na volatilidade do mercado
  5. Relatório de risco-recompensa personalizável para satisfazer as necessidades de diferentes utilizadores
  6. Fornece múltiplos parâmetros personalizáveis para os utilizadores ajustarem com base nos mercados

Análise de riscos

Os principais riscos desta estratégia são:

  1. As passagens da EMA podem ter falhas de travagem, gerando assim sinais incorretos
  2. O próprio estocástico tem propriedades de atraso, pode perder o melhor momento para reversões de preços
  3. Uma única estratégia não pode adaptar-se plenamente a um ambiente de mercado em constante mudança

Para mitigar os riscos acima mencionados, podemos tomar as seguintes medidas:

  1. Ajustar os parâmetros do período EMA para evitar muitos sinais falsos
  2. Incorporar mais indicadores para avaliar as tendências e os níveis de apoio para garantir sinais fiáveis
  3. Definir estratégias claras de gestão de fundos para controlar a exposição ao risco por transação
  4. Adotar estratégias combinadas para que diferentes estratégias possam verificar os sinais e melhorar a estabilidade

Orientações de otimização

A estratégia pode ser ainda melhorada nos seguintes aspectos:

  1. Adicione o módulo de ajustamento de posição baseado em volatilidade, reduza o tamanho quando a volatilidade aumenta e aumenta quando se acalma.
  2. Adicionar o julgamento das tendências de prazo mais longo para evitar operações contrárias à tendência, por exemplo, combinando tendências diárias ou semanais.
  3. Adicionar modelos de aprendizagem de máquina para ajudar a geração de sinal.
  4. Otimizar os módulos de gestão de dinheiro para tornar as paradas e os tamanhos mais inteligentes.

Conclusão

Esta estratégia integra os prós de ambos tendência seguindo e média de reversão, considerando ambos os ambientes de mercado de maior prazo e comportamentos de preços atuais. É uma estratégia eficaz vale a pena rastreamento e teste em tempo real. Através da otimização contínua em parâmetros, adicionando módulos de julgamento de tendência, etc, ainda há um grande espaço para melhoria do desempenho, vale a pena derramar mais esforços de pesquisa.


/*backtest
start: 2023-11-18 00:00:00
end: 2023-12-18 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/
// © LucasVivien

// Since this Strategy may have its stop loss hit within the opening candle, consider turning on 'Recalculate : After Order is filled' in the strategy settings, in the "Properties" tabs

//@version=5
strategy("Stochastic Moving Average", shorttitle="Stoch. EMA", overlay=true, default_qty_type= strategy.cash, initial_capital=10000, default_qty_value=100)

//==============================================================================
//==============================   USER INPUT   ================================
//==============================================================================

var g_tradeSetup = "     Trade Setup"
activateLongs  = input.bool (title="Long Trades"        , defval=true                                       , inline="A1", group=g_tradeSetup, tooltip="")
activateShorts = input.bool (title="Short Trades"       , defval=true                                       , inline="A1", group=g_tradeSetup, tooltip="")
rr             = input.float(title="Risk : Reward"      , defval=1   , minval=0, maxval=100       , step=0.1, inline=""  , group=g_tradeSetup, tooltip="")
RiskEquity     = input.bool (title="Risk = % Equity    ", defval=false                                      , inline="A2", group=g_tradeSetup, tooltip="Set stop loss size as a percentage of 'Initial Capital' -> Strategy Parameter -> Properties tab (Low liquidity markets will affect will prevent to get an exact amount du to gaps)")
riskPrctEqui   = input.float(title=""                   , defval=1   , minval=0, maxval=100       , step=0.1, inline="A2", group=g_tradeSetup, tooltip="")
RiskUSD        = input.bool (title="Risk = $ Amount   " , defval=false                                      , inline="A3", group=g_tradeSetup, tooltip="Set stop loss size as a fixed Base currency amount (Low liquidity markets will affect will prevent to get an exact amount du to gaps)")
riskUSD        = input.float(title=""                   , defval=1000, minval=0, maxval=1000000000, step=100, inline="A3", group=g_tradeSetup, tooltip="")

var g_stopLoss = "     Stop Loss"
atrMult = input.float(title="ATR Multiplier", defval=1 , minval=0, maxval=100 , step=0.1, tooltip="", inline="", group=g_stopLoss)
atrLen  = input.int  (title="ATR Lookback"  , defval=14, minval=0, maxval=1000, step=1  , tooltip="", inline="", group=g_stopLoss)

var g_stochastic = "     Stochastic"
Klen            = input.int  (title="K%"                   , defval=14, minval=0, maxval=1000, step=1, inline="S2", group=g_stochastic, tooltip="")
Dlen            = input.int  (title=" D%"                  , defval=3 , minval=0, maxval=1000, step=1, inline="S2", group=g_stochastic, tooltip="")
OBstochLvl      = input.int  (title="OB"                   , defval=80, minval=0, maxval=100 , step=1, inline="S1", group=g_stochastic, tooltip="")
OSstochLvl      = input.int  (title=" OS"                  , defval=20, minval=0, maxval=100 , step=1, inline="S1", group=g_stochastic, tooltip="")
OBOSlookback    = input.int  (title="Stoch. OB/OS lookback", defval=0 , minval=0, maxval=100 , step=1, inline=""  , group=g_stochastic, tooltip="This option allow to look 'x' bars back for a value of the Stochastic K line to be overbought or oversold when detecting an entry signal (if 0, looks only at current bar. if 1, looks at current and previous and so on)")
OBOSlookbackAll = input.bool (title="All must be OB/OS"    , defval=false                            , inline=""  , group=g_stochastic, tooltip="If turned on, all bars within the Stochastic K line lookback period must be overbought or oversold to return a true signal")
entryColor      = input.color(title="   "                  , defval=#00ffff                          , inline="S3", group=g_stochastic, tooltip="")
baseColor       = input.color(title="  "                   , defval=#333333                          , inline="S3", group=g_stochastic, tooltip="Will trun to designated color when stochastic gets to opposite extrem zone of current trend / Number = transparency")
transp          = input.int  (title="   "                  , defval=50, minval=0, maxval=100, step=10, inline="S3", group=g_stochastic, tooltip="")

var g_ema = "     Exp. Moving Average"
ema1len = input.int  (title="Fast EMA     ", defval=21, minval=0, maxval=1000, step=1, inline="E1", group=g_ema, tooltip="")
ema2len = input.int  (title="Slow EMA     ", defval=50, minval=0, maxval=1000, step=1, inline="E2", group=g_ema, tooltip="")
ema1col = input.color(title="     "        , defval=#0066ff                          , inline="E1", group=g_ema, tooltip="")
ema2col = input.color(title="     "        , defval=#0000ff                          , inline="E2", group=g_ema, tooltip="")

var g_referenceMarket ="     Reference Market"
refMfilter = input.bool     (title="Reference Market Filter", defval=false            , inline="", group=g_referenceMarket)
market     = input   (title="Market"                 , defval="BTC_USDT:swap", inline="", group=g_referenceMarket)
res        = input.timeframe(title="Timeframe"              , defval="30"             , inline="", group=g_referenceMarket)
len        = input.int      (title="EMA Length"             , defval=50               , inline="", group=g_referenceMarket)


//==============================================================================
//==========================   FILTERS & SIGNALS   =============================
//==============================================================================

//------------------------------   Stochastic   --------------------------------
K = ta.stoch(close, high, low, Klen)
D = ta.sma(K, Dlen)
stochBullCross = ta.crossover(K, D)
stochBearCross = ta.crossover(D, K)
OSstoch = false
OBstoch = false
for i = 0 to OBOSlookback
    if K[i] < OSstochLvl
        OSstoch := true
    else 
        if OBOSlookbackAll
            OSstoch := false
for i = 0 to OBOSlookback
    if K[i] > OBstochLvl
        OBstoch := true
    else 
        if OBOSlookbackAll
            OBstoch := false

//----------------------------   Moving Averages   -----------------------------
ema1 = ta.ema(close, ema1len)
ema2 = ta.ema(close, ema2len)
emaBull = ema1 > ema2
emaBear = ema1 < ema2

//----------------------------   Price source   --------------------------------
bullRetraceZone = (close < ema1 and close >= ema2) 
bearRetraceZone = (close > ema1 and close <= ema2)

//---------------------------   Reference market   -----------------------------
ema      = ta.ema(close, len)
emaHTF   = request.security(market, res, ema  [barstate.isconfirmed ? 0 : 1])
closeHTF = request.security(market, res, close[barstate.isconfirmed ? 0 : 1])

bullRefMarket = (closeHTF > emaHTF or closeHTF[1] > emaHTF[1])
bearRefMarket = (closeHTF < emaHTF or closeHTF[1] < emaHTF[1])

//--------------------------   SIGNAL VALIDATION   -----------------------------
validLong  = stochBullCross and OSstoch and emaBull and bullRetraceZone 
 and activateLongs  and (refMfilter ? bullRefMarket : true) and strategy.position_size == 0
validShort = stochBearCross and OBstoch and emaBear and bearRetraceZone 
 and activateShorts and (refMfilter ? bearRefMarket : true) and strategy.position_size == 0


//==============================================================================
//===========================   STOPS & TARGETS   ==============================
//==============================================================================

SLdist      = ta.atr(atrLen) * atrMult
longSL      = close - SLdist
longSLDist  = close - longSL
longTP      = close + (longSLDist * rr)
shortSL     = close + SLdist
shortSLDist = shortSL - close
shortTP     = close - (shortSLDist * rr)
var SLsaved = 0.0
var TPsaved = 0.0
if validLong or validShort
    SLsaved := validLong ? longSL : validShort ? shortSL : na
    TPsaved := validLong ? longTP : validShort ? shortTP : na


//==============================================================================
//==========================   STRATEGY COMMANDS   =============================
//==============================================================================
 
if validLong 
    strategy.entry("Long", strategy.long, 
     qty = RiskEquity ? ((riskPrctEqui/100)*strategy.equity)/longSLDist : RiskUSD ? riskUSD/longSLDist : na)
if validShort 
    strategy.entry("Short", strategy.short, 
     qty = RiskEquity ? ((riskPrctEqui/100)*strategy.equity)/shortSLDist  : RiskUSD ? riskUSD/shortSLDist : na)

strategy.exit(id="Long Exit" , from_entry="Long" , limit=TPsaved, stop=SLsaved, when=strategy.position_size > 0)
strategy.exit(id="Short Exit", from_entry="Short", limit=TPsaved, stop=SLsaved, when=strategy.position_size < 0)


//==============================================================================
//=============================   CHART PLOTS   ================================
//==============================================================================
    
//----------------------------   Stops & Targets   -----------------------------
plot(strategy.position_size != 0 or (strategy.position_size[1] != 0 and strategy.position_size == 0) ? SLsaved : na,
 color=color.red  , style=plot.style_linebr)
plot(strategy.position_size != 0 or (strategy.position_size[1] != 0 and strategy.position_size == 0) ? TPsaved : na,
 color=color.green, style=plot.style_linebr) 

//---------------------------------   EMAs   -----------------------------------
l1 = plot(ema1, color=#0066ff, linewidth=2)
l2 = plot(ema2, color=#0000ff, linewidth=2)

//--------------------------   Stochastic gradient   ---------------------------
// fill(l1, l2, color.new(color.from_gradient(K, OSstochLvl, OBstochLvl,
//  emaBull ? entryColor : emaBear ? baseColor : na, 
//  emaBull ? baseColor  : emaBear ? entryColor : na), transp))
    
//----------------------------   Trading Signals   -----------------------------
plotshape(validLong, color=color.green, location=location.belowbar, style=shape.xcross, size=size.small)
plotshape(validShort, color=color.red , location=location.abovebar, style=shape.xcross, size=size.small)

//----------------------------   Reference Market   ----------------------------
bgcolor(bullRefMarket and refMfilter ? color.new(color.green,90) : na)
bgcolor(bearRefMarket and refMfilter ? color.new(color.red  ,90) : na)



Mais.