Chiến lược giao dịch lưới thông minh thích nghi

Tác giả:ChaoZhang, Ngày: 2024-01-16 14:51:48
Tags:

img

Tổng quan

Chiến lược này là một chiến lược giao dịch lưới thông minh thích nghi dựa trên nền tảng TradingView, được viết bằng Pine Script v4. Nó chồng lên biểu đồ giá và tạo ra một lưới trong giới hạn được chỉ định để tạo ra tín hiệu mua và bán.

Chiến lược logic

Các đặc điểm chính

  1. Kim tự tháp và quản lý tiền:

    • Cho phép tối đa 14 lần bổ sung theo cùng một hướng (đồ kim tự tháp),
    • Sử dụng một chiến lược dựa trên tiền mặt để quản lý kích thước vị trí,
    • vốn ban đầu được thiết lập ở mức 100 USD cho mục đích mô phỏng,
    • Một khoản hoa hồng nhỏ 0,1% được tính cho mỗi giao dịch.
  2. Biên giới lưới:

    • Người dùng có thể lựa chọn sử dụng các ranh giới tự động tính toán hoặc thiết lập thủ công các ranh giới trên và dưới của lưới,
    • Các giới hạn tự động có thể được bắt nguồn từ giá cao & thấp gần đây hoặc từ Mức trung bình di chuyển đơn giản (SMA),
    • Người dùng có thể xác định thời gian xem lại để tính toán giới hạn và điều chỉnh độ lệch để mở rộng hoặc thu hẹp giới hạn.
  3. Đường lưới:

    • Chiến lược cho phép số lượng đường lưới có thể tùy chỉnh trong ranh giới, với phạm vi khuyến cáo từ 3 đến 15,
    • Các đường lưới được phân cách đồng đều giữa các ranh giới trên và dưới.

Chiến lược logic

  • Đăng ký:

    • Các kịch bản đặt lệnh mua khi giá giảm xuống dưới một đường lưới và không có lệnh hiện có được liên kết với đường lưới đó.
    • Mỗi số lượng lệnh mua được tính trên cơ sở vốn ban đầu chia cho số lượng đường lưới, điều chỉnh cho giá hiện tại.
  • Lối ra:

    • Các lệnh bán được kích hoạt khi giá tăng trên đường lưới, miễn là có một lệnh mở tương ứng với đường lưới thấp hơn tiếp theo.
  • Mạng lưới thích nghi:

    • Nếu được đặt thành giới hạn tự động, lưới thích nghi với các điều kiện thị trường thay đổi bằng cách tính lại giới hạn trên và dưới và điều chỉnh lưới phù hợp.

Phân tích lợi thế

Chiến lược này tích hợp bản chất có hệ thống và thực hiện hiệu quả giao dịch lưới. Cho phép kim tự tháp và sử dụng quản lý tiền có thể kiểm soát rủi ro hiệu quả. Mạng tự động thích nghi phù hợp với các điều kiện thị trường khác nhau. Các tham số có thể điều chỉnh phục vụ các phong cách giao dịch khác nhau.

Phân tích rủi ro

Một sự đột phá giá vượt ra ngoài ranh giới lưới có thể gây ra tổn thất nghiêm trọng. Các thông số nên được điều chỉnh đúng cách hoặc kết hợp với một mức dừng lỗ để kiểm soát rủi ro. Ngoài ra, giao dịch quá mức làm tăng chi phí giao dịch.

Hướng dẫn tối ưu hóa

Xem xét kết hợp với bộ lọc xu hướng hoặc tối ưu hóa các thông số lưới.

Kết luận

Chiến lược này có hệ thống tạo ra các mục nhập và thoát trong khi quản lý các vị trí. Thông qua điều chỉnh tham số, nó thích nghi với các sở thích khác nhau. Nó kết hợp bản chất dựa trên quy tắc của giao dịch lưới với tính linh hoạt của giao dịch xu hướng, giảm bớt sự phức tạp của hoạt động trong khi vẫn giữ được độ bền.


