Chiến lược giao dịch dài hạn và ngắn hạn linh hoạt dựa trên kênh Keltner

ATR EMA SMA MA TR
Ngày tạo: 2025-02-10 15:07:12 sửa đổi lần cuối: 2025-02-10 15:07:12
sao chép: 4 Số nhấp chuột: 448
1
tập trung vào
1617
Người theo dõi

Chiến lược giao dịch dài hạn và ngắn hạn linh hoạt dựa trên kênh Keltner

Tổng quan

Đây là một chiến lược giao dịch linh hoạt dựa trên Keltner Channel. Chiến lược này hỗ trợ giao dịch hai chiều đa luồng, giao dịch bằng cách theo dõi giá phá vỡ kênh lên xuống.

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

Chiến lược này dựa trên một số nguyên tắc cốt lõi:

  1. Xu hướng trung tâm của giá được tính toán thông qua EMA hoặc SMA, tạo thành đường trung tâm của kênh
  2. Sử dụng ATR, TR hoặc Range tính toán tỷ lệ dao động, xây dựng đường dẫn lên và xuống đường ray
  3. Khi giá phá vỡ đường đua lên, kích hoạt nhiều tín hiệu, khi phá vỡ đường đua xuống, kích hoạt tín hiệu trống
  4. Sử dụng một cơ chế đơn đặt hàng dừng lỗ để vào và ra thị trường, tăng độ tin cậy của việc thực hiện giao dịch
  5. Hỗ trợ lựa chọn mô hình giao dịch linh hoạt: giao dịch chỉ nhiều, chỉ trần hoặc giao dịch hai chiều

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

  1. Khả năng thích ứng - Chuyển đổi chiều rộng kênh động thông qua ATR, cho phép chiến lược thích ứng với môi trường biến động thị trường khác nhau
  2. Kiểm soát rủi ro hoàn hảo - Sử dụng giao dịch đơn vị ủy quyền dừng lỗ để kiểm soát rủi ro hiệu quả
  3. Tính linh hoạt hoạt động - hỗ trợ nhiều mô hình giao dịch, có thể điều chỉnh theo đặc điểm thị trường và sở thích giao dịch
  4. Xác minh hiệu quả - hoạt động tốt trong thị trường tiền điện tử và chứng khoán, đặc biệt là trong thị trường có nhiều biến động
  5. Hiển thị rõ ràng - cung cấp tín hiệu giao dịch và hiển thị trực quan tình trạng giữ vị trí

Rủi ro chiến lược

  1. Rủi ro thị trường rung động - có thể tạo ra các tín hiệu phá vỡ sai thường xuyên trong thị trường rung động ngang
  2. Rủi ro trượt điểm - Các giao dịch dừng lỗ có thể có nguy cơ trượt điểm lớn hơn trong thị trường thiếu thanh khoản
  3. Rủi ro đảo ngược xu hướng - có thể chịu tổn thất lớn hơn nếu xu hướng đột ngột đảo ngược
  4. Tính nhạy cảm của tham số - sự lựa chọn tham số của kênh có ảnh hưởng quan trọng đến hiệu suất của chiến lược

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

  1. Tiết xuất bộ lọc xu hướng - giảm tín hiệu phá vỡ giả bằng cách thêm các chỉ số đánh giá xu hướng
  2. Tối ưu hóa tham số động - điều chỉnh tham số kênh động theo biến động của thị trường
  3. Cải thiện cơ chế dừng lỗ - Tăng chức năng dừng lỗ di động để bảo vệ lợi nhuận tốt hơn
  4. Tăng xác nhận khối lượng giao dịch - Kết hợp các chỉ số khối lượng giao dịch để tăng độ tin cậy tín hiệu
  5. Tối ưu hóa quản lý vị thế - giới thiệu quản lý vị thế động để kiểm soát rủi ro tốt hơn

Tóm tắt

Chiến lược này là một hệ thống giao dịch được thiết kế hoàn hảo, logic rõ ràng, thực hiện việc nắm bắt cơ hội thị trường hiệu quả bằng cách sử dụng các kênh Kettner và nhiều chỉ số kỹ thuật một cách linh hoạt. Chiến lược có khả năng tùy biến mạnh mẽ, phù hợp với các nhà giao dịch có sở thích rủi ro khác nhau.

