Estratégia de cruzamento do ângulo de tendência da média móvel

Autora:ChaoZhang, Data: 2024-01-25 14:35:13
Tags:

img

Resumo

Esta estratégia determina a direção da tendência calculando o ângulo de inclinação das médias móveis, combinado com o indicador de taxa de mudança de preço para negociação longa e curta.

Estratégia lógica

A estratégia baseia-se principalmente nos seguintes indicadores de avaliação:

  1. Ângulo de inclinação da média móvel: Calcule os ângulos de inclinação da média móvel de Jurik e da média móvel exponencial para determinar a direção da tendência do preço.

  2. Taxa de variação de preço: Calcular a taxa de variação do preço de fechamento nos últimos 12 bares para filtrar os sinais por volatilidade.

Quando a inclinação da média móvel subir (maior que 0) e a taxa de mudança de preço atender aos critérios, vá longo.

Especificamente, a estratégia primeiro calcula os ângulos de inclinação do Jurik MA e da EMA. Em seguida, o indicador de taxa de mudança de preço é calculado para filtrar o período limitado ao intervalo. Quando ambos os sinais de inclinação média móvel tendência e taxa de mudança de preço atende aos critérios, o sinal de negociação é gerado.

Análise das vantagens

As vantagens desta estratégia:

  1. Usando MA inclinação para determinar a tendência é muito confiável com boa taxa de vitória.

  2. O indicador de taxa de variação de preços filtra efetivamente a flutuação do intervalo para evitar transações inválidas.

  3. Jurik MA dá uma resposta rápida à ruptura, enquanto a EMA oferece um julgamento de tendência estável, ambos complementares.

  4. Ir longo e curto no mercado de tendências poderia capturar um lucro maior.

Análise de riscos

Alguns riscos desta estratégia:

  1. Em casos extremos, o MA pode gerar sinais errados, que podem ser reduzidos pela otimização de parâmetros.

  2. Os sinais podem mudar frequentemente durante a variação, causando negociações desnecessárias.

  3. O stop loss pode ser quebrado em eventos repentinos de diferença de preço.

Orientações de otimização

A estratégia pode ser otimizada nos seguintes aspectos:

  1. Otimizar os parâmetros MA para encontrar a melhor combinação de parâmetros que melhore a estabilidade.

  2. Adicionar volatilidade, filtros de volume, etc. para reduzir ainda mais as operações inválidas.

  3. Incorporar outros indicadores para um posicionamento de stop loss mais inteligente.

  4. Desenvolver algoritmos de dimensionamento de posição adaptativos para uma rentabilidade mais estável.

Conclusão

Em geral, esta é uma estratégia de tendência muito prática. Ela determina de forma confiável a tendência usando o ângulo de inclinação MA e efetivamente filtra sinais de ruído usando o indicador de taxa de mudança de preço. Tomar posições longas e curtas pode obter um bom lucro. Com otimizações contínuas, essa estratégia pode se tornar uma estratégia quantitativa muito estável e confiável.


/*backtest
start: 2023-12-01 00:00:00
end: 2023-12-31 23:59:59
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=4
// Based on ma angles code by Duyck which also uses Everget Jurik MA calulation and angle calculation by KyJ
strategy("Trend Angle BF", overlay=false)

/////////////// Time Frame ///////////////
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
    
src=input(ohlc4,title="source")

// definition of "Jurik Moving Average", by Everget
jma(_src,_length,_phase,_power) =>
    phaseRatio = _phase < -100 ? 0.5 : _phase > 100 ? 2.5 : _phase / 100 + 1.5
    beta = 0.45 * (_length - 1) / (0.45 * (_length - 1) + 2)
    alpha = pow(beta, _power)
    jma = 0.0
    e0 = 0.0
    e0 := (1 - alpha) * _src + alpha * nz(e0[1])
    e1 = 0.0
    e1 := (_src - e0) * (1 - beta) + beta * nz(e1[1])
    e2 = 0.0
    e2 := (e0 + phaseRatio * e1 - nz(jma[1])) * pow(1 - alpha, 2) + pow(alpha, 2) * nz(e2[1])
    jma := e2 + nz(jma[1])

//// //// Determine Angle by KyJ //// //// 
angle(_src) =>
    rad2degree=180/3.14159265359  //pi 
    ang=rad2degree*atan((_src[0] - _src[1])/atr(14)) 

jma_line=jma(src,10,50,1)
ma=ema(src,input(56))
jma_slope=angle(jma_line)
ma_slope=angle(ma)

///////////// Rate Of Change ///////////// 
source = close
roclength = input(12, minval=1)
pcntChange = input(2, 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 = ma_slope>=0 and isMoving()
short = ma_slope<=0 and isMoving()

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])
sl_inp = input(2.0, title='Stop Loss %') / 100
tp_inp = input(900.0, title='Take Profit %') / 100 
 
take_level_l = strategy.position_avg_price * (1 + tp_inp)
take_level_s = strategy.position_avg_price * (1 - tp_inp) 

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

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("Long",  strategy.long, when=long)
    strategy.entry("Short", strategy.short, when=short)
    strategy.exit("Long Ex", "Long", stop=long_sl, limit=take_level_l, when=since_longEntry > 0)
    strategy.exit("Short Ex", "Short", stop=short_sl, limit=take_level_s, when=since_shortEntry > 0)
    
///////////// Plotting /////////////
hline(0, title='Zero line', color=color.purple, linewidth=1)
plot(ma_slope,title="ma slope", linewidth=2,color=ma_slope>=0?color.lime:color.red)
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) 


Mais.