
Chiến lược này tạo ra một mạng lưới giao dịch được điều chỉnh động để đạt được lợi nhuận ổn định trong điều kiện biến động. Chiến lược sẽ tự động tính toán khoảng cách lưới và giá trên và dưới dựa trên số lượng lưới được thiết lập. Khi giá vượt qua mỗi đường lưới, sẽ tạo thêm hoặc làm trống hàng loạt.
Tính toán biên lưới và mảng giá đường lưới dựa trên tham số đầu vào.
Khi giá thấp hơn một đường lưới và đường lưới đó không có đơn đặt hàng tương ứng, hãy tạo thêm đơn tại điểm giá của đường lưới đó; khi giá cao hơn đường lưới trước ((trừ đường lưới đầu tiên) và đường lưới trước có đơn giữ tương ứng, hãy xóa đơn đặt hàng tương ứng của đường lưới trước.
Nếu kích hoạt tham số tự động điều chỉnh lưới, giá, khoảng cách lưới và mảng lưới sẽ được tính toán lại thường xuyên dựa trên số lượng dữ liệu K-line gần đây nhất.
Đạt được mục tiêu của lợi nhuận trong tình trạng biến động. Trong tình trạng giảm giá, có thể thiết lập các vị trí giữ và dừng ở các điểm giá khác nhau để đạt được lợi nhuận tổng thể.
Bạn có thể chọn điều chỉnh các tham số lưới bằng tay hoặc tự động. Điều chỉnh bằng tay đòi hỏi sự can thiệp của con người, nhưng có thể kiểm soát được nhiều hơn. Điều chỉnh tự động làm giảm công việc vận hành, cho phép chiến lược có thể thích nghi với sự thay đổi của môi trường thị trường.
Bạn có thể kiểm soát rủi ro một chiều bằng cách giới hạn số lượng lưới tối đa. Khi giá vượt qua tất cả các đường lưới, rủi ro theo hướng này sẽ được kiểm soát.
Bạn có thể điều chỉnh khoảng cách lưới để kiểm soát mức lỗ hổng của mỗi đơn. Giảm khoảng cách lưới có thể làm giảm lỗ hổng đơn.
Trong trường hợp có sự biến động lớn, có nguy cơ bị đánh giá. Nếu giá dao động nhanh giữa nhiều lưới, có thể có nguy cơ đánh giá.
Cần thiết lập số tiền ban đầu hợp lý. Nếu số tiền ban đầu không đủ, không thể hỗ trợ đủ số dây lưới.
Quá lớn hoặc quá nhỏ số lượng lưới là không tốt cho lợi nhuận chiến lược. Quá ít số lưới không thể tận dụng đầy đủ sự biến động; quá nhiều là đơn thuần lỗ quá nhỏ. Cần thử nghiệm để xác định các tham số tối ưu.
Tự động điều chỉnh tham số lưới có nguy cơ bị thao tác. Tính toán tham số lưới phụ thuộc vào số lượng K, có thể bị ảnh hưởng bởi hoạt động ngắn hạn.
Thêm logic dừng lỗ, chẳng hạn như thiết lập dừng nổi hoặc theo dõi dừng lỗ, để kiểm soát thêm rủi ro thua lỗ đơn phương.
Thêm thuật toán tối ưu hóa tham số lưới. Bạn có thể thử nghiệm các thiết lập tham số ở các giai đoạn thị trường khác nhau, sau đó đào tạo mô hình bằng phương pháp học máy để tự động tối ưu hóa tham số.
Kết hợp các chỉ số khác để đánh giá tình hình. Các chỉ số như MACD, KD và các chỉ số khác để xác định hiện tại có xu hướng tăng hay giảm để điều chỉnh số lượng lưới hoặc tham số.
Tối ưu hóa kiểm soát rút tiền. Ví dụ: thiết lập tỷ lệ rút tiền tối đa, đóng chiến lược khi đạt ngưỡng, tránh tổn thất mở rộng hơn nữa.
Chiến lược này tận dụng đầy đủ các đặc điểm của tình huống biến động, đạt được mục tiêu lợi nhuận ổn định thông qua giao dịch lưới động. Chiến lược này xem xét cả tính linh hoạt của thiết lập tham số và giảm cường độ công việc của hoạt động. Có thể nói rằng trong tình huống biến động, chiến lược này là lựa chọn lợi nhuận lý tưởng.
/*backtest
start: 2024-01-02 00:00:00
end: 2024-02-01 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
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)