O recurso está a ser carregado... Carregamento...

Estratégia de média móvel de ruptura em espiral

Autora:ChaoZhang, Data: 2024-01-15 11:45:23
Tags:

img

Resumo

Esta estratégia combina o indicador do canal espiral e o indicador da taxa de mudança (ROC). Gerar sinais de compra quando o preço atravessa a faixa superior e a média móvel, e sinais de venda quando o preço atravessa a faixa inferior e a média móvel.

Estratégia lógica

A estratégia baseia-se em dois indicadores-chave:

  1. Canais espirais: traçar as faixas superior e inferior para determinar a direção da tendência.

  2. Taxa de Mudança (ROC): Detecta aceleração de preços. ROC acima de um limiar positivo sugere aceleração do movimento de preços para cima, enquanto ROC abaixo de um limiar negativo indica aceleração do movimento para baixo.

Os sinais de compra são gerados quando o canal espiral e o ROC dão indicações de alta, ou seja, a quebra do preço acima da faixa superior, juntamente com a aceleração do ímpeto ascendente.

Os sinais combinados ajudam a evitar a negociação contra a tendência e a melhorar a fiabilidade.

Vantagens

  1. Sinais confiáveis com maior taxa de ganho, exigindo acordo entre tendência e impulso.

  2. Frequência de negociação personalizável através de ajuste de parâmetros, por exemplo, ajuste de parâmetros ROC.

  3. Parar perdas para limitar o risco de queda em operações individuais.

  4. Re-entrar no mecanismo para acompanhar as tendências e aumentar ainda mais a rentabilidade.

Riscos

  1. Perda de algumas oportunidades de negociação e limitação do potencial de lucro devido ao requisito de fiabilidade do sinal.

  2. Vulnerável a ser preso quando a tendência se inverte, levando potencialmente a grandes perdas.

  3. A má regulação dos parâmetros pode resultar em muito poucos ou muitos sinais.

  4. Percentagem fixa de stop loss incapaz de evitar perdas graves em grandes oscilações adversas de preços.

Oportunidades de melhoria

  1. Otimizar os parâmetros ROC para melhor desempenho.

  2. Teste diferentes níveis de stop loss para equilibrar risco e recompensa.

  3. Adicione outros filtros como volume, indicadores de volatilidade para refinar os sinais.

  4. Avaliar o desempenho em diferentes mercados para encontrar o melhor ajuste.

  5. Introduzir o dimensionamento dinâmico das posições para diferentes condições de mercado.

Conclusão

A estratégia combina o canal espiral e o ROC para avaliar a direção e o impulso da tendência. O objetivo é a confiabilidade do sinal, mantendo a lucratividade através da reentrada e ajuste de parâmetros. O risco é controlado principalmente por stop loss de porcentagem fixa. No geral, é uma estrutura relativamente completa digna como uma estratégia de negociação quantitativa de base.


