Estratégia de negociação de tendências baseada na média móvel

Autora:ChaoZhang, Data: 2023-10-30 15:53:25
Tags:

img

Resumo

Esta estratégia usa um sistema de média móvel para determinar a direção da tendência atual e faz posições longas ou curtas de acordo com a tendência. Quando a média móvel sobe, a confiança em longo é maior, então vá longo. Quando a média móvel desce, a confiança em curto é maior, então vá curto. Esta estratégia usa principalmente o sistema de média móvel para determinar a direção da tendência do mercado, pertencente à estratégia de tendência seguinte.

Estratégia lógica

  1. Calcular a média móvel ponderada vwma como indicador da média móvel para um determinado período (período por defeito 400).

  2. Determine se a média móvel vwma está em alta, se em alta, defina a tendência ascendente do sinal longo; se em queda, defina a tendência descendente do sinal curto.

  3. Quando a tendência ascendente é verdadeira, vá longo; quando a tendência descendente é verdadeira, feche longo e vá curto.

  4. Calcule a estratégia de retorno bar_pnl e buy & hold return bar_bh para cada barra.

  5. De acordo com os horários trimestrais e anuais, calcule o retorno trimestral da estratégia quarter_pnl, o retorno anual year_pnl e os correspondentes retornos de compra e retenção quarter_bh, year_bh.

  6. Mostrar o retorno da estratégia trimestral em relação ao retorno da compra e retenção num quadro.

Análise das vantagens

As principais vantagens desta estratégia são:

  1. Determina a tendência do mercado pela média móvel, fácil de entender.

  2. Seguir a tendência reduz as perdas em mercados não em tendência.

  3. Poucos parâmetros ajustáveis, ajustando principalmente o período da média móvel, fácil de testar e otimizar.

  4. Tabela de retorno intuitiva para mostrar os resultados claramente.

  5. Adicionar o retorno de compra e retenção na tabela para comparação, mostra o retorno excedente.

  6. Posição flexível da mesa, fácil de integrar com outras estratégias.

Análise de riscos

Há também alguns riscos:

  1. Performance inferior no mercado de touros de longa duração em comparação com buy & hold.

  2. Pode adicionar condições de filtro como quebrar o máximo anterior para reduzir as transações.

  3. A média móvel tem má capacidade de ajuste da curva, pode perder pontos de virada da tendência.

  4. Não há mecanismo de stop loss, riscos de grande retração, pode definir stop loss dinâmico ou dimensionamento de posição.

  5. Para a tabela, pode adicionar métricas de risco como Sharpe ratio, drawdown máximo.

Orientações de otimização

A estratégia pode ser otimizada nos seguintes aspectos:

  1. Otimizar os parâmetros da média móvel, ajustar o período com base nos regimes de mercado.

  2. Adicionar filtros como quebrar o máximo anterior para reduzir os golpes.

  3. Tente diferentes tipos de médias móveis, como WMA, DEMA etc.

  4. Adicionar mecanismos de stop loss, como paradas dinâmicas ou dimensionamento de posição.

  5. Enriquecer o conteúdo da tabela, adicionar métricas como a proporção de níveis, o máximo de aproveitamento.

  6. Combine com outros indicadores como MACD, Bollinger Bands para determinar tendências.

  7. Otimizar o dimensionamento das posições, ajustar as posições de forma dinâmica com base nas condições do mercado.

  8. Teste em diferentes produtos, para encontrar o melhor âmbito de aplicação.

Conclusão

A estratégia de negociação de média móvel é relativamente simples e direta. Segue a tendência determinando a tendência usando a média móvel, com bom controle de drawdown, adequado para os traders que seguem a tendência. Ainda há grande espaço para otimização, como o sistema de média móvel, mecanismo de stop loss, dimensionamento de posição, etc., para torná-lo adaptável a ambientes de mercado complexos.


