Esta é uma estratégia de negociação de grelha dinâmica adaptativa longa-curta baseada em Pine Script. A ideia central desta estratégia é calcular automaticamente os limites superior e inferior de uma grelha com base nos recentes máximos e mínimos de preços ou em uma média móvel simples, e depois dividir esse intervalo uniformemente em várias linhas de grelha. Quando o preço atinge uma determinada linha de grelha, ele abrirá uma posição longa ou fechará uma posição nesse nível. Desta forma, a estratégia pode abrir e fechar continuamente posições em um mercado de intervalo para capturar o spread de preços. Ao mesmo tempo, ajustando dinamicamente os limites da grelha, também pode se adaptar a diferentes tendências do mercado.
Calcular os limites da grade. Com base na escolha do usuário, os limites podem ser calculados a partir dos pontos mais altos e mais baixos das velas N recentes, com a opção de ampliar ou reduzir o intervalo em uma porcentagem; ou podem ser baseados na média móvel simples dos preços de fechamento das velas N recentes, com a opção de definir as taxas de desvio para cima e para baixo.
De acordo com o número definido de linhas de rede, divida a faixa de rede uniformemente para gerar uma matriz de preços de linhas de rede.
Entrar/Adicionar posição. Atravessar as linhas da grade de baixo para cima. Se o preço de fechamento atual for menor do que um preço da linha da grade e não houver posição nessa linha da grade, abra uma posição longa nesse nível. Dessa forma, quando o preço atingir linhas de grade mais altas, ele continuará adicionando posições.
Se o preço de fechamento atual for maior do que o preço da linha da grade e houver uma posição na linha da grade abaixo, feche a posição longa na linha da grade inferior. Desta forma, quando o preço cair, ele continuará a reduzir as posições.
Ajuste dinâmico: se a função de grade dinâmica for selecionada, os limites superior e inferior da grade e a matriz de linhas da grade serão recalculados em cada vela, de modo que a grade possa se adaptar constantemente às mudanças do mercado.
Forte adaptabilidade. A estratégia de negociação de rede pode se adaptar tanto aos mercados de rangebound quanto aos de tendência. Em um mercado de rangebound, a estratégia de rede pode abrir e fechar continuamente posições para ganhar o spread de preços; em um mercado de tendência, porque a rede segue o movimento de preços, também pode manter uma certa posição para obter ganhos de tendência.
Risco controlado. O tamanho da posição de cada abertura é determinado pelo número definido de grades, de modo que a exposição ao risco individual é pequena e controlável. Ao mesmo tempo, uma vez que alcançar as linhas superiores da grade fechará as posições com lucro, também cobre perdas potenciais até certo ponto.
Este tipo de estratégia pode ser executada totalmente automaticamente sem intervenção manual, o que é adequado para investidores que precisam de retornos constantes a longo prazo.
Parâmetros flexíveis: os utilizadores podem definir de forma flexível o número de linhas de rede, os parâmetros dinâmicos da rede, etc., de acordo com as características do mercado para otimizar o desempenho da estratégia.
Risco de cisne negro. Em caso de um crash extremo do mercado, se o preço cair diretamente abaixo da linha de grelha mais baixa, a estratégia estará em posições completas e enfrentará um drawdown maior. Para reduzir esse risco, uma condição de stop-loss pode ser definida para fechar todas as posições uma vez que a perda atinja um limiar.
A definição dos parâmetros da rede é inadequada. Se a densidade da rede for muito alta, o spread de cada abertura e fechamento será muito pequeno, e os custos de transação podem corroer a maioria dos ganhos. Se a largura da rede for muito grande, a taxa de abertura única é alta e a exposição ao risco é grande. As características do ativo subjacente precisam ser cuidadosamente avaliadas para selecionar parâmetros apropriados da rede.
Risco de base. Esta estratégia define as condições de abertura e fechamento com base no preço atual. Em mercados como futuros, se o preço do contrato difere muito do preço subjacente, os preços reais de abertura e fechamento podem desviar significativamente das expectativas.
Adicionar filtro de tendência. As estratégias de grade não funcionam bem em mercados de tendência unilaterais. Os indicadores de tendência podem ser adicionados como um filtro, como ativar a grade apenas quando o ADX está abaixo de um limiar e fechar a grade quando a tendência é óbvia, mantendo apenas posições unilaterais.
Optimização do sinal. Outros sinais podem ser sobrepostos com base na grade, como grade + média móvel, ou seja, a abertura e fechamento são principalmente determinados pela grade, mas apenas posições abertas quando o preço cruza uma certa média móvel, caso contrário, não abra posições. Isso pode reduzir o custo de abertura e fechamento frequentes.
Atualmente, a posição de cada rede na estratégia é fixa. Pode ser definida para reduzir adequadamente a posição de cada rede quando o preço está longe do preço médio do mercado e aumentar a posição quando está perto do preço médio do mercado para melhorar a eficiência da utilização do capital.
Densidade de rede adaptável. Ajuste dinamicamente a densidade da rede de acordo com a volatilidade dos preços. Quando a volatilidade é alta, o número de redes pode ser apropriadamente aumentado; quando a volatilidade é baixa, o número de redes pode ser reduzido. Isso pode otimizar a largura da rede e melhorar a utilização do capital.
Através de grades dinâmicas adaptativas, esta estratégia pode freqüentemente abrir e fechar posições para ganhar spreads de preço em mercados de faixa, e também pode manter um certo grau de direção de exposição em mercados de tendência para obter ganhos de tendência. É uma estratégia quantitativa de médio a longo prazo com forte adaptabilidade. Ao definir razoavelmente a rede desencadeando lógica e gerenciamento de posição, retornos estáveis podem ser alcançados. No entanto, é necessário prestar atenção aos riscos de condições extremas de mercado e lacunas de preços, o que requer definir condições de stop-loss apropriadas para controlar. Além disso, há mais espaço para otimização na configuração de parâmetros e gerenciamento de risco. A robustez e lucratividade da estratégia podem ser melhoradas através da introdução de filtragem de tendência, sobreposição de sinais, gerenciamento de posição, densidade de rede adaptativa e outros meios. Em resumo, com base na lógica básica das grades, esta estratégia incorpora um mecanismo adaptativo, que pode fornecer novas
// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/ // © jcloyd //@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)