
A principal ideia desta estratégia é usar a direção da tendência de identificação de bandas de ruptura para gerenciar o risco, em combinação com um stop loss fixo. A estratégia primeiro calcula o preço máximo e o preço mínimo em um determinado período, formando uma banda de ruptura. Quando o preço quebra a banda de ruptura, um sinal de negociação é gerado.
A estratégia consiste em quatro partes principais: gerenciamento de posições, identificação de bandas de ruptura, configuração de stop loss e quantificação.
Em primeiro lugar, a estratégia deve determinar se há uma posição atual ou não. Se já houver uma posição, nenhum novo sinal será gerado.
Em segundo lugar, a estratégia calcula o preço máximo e o preço mínimo em um determinado período, formando uma faixa de ruptura. Quando o preço se move de dentro para fora da faixa de ruptura, um sinal de negociação é gerado.
Além disso, quando se produzem vários sinais, a estratégia define o ponto médio da faixa de ruptura como um ponto de parada. Quando se produz um sinal de curto prazo, o ponto de parada também é definido. Para rastrear o ponto de parada, a estratégia também ajusta o ponto de parada em tempo real durante a posse.
Finalmente, a estratégia permite definir um valor de stop-loss fixo. Quando o sinal é gerado, a estratégia calcula a distância entre o ponto de stop-loss e o preço atual, em combinação com fatores como a unidade de cotação e a taxa de câmbio, para calcular o valor representado pela mudança de preço entre os pontos de stop-loss.
A estratégia é baseada no princípio de que o risco é controlado através da identificação da direção da tendência através da ruptura da faixa e do uso de stop loss fixo.
Esta estratégia de stop loss fixo com faixa de ruptura tem as seguintes vantagens:
A estratégia é usar um valor fixo de stop loss em vez de uma distância fixa de stop loss. Isso evita o problema do risco não fixo causado pela diferença de valor de ponto entre diferentes variedades. Do ponto de vista da gestão de risco, o valor fixo de stop loss é mais avançado.
A estratégia é capaz de calcular inteligentemente o número de transações com base no valor fixo de stop loss, permitindo que cada perda seja controlada, permitindo assim um controle razoável da abertura de risco.
A identificação de breakouts é simples e eficaz. A identificação de bandas de ruptura é simples e direta, permitindo a identificação eficaz da direção da tendência. Comparado a apenas a ruptura de um determinado nível de preço, essa identificação de bandas de ruptura evita mais falsos sinais que saem da direção da tendência.
A estratégia pode ajustar a posição de parada em tempo real, para rastrear a parada, ajudando a bloquear mais lucros.
Ampliação de aplicabilidade. A estratégia pode ser aplicada a qualquer variedade, desde que os parâmetros sejam bem definidos, o controle de risco de perda de quantidade fixa pode ser feito, portanto, tem uma aplicação muito ampla.
A estrutura do código é clara. A estrutura do código da estratégia é razoavelmente clara, os módulos funcionais são bem resolvidos, facilitando a compreensão e a otimização posterior.
Apesar dos benefícios mencionados acima, a estratégia apresenta alguns riscos a serem levados em conta:
Não é possível avaliar a qualidade da forma de ruptura. A estratégia não pode avaliar a qualidade da forma de ruptura, podendo gerar sinais de baixa qualidade. É necessário realizar filtragem em combinação com outros indicadores.
O stop-loss fixo pode ser muito mecânico. Os preços de mercado tendem a ter características de salto alto. O stop-loss fixo pode ser muito dependente das regras e não pode ser ajustado com flexibilidade.
Não é possível limitar a frequência das negociações. A estratégia não é possível limitar a frequência das negociações, podendo ocorrer muito frequentemente. A frequência de limitação deve ser combinada com outras regras.
A definição do limite de perda fixo depende dos parâmetros. A definição do limite de perda fixa é relacionada ao controle de abertura geral e precisa ser razoavelmente ajustada de acordo com o tamanho do capital, as preferências de risco e outros aspectos.
A direção de ruptura pode gerar um sinal de ruptura errónea. Quando o preço se move ou correção, pode gerar um sinal de ruptura errada.
A falta de um parâmetro de parada. A estratégia atualmente não tem um parâmetro de parada e não pode determinar o lucro de forma ativa. Isso pode levar a lucros desejáveis.
Para os riscos acima mencionados, podemos otimizar em vários aspectos:
Adicionar indicadores para julgar a forma, filtrar a qualidade do sinal. Por exemplo, MACD, KD, etc.
Combinando o indicador de força de ruptura com a avaliação da qualidade da ruptura. Por exemplo, a mudança na quantidade de transações é usada para avaliar a força da ruptura.
Aumentar a frequência de abertura de posições. Por exemplo, apenas uma transação por dia ou regras similares.
Optimizar a lógica de configuração de stop-loss fixo. Por exemplo, mudar o stop-loss para o stop-loss percentual de acordo com um determinado limite.
Adicionar outras condições de filtragem, como aumento de stop loss, taxa de flutuação de preços, etc.
Adicionar estratégias de suspensão. Por exemplo, suspensão quando se aproxima da resistência.
De acordo com a análise acima, a estratégia pode ser otimizada em vários aspectos:
Aumentar as condições de filtragem para melhorar a qualidade do sinal. Pode ser adicionado vários indicadores técnicos para julgar a qualidade da tendência e evitar sinais de ruptura indesejáveis. Também pode ser julgado a intensidade da ruptura.
Optimizar a estratégia de stop loss, tornando-a mais flexível. Pode ser alterado para stop loss proporcional depois de um determinado intervalo de retração. Pode também ser otimizado em tempo real de acordo com a taxa de flutuação.
Controlar a frequência de negociação para evitar o excesso de negociação. Pode definir condições de filtragem para períodos de tempo ou para reduzir a frequência de negociação.
Combinando os indicadores de tendência, escolha o momento de entrada. Por exemplo, otimize para entrar novamente após a confirmação da tendência.
Otimizar a estratégia de stop-loss e aumentar a rentabilidade. Pode definir o lucro-alvo, mover o stop-loss, oscilação do stop-loss, etc.
Otimizar a configuração dos parâmetros de risco. Pode-se definir um conjunto de parâmetros mais adequado de acordo com os resultados da avaliação, como o valor fixo de parada, o ciclo de ruptura, etc.
Melhorar a estrutura do código, aumentar a escalabilidade. Desbloquear ainda mais os módulos de geração de sinais, filtragem, controle de vento e ganho.
Teste mais espaços de arbitragem de variedades. Avalie as vantagens de arbitragem de diferentes combinações de variedades.
Otimizando todos os aspectos acima, pode-se aumentar ainda mais a estabilidade e a lucratividade desta estratégia de parada de perdas de ruptura. Ao mesmo tempo, a base para a futura expansão para mais pacotes de estratégias é construída.
A estratégia global é razoável, usando a identificação de tendências de bandas de ruptura e o uso de perda de quantidade fixa para o controle de risco. Isso é avançado na gestão de risco. A ideia de calcular o número de transações ao mesmo tempo também é razoável e pode controlar cada perda. Mas a estratégia pode ser otimizada em vários aspectos para melhorar a qualidade do sinal, a flexibilidade da estratégia de parada e a equidade de lucro.
/*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)