/*backtest
start: 2022-10-23 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/
// © Dannnnnnny

//@version=4
strategy(title="Quarterly Returns in Strategies vs Buy & Hold", initial_capital= 1000, overlay=true,default_qty_type = strategy.percent_of_equity, default_qty_value = 100, commission_type = strategy.commission.percent, commission_value = 0.1)
maLength= input(400)

wma= vwma(hl2,maLength)
uptrend= rising(wma, 5)
downtrend= falling(wma,5)

plot(wma)

if uptrend
    strategy.entry("Buy", strategy.long)
else
    strategy.close("Buy")//

///////////////////
// QUARTERLY TABLE //
enableQuarterlyTable = input(title="Enable Quarterly Return table", type=input.bool, defval=false)
enableCompareWithMarket = input(title="Compare with Market Benchmark", type=input.bool, defval=false)
table_position = input(title="Table Position", type=input.string, defval='bottom_right', options=['bottom_right','bottom_left','top_right', 'top_left'])
precision = 2
new_quarter = ceil(month(time)/3)  != ceil(month(time[1])/3)
new_year  = year(time)  != year(time[1])

eq = strategy.equity

bar_pnl = eq / eq[1] - 1
bar_bh = (close-close[1])/close[1]

cur_quarter_pnl = 0.0
cur_year_pnl  = 0.0
cur_quarter_bh = 0.0
cur_year_bh  = 0.0

// Current Quarterly P&L
cur_quarter_pnl := new_quarter ? 0.0 : 
                 (1 + cur_quarter_pnl[1]) * (1 + bar_pnl) - 1 
cur_quarter_bh := new_quarter ? 0.0 : 
                 (1 + cur_quarter_bh[1]) * (1 + bar_bh) - 1

// Current Yearly P&L
cur_year_pnl := new_year ? 0.0 : 
                 (1 + cur_year_pnl[1]) * (1 + bar_pnl) - 1
cur_year_bh := new_year ? 0.0 : 
                 (1 + cur_year_bh[1]) * (1 + bar_bh) - 1

// Arrays to store Yearly and Quarterly P&Ls
var quarter_pnl  = array.new_float(0)
var quarter_time = array.new_int(0)
var quarter_bh  = array.new_float(0)

var year_pnl  = array.new_float(0)
var year_time = array.new_int(0)
var year_bh  = array.new_float(0)

end_time = false

end_time:= time_close + (time_close - time_close[1]) > timenow or barstate.islastconfirmedhistory

if (not na(cur_quarter_pnl[1]) and (new_quarter or end_time))
    if (end_time[1])
        array.pop(quarter_pnl)
        array.pop(quarter_time)
        
    array.push(quarter_pnl , cur_quarter_pnl[1])
    array.push(quarter_time, time[1])
    array.push(quarter_bh , cur_quarter_bh[1])

if (not na(cur_year_pnl[1]) and (new_year or end_time))
    if (end_time[1])
        array.pop(year_pnl)
        array.pop(year_time)
        
    array.push(year_pnl , cur_year_pnl[1])
    array.push(year_time, time[1])
    array.push(year_bh , cur_year_bh[1])

// Quarterly P&L Table    
var quarterly_table = table(na)

getCellColor(pnl, bh)  => 
    if pnl > 0
        if bh < 0 or pnl > 2 * bh
            color.new(color.green, transp = 20)
        else if pnl > bh
            color.new(color.green, transp = 50)
        else
            color.new(color.green, transp = 80)
    else
        if bh > 0 or pnl < 2 * bh
            color.new(color.red, transp = 20)
        else if pnl < bh
            color.new(color.red, transp = 50)
        else
            color.new(color.red, transp = 80)

if (end_time and enableQuarterlyTable)
    quarterly_table := table.new(table_position, columns = 14, rows = array.size(year_pnl) + 1, border_width = 1)

    table.cell(quarterly_table, 0,  0, "",     bgcolor = #cccccc)
    table.cell(quarterly_table, 1,  0, "Q1",  bgcolor = #cccccc)
    table.cell(quarterly_table, 2,  0, "Q2",  bgcolor = #cccccc)
    table.cell(quarterly_table, 3,  0, "Q3",  bgcolor = #cccccc)
    table.cell(quarterly_table, 4,  0, "Q4",  bgcolor = #cccccc)
    table.cell(quarterly_table, 5,  0, "Year", bgcolor = #999999)


    for yi = 0 to array.size(year_pnl) - 1
        table.cell(quarterly_table, 0,  yi + 1, tostring(year(array.get(year_time, yi))), bgcolor = #cccccc)
        
        y_color = getCellColor(array.get(year_pnl, yi), array.get(year_bh, yi))
        table.cell(quarterly_table, 5, yi + 1, enableCompareWithMarket ? tostring(round(array.get(year_pnl, yi) * 100, precision)) + " (" + tostring(round(array.get(year_bh, yi) * 100, precision)) + ")" : tostring(round(array.get(year_pnl, yi) * 100, precision)), bgcolor = y_color, text_color=#bfbfbf)
        
    for mi = 0 to array.size(quarter_time) - 1
        m_row   = year(array.get(quarter_time, mi))  - year(array.get(year_time, 0)) + 1
        m_col   = ceil(month(array.get(quarter_time, mi)) / 3)
        m_color = getCellColor(array.get(quarter_pnl, mi), array.get(quarter_bh, mi))
        
        table.cell(quarterly_table, m_col, m_row, enableCompareWithMarket ?  tostring(round(array.get(quarter_pnl, mi) * 100, precision)) + " (" + tostring(round(array.get(quarter_bh, mi) * 100,precision)) +")" : tostring(round(array.get(quarter_pnl, mi) * 100, precision)), bgcolor = m_color, text_color=#bfbfbf)

Mais.