Chiến lược này sử dụng phương pháp giao dịch lưới trong lý thuyết đại dương để đặt lệnh mua và bán trong phạm vi giá đã đặt trước. Chiến lược có tính toán tự động phạm vi giá lưới và phân phối thống nhất các đường lưới, giúp quản lý rủi ro hiệu quả.
Chiến lược này đầu tiên tính toán giới hạn trên và dưới của lưới giá dựa trên lựa chọn của người dùng hoặc cài đặt mặc định. Có hai cách tính toán: lấy giá cao nhất và thấp nhất trong thời gian kiểm tra lại, hoặc tính toán trung bình động trong một khung thời gian. Sau đó các đường lưới được phân phối đồng đều theo số lưới được thiết lập bởi người dùng.
Các tín hiệu giao dịch được tạo ra dựa trên mối quan hệ giữa giá và đường lưới. Khi giá dưới đường lưới, một vị trí dài được mở ở giá đường lưới với số lượng cố định; khi giá vượt quá đường lưới, vị trí được đóng ở đường lưới bên dưới. Khi giá dao động trong lưới, các vị trí thay đổi tương ứng để kiếm lợi nhuận.
Cụ thể, chiến lược duy trì một mảng giá đường lưới và một mảng bool chỉ ra liệu các lệnh có được đặt ở mỗi dòng hay không. Khi giá thấp hơn một dòng mà không có lệnh, vị trí dài được mở ở dòng; khi giá cao hơn một dòng trong khi các lệnh tồn tại ở dòng bên dưới, các vị trí được đóng ở dòng dưới. Giao dịch lưới được thực hiện theo cách này.
Phạm vi lưới được tính toán tự động, tránh khó khăn thiết lập bằng tay.
Các đường lưới được phân phối đồng đều để tránh giao dịch quá mức do lưới dày đặc.
Phương pháp giao dịch lưới có hiệu quả kiểm soát rủi ro. Lợi nhuận có thể đạt được miễn là giá dao động trong lưới.
Không có giả định về hướng giá, phù hợp với thị trường giới hạn phạm vi.
Các thiết lập phí hoa hồng và kích thước vị trí tùy chỉnh cho các công cụ giao dịch khác nhau.
Hiển thị các đường lưới giúp hiểu tình hình giao dịch.
Rủi ro phá vỡ giá. Vi phạm giới hạn lưới trên hoặc dưới có thể dẫn đến tổn thất lớn hơn.
Rủi ro không gian lưới quá nhiều. Mạng lưới quá lỏng lẻo không thể kiếm được lợi nhuận dễ dàng trong khi quá hẹp làm tăng chi phí. Cần cân bằng.
Rủi ro nắm giữ lâu dài làm cho lợi nhuận khó khăn nhưng tăng chi phí.
Rủi ro cài đặt tham số không chính xác: Thời gian kiểm tra ngược hoặc thời gian trung bình động có thể ảnh hưởng đến tính toán phạm vi lưới nếu được thiết lập không chính xác.
Rủi ro thị trường hệ thống: thích hợp hơn cho các thị trường giới hạn trong phạm vi thay vì các thị trường xu hướng dài hạn.
Tối ưu hóa các thông số lưới điện. Xem xét toàn diện các điều kiện thị trường, chi phí v.v. để tối ưu hóa số lượng lưới điện, thời gian xem lại v.v.
Đưa ra điều chỉnh phạm vi lưới năng động. Điều chỉnh phạm vi lưới khi có thay đổi thị trường đáng kể.
Kết hợp các cơ chế dừng lỗ. Thiết lập các đường dừng lỗ thích hợp để hạn chế lỗ. Có thể được điều chỉnh năng động.
Thêm các bộ lọc sử dụng các chỉ số khác như Bollinger Bands, chỉ số xu hướng vv để tránh giao dịch không phù hợp.
Cải thiện hiệu quả sử dụng vốn. giới thiệu phân tích biến động để giảm giao dịch trong thời gian ổn định.
Chiến lược này thực hiện giao dịch phạm vi có thể kiểm soát rủi ro bằng cách tận dụng các nguyên tắc giao dịch lưới. Tính toán lưới tự động và phân phối đồng đều cung cấp những lợi thế phù hợp với các thị trường khác nhau thông qua điều chỉnh tham số. Rủi ro bị hạn chế và dễ vận hành. Tuy nhiên, có những hạn chế và cần cải tiến liên tục để thích nghi với thị trường đang phát triển. Nhìn chung, chiến lược cung cấp một cách tiếp cận tiêu chuẩn và tham số để thực hiện giao dịch lưới.
/*backtest start: 2023-09-12 00:00:00 end: 2023-10-12 00:00:00 period: 1h basePeriod: 15m 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 strategy.initial_capital = 50000 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 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)