/*backtest
start: 2024-01-07 00:00:00
end: 2024-01-14 00:00:00
period: 45m
basePeriod: 5m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=4
strategy("SSL Chaikin BF 🚀", overlay=true, precision=2, initial_capital=10000, default_qty_type=strategy.percent_of_equity, default_qty_value=100, commission_type=strategy.commission.percent, commission_value=0.075)

/////////////// Time Frame ///////////////
_0 = input(false,  "════════ Test Period ═══════")
testStartYear = input(2017, "Backtest Start Year") 
testStartMonth = input(1, "Backtest Start Month")
testStartDay = input(1, "Backtest Start Day")
testPeriodStart = timestamp(testStartYear,testStartMonth,testStartDay, 0, 0)

testStopYear = input(2019, "Backtest Stop Year")
testStopMonth = input(12, "Backtest Stop Month")
testStopDay = input(31, "Backtest Stop Day")
testPeriodStop = timestamp(testStopYear,testStopMonth,testStopDay, 0, 0)

testPeriod() => true

/////////////// Chaikin MF /////////////// 
_1 = input(false,  "═══════ Chaikin MF ═══════")
length = input(20, minval=1, title = "Chaikin SMA Length")
upperThreshold = input(0.04, step=0.01, title="Upper Threshold")
lowerThreshold = input(0.02, step=0.01, title="Lower Threshold")
ad = close==high and close==low or high==low ? 0 : ((2*close-low-high)/(high-low))*volume
mf = sum(ad, length) / sum(volume, length)

/////////////// SSL Channels /////////////// 
_2 = input(false,  "═════════ SSL ══════════")
len1=input(title="SMA Length 1", defval=12)
len2=input(title="SMA Length 2", defval=13)

smaHigh = sma(high, len1)
smaLow = sma(low, len2)

Hlv = 0
Hlv := close > smaHigh ? 1 : close < smaLow ? -1 : Hlv[1]
sslDown = Hlv < 0 ? smaHigh : smaLow
sslUp = Hlv < 0 ? smaLow : smaHigh

///////////// Rate Of Change ///////////// 
_3 = input(false,  "══════ Rate of Change ══════")
source = close
roclength = input(13, "ROC Length",  minval=1)
pcntChange = input(4, "ROC % Change", minval=1)
roc = 100 * (source - source[roclength]) / source[roclength]
emaroc = ema(roc, roclength / 2)
isMoving() => emaroc > (pcntChange / 2) or emaroc < (0 - (pcntChange / 2))

///////////////  Strategy  /////////////// 
long = sslUp > sslDown and isMoving() or crossover(mf, upperThreshold)
short = sslUp < sslDown and isMoving() or crossunder(mf, lowerThreshold)

last_long = 0.0
last_short = 0.0
last_long := long ? time : nz(last_long[1])
last_short := short ? time : nz(last_short[1])

long_signal = crossover(last_long, last_short)
short_signal = crossover(last_short, last_long)

last_open_long_signal = 0.0
last_open_short_signal = 0.0
last_open_long_signal := long_signal ? open : nz(last_open_long_signal[1])
last_open_short_signal := short_signal ? open : nz(last_open_short_signal[1])

last_long_signal = 0.0
last_short_signal = 0.0
last_long_signal := long_signal ? time : nz(last_long_signal[1])
last_short_signal := short_signal ? time : nz(last_short_signal[1])

in_long_signal = last_long_signal > last_short_signal
in_short_signal = last_short_signal > last_long_signal

last_high = 0.0
last_low = 0.0
last_high := not in_long_signal ? na : in_long_signal and (na(last_high[1]) or high > nz(last_high[1])) ? high : nz(last_high[1])
last_low := not in_short_signal ? na : in_short_signal and (na(last_low[1]) or low < nz(last_low[1])) ? low : nz(last_low[1])

since_longEntry = barssince(last_open_long_signal != last_open_long_signal[1]) 
since_shortEntry = barssince(last_open_short_signal != last_open_short_signal[1]) 

//////////////// Stop loss /////////////// 
_4 = input(false,  "════════ Stop Loss ═══════")
sl_inp = input(2.0, title='Stop Loss %') / 100

slLong = in_long_signal ? strategy.position_avg_price * (1 - sl_inp) : na
slShort = strategy.position_avg_price * (1 + sl_inp)
long_sl = in_long_signal ? slLong : na
short_sl = in_short_signal ? slShort : na

/////////////// Execution /////////////// 
if testPeriod()
    strategy.entry("L", strategy.long, when=long)
    strategy.entry("S", strategy.short, when=short)
    strategy.exit("L SL", "L", stop=long_sl, when=since_longEntry > 0)
    strategy.exit("S SL", "S", stop=short_sl, when=since_shortEntry > 0)

/////////////// Plotting /////////////// 
p1 = plot(sslDown, linewidth = 1, color=color.red)
p2 = plot(sslUp, linewidth = 1, color=color.lime)
fill(p1, p2,  color = sslDown < sslUp ? color.lime : color.red, transp=80)
bgcolor(isMoving() ? long ? color.green : short ? color.red : na : color.white, transp=80)
bgcolor(long_signal ? color.lime : short_signal ? color.red : na, transp=30)
bgcolor(crossover(mf, upperThreshold) ? color.blue : crossunder(mf, lowerThreshold) ? color.orange : na, transp=30)

Mais.