동적 지지 및 저항과 볼린저 밴드 다중 지표 크로스오버 전략

SR BB EMA21 Pivot CROSS
생성 날짜: 2025-01-17 14:24:33 마지막으로 수정됨: 2025-01-17 14:24:33
복사: 1 클릭수: 427
avatar of ChaoZhang ChaoZhang
1
집중하다
1617
수행원

동적 지지 및 저항과 볼린저 밴드 다중 지표 크로스오버 전략

개요

이 전략은 역동적인 지지선과 저항선, 볼린저 밴드, EMA21 이동평균선을 결합한 다중 지표 크로스오버 거래 전략입니다. 이 전략은 기술 지표의 교차 신호와 결합하여 주요 가격 수준의 돌파구를 식별하여 거래 결정을 내립니다. 이 전략은 시장 구조에서 중요한 지지선과 저항선을 동적으로 식별할 수 있을 뿐만 아니라, 볼린저 밴드와 이동평균선을 조정하여 거래 신호의 신뢰성을 확인할 수도 있습니다.

전략 원칙

이 전략은 다음과 같은 핵심 구성 요소를 기반으로 합니다.

  1. 동적 지지 및 저항 계산: 피벗 포인트 방법을 사용하여 시장의 지지 및 저항 수준을 동적으로 계산하고, 채널 너비와 최소 강도 요구 사항을 설정하여 효과적인 가격 영역을 필터링합니다.
  2. 볼린저 밴드 지표: 20기간, 2표준편차의 볼린저 밴드를 사용하여 가격 변동 범위를 정의합니다.
  3. EMA21 이동평균선: 중기 추세 판단을 위한 기준선으로 사용됩니다.
  4. 거래 신호 생성: 가격이 지지선과 저항선을 돌파하고 볼린저 밴드 신호가 발동할 때 거래합니다.

전략적 이점

  1. 다차원 확인: 여러 기술 지표를 결합하여 거래 신호의 신뢰성을 향상시킵니다.
  2. 동적 적응: 지지 및 저항 수준은 시장 구조가 변화함에 따라 자동으로 조정됩니다.
  3. 위험 관리: 볼린저 밴드는 매수 과다와 매도 과다 영역을 명확하게 정의해줍니다.
  4. 추세 확인: EMA21 이동 평균선은 중기 추세 방향을 확인하는 데 도움이 됩니다.
  5. 시각화: 전략은 쉬운 분석과 최적화를 위해 명확한 시각적 피드백을 제공합니다.

전략적 위험

  1. 변동성이 큰 시장의 위험: 횡보장이고 변동성이 큰 시장에서는 잘못된 돌파 신호가 너무 많이 생성될 수 있습니다.
  2. 지연 위험: 기술적 지표 계산에는 어느 정도 지연이 발생하며, 최적의 진입 기회를 놓칠 수 있습니다.
  3. 매개변수 민감도: 전략의 효과는 매개변수 설정에 따라 달라지며 다양한 시장 환경에 맞게 최적화되어야 합니다.
  4. 거짓 돌파 위험: 지지 또는 저항 수준의 돌파는 거짓 돌파일 수 있으며, 다른 지표의 확인이 필요합니다.

전략 최적화 방향

  1. 볼륨 지표 소개: 돌파구를 확인할 때 볼륨 분석을 추가하여 신호의 신뢰성을 개선합니다.
  2. 매개변수 적응 최적화: 전략이 다양한 시장 환경에 더 잘 적응할 수 있도록 적응형 매개변수 조정 메커니즘을 개발합니다.
  3. 손절매 메커니즘 추가: 하락 위험을 통제하기 위해 보다 완벽한 손절매 전략을 설계합니다.
  4. 트렌드 필터링 추가: 트렌드 강도에 대한 판단력을 높이고 약한 트렌드 환경에서의 거래를 피하세요.
  5. 시간 프레임 최적화: 다양한 시간 프레임 조합의 효과를 연구하여 최적의 구성을 찾습니다.

요약하다

이 전략은 동적 지지선과 저항선, 볼린저 밴드, EMA21 이동평균선을 결합하여 비교적 완전한 거래 시스템을 구축합니다. 이 전략의 장점은 다차원적인 신호 확인과 시장 변화에 대한 역동적인 적응에 있지만, 매개변수 최적화와 거짓 돌파구의 위험도 있습니다. 지속적으로 위험 관리 메커니즘을 최적화하고 개선함으로써 이 전략은 실제 거래에서 더 나은 성과를 달성할 것으로 기대됩니다.

전략 소스 코드
//@version=5
strategy("Support Resistance & Bollinger & EMA21", overlay=true)

