Эта стратегия устанавливает динамическую торговую сетку для достижения устойчивой прибыли на волатильных рынках. Она автоматически рассчитывает расстояние между сетками и верхний / нижний предел на основе предварительно установленного количества линий сетки. Когда цена проходит через каждую линию сетки, длинные / короткие позиции будут построены по партиям. Прибыль будет получена, когда цена снова достигнет первоначальных линий сетки. Стратегия поддерживает как ручное, так и автоматическое регулирование параметров сетки, чтобы адаптироваться к изменяющимся рыночным условиям.
Вычислить границы сети и ценовой массив сети на основе входных параметров.
Когда цена опускается ниже сетевой линии без соответствующих ордеров, длинные ордера размещаются по цене сетевой линии. Когда цена поднимается выше предыдущей сетевой линии (первая исключена) с существующей позицией, длинные ордера предыдущей линии закрываются.
Если автоматическое регулирование включено, верхние/нижние пределы сетки, расстояние между сетками и массивы сетки будут периодически пересчитываться на основе последних данных свечей.
Долгие/короткие позиции создаются и закрываются в партии на разных уровнях цен для достижения общей прибыли.
Поддержка ручной и автоматической настройки параметров. Ручная настройка обеспечивает лучший контроль, но требует вмешательства. Автоматическая настройка уменьшает нагрузку и адаптируется к изменяющейся динамике рынка.
Максимальная потеря ограничена ограничением максимального количества линий сети.
Настройка расстояния между сетками для корректировки прибыли/убытка на одну сделку.
Риск попасть в ловушку. Частые колебания цен в пределах сетевого диапазона могут привести к потерям.
Недостаточное финансирование не может обеспечить достаточное количество линий сети.
Слишком мало сетей не могут в полной мере воспользоваться волатильностью, в то время как слишком много сетей приводят к минимальной прибыли на сделку.
Автоматическая корректировка рискует манипулировать ценами, опираясь на недавние свечи, на которые могут повлиять краткосрочные ценовые операции.
Внедрить логику стоп-лосса, такую как стоп-лосс, чтобы еще больше ограничить риск снижения по направлению.
Оптимизировать параметры сетки с помощью машинного обучения. Испытать различные параметры в рыночных условиях и обучить модели ML для получения оптимальных адаптивных параметров.
Оцените силу текущего тренда с помощью таких индикаторов, как MACD и RSI, чтобы направлять количество сетки и настройку параметров.
Улучшить контроль рисков путем установления максимально допустимого процента привлечения.
Эта стратегия в полной мере использует характеристики волатильных рынков и достигает устойчивой прибыли благодаря динамической сетевой торговой структуре, которая предлагает как гибкость параметров, так и простоту работы.
/*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)