Mã nguồn chiến lược
/*backtest
start: 2022-02-11 00:00:00
end: 2025-02-08 08:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=6
strategy(title = "Jaakko's Keltner Strategy", overlay = true, initial_capital = 10000, default_qty_type = strategy.percent_of_equity, default_qty_value = 100)

// ──────────────────────────────────────────────────────────────────────────────
// ─── USER INPUTS ─────────────────────────────────────────────────────────────
// ──────────────────────────────────────────────────────────────────────────────
length      = input.int(20,     minval=1,  title="Keltner MA Length")
mult        = input.float(2.0,             title="Multiplier")
src         = input(close,                 title="Keltner Source")
useEma      = input.bool(true,             title="Use Exponential MA")
BandsStyle  = input.string(title = "Bands Style", defval  = "Average True Range", options = ["Average True Range", "True Range", "Range"])
atrLength   = input.int(10,                title="ATR Length")

// Choose which side(s) to trade
tradeMode = input.string(title   = "Trade Mode", defval  = "Long Only", options = ["Long Only", "Short Only", "Both"])

// ──────────────────────────────────────────────────────────────────────────────
// ─── KELTNER MA & BANDS ───────────────────────────────────────────────────────
// ──────────────────────────────────────────────────────────────────────────────
f_ma(source, length, emaMode) =>
    maSma = ta.sma(source, length)
    maEma = ta.ema(source, length)
    emaMode ? maEma : maSma

ma    = f_ma(src, length, useEma)
rangeMa = BandsStyle == "True Range" ? ta.tr(true) : BandsStyle == "Average True Range" ? ta.atr(atrLength) : ta.rma(high - low, length)

upper = ma + rangeMa * mult
lower = ma - rangeMa * mult

// ──────────────────────────────────────────────────────────────────────────────
// ─── CROSS CONDITIONS ─────────────────────────────────────────────────────────
// ──────────────────────────────────────────────────────────────────────────────
crossUpper = ta.crossover(src, upper) // potential long signal
crossLower = ta.crossunder(src, lower) // potential short signal

// ──────────────────────────────────────────────────────────────────────────────
// ─── PRICE LEVELS FOR STOP ENTRY (LONG) & STOP ENTRY (SHORT) ─────────────────
// ──────────────────────────────────────────────────────────────────────────────
bprice = 0.0
bprice := crossUpper ? high + syminfo.mintick : nz(bprice[1])

sprice = 0.0
sprice := crossLower ? low - syminfo.mintick : nz(sprice[1])

// ──────────────────────────────────────────────────────────────────────────────
// ─── BOOLEAN FLAGS FOR PENDING LONG/SHORT ─────────────────────────────────────
// ──────────────────────────────────────────────────────────────────────────────
crossBcond = false
crossBcond := crossUpper ? true : crossBcond[1]

crossScond = false
crossScond := crossLower ? true : crossScond[1]

// Cancel logic for unfilled orders (same as original)
cancelBcond = crossBcond and (src < ma or high >= bprice)
cancelScond = crossScond and (src > ma or low <= sprice)

// ──────────────────────────────────────────────────────────────────────────────
// ─── LONG SIDE ────────────────────────────────────────────────────────────────
// ──────────────────────────────────────────────────────────────────────────────
if (tradeMode == "Long Only" or tradeMode == "Both")  // Only run if mode is long or both
    // Cancel unfilled long if invalid
    if cancelBcond
        strategy.cancel("KltChLE")

    // Place long entry
    if crossUpper
        strategy.entry("KltChLE", strategy.long, stop=bprice, comment="Long Entry")

    // If we are also using “Both,” we rely on short side to flatten the long.
    // But if “Long Only,” we can exit on crossLower or do nothing.
    // Let’s do a "stop exit" if in "Long Only" (like the improved version).
    if tradeMode == "Long Only"
        // Cancel unfilled exit
        if cancelScond
            strategy.cancel("KltChLX")

        // Place exit if crossLower
        if crossLower
            strategy.exit("KltChLX", from_entry="KltChLE", stop=sprice, comment="Long Exit")

// ──────────────────────────────────────────────────────────────────────────────
// ─── SHORT SIDE ───────────────────────────────────────────────────────────────
// ──────────────────────────────────────────────────────────────────────────────
if (tradeMode == "Short Only" or tradeMode == "Both") // Only run if mode is short or both
    // Cancel unfilled short if invalid
    if cancelScond
        strategy.cancel("KltChSE")

    // Place short entry
    if crossLower
        strategy.entry("KltChSE", strategy.short, stop=sprice, comment="Short Entry")

    // If “Short Only,” we might do a symmetrical exit approach for crossUpper
    // Or if "Both," going long automatically flattens the short in a no-hedge account.
    // Let's replicate "stop exit" for short side if "Short Only" is chosen:
    if tradeMode == "Short Only"
        // Cancel unfilled exit
        if cancelBcond
            strategy.cancel("KltChSX")

        // Place exit if crossUpper
        if crossUpper
            strategy.exit("KltChSX", from_entry="KltChSE", stop=bprice, comment="Short Exit")

// ──────────────────────────────────────────────────────────────────────────────
// ─── OPTIONAL VISUALS ─────────────────────────────────────────────────────────
// ──────────────────────────────────────────────────────────────────────────────
barcolor(strategy.position_size > 0 ? color.green : strategy.position_size < 0 ? color.red : na)

plotshape(    strategy.position_size > 0 and strategy.position_size[1] <= 0, title     = "BUY",  text      = '🚀',  style     = shape.labelup,    location  = location.belowbar,     color     = color.green,     textcolor = color.white,      size      = size.small)

plotshape(    strategy.position_size <= 0 and strategy.position_size[1] > 0,     title     = "SELL",     text      = '☄️',     style     = shape.labeldown,     location  = location.abovebar,     color     = color.red,       textcolor = color.white,     size      = size.small)

plotshape(crossLower, style=shape.triangledown, color=color.red, location=location.abovebar, title="CrossLower Trigger")