Chiến lược hỗ trợ và kháng cự động và giao cắt đa chỉ báo của dải Bollinger

SR BB EMA21 Pivot CROSS
Ngày tạo: 2025-01-17 14:24:33 sửa đổi lần cuối: 2025-01-17 14:24:33
sao chép: 0 Số nhấp chuột: 78
1
tập trung vào
1166
Người theo dõi

Chiến lược hỗ trợ và kháng cự động và giao cắt đa chỉ báo của dải Bollinger

Tổng quan

Chiến lược này là chiến lược giao dịch giao thoa đa chỉ báo kết hợp hỗ trợ và kháng cự động, dải Bollinger và đường trung bình động EMA21. Chiến lược này đưa ra quyết định giao dịch bằng cách xác định sự đột phá của các mức giá quan trọng kết hợp với các tín hiệu giao nhau từ các chỉ báo kỹ thuật. Chiến lược này không chỉ có thể xác định động các mức hỗ trợ và kháng cự quan trọng trong cấu trúc thị trường mà còn xác nhận độ tin cậy của các tín hiệu giao dịch thông qua sự phối hợp của Dải Bollinger và đường trung bình động.

Nguyên tắc chiến lược

Chiến lược này dựa trên các thành phần cốt lõi sau:

  1. Tính toán hỗ trợ và kháng cự động: Sử dụng phương pháp điểm trục để tính toán động các mức hỗ trợ và kháng cự của thị trường và lọc vùng giá hiệu quả bằng cách thiết lập độ rộng kênh và yêu cầu sức mạnh tối thiểu.
  2. Chỉ báo Bollinger Band: Sử dụng Bollinger Band 20 kỳ, độ lệch chuẩn 2 để xác định phạm vi biến động giá.
  3. Đường trung bình động EMA21: được sử dụng làm đường tham chiếu để đánh giá xu hướng trung hạn.
  4. Tạo tín hiệu giao dịch: Giao dịch khi giá vượt qua mức hỗ trợ và kháng cự và kích hoạt tín hiệu Bolin Band.

Lợi thế chiến lược

  1. Xác nhận đa chiều: Cải thiện độ tin cậy của tín hiệu giao dịch bằng cách kết hợp nhiều chỉ báo kỹ thuật.
  2. Thích ứng động: Mức hỗ trợ và kháng cự sẽ tự động điều chỉnh khi cấu trúc thị trường thay đổi.
  3. Quản lý rủi ro: Dải Bollinger cung cấp định nghĩa rõ ràng về vùng quá mua và quá bán.
  4. Xác nhận xu hướng: Đường trung bình động EMA21 giúp xác nhận hướng xu hướng trung hạn.
  5. Hình ảnh hóa: Các chiến lược cung cấp phản hồi trực quan rõ ràng để dễ dàng phân tích và tối ưu hóa.

Rủi ro chiến lược

  1. Rủi ro thị trường biến động: Quá nhiều tín hiệu đột phá sai có thể được tạo ra trong thị trường đi ngang và biến động.
  2. Rủi ro độ trễ: Việc tính toán các chỉ báo kỹ thuật có độ trễ nhất định và bạn có thể bỏ lỡ cơ hội vào lệnh tốt nhất.
  3. Độ nhạy của tham số: Hiệu quả của chiến lược nhạy cảm với các cài đặt tham số và cần được tối ưu hóa cho các môi trường thị trường khác nhau.
  4. Rủi ro đột phá sai: Việc đột phá qua mức hỗ trợ hoặc kháng cự có thể là đột phá sai và cần có xác nhận từ các chỉ báo khác.

Hướng tối ưu hóa chiến lược

  1. Giới thiệu chỉ báo khối lượng: Thêm phân tích khối lượng khi xác nhận đột phá để cải thiện độ tin cậy của tín hiệu.
  2. Tối ưu hóa khả năng thích ứng tham số: Phát triển cơ chế điều chỉnh tham số thích ứng để giúp các chiến lược thích ứng tốt hơn với các môi trường thị trường khác nhau.
  3. Thêm cơ chế dừng lỗ: thiết kế chiến lược dừng lỗ hoàn thiện hơn để kiểm soát rủi ro mất vốn.
  4. Thêm bộ lọc xu hướng: tăng khả năng phán đoán sức mạnh của xu hướng và tránh giao dịch trong môi trường xu hướng yếu.
  5. Tối ưu hóa khung thời gian: Nghiên cứu tác động của các kết hợp khung thời gian khác nhau để tìm ra cấu hình tối ưu.

Tóm tắt

Chiến lược này xây dựng một hệ thống giao dịch tương đối hoàn chỉnh bằng cách kết hợp hỗ trợ và kháng cự động, dải Bollinger và đường trung bình động EMA21. Ưu điểm của chiến lược này nằm ở khả năng xác nhận tín hiệu đa chiều và thích ứng linh hoạt với những thay đổi của thị trường, nhưng nó cũng phải đối mặt với rủi ro về tối ưu hóa tham số và đột phá sai lầm. Bằng cách liên tục tối ưu hóa và cải thiện cơ chế kiểm soát rủi ro, chiến lược này kỳ vọng sẽ đạt được hiệu suất tốt hơn trong các giao dịch thực tế.

Mã nguồn chiến lược
//@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")