/*backtest
start: 2024-01-08 00:00:00
end: 2024-01-15 00:00:00
period: 5m
basePeriod: 1m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=4
strategy("(IK) Grid Script", overlay=true, pyramiding=14, close_entries_rule="ANY", default_qty_type=strategy.cash, initial_capital=100.0, currency="USD", commission_type=strategy.commission.percent, commission_value=0.1)
i_autoBounds    = input(group="Grid Bounds", title="Use Auto Bounds?", defval=true, type=input.bool)                             // calculate upper and lower bound of the grid automatically? This will theorhetically be less profitable, but will certainly require less attention
i_boundSrc      = input(group="Grid Bounds", title="(Auto) Bound Source", defval="Hi & Low", options=["Hi & Low", "Average"])     // should bounds of the auto grid be calculated from recent High & Low, or from a Simple Moving Average
i_boundLookback = input(group="Grid Bounds", title="(Auto) Bound Lookback", defval=250, type=input.integer, maxval=500, minval=0) // when calculating auto grid bounds, how far back should we look for a High & Low, or what should the length be of our sma
i_boundDev      = input(group="Grid Bounds", title="(Auto) Bound Deviation", defval=0.10, type=input.float, maxval=1, minval=-1)  // if sourcing auto bounds from High & Low, this percentage will (positive) widen or (negative) narrow the bound limits. If sourcing from Average, this is the deviation (up and down) from the sma, and CANNOT be negative.
i_upperBound    = input(group="Grid Bounds", title="(Manual) Upper Boundry", defval=0.285, type=input.float)                      // for manual grid bounds only. The upperbound price of your grid
i_lowerBound    = input(group="Grid Bounds", title="(Manual) Lower Boundry", defval=0.225, type=input.float)                      // for manual grid bounds only. The lowerbound price of your grid.
i_gridQty       = input(group="Grid Lines",  title="Grid Line Quantity", defval=8, maxval=15, minval=3, type=input.integer)       // how many grid lines are in your grid

f_getGridBounds(_bs, _bl, _bd, _up) =>
    if _bs == "Hi & Low"
        _up ? highest(close, _bl) * (1 + _bd) : lowest(close, _bl)  * (1 - _bd)
    else
        avg = sma(close, _bl)
        _up ? avg * (1 + _bd) : avg * (1 - _bd)

f_buildGrid(_lb, _gw, _gq) =>
    gridArr = array.new_float(0)
    for i=0 to _gq-1
        array.push(gridArr, _lb+(_gw*i))
    gridArr

f_getNearGridLines(_gridArr, _price) =>
    arr = array.new_int(3)
    for i = 0 to array.size(_gridArr)-1
        if array.get(_gridArr, i) > _price
            array.set(arr, 0, i == array.size(_gridArr)-1 ? i : i+1)
            array.set(arr, 1, i == 0 ? i : i-1)
            break
    arr

var upperBound      = i_autoBounds ? f_getGridBounds(i_boundSrc, i_boundLookback, i_boundDev, true) : i_upperBound  // upperbound of our grid
var lowerBound      = i_autoBounds ? f_getGridBounds(i_boundSrc, i_boundLookback, i_boundDev, false) : i_lowerBound // lowerbound of our grid
var gridWidth       = (upperBound - lowerBound)/(i_gridQty-1)                                                       // space between lines in our grid
var gridLineArr     = f_buildGrid(lowerBound, gridWidth, i_gridQty)                                                 // an array of prices that correspond to our grid lines
var orderArr        = array.new_bool(i_gridQty, false)                                                              // a boolean array that indicates if there is an open order corresponding to each grid line

var closeLineArr    = f_getNearGridLines(gridLineArr, close)                                                        // for plotting purposes - an array of 2 indices that correspond to grid lines near price
var nearTopGridLine = array.get(closeLineArr, 0)                                                                    // for plotting purposes - the index (in our grid line array) of the closest grid line above current price
var nearBotGridLine = array.get(closeLineArr, 1)                                                                    // for plotting purposes - the index (in our grid line array) of the closest grid line below current price
strategy.initial_capital = 50000
for i = 0 to (array.size(gridLineArr) - 1)
    if close < array.get(gridLineArr, i) and not array.get(orderArr, i) and i < (array.size(gridLineArr) - 1)
        buyId = i
        array.set(orderArr, buyId, true)
        strategy.entry(id=tostring(buyId), long=true, qty=(strategy.initial_capital/(i_gridQty-1))/close, comment="#"+tostring(buyId))
    if close > array.get(gridLineArr, i) and i != 0
        if array.get(orderArr, i-1)
            sellId = i-1
            array.set(orderArr, sellId, false)
            strategy.close(id=tostring(sellId), comment="#"+tostring(sellId))

if i_autoBounds
    upperBound  := f_getGridBounds(i_boundSrc, i_boundLookback, i_boundDev, true)
    lowerBound  := f_getGridBounds(i_boundSrc, i_boundLookback, i_boundDev, false)
    gridWidth   := (upperBound - lowerBound)/(i_gridQty-1)
    gridLineArr := f_buildGrid(lowerBound, gridWidth, i_gridQty)

closeLineArr    := f_getNearGridLines(gridLineArr, close)
nearTopGridLine := array.get(closeLineArr, 0)
nearBotGridLine := array.get(closeLineArr, 1)

Thêm nữa