Estratégia de inversão de faixa latente

Autora:ChaoZhang, Data: 2023-10-30 10:54:00
Tags:

img

Resumo

A estratégia de reversão de faixa adormecida utiliza períodos de diminuição da volatilidade como sinais de entrada e visa lucrar quando a volatilidade retoma novamente. Identifica situações em que o preço está contido dentro de uma faixa adormecida estreita e capta a tendência de preços futura. Esta estratégia funciona bem quando a volatilidade atual é baixa, mas uma ruptura é esperada.

Estratégia lógica

A estratégia primeiro identifica um intervalo latente, que é quando o preço está contido dentro do intervalo de preços do dia de negociação anterior. Isso indica que a volatilidade diminuiu em comparação com alguns dias atrás. Verificamos se o alto do dia atual < alto de n dias atrás (normalmente 4 dias) e o baixo do dia atual > baixo de n dias atrás para se qualificar como um intervalo latente.

Uma vez que um intervalo latente é identificado, a estratégia coloca duas ordens pendentes - uma parada de compra perto do topo do intervalo e uma parada de venda perto da parte inferior do intervalo.

Após a entrada, as ordens de stop loss e take profit são colocadas. O stop loss controla o risco de queda e o take profit fecha a negociação para obter lucro. O stop loss é colocado a uma distância de % do preço de entrada, conforme definido nos parâmetros de risco. O take profit é colocado a uma distância igual ao tamanho do intervalo latente, pois esperamos que o preço se mova de forma semelhante à volatilidade anterior.

Por fim, um modelo de dimensionamento de posição fracionário fixo gerencia o tamanho da negociação.

Vantagens

As vantagens desta estratégia são as seguintes:

  1. Captura a tendência futura utilizando como sinal a volatilidade reduzida.

  2. As ordens bidirecionais captam tendências ascendentes ou descendentes.

  3. O controlo de perdas e lucros do risco de negociação única.

  4. O dimensionamento fracionário fixo melhora a eficiência do capital.

  5. Lógica simples, fácil de implementar.

Riscos

Os riscos a considerar são:

  1. Direção errada de fuga se a fuga não for clara.

  2. A ruptura pode ser apenas uma reversão curta, não uma tendência duradoura.

  3. Risco de ser eliminado por grandes movimentos.

  4. O dimensionamento de frações fixas pode amplificar as perdas quando se somam às operações perdedoras.

  5. Desempenho fraco se os parâmetros não forem definidos adequadamente.

Oportunidades de melhoria

Algumas formas de melhorar a estratégia:

  1. Adicione filtros como divergência para evitar falsas fugas.

  2. Melhorar o stop loss com perdas de trailing ou stop order.

  3. Adicionar um filtro de tendência para evitar entradas contra tendência.

  4. Otimizar os rácios de fracção fixa para equilibrar o risco/recompensa.

  5. Olhe para vários prazos para melhorar a vantagem.

  6. Utilize o aprendizado de máquina para otimização automatizada de parâmetros.

Conclusão

A estratégia de reversão de faixa adormecida tem uma lógica clara e potencial de lucro. O ajuste fino através de otimizações, gerenciamento de risco e filtragem de sinal pode melhorar ainda mais a consistência.


