스토카스틱 이동 평균 전략

저자:차오장, 날짜: 2023-12-19 11:41:40
태그:

img

전반적인 설명

이 전략은 트렌드를 따라가며 계속되는 방식으로 기하급수적인 이동 평균 (EMA) 과 스토카스틱 오시레이터를 결합하고 몇 가지 멋진 기능과 함께합니다. 이 전략을 특히 altcoin 거래를 위해 설계했지만 Bitcoin 자체와 일부 Forex 쌍에서 똑같이 잘 작동합니다.

전략 논리

이 전략은 거래 신호를 잠금 해제하기 위해 4 가지 필수 조건이 있습니다. 아래의 긴 거래에 대한 이러한 조건을 찾으십시오 (단거리 거래에 대해 정확히 반대 방향으로 작동합니다)

  • 빠른 EMA는 느린 EMA보다 높아야 합니다.
  • 스토카스틱 K% 라인은 과잉 매입 영역에 있어야 합니다.
  • 스토카스틱 K% 라인은 스토카스틱 D% 라인을 넘어야 합니다.
  • 느린 EMA와 빠른 EMA 사이의 폐쇄 가격 모든 조건이 맞으면 다음 촛불을 열면 거래가 시작됩니다.

이점 분석

이 전략은 EMA와 스토카스틱의 장점을 결합하여 중장기 거래에 적합한 트렌드의 시작과 지속을 효과적으로 포착합니다. 동시에 전략은 사용자가 거래 스타일과 시장 특성에 따라 조정 할 수있는 많은 사용자 지정 매개 변수를 제공합니다.

특히 전략의 장점은 다음과 같습니다.

  1. EMA 교차로에서 트렌드 방향을 판단하고 신호 안정성과 신뢰성을 향상시킵니다.
  2. 스토카스틱 판사는 회전 기회를 찾기 위해 과소매와 과소매 수준을 높였습니다.
  3. 두 가지 지표를 결합하여, 트렌드와 평균 반전을 모두 나타냅니다.
  4. ATR은 자동으로 스톱 로스 거리를 계산하여 시장 변동성에 따라 스톱을 조정합니다.
  5. 각기 다른 사용자의 필요를 충족시키기 위해 조정 가능한 위험 보상 비율
  6. 사용자가 시장에 따라 조정할 수 있는 여러 가지 사용자 지정 매개 변수를 제공합니다.

위험 분석

이 전략의 주요 위험은 다음과 같습니다.

  1. EMA 교차로에는 잘못된 브레이크가 있을 수 있어 잘못된 신호가 발생한다.
  2. 스토카스틱 자체는 뒤떨어진 특성을 가지고 있으며, 가격 반전을위한 최고의 타이밍을 놓칠 수 있습니다.
  3. 단일 전략은 끊임없이 변화하는 시장 환경에 완전히 적응할 수 없습니다.

위의 위험을 줄이기 위해 다음의 조치를 취할 수 있습니다.

  1. 너무 많은 잘못된 신호를 피하기 위해 EMA 기간 매개 변수를 조정합니다.
  2. 신뢰성 있는 신호를 보장하기 위해 트렌드 및 지원 수준을 판단하기 위해 더 많은 지표를 포함
  3. 거래별로 위험 노출을 제어하기 위한 명확한 자금 관리 전략을 정의합니다.
  4. 다른 전략이 신호를 확인하고 안정성을 향상시킬 수 있도록 조합 전략을 채택하십시오.

최적화 방향

이 전략은 다음 측면에서 더 이상 최적화 될 수 있습니다.

  1. 변동성 기반 포지션 조정 모듈을 추가합니다. 변동성이 급증할 때 크기를 줄이고 평온할 때 크기를 증가시킵니다.
  2. 예를 들어 일일 또는 주간 트렌드를 결합하는 것과 같은 역 트렌드 거래를 피하기 위해 더 높은 시간 프레임 트렌드의 판단을 추가합니다.
  3. 신호 생성에 도움이 되는 기계 학습 모델을 추가합니다. 역사적인 데이터에 기반한 기차 분류 모델을 추가합니다.
  4. 금전 관리 모듈을 최적화하여 정류장과 크기를 더 지능화합니다.

결론

이 전략은 높은 시간 프레임 시장 환경과 현재 가격 행동 모두를 고려하여 트렌드 다음과 평균 반전의 장점을 통합합니다. 실시간 추적 및 테스트를 가치가있는 효과적인 전략입니다. 매개 변수에 대한 지속적인 최적화, 트렌드 판단 모듈 등을 추가함으로써 여전히 더 많은 연구 노력에 쏟아 부을 가치가있는 성능 향상에 큰 여지가 있습니다.


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



더 많은