
Esta estrategia permite obtener ganancias estables en situaciones de volatilidad mediante la creación de una red de operaciones que se ajusta dinámicamente. La estrategia calcula automáticamente el intervalo de la red y el precio superior y inferior según el número de redes configurado.
Los límites de la red y el precio de la línea de la red se calculan según los parámetros de entrada.
Cuando el precio está por debajo de una de las líneas de la red y no hay un pedido correspondiente en la línea de la red, en el punto de precio de la línea de la red se crea una orden de compra; cuando el precio es más alto que la línea de la red anterior (excepto el primero) y la línea de la red anterior existe una orden de posesión correspondiente, se elimina la orden de compra correspondiente a la línea de la red anterior.
Si se activa el parámetro de ajuste automático de la grilla, se recalcula periódicamente el precio límite superior e inferior de la grilla, el intervalo de la grilla y el array de la grilla en función de la cantidad más reciente de datos de la línea K.
El objetivo de obtener ganancias en situaciones de fluctuación. En situaciones de alza y bajada, la capacidad de establecer una posición de mantenimiento y una posición de parada en diferentes puntos de precio en lotes, con lo que se logra una ganancia general.
Se puede elegir entre ajustar manualmente o automáticamente los parámetros de la red. El ajuste manual requiere intervención humana, pero es más controlado; el ajuste automático reduce el trabajo operativo y permite que la estrategia se adapte a los cambios en el entorno del mercado.
Se puede controlar el riesgo unilateral al limitar el número máximo de grillas. El riesgo en esta dirección se controla cuando el precio rompe todas las líneas de la grilla.
Se puede controlar el margen de pérdidas de cada partida ajustando el espacio entre las rejillas. Reducir el espacio entre las rejillas puede reducir las pérdidas individuales.
En situaciones de gran volatilidad, existe el riesgo de ser arbitraje. Si el precio fluctúa rápidamente entre varias grillas, puede haber riesgo de arbitraje.
Es necesario establecer una cantidad razonable de capital inicial. Si el capital inicial es insuficiente, no se puede apoyar la cantidad suficiente de líneas de red.
El exceso de grillas o el exceso de pequeñas grillas no favorecen el beneficio de la estrategia. El exceso de grillas no permite aprovechar al máximo la volatilidad; el exceso de grillas es demasiado pequeño para una ganancia individual. Se requiere prueba para determinar los parámetros óptimos.
Hay un riesgo de manipulación de los parámetros de la grilla de ajuste automático. El cálculo de los parámetros de la grilla depende de un cierto número de líneas K y puede verse afectado por operaciones a corto plazo.
Aumentar la lógica de stop loss, como la configuración de stop floating o stop tracking, para controlar aún más el riesgo de pérdidas unilaterales.
Se puede probar la configuración de los parámetros en las diferentes etapas del mercado, y luego entrenar el modelo con métodos de aprendizaje automático para optimizar los parámetros.
Combine más indicadores para juzgar la situación. Decidir si el MACD, el KD, etc. se encuentra actualmente en una tendencia alcista o bajista para ajustar el número o los parámetros de la grilla.
Optimización de los controles de retiro, como el establecimiento de un porcentaje máximo de retiro, y el cierre de la estrategia cuando se alcanza el umbral, para evitar que las pérdidas se expandan aún más.
Esta estrategia aprovecha al máximo las características de las situaciones de fluctuación y logra el objetivo de obtener ganancias estables a través de la negociación de la red dinámica. La estrategia tiene en cuenta la flexibilidad de la configuración de los parámetros y reduce la intensidad del trabajo de la operación. Se puede decir que en situaciones de fluctuación, esta estrategia es la opción ideal para obtener ganancias.
/*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)