/*backtest
start: 2023-09-29 00:00:00
end: 2023-10-29 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © gsanson66


//This code is based on the Narrow Range strategy
//Interactive Broker fees are applied on this strategy
//@version=5
strategy("NARROW RANGE BACKTESTING", shorttitle="NR BACKTESTING", overlay=true, initial_capital=1000, default_qty_type=strategy.fixed, commission_type=strategy.commission.percent, commission_value=0.18)


//--------------------------------FUNCTIONS------------------------------------//

//@function to print label
debugLabel(txt, color) =>
    label.new(bar_index, high, text = txt, color=color, style = label.style_label_lower_right, textcolor = color.black, size = size.small)

//@function which looks if the close date of the current bar falls inside the date range
inBacktestPeriod(start, end) => (time >= start) and (time <= end)


//--------------------------------USER INPUTS------------------------------------//

//Narrow Range Length 
nrLength = input.int(4, minval=2, title="Narrow Range Length", group="Strategy parameters")
//Risk Management
stopLossInput = input.float(0.5, title="Stop Loss (in percentage of reference range)", group="Strategy parameters")
//Money Management
fixedRatio = input.int(defval=400, minval=1, title="Fixed Ratio Value ($)", group="Money Management")
increasingOrderAmount = input.int(defval=200, minval=1, title="Increasing Order Amount ($)", group="Money Management")
//Backtesting period
startDate = input(title="Start Date", defval=timestamp("1 Janv 2020 00:00:00"), group="Backtesting Period")
endDate = input(title="End Date", defval=timestamp("1 July 2024 00:00:00"), group="Backtesting Period")


//--------------------------------VARIABLES INITIALISATION--------------------------//
strategy.initial_capital = 50000
bool nr = na
var bool long = na
var bool short = na
var float stopPriceLong = na
var float stopLossLong = na
var float takeProfitLong = na
var float stopPriceShort = na
var float stopLossShort = na
var float takeProfitShort = na
var float takeProfit = na
var float stopLoss = na
bool inRange = na
int closedtrades = strategy.closedtrades
equity = math.abs(strategy.equity - strategy.openprofit)
var float capital_ref = strategy.initial_capital
var float cashOrder = strategy.initial_capital * 0.95


//------------------------------CHECKING SOME CONDITIONS ON EACH SCRIPT EXECUTION-------------------------------//

//Checking if the date belong to the range
inRange := true

//Checking performances of the strategy
if equity > capital_ref + fixedRatio
    spread = (equity - capital_ref)/fixedRatio
    nb_level = int(spread)
    increasingOrder = nb_level * increasingOrderAmount
    cashOrder := cashOrder + increasingOrder
    capital_ref := capital_ref + nb_level*fixedRatio
if equity < capital_ref - fixedRatio
    spread = (capital_ref - equity)/fixedRatio
    nb_level = int(spread)
    decreasingOrder = nb_level * increasingOrderAmount
    cashOrder := cashOrder - decreasingOrder
    capital_ref := capital_ref - nb_level*fixedRatio

//We check if a trade has been closed to cancel all previous orders
if closedtrades > closedtrades[1]
    strategy.cancel("Long")
    strategy.cancel("Short")
    stopPriceLong := na
    stopPriceShort := na

//Checking if we close all trades in case where we exit the backtesting period
if strategy.position_size!=0 and not inRange
    debugLabel("END OF BACKTESTING PERIOD : we close the trade", color=color.rgb(116, 116, 116))
    strategy.close_all()
    long := na
    short := na
    stopPriceLong := na
    stopLossLong := na
    takeProfitLong := na
    stopPriceShort := na
    stopLossShort := na
    takeProfitShort := na
    takeProfit := na
    stopLoss := na

//----------------------------------FINDING NARROW RANGE DAY------------------------------------------//

// We find the Narrow Range Day
if low > low[nrLength] and high < high[nrLength]
    nr := true 


//------------------------------------STOP ORDERS--------------------------------------------//

// We handle plotting of stop orders and cancellation of other side order if one order is triggered
if strategy.position_size > 0 and not na(stopPriceLong) and not na(stopPriceShort)
    long := true
    strategy.cancel("Short")
    stopPriceLong := na
    stopPriceShort := na
    takeProfit := takeProfitLong
    stopLoss := stopLossLong
if strategy.position_size < 0 and not na(stopPriceLong) and not na(stopPriceShort)
    short := true
    strategy.cancel("Long") 
    stopPriceLong := na
    stopPriceShort := na
    takeProfit := takeProfitShort
    stopLoss := stopLossShort


//------------------------------------STOP LOSS & TAKE PROFIT--------------------------------//

// If an order is triggered we plot TP and SL
if not na(takeProfit) and not na(stopLoss) and long
    if high >= takeProfit and closedtrades == closedtrades[1] + 1
        takeProfit := na
        stopLoss := na
        long := na
    if low <= stopLoss and closedtrades == closedtrades[1] + 1
        takeProfit := na
        stopLoss := na
        long := na
if not na(takeProfit) and not na(stopLoss) and short
    if high >= stopLoss and closedtrades == closedtrades[1] + 1
        takeProfit := na
        stopLoss := na
        short := na
    if low <= takeProfit and closedtrades == closedtrades[1] + 1
        takeProfit := na
        stopLoss := na
        short := na


//-----------------------------LONG/SHORT CONDITION-------------------------//

// Conditions to create two stop orders (one for Long and one for Short) and SL & TP calculation
if nr and inRange and strategy.position_size == 0
    stopPriceLong := high[4]
    takeProfitLong := high[4] + (high[4] - low[4])
    stopLossLong := high[4] - (high[4] - low[4])*stopLossInput
    qtyLong = cashOrder/stopPriceLong
    strategy.entry("Long", strategy.long, qtyLong, stop=stopPriceLong)
    strategy.exit("Exit Long", "Long", limit=takeProfitLong ,stop=stopLossLong)
    stopPriceShort := low[4]
    takeProfitShort := low[4] - (high[4] - low[4])
    stopLossShort := low[4] + (high[4] - low[4])*stopLossInput
    qtyShort = cashOrder/stopPriceShort
    strategy.entry("Short", strategy.short, qtyShort, stop=stopPriceShort)
    strategy.exit("Exit Short", "Short", limit=takeProfitShort ,stop=stopLossShort)


//--------------------------PLOTTING ELEMENT----------------------------//

plotshape(nr, "NR", shape.arrowdown, location.abovebar, color.rgb(255, 132, 0), text= "NR4", size=size.huge)
plot(stopPriceLong, "Stop Order", color.blue, 3, plot.style_linebr)
plot(stopPriceShort, "Stop Order", color.blue, 3, plot.style_linebr)
plot(takeProfit, "Take Profit", color.green, 3, plot.style_linebr)
plot(stopLoss, "Stop Loss", color.red, 3, plot.style_linebr)

Mais.