이중 지표 하이브리드 양적 거래 전략

저자:차오장, 날짜: 2023-12-20 10:31:06
태그:

img

전반적인 설명

이 전략은 트렌드 방향을 파악하고 거래를 수행하기 위해 이중 지표를 결합합니다. 첫째, 단기 트렌드를 판단하기 위해 두 이동 평균 (고속 및 중) 의 교차를 사용합니다. 둘째, 채널 범위와 장기 이동 평균을 사용하여 주요 트렌드 방향을 결정합니다. 두 판단이 일관 할 때만 거래 신호가 생성됩니다. 여러 지표를 사용하는 하이브리드 전략은 잘못된 신호를 효과적으로 필터링하고 안정성을 향상시킬 수 있습니다.

전략 원칙

이 전략은 판단을 위해 세 개의 세트를 사용합니다. 첫째, 단기 트렌드를 결정하기 위해 빠른 EMA (26 기간) 과 중간의 EMA (50 기간) 의 황금 십자 및 죽음의 십자; 둘째, 중기 트렌드를 판단하기 위해 채널 범위를 계산; 마지막으로, 장기 SMA (200 기간) 를 계산하고 주요 트렌드 방향을 결정하기 위해 가격과 비교하십시오. 세 가지 판단이 일관 될 때만 거래 신호가 생성됩니다.

구체적으로, 논리는 다음과 같습니다.

  1. 단기 트렌드를 결정하기 위해 빠른 평균과 중간 이동 평균의 크로스 오버 (부시의 황금 십자, 하락의 죽음의 십자).

  2. 중장기 트렌드를 결정하기 위해 가격이 채널 범위를 통과하는지 여부. 채널 범위는 장기 MA 더하기 / 마이너스 ATR 곱하기 계수를 기반으로합니다. 상위 한도를 깨는 신호는 상승하고, 하위 한도를 깨는 신호는 하락합니다.

  3. 주요 트렌드를 결정하기 위해 장기 MA와 가격을 비교합니다.

마지막으로, 거래 신호는 세 가지 판단이 일치 할 때만 생성됩니다. 이 하이브리드 메커니즘은 잘못된 신호를 효과적으로 필터하고 안정성을 향상시킬 수 있습니다.

전략적 장점

이 두 가지 지표의 하이브리드 전략은 몇 가지 장점을 가지고 있습니다.

  1. 잘못된 신호를 효과적으로 필터하고 안정성을 향상시킵니다. 거래 신호는 단일 메트릭에서 오류를 피하기 위해 여러 지표로부터 검증이 필요합니다.

  2. 다양한 시장에 대한 매개 변수를 조정하는 데 높은 유연성. MA와 채널 범위의 매개 변수는 다양한 환경에 맞게 조정할 수 있습니다.

  3. 트렌드 트레이딩과 범위 트레이딩을 결합합니다. 중장기 및 단기 지표는 트렌드를 잡으며 장기 지표는 범위를 결정합니다. 전반적으로 트렌드 및 평균 역전 전략의 장점을 가지고 있습니다.

  4. 높은 자본 사용 효율성. 여러 지표가 일치 할 때만 주문을하십시오. 불필요한 거래를 피하기 위해 자본이 효과적으로 사용될 수 있습니다.

전략 위험

또한 몇 가지 위험이 있습니다.

  1. 위험 설정 매개 변수: MA 기간 및 채널 범위는 적절한 구성이 필요합니다. 부적절한 설정은 트렌드를 감지하지 못하거나 과도한 잘못된 신호를 유발할 수 있습니다.

  2. 이중 지표의 기회 비용 증가 단일 지표 전략에 비해 최적의 지점에서 입출이 불가능하여 일부 거래 기회를 놓칠 수 있습니다.

  3. 스톱 로스 메커니즘은 신중해야 합니다. 여기서 브레이크 로스 (breakout stop loss) 는 불필요한 손실을 일으킬 수 있습니다. 스톱 로스 비율은 신중한 구성이 필요합니다.

  4. 매우 변동적인 시장에서 저조한 성과를 낼 수 있습니다. 이 전략은 명백한 추세를 보이는 시장에서 더 잘 작동합니다.

