Chiến lược này thiết lập một lưới giao dịch năng động để đạt được lợi nhuận ổn định giữa các thị trường biến động. Nó tự động tính toán khoảng cách lưới và giới hạn trên / dưới dựa trên số lượng các đường lưới đã đặt trước. Khi giá vượt qua từng đường lưới, các vị trí dài / ngắn sẽ được xây dựng theo lô. Lợi nhuận sẽ được lấy khi giá chạm vào các đường lưới ban đầu một lần nữa. Chiến lược hỗ trợ cả điều chỉnh thủ công và tự động các thông số lưới để thích nghi với điều kiện thị trường thay đổi.
Tính toán ranh giới lưới và mảng giá đường lưới dựa trên các thông số đầu vào.
Khi giá giảm xuống dưới một đường lưới mà không có lệnh tương ứng, các lệnh dài sẽ được đặt ở mức giá đường lưới. Khi giá tăng lên trên đường lưới trước (đầu tiên bị loại trừ) với vị trí hiện có, các lệnh dài của dòng trước sẽ được đóng.
Nếu điều chỉnh tự động được bật, giới hạn trên/dưới lưới, khoảng cách lưới và mảng lưới sẽ được tính lại theo định kỳ dựa trên dữ liệu nến gần đây.
Thực hiện lợi nhuận ổn định trong bối cảnh thị trường biến động. các vị trí dài / ngắn được xây dựng và đóng theo lô ở các mức giá khác nhau để đạt được lợi nhuận tổng thể.
Hỗ trợ cả điều chỉnh tham số thủ công và tự động. Điều chỉnh thủ công cung cấp kiểm soát tốt hơn nhưng đòi hỏi sự can thiệp. Điều chỉnh tự động làm giảm khối lượng công việc và thích nghi với sự thay đổi động lực thị trường.
Khi giá phá vỡ tất cả các đường lưới, rủi ro được kiểm soát.
Điều chỉnh khoảng cách lưới để điều chỉnh lợi nhuận / lỗ cho mỗi giao dịch.
Rủi ro bị mắc kẹt trong chấn thương.
Cần vốn ban đầu đầy đủ.
Số lưới cực đoan gây bất lợi cho lợi nhuận. Quá ít lưới không thể tận dụng đầy đủ sự biến động trong khi quá nhiều lưới dẫn đến lợi nhuận tối thiểu cho mỗi giao dịch. Kiểm tra rộng rãi cần thiết để xác định cài đặt tối ưu.
Điều chỉnh tự động rủi ro thao túng giá dựa trên các ngọn nến gần đây có thể bị ảnh hưởng bởi các hoạt động giá ngắn hạn.
Đưa ra logic dừng lỗ như dừng lỗ theo dõi để hạn chế thêm rủi ro giảm theo hướng.
Tối ưu hóa các tham số lưới thông qua học máy. Kiểm tra các tham số khác nhau trên các điều kiện thị trường và đào tạo các mô hình ML để có được các tham số thích nghi tối ưu.
Bao gồm các chỉ số kỹ thuật bổ sung. Đánh giá sức mạnh xu hướng hiện tại với các chỉ số như MACD và RSI để hướng dẫn số lượng lưới và điều chỉnh tham số.
Tăng cường kiểm soát rủi ro bằng cách thiết lập tỷ lệ rút tiền tối đa được phép.
Chiến lược này sử dụng đầy đủ các đặc điểm của thị trường biến động và đạt được lợi nhuận ổn định thông qua khuôn khổ giao dịch lưới năng động cung cấp cả tính linh hoạt của các tham số và dễ vận hành.
/*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)