A principal ideia desta estratégia é usar a faixa de ruptura para identificar a direção da tendência e combinar stop loss fixo para gerenciamento de riscos. A estratégia primeiro calcula os preços mais altos e mais baixos em um determinado período para formar uma faixa de ruptura. Quando o preço atravessa a faixa de ruptura, um sinal de negociação é gerado. Além disso, a estratégia permite que os comerciantes definam um montante de stop loss fixo.
A estratégia consiste em quatro partes principais: gestão de posições, identificação da faixa de ruptura, definição de stop loss e dimensionamento de posições.
Em primeiro lugar, a estratégia verifica se há alguma posição aberta, caso existam, não serão gerados novos sinais.
Em segundo lugar, a estratégia calcula os preços mais altos e mais baixos em um período para formar uma faixa de ruptura. Quando o preço sai da faixa, um sinal de negociação é gerado. Especificamente, se o preço quebra acima da faixa superior, um sinal longo é gerado. Se o preço quebra abaixo da faixa inferior, um sinal curto é gerado.
Além disso, quando um sinal longo é gerado, a estratégia define o ponto médio da faixa de ruptura como o stop loss.
Por fim, a estratégia permite definir um valor fixo de stop loss. Quando um sinal é gerado, a estratégia calcula o número de pips do stop loss ao preço atual e combina fatores como o tamanho do tick e a taxa de câmbio, para determinar a mudança de preço entre o stop loss e o preço atual em termos monetários. O tamanho da posição é então calculado com base no valor fixo de stop loss.
Os principais conceitos são identificar a direcção da tendência com bandas de ruptura e controlar o risco com stop loss fixo.
Esta estratégia de stop loss fixa de faixa de ruptura tem as seguintes vantagens:
Concepção avançada de stop loss. A estratégia usa quantidade fixa de stop loss em vez de distância fixa de stop loss. Isso evita o problema de não ser possível fixar o risco em produtos com diferentes valores de tick.
Dimensão razoável da posição: a estratégia pode calcular de forma inteligente o tamanho da posição com base no montante fixo de stop loss, de modo a controlar a perda por transação, gerindo assim razoavelmente a exposição ao risco.
Identificação de breakout com bandas é simples e direta, e pode identificar efetivamente a direção da tendência.
A capacidade da estratégia de ajustar a perda de parada em tempo real para a perda de parada de atraso ajuda a bloquear mais lucros.
Ampla aplicabilidade. A estratégia é aplicável a qualquer produto. Desde que os parâmetros sejam definidos corretamente, o controle de risco de stop loss de quantidade fixa pode ser alcançado, tornando a estratégia altamente versátil.
A estrutura do código é clara e modular, tornando-a fácil de entender e otimizar.
Apesar das vantagens, há alguns riscos a observar para a estratégia:
A estratégia não julga a qualidade do padrão de ruptura e pode gerar alguns sinais de baixa qualidade. Outros indicadores são necessários para filtrar sinais.
A perda fixa pode ser muito mecânica. Os preços de mercado geralmente diferem. A perda fixa pode depender demais de regras e não ter flexibilidade no ajuste.
A estratégia não limita a frequência do comércio e pode negociar com demasiada frequência.
A fixação do montante do stop loss é crucial para o controlo geral do risco e deve considerar o tamanho do capital, o apetite pelo risco, etc.
A direção do breakout pode dar sinais errados. Sinais errados de breakout podem ocorrer durante oscilações de preços ou retrações. Mais condições são necessárias para otimizar a estratégia.
A estratégia atualmente não possui capacidade de captação de lucros para bloquear ativamente os lucros. Isso pode levar a lucros insatisfatórios.
Para enfrentar estes riscos, algumas formas de otimizar a estratégia incluem:
Adição de indicadores para filtrar a qualidade do sinal, por exemplo MACD, KD, etc.
Incorporar indicadores de resistência de ruptura para avaliar a qualidade, por exemplo, julgar a resistência através de alterações de volume.
Adicionar limites de frequência de negociação aberta, por exemplo, uma negociação por dia.
Otimizar a lógica de stop loss fixa, por exemplo, stop loss baseado em percentagem acima de um limiar.
Adição de outros filtros, por exemplo, volatilidade, melhoria do stop loss, etc.
Incorporar estratégias de obtenção de lucro, por exemplo, obtenção de lucro perto da resistência.
Com base na análise, a estratégia pode ser otimizada nos seguintes aspectos:
Adicionar filtros para melhorar a qualidade do sinal usando múltiplos indicadores técnicos e avaliar a qualidade da tendência.
Optimizar stop loss para maior flexibilidade. Pode mudar para stop de trailing baseado em porcentagem após um certo retracement. Também pode otimizar dinamicamente com base na volatilidade.
Controlar a frequência de negociação para evitar a troca excessiva adicionando filtros em períodos de tempo ou frequência.
Incorporar indicadores de tendência para melhorar o calendário, por exemplo, aguardar a confirmação da tendência.
Otimizar as estratégias de captação de lucro para melhorar a rentabilidade através de meta de lucro, parada de lucro, parada de volatilidade, etc.
Optimização dos parâmetros de risco com base em backtests, tais como quantidade fixa de stop, período de ruptura, etc.
Refatoração do código para uma melhor extensibilidade através da desconexão adicional dos módulos de sinal, filtro, risco e lucro.
Testar mais produtos para oportunidades de arbitragem.
Através dessas dimensões de otimização, a estratégia de stop loss pode se tornar mais robusta e lucrativa.
Em geral, a estratégia é razoável em usar bandas de ruptura para identificar tendências e paradas de quantidade fixa para controle de risco. Os conceitos são progressivos para gerenciamento de risco. A lógica de dimensionamento de posição também é boa para controlar a perda por comércio. Mas a estratégia pode ser aprimorada por meio de várias otimizações para melhorar a qualidade do sinal, flexibilidade no stop loss, lucratividade, etc. Ao incorporar filtros de tendência, melhorar a tomada de lucro e controlar estritamente a frequência do comércio, uma melhoria significativa pode ser alcançada. Em conclusão, a estratégia fornece uma estrutura para aprender técnicas de gerenciamento de risco e dimensionamento de posição, estabelecendo as bases para mais pesquisas em sistemas de arbitragem e multi-estratégia mais complexos.
/*backtest start: 2023-10-26 00:00:00 end: 2023-10-28 03:00:00 period: 10m basePeriod: 1m 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/ //@version=4 //@author=Takazudo strategy("Fixed price SL", overlay=true, default_qty_type=strategy.fixed, initial_capital=0, currency=currency.USD) var COLOR_TRANSPARENT = color.new(#000000, 100) var COLOR_ENTRY_BAND = color.new(#43A6F5, 30) //============================================================================ // config //============================================================================ // Money management _g1 = 'Money management' var config_riskPrice = input(100, minval=1, title="Risk price for each entry", group=_g1) var config_depositCurrency = input(title="Deposit currency", type=input.string, defval="USD", options=["USD"], group=_g1) // Entry strategy _g2 = 'Entry strategy' var config_entryBandBars = input(defval = 100, title = "Entry band bar count", minval=1, group=_g2) // Backtesting range _g3 = 'Backtesting range' fromYear = input(defval = 2018, title = "From Year", minval = 1970, group=_g3) fromMonth = input(defval = 1, title = "From Month", minval = 1, maxval = 12, group=_g3) fromDay = input(defval = 1, title = "From Day", minval = 1, maxval = 31, group=_g3) toYear = input(defval = 2020, title = "To Year", minval = 1970, group=_g3) toMonth = input(defval = 12, title = "To Month", minval = 1, maxval = 12, group=_g3) toDay = input(defval = 31, title = "To Day", minval = 1, maxval = 31, group=_g3) //============================================================================ // exchange caliculations //============================================================================ // mico pip size caliculation // ex1: AUDCAD -> 0.0001 // ex2: USDJPY -> 0.01 f_calcMicroPipSize() => _base = syminfo.basecurrency _quote = syminfo.currency _result = 0.0001 if _quote == 'JPY' _result := _result * 100 if _base == 'BTC' _result := _result * 100 _result // convert price to pips f_convertPriceToPips(_price) => _microPipSize = f_calcMicroPipSize() _price / _microPipSize // caliculate exchange rate between deposit and quote currency f_calcDepositExchangeSymbolId() => _result = '' _deposit = config_depositCurrency _quote = syminfo.currency if (_deposit == 'USD') and (_quote == 'USD') _result := na if (_deposit == 'USD') and (_quote == 'AUD') _result := 'OANDA:AUDUSD' if (_deposit == 'EUR') and (_quote == 'USD') _result := 'OANDA:EURUSD' if (_deposit == 'USD') and (_quote == 'GBP') _result := 'OANDA:GBPUSD' if (_deposit == 'USD') and (_quote == 'NZD') _result := 'OANDA:NZDUSD' if (_deposit == 'USD') and (_quote == 'CAD') _result := 'OANDA:USDCAD' if (_deposit == 'USD') and (_quote == 'CHF') _result := 'OANDA:USDCHF' if (_deposit == 'USD') and (_quote == 'JPY') _result := 'OANDA:USDJPY' _result // Let's say we need CAD to USD exchange // However there's only "OANDA:USDCAD" symbol. // Then we need to invert the exhchange rate. // this function tells us whether we should invert the rate or not f_calcShouldInvert() => _result = false _deposit = config_depositCurrency _quote = syminfo.currency if (_deposit == 'USD') and (_quote == 'CAD') _result := true if (_deposit == 'USD') and (_quote == 'CHF') _result := true if (_deposit == 'USD') and (_quote == 'JPY') _result := true _result // caliculate how much quantity should I buy or sell f_calcQuantitiesForEntry(_depositExchangeRate, _slPips) => _microPipSize = f_calcMicroPipSize() _priceForEachPipAsDeposit = _microPipSize * _depositExchangeRate _losePriceOnSl = _priceForEachPipAsDeposit * _slPips floor(config_riskPrice / _losePriceOnSl) //============================================================================ // Quantity caliculation //============================================================================ depositExchangeSymbolId = f_calcDepositExchangeSymbolId() // caliculate deposit exchange rate rate = security(depositExchangeSymbolId, timeframe.period, hl2) shouldInvert = f_calcShouldInvert() depositExchangeRate = if config_depositCurrency == syminfo.currency // if USDUSD, no exchange of course 1 else // else, USDCAD to CADUSD invert if we need shouldInvert ? (1 / rate) : rate //============================================================================ // Range Edge caliculation //============================================================================ f_calcEntryBand_high() => _highest = max(open[3], close[3]) for i = 4 to (config_entryBandBars - 1) _highest := max(_highest, open[i], close[i]) _highest f_calcEntryBand_low() => _lowest = min(open[3], close[3]) for i = 4 to (config_entryBandBars - 1) _lowest := min(_lowest, open[i], close[i]) _lowest entryBand_high = f_calcEntryBand_high() entryBand_low = f_calcEntryBand_low() entryBand_height = entryBand_high - entryBand_low plot(entryBand_high, color=COLOR_ENTRY_BAND, linewidth=1) plot(entryBand_low, color=COLOR_ENTRY_BAND, linewidth=1) rangeBreakDetected_long = entryBand_high < close rangeBreakDetected_short = entryBand_low > close shouldMakeEntryLong = (strategy.position_size == 0) and rangeBreakDetected_long shouldMakeEntryShort = (strategy.position_size == 0) and rangeBreakDetected_short //============================================================================ // SL & Quantity //============================================================================ var sl_long = hl2 var sl_short = hl2 entryQty = 0 slPips = 0.0 // just show info bubble f_showEntryInfo(_isLong) => _str = 'SL pips: ' + tostring(slPips) + '\n' + 'Qty: ' + tostring(entryQty) _bandHeight = entryBand_high - entryBand_low _y = _isLong ? (entryBand_low + _bandHeight * 1/4) : (entryBand_high - _bandHeight * 1/4) _style = _isLong ? label.style_label_up : label.style_label_down label.new(bar_index, _y, _str, size=size.large, style=_style) if shouldMakeEntryLong sl_long := (entryBand_high + entryBand_low) / 2 slPips := f_convertPriceToPips(close - sl_long) entryQty := f_calcQuantitiesForEntry(depositExchangeRate, slPips) if shouldMakeEntryShort sl_short := (entryBand_high + entryBand_low) / 2 slPips := f_convertPriceToPips(sl_short - close) entryQty := f_calcQuantitiesForEntry(depositExchangeRate, slPips) // trailing SL if strategy.position_size > 0 sl_long := max(sl_long, entryBand_low) if strategy.position_size < 0 sl_short := min(sl_short, entryBand_high) //============================================================================ // backtest duration //============================================================================ // Calculate start/end date and time condition startDate = timestamp(fromYear, fromMonth, fromDay, 00, 00) finishDate = timestamp(toYear, toMonth, toDay, 00, 00) //============================================================================ // make entries //============================================================================ if (true) if shouldMakeEntryLong strategy.entry(id="Long", long=true, stop=close, qty=entryQty) f_showEntryInfo(true) if shouldMakeEntryShort strategy.entry(id="Short", long=false, stop=close, qty=entryQty) f_showEntryInfo(false) strategy.exit('Long-SL/TP', 'Long', stop=sl_long) strategy.exit('Short-SL/TP', 'Short', stop=sl_short) //============================================================================ // plot misc //============================================================================ sl = strategy.position_size > 0 ? sl_long : strategy.position_size < 0 ? sl_short : na plot(sl, color=color.red, style=plot.style_cross, linewidth=2, title="SL") value_bgcolor = rangeBreakDetected_long ? color.green : rangeBreakDetected_short ? color.red : COLOR_TRANSPARENT bgcolor(value_bgcolor, transp=95)