전략 최적화

이 전략은 다음과 같은 측면에서 개선될 수 있습니다.

  1. 다양한 매개 변수 조합을 테스트하여 최적을 찾습니다.

  2. 적응 스톱 손실 메커니즘을 추가합니다. 변동 지표에 기반한 스톱 손실 수준을 동적으로 조정합니다.

  3. 중요한 지점에서의 부피 지표에 도움을 주며 자본 효율을 높이기 위해 부피에 따라 포지션 크기를 판단합니다.

  4. 입시 논리를 최적화합니다. 단일 입시 위험을 줄이기 위해 비용 평균화와 단계적 입시를 고려하십시오.

  5. 기계 학습 모델을 결합하고, 모델의 견고성과 적합성을 판단하기 위해 신경망을 도입합니다.

요약

이 전략은 허위 신호를 억제하고 안정성을 향상시키기 위해 삼중 시간 프레임 지표와 이중 검증을 활용합니다. 한편, 높은 자본 사용 효율성을 갖춘 트렌드 및 범위 거래의 장점을 가지고 있습니다. 매개 변수 최적화, 스톱 로스 튜닝, 볼륨 지표와 통합 등을 통해 향상 될 수 있습니다. 권장 하이브리드 양적 전략.


/*backtest
start: 2023-11-19 00:00:00
end: 2023-12-19 00:00:00
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=5
// Indicator to combines:
//           Trend Channel[Gu5] (SMA 200) +
//           EMA's cross  (26, 50 ) +
//           Golden Cross (50, 200)
// Author: @gu5tavo71 08/2019
// v2.3.6, 2022.02.18
// Trend Channel [Gu5] // Author: @gu5tavo71 08/2019
//
// This source code is subject to these terms:
// Attribution-NonCommercial 4.0 International (CC BY-NC 4.0)
// https://www.safecreative.org/work/2202190517452-mix1-ema-cross-trend-channel-gu5-
// You are free to:
// Share, copy and redistribute this script
// Adapt, transform and build on this script
// Under the following terms:
// Non-commercial: You cannot sell my indicator. You can't sell my work.
// Attribution: If you post part of my code, you must give me proper credit
//
// I am using part of this code published by @PineCoders and Public Library
// Disclaimer: I am not a financial advisor.
//             For purpose educate only. Use at your own risk.
strategy(title = 'Mix1 : Ema Cross + Trend Channel [Gu5] - Backtest', shorttitle = 'Mix01', overlay = true,
  initial_capital = 100,
  default_qty_value = 100,
  default_qty_type = strategy.percent_of_equity,
  commission_value = 0.075,
  commission_type = strategy.commission.percent,
  format = format.price,
  precision = 2,
  process_orders_on_close = true)


// ---------   Inputs                       "=============================="           |
i_maSrc      = input.source     (close,     'MA Source'                     , group    = 'EMAs')
i_maFast1    = input.int        (26,        'EMA Fast'                      , group    = 'EMAs')
i_maFast2    = input.int        (50,        'EMA Medium'                    , group    = 'EMAs')
i_maLen      = input.int        (200,       'MA Trend'                      , group    = 'Trend Channel')
o_maLen1     =                              'EMA'
o_maLen2     =                              'SMA'
i_maLenSel   = input.string     (o_maLen2,  'MA Type'                       , group    = 'Trend Channel',
               options = [o_maLen1, o_maLen2],
               tooltip = "EMA or SMA")
i_htf        = input.timeframe  ('',        'Select Higher Timeframe'       , tooltip  = 'Only for MA Trend'  , group    = 'Trend Channel')
i_rangeLen   = input.float      (0.618,     'Channel Range Length'          , tooltip  = 'ATR of the MA Trend', group    = 'Trend Channel')
i_slOn       = input.bool       (false,     '■ Stop Loss On/Off'            , group    = 'Stop Loss')
i_sl         = input.float      (2.618,     'SL %'                          , step     = 0.1, group    = 'Stop Loss')
i_periodSw   = input.bool       (true,      '■ Period On/Off'               , group    = 'Period')
o_start      = timestamp        (           '2020-01-01 00:00 GMT-3'        )
o_end        = timestamp        (           '2099-12-31 00:00 GMT-3'        )
i_periodStar = input       (o_start,   'Start Time'                    , group    = 'Period')
i_periodEnd  = input       (o_end,     'End Time'                      , group    = 'Period')
o_posSel1    =                              'Only Long'
o_posSel2    =                              'Only Short'
o_posSel3    =                              'Both'
i_posSel     = input.string     (o_posSel3, 'Position Type'                 , group   = 'Strategy',
               options = [o_posSel1, o_posSel2, o_posSel3],
               tooltip = "Only Long, Only short or Both")
o_typeS1     =                              'Strategy 1'
o_typeS2     =                              'Strategy 2'
i_typeS      = input.string     (o_typeS2,  'Strategy Type'                 , group   = 'Strategy',
               options = [o_typeS1, o_typeS2],
               tooltip = "Strategy 1:\nLong, when the price (close) crosses the ema.\nStrategy 2:\nLong, only when ema goes up")
i_barColOn   = input.bool       (true,      '■ Bar Color On/Off'            , group   = 'Display')
i_alertOn    = input.bool       (false,     '■ Alert On/Off'                , group   = 'Display')
i_channelOn  = input.bool       (false,     '■ Channel Range On/Off'        , tooltip = 'If the price (close) is over than the channel, the trend is bullish. If the price is under, bearish. And if the price is in the channel, it is in range', group   = 'Display')
i_goldenOn   = input.bool       (false,     '■ Golden Cross On/Off'         )
o_alert      =                              '{{strategy.order.comment}}'
i_alert      = input.string     (o_alert,   'Setting alert'                 , tooltip = 'For Alerts, just copy {{strategy.order.comment}} and paste in alert window.', group   = 'Display')

// ---------   Calculations
maFast1      = ta.ema(i_maSrc, i_maFast1)
maFast2      = ta.ema(i_maSrc, i_maFast2)
maDir        = maFast1 > maFast2 ? 1 : -1
maTrend      = request.security(syminfo.tickerid, i_htf,
               i_maLenSel == "SMA" ? ta.sma(close, i_maLen)[1] : ta.ema(close, i_maLen)[1],
               lookahead = barmerge.lookahead_on)  //No repaint
maTrendDir   = i_maSrc >= maTrend ? 1 : -1
rangeAtr     = ta.atr(i_maLen) * i_rangeLen
rangeTop     = maTrend + rangeAtr
rangeBot     = maTrend - rangeAtr
rangeCh      = (open <= rangeTop or close <= rangeTop) and
               (open >= rangeBot or close >= rangeBot)
trendDir     = i_typeS  ==  'Strategy 1'                            ?
               rangeCh                                                ?  0 :
               maTrendDir ==  1 and maDir ==  1 and maTrend > maFast2 ?  0 :
               maTrendDir == -1 and maDir == -1 and maTrend < maFast2 ?  0 :
               maTrendDir ==  1 and maDir ==  1                       ?  1 :
               maTrendDir == -1 and maDir == -1                       ? -1 : 0 :
               rangeCh                                                ?  0 :
               maTrendDir ==  1 and maDir ==  1                       ?  1 :
               maTrendDir == -1 and maDir == -1                       ? -1 : 0
GCross       = i_goldenOn ? ta.crossover (maFast2, maTrend) : na
DCross       = i_goldenOn ? ta.crossunder(maFast2, maTrend) : na

period       = true
// Set initial values
condition    = 0.0
entryLong    = trendDir ==  1 and
               i_posSel != 'Only Short' and
               (i_periodSw ? period : true)
entryShort   = trendDir == -1 and
               i_posSel != 'Only Long' and
               (i_periodSw ? period : true)
exitLong     = (trendDir !=  1 or maDir == -1) and
               condition[1] == 1 and 
               i_posSel != 'Only Short' and
               (i_periodSw ? period : true)
exitShort    = (trendDir != -1 or maDir ==  1) and
               condition[1] == -1 and
               i_posSel != 'Only Long' and
               (i_periodSw ? period : true)
closeCond    = exitLong or exitShort
// Stop Loss (sl)
slEntry      = close * i_sl / 100
slTop        = close + slEntry
slBot        = close - slEntry
slTopBuff    = ta.valuewhen(condition[1] !=  1 and entryLong,  slBot, 0)
slBotBuff    = ta.valuewhen(condition[1] != -1 and entryShort, slTop, 0)
slLine       = condition[1] == -1 and entryLong  ? slTopBuff :
               condition[1] ==  1 and entryShort ? slBotBuff :
               condition[1] ==  1  or entryLong  ? slTopBuff :
               condition[1] == -1  or entryShort ? slBotBuff : na
slTopCross   = condition[1] ==  1 and ta.crossunder(close, slLine) or high > slLine and low < slLine
slBotCross   = condition[1] == -1 and ta.crossover (close, slLine) or high > slLine and low < slLine
slExit       = i_slOn ? slTopCross or slBotCross : na
// Conditions
condition   := condition[1] !=  1 and entryLong  ?  1 :
               condition[1] != -1 and entryShort ? -1 :
               condition[1] !=  0 and slExit     ?  0 :
               condition[1] !=  0 and exitLong   ?  0 :
               condition[1] !=  0 and exitShort  ?  0 : nz(condition[1])
long         = condition[1] !=  1 and condition ==  1
short        = condition[1] != -1 and condition == -1
xl           = condition[1] ==  1 and exitLong and not slExit
xs           = condition[1] == -1 and exitShort and not slExit
sl           = condition[1] !=  0 and slExit

// ---------   Colors
c_green      = #006400  //Green
c_greenLight = #388e3c  //Green Light
c_red        = #8B0000  //Red
c_redLight   = #b71c1c  //Red Light
c_emas       = xl                             ? color.new(color.orange, 99) :
               xs                             ? color.new(color.orange, 99) :
               trendDir ==  1 and maDir ==  1 ? color.new(c_green,      99) :
               trendDir == -1 and maDir == -1 ? color.new(c_red,        99) :
               color.new(color.orange, 99)
c_maFill     = xl                             ? color.new(color.orange, 70) :
               xs                             ? color.new(color.orange, 70) :
               trendDir ==  1 and maDir ==  1 ? color.new(c_green,      70) :
               trendDir == -1 and maDir == -1 ? color.new(c_red,        70) :
               color.new(color.orange, 70)
c_maTrend    = trendDir ==  0                           ? color.new(color.orange,  0) :
               trendDir ==  1 and maTrend[1]  < maTrend ? color.new(c_green,       0) :
               trendDir ==  1 and maTrend[1] >= maTrend ? color.new(c_greenLight,  0) :
               trendDir == -1 and maTrend[1]  < maTrend ? color.new(c_redLight,    0) :
               trendDir == -1 and maTrend[1] >= maTrend ? color.new(c_red,         0) : na
c_ch         = trendDir ==  0                           ? color.new(color.orange, 50) :
               trendDir ==  1                           ? color.new(c_green,      50) :
               trendDir == -1                           ? color.new(c_red,        50) : na
c_slLineUp   = ta.rising (slLine, 1)
c_slLineDn   = ta.falling(slLine, 1)
c_slLine     = c_slLineUp ? na :
               c_slLineDn ? na : color.red
c_barCol     = trendDir ==  0                   ? color.new(color.orange,  0) :
               trendDir ==  1 and open <= close ? color.new(c_green,       0) :
               trendDir ==  1 and open  > close ? color.new(c_greenLight,  0) :
               trendDir == -1 and open >= close ? color.new(c_red,         0) :
               trendDir == -1 and open  < close ? color.new(c_redLight,    0) :
               color.new(color.orange, 0)

// ---------   Plots
p_maFast1    = plot(
  maFast1,
  title      = 'EMA Fast 1',
  color      = c_emas,
  linewidth  = 1)
p_maFast2    = plot(
  maFast2,
  title      = 'EMA Fast 2',
  color      = c_emas,
  linewidth  = 2)
fill(
  p_maFast1, p_maFast2,
  title      = 'EMAs Fill',
  color      = c_maFill)
plot(
  maTrend,
  title      = 'SMA Trend',
  color      = c_maTrend,
  linewidth  = 3)
p_chTop      = plot(
  i_channelOn   ? rangeTop : na,
  title      = 'Top Channel',
  color      = c_maTrend,
  linewidth  = 1)
p_chBot      = plot(
  i_channelOn   ? rangeBot : na,
  title      = 'Bottom Channel',
  color      = c_maTrend,
  linewidth  = 1)
fill(
  p_chTop, p_chBot,
  title      = 'Channel',
  color      = c_ch)
plot(
  i_slOn and condition != 0 ? slLine : na,
  title      = 'Stop Loss Line',
  color      = c_slLine,
  linewidth  = 1,
  style      = plot.style_linebr)

// ---------   Alerts
barcolor(i_barColOn ? c_barCol : na)

plotshape(
  i_alertOn and long ? high : na,
  title      = 'Long Label',
  text       = 'Long',
  textcolor  = color.white,
  color      = color.new(c_green, 0),
  style      = shape.labelup,
  size       = size.normal,
  location   = location.belowbar)
plotshape(
  i_alertOn and short ? low : na,
  title      = 'Short Label',
  text       = 'Short',
  textcolor  = color.white,
  color      = color.new(c_red, 0),
  style      = shape.labeldown,
  size       = size.normal,
  location   = location.abovebar)
plotshape(
  i_alertOn and (xl or xs) ? close : na,
  title      = 'Close Label',
  text       = 'Close',
  textcolor  = color.orange,
  color      = color.new(color.orange, 0),
  style      = shape.xcross,
  size       = size.small,
  location   = location.absolute)
plotshape(
  i_alertOn and sl ? slLine : na,
  title      = 'Stop Loss',
  text       = 'Stop\nLoss',
  textcolor  = color.orange,
  color      = color.new(color.orange, 0),
  style      = shape.xcross,
  size       = size.small,
  location   = location.absolute)
plotshape(
  i_alertOn and i_goldenOn and GCross ? maTrend : na,
  title      = 'Golden Cross Label',
  text       = 'Golden\nCross',
  textcolor  = color.white,
  color      = color.new(color.orange, 0),
  style      = shape.labelup,
  size       = size.normal,
  location   = location.absolute)
plotshape(
  i_alertOn and i_goldenOn and DCross ? maTrend : na,
  title      = 'Death Cross Label',
  text       = 'Death\nCross',
  textcolor  = color.white,
  color      = color.new(color.orange, 0),
  style      = shape.labeldown,
  size       = size.normal,
  location   = location.absolute)

bgcolor(
  i_periodSw and not period ? color.new(color.gray, 90) : na,
  title      = 'Session')

// ---------   Backtest
if long  and strategy.position_size == 0 and barstate.isconfirmed
    strategy.entry('Long',  strategy.long,  comment = 'long')
if short and strategy.position_size == 0 and barstate.isconfirmed
    strategy.entry('Short', strategy.short, comment = 'short')
strategy.exit(
  id         = 'XL',
  from_entry = 'Long',
  stop       = i_slOn ? slLine : na)
strategy.exit(
  id         = 'XS',
  from_entry = 'Short',
  stop       = i_slOn ? slLine : na)
strategy.close(
  'Long',
  comment    = 'Close',
  when       = xl)
strategy.close(
  'Short',
  comment    = 'Close',
  when = xs)

더 많은