// Parámetros de S/R
prd = input.int(defval=10, title='Pivot Period', minval=4, maxval=30, group='Setup')
ppsrc = input.string(defval='High/Low', title='Source', options=['High/Low', 'Close/Open'], group='Setup')
maxnumpp = input.int(defval=20, title='Maximum Number of Pivot', minval=5, maxval=100, group='Setup')
ChannelW = input.int(defval=10, title='Maximum Channel Width %', minval=1, group='Setup')
maxnumsr = input.int(defval=5, title='Maximum Number of S/R', minval=1, maxval=10, group='Setup')
min_strength = input.int(defval=2, title='Minimum Strength', minval=1, maxval=10, group='Setup')
labelloc = input.int(defval=20, title='Label Location', group='Colors', tooltip='Positive numbers reference future bars, negative numbers reference historical bars')
linestyle = input.string(defval='Solid', title='Line Style', options=['Solid', 'Dotted', 'Dashed'], group='Colors')
linewidth = input.int(defval=2, title='Line Width', minval=2, maxval=2, group='Colors')
resistancecolor = input.color(defval=color.black, title='Resistance Color', group='Colors')
supportcolor = input.color(defval=color.black, title='Support Color', group='Colors')
showpp = input(false, title='Show Point Points')

// Parámetros de Bandas de Bollinger y EMA21
periodo_bollinger = input.int(title="Periodo de Bollinger", defval=20)
multiplicador_bollinger = input.float(title="Multiplicador de Bollinger", defval=2.0)
periodo_ema21 = input.int(title="Periodo EMA21", defval=21)

// Cálculo de las Bandas de Bollinger y EMA21
[middle, superior, inferior] = ta.bb(close, periodo_bollinger, multiplicador_bollinger)
ema21 = ta.ema(close, periodo_ema21)

// Ploteo de las Bandas de Bollinger y EMA21
plot(middle, color=color.rgb(60, 60, 60), linewidth=2, title="Media Móvil de Bollinger")
plot(superior, color=color.rgb(184, 11, 8), linewidth=2, title="Banda Superior")
plot(inferior, color=color.rgb(6, 124, 4), linewidth=2, title="Banda Inferior")
plot(ema21, color=color.rgb(6, 150, 240), linewidth=1, style=plot.style_circles, title="EMA21")

// Condiciones para señales de compra y venta
senal_compra = close <= inferior
senal_venta = close >= superior

// Mostrar señales en el gráfico
plotshape(senal_compra, title="Compra", location=location.belowbar, color=color.green, style=shape.labelup, text="BUY")
plotshape(senal_venta, title="Venta", location=location.abovebar, color=color.red, style=shape.labeldown, text="SELL")

// Código de soporte y resistencia
float src1 = ppsrc == 'High/Low' ? high : math.max(close, open)
float src2 = ppsrc == 'High/Low' ? low : math.min(close, open)
float ph = ta.pivothigh(src1, prd, prd)
float pl = ta.pivotlow(src2, prd, prd)

plotshape(ph and showpp, text='H', style=shape.labeldown, color=na, textcolor=color.new(color.red, 0), location=location.abovebar, offset=-prd)
plotshape(pl and showpp, text='L', style=shape.labelup, color=na, textcolor=color.new(color.lime, 0), location=location.belowbar, offset=-prd)

// Calcular ancho máximo del canal S/R
prdhighest = ta.highest(300)
prdlowest = ta.lowest(300)
cwidth = (prdhighest - prdlowest) * ChannelW / 100

var pivotvals = array.new_float(0)

if ph or pl
    array.unshift(pivotvals, ph ? ph : pl)
    if array.size(pivotvals) > maxnumpp  // Limitar el tamaño del array
        array.pop(pivotvals)

get_sr_vals(ind) =>
    float lo = array.get(pivotvals, ind)
    float hi = lo
    int numpp = 0
    for y = 0 to array.size(pivotvals) - 1 by 1
        float cpp = array.get(pivotvals, y)
        float wdth = cpp <= lo ? hi - cpp : cpp - lo
        if wdth <= cwidth  // Ajusta al ancho máximo del canal?
            if cpp <= hi
                lo := math.min(lo, cpp)
            else
                hi := math.max(hi, cpp)
            numpp += 1
    [hi, lo, numpp]

var sr_up_level = array.new_float(0)
var sr_dn_level = array.new_float(0)
sr_strength = array.new_float(0)

find_loc(strength) =>
    ret = array.size(sr_strength)
    for i = ret > 0 ? array.size(sr_strength) - 1 : na to 0 by 1
        if strength <= array.get(sr_strength, i)
            break
        ret := i
    ret

check_sr(hi, lo, strength) =>
    ret = true
    for i = 0 to array.size(sr_up_level) > 0 ? array.size(sr_up_level) - 1 : na by 1
        if array.get(sr_up_level, i) >= lo and array.get(sr_up_level, i) <= hi or array.get(sr_dn_level, i) >= lo and array.get(sr_dn_level, i) <= hi
            if strength >= array.get(sr_strength, i)
                array.remove(sr_strength, i)
                array.remove(sr_up_level, i)
                array.remove(sr_dn_level, i)
                ret
            else
                ret := false
            break
    ret

// var sr_lines = array.new_line(11, na)
// var sr_labels = array.new_label(11, na)

// for x = 1 to 10 by 1
//     rate = 100 * (label.get_y(array.get(sr_labels, x)) - close) / close
//     label.set_text(array.get(sr_labels, x), text=str.tostring(label.get_y(array.get(sr_labels, x))) + '(' + str.tostring(rate, '#.##') + '%)')
//     label.set_x(array.get(sr_labels, x), x=bar_index + labelloc)
//     label.set_color(array.get(sr_labels, x), color=label.get_y(array.get(sr_labels, x)) >= close ? color.red : color.lime)
//     label.set_textcolor(array.get(sr_labels, x), textcolor=label.get_y(array.get(sr_labels, x)) >= close ? color.white : color.black)
//     label.set_style(array.get(sr_labels, x), style=label.get_y(array.get(sr_labels, x)) >= close ? label.style_label_down : label.style_label_up)
//     line.set_color(array.get(sr_lines, x), color=line.get_y1(array.get(sr_lines, x)) >= close ? resistancecolor : supportcolor)

if ph or pl
    // Debido a los nuevos cálculos, eliminar niveles S/R antiguos
    array.clear(sr_up_level)
    array.clear(sr_dn_level)
    array.clear(sr_strength)
    // Encontrar zonas S/R
    for x = 0 to array.size(pivotvals) - 1 by 1
        [hi, lo, strength] = get_sr_vals(x)
        if check_sr(hi, lo, strength)
            loc = find_loc(strength)
            // Si la fuerza está en los primeros maxnumsr sr, entonces insértala en los arrays
            if loc < maxnumsr and strength >= min_strength
                array.insert(sr_strength, loc, strength)
                array.insert(sr_up_level, loc, hi)
                array.insert(sr_dn_level, loc, lo)
                // Mantener el tamaño de los arrays = 5
                if array.size(sr_strength) > maxnumsr
                    array.pop(sr_strength)
                    array.pop(sr_up_level)
                    array.pop(sr_dn_level)

    // for x = 1 to 10 by 1
    //     line.delete(array.get(sr_lines, x))
    //     label.delete(array.get(sr_labels, x))

    for x = 0 to array.size(sr_up_level) > 0 ? array.size(sr_up_level) - 1 : na by 1
        float mid = math.round_to_mintick((array.get(sr_up_level, x) + array.get(sr_dn_level, x)) / 2)
        rate = 100 * (mid - close) / close
        // array.set(sr_labels, x + 1, label.new(x=bar_index + labelloc, y=mid, text=str.tostring(mid) + '(' + str.tostring(rate, '#.##') + '%)', color=mid >= close ? color.red : color.lime, textcolor=mid >= close ? color.white : color.black, style=mid >= close ? label.style_label_down : label.style_label_up))
        // array.set(sr_lines, x + 1, line.new(x1=bar_index, y1=mid, x2=bar_index - 1, y2=mid, extend=extend.both, color=mid >= close ? resistancecolor : supportcolor, style=line.style_solid, width=2))

f_crossed_over() =>
    ret = false
    for x = 0 to array.size(sr_up_level) > 0 ? array.size(sr_up_level) - 1 : na by 1
        float mid = math.round_to_mintick((array.get(sr_up_level, x) + array.get(sr_dn_level, x)) / 2)
        if close[1] <= mid and close > mid
            ret := true
    ret

f_crossed_under() =>
    ret = false
    for x = 0 to array.size(sr_up_level) > 0 ? array.size(sr_up_level) - 1 : na by 1
        float mid = math.round_to_mintick((array.get(sr_up_level, x) + array.get(sr_dn_level, x)) / 2)
        if close[1] >= mid and close < mid
            ret := true
    ret

crossed_over = f_crossed_over()
crossed_under = f_crossed_under()
alertcondition(crossed_over, title='Resistance Broken', message='Resistance Broken')
alertcondition(crossed_under, title='Support Broken', message='Support Broken')
alertcondition(crossed_over or crossed_under, title='Support or Resistance Broken', message='Support or Resistance Broken')

// Estrategia de compra y venta basada en el cruce de niveles S/R
if (crossed_over and senal_compra)
    strategy.entry("Compra", strategy.long)

if (crossed_under and senal_venta)
    strategy.close("Compra")