모멘텀 스토캐스틱 평활 이동 평균 전략


생성 날짜: 2023-12-19 11:41:40 마지막으로 수정됨: 2023-12-19 11:41:40
복사: 0 클릭수: 663
avatar of ChaoZhang ChaoZhang
1
집중하다
1621
수행원

모멘텀 스토캐스틱 평활 이동 평균 전략

개요

이 전략은 지수 이동 평균 (EMA) 과 무작위 지표 (Stochastic Oscillator) 을 결합하여 추세를 따라가고 지속하는 방식을 채택하고 있으며 몇 가지 멋진 기능이 있습니다. 나는 이 전략을 거래 대안 화폐를 위해 특별히 설계했지만, 비트코인 자체와 일부 외환 거래 쌍에도 적용됩니다.

전략 원칙

이 전략에는 4개의 거래 신호를 시작하는 필수 조건이 있다. 아래는 다중 거래를 시작하는 조건이다.

  • 빠른 EMA가 느린 EMA보다 높습니다.
  • 무작위 K선들은 과매매 구역에 있습니다.
  • 임의의 K 선은 임의의 D 선을 상향으로 가로질러
  • 가격이 느린 EMA와 빠른 EMA 사이에 닫히기

모든 조건이 참이라면, 다음 K 선이 열릴 때 포지션이 열립니다.

우위 분석

이 전략은 EMA와 무작위 지표의 장점을 결합하여 트렌드의 시작과 지속을 효과적으로 캡처 할 수 있으며 중장선 작업에 적합합니다. 전략은 사용자 자신의 거래 스타일과 시장 특성에 따라 조정할 수있는 다양한 사용자 정의 가능한 매개 변수를 제공합니다.

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

  1. EMA는 트렌드 방향을 교차하여 신호의 안정성과 신뢰성을 강화합니다.
  2. 무작위적인 지표로 과매매를 판단하고 역전 기회를 찾습니다.
  3. 두가지 지표가 결합되어 트렌드를 따라가는 것과 역동적인 거래가 있습니다.
  4. ATR은 자동으로 스톱로즈 거리를 계산하고, 스톱로즈는 시장의 변동성에 따라 조정됩니다.
  5. 사용자 정의 가능한 리스크/이익 비율, 다양한 사용자 요구에 맞게
  6. 다양한 변수 사용자 정의를 제공하여 사용자가 시장에 따라 조정할 수 있습니다.

위험 분석

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

  1. EMA 교차로 형성된 신호는 가짜 뚫림이 발생할 수 있으며, 이로 인해 잘못된 신호가 발생한다.
  2. 무작위 지표 자체는 지연되어 가격 반전의 최적의 시점을 놓칠 수 있습니다.
  3. 단일 전략은 시장의 변화된 환경에 완전히 적응할 수 없습니다.

위와 같은 위험을 줄이기 위해 다음과 같은 조치를 취할 수 있습니다.

  1. 과도한 가짜 신호를 방지하기 위해 EMA 주기 변수를 적절하게 조정합니다.
  2. 트렌드와 지지를 판단하는 더 많은 지표와 결합하여 거래 신호의 신뢰성을 보장합니다.
  3. 명확한 자금 관리 전략을 수립하고 거래마다 위험을 통제하십시오.
  4. 복합 전략으로, 서로 다른 전략이 서로 다른 신호를 검증하여 안정성을 높일 수 있습니다.

최적화 방향

이 전략은 다음의 몇 가지 측면에서 더 개선될 수 있습니다.

  1. 변동률에 기반한 포지션 조정 모듈을 추가한다. 시장의 변동이 심해지면 포지션을 적절히 줄이고, 변동이 약해지면 포지션을 확대한다.
  2. 대규모의 추세에 대한 판단을 높이고, 역행동을 피한다. 예를 들어, 매일 또는 주간 K선과 결합하여 추세 방향을 판단한다.
  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)