Estratégia de negociação de criptomoedas de alta/baixa baseada em correlação baseada no índice CCI de Wall Street

Autora:ChaoZhang, Data: 2023-11-01 11:27:20
Tags:

img

Resumo

Esta é uma estratégia de negociação automatizada que gera sinais longos/cortos/fechados na criptomoeda-alvo com base na tendência calculada de uma criptomoeda de referência considerada correlacionada com ela, utilizando o Wall Street Chasing Ring Index.

Com parâmetros padrão e ETH/USDT como símbolo de base, a estratégia mostra bons resultados de backtest em símbolos como DENT/USDT, BTT/USDT, FTT/USDT, DOT/USDT etc. Isso faz sentido, pois a ETH é bastante influente nos mercados de criptomoedas, por isso muitas criptomoedas tendem a seguir os principais movimentos da ETH.

Nota: A estratégia com parâmetros padrão destina-se a um período de 4h. Em outros prazos, tente um comprimento de suporte diferente.

Como funciona a estratégia

  1. A WMA é calculada com base no símbolo de base, com comprimento 200 por defeito.

  2. Quando a WMA está a subir, vai longo, quando está a cair vai curto.

  3. O TakeProfit para Long/Short e o StopLoss para Long/Short são percentagens calculadas, portanto 0,05 = 5% etc. Além disso, o TakeProfit/StopLoss são calculados no símbolo de base e não no símbolo do gráfico.

  4. A estratégia utiliza ordens de mercado para entrada e saída com base na seguinte lógica:

    • Quando a WMA subir e não houver posição, entrada longa

    • Quando a WMA cair e não houver posição, entrada curta

    • Quando o lucro da posição longa >= TakeProfitLong por cento, fechar longa

    • Quando o lucro da posição curta >= TakeProfitShort em percentagem, fechar em curto

    • Quando a perda da posição longa >= StopLossLong por cento, fechar longa

    • Quando a perda da posição curta >= StopLossShort em percentagem, fechar curta

  5. Os preços TakeProfit e StopLoss são atualizados em tempo real com base nas alterações de preço do símbolo de base.

Análise das vantagens

  1. A estratégia é altamente adaptável para uso em várias criptomoedas por ajuste de parâmetros.

  2. O uso do CCI de Wall Street para determinar a tendência evita negócios errados conduzidos pelo ruído.

  3. Incorporar TakeProfit e StopLoss permite seguir a tendência enquanto controla a perda por negociação.

  4. A negociação totalmente automatizada, sem intervenção manual, permite a execução 24 horas por dia, 7 dias por semana.

Análise de riscos

  1. Risco de desacoplamento do preço de criptomoeda alvo da criptomoeda base, levando ao fracasso da estratégia. Pode otimizar usando várias criptomoedas base e escolhendo a mais correlacionada.

  2. Risco de volatilidade súbita, pode ajustar StopLoss em percentagem ou usar trailing stops.

  3. Risco de TakeProfit por cento muito pequeno para capturar ganhos de tendência suficientes.

  4. Pode ajustar parâmetros CCI ou adicionar lógica de reentrada.

Orientações de otimização

  1. Utilize a análise de correlação entre várias criptomoedas de base e combine indicadores para reduzir o risco criptográfico de base única.

  2. Adicionar rastreamento de tendências para ajustar dinamicamente o TakeProfit/StopLoss com base na volatilidade.

  3. Adicione paradas escalonadas para evitar que movimentos extremos parem posições.

  4. Adicionar lógica de reentrada para evitar perder novas tendências após a saída de stop loss.

  5. Otimizar os parâmetros e configurações CCI para melhorar a eficácia do sinal.

  6. Otimizar os parâmetros separadamente para cada cripto alvo para melhorar a adaptabilidade.

  7. Otimizar o dimensionamento das posições com base no tamanho da conta.

Resumo

Em geral, esta é uma estratégia típica de tendência. A ideia central é determinar a direção de tendência de uma criptomoeda de referência usando o Wall Street CCI e negociar a criptomoeda-alvo em conformidade. A estratégia tem algumas vantagens, mas também riscos a serem notados.


/*backtest
start: 2022-10-25 00:00:00
end: 2023-10-31 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/
// © levieux

//@version=5
strategy(title='Correlation Strategy', shorttitle='Correlation Strategy', 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)

supportLength = input.int(200, minval=1, title='Support Length')
supportSymbol = input('BTC_USDT:swap', title='Correlated Symbol')
supportSource = input(hlc3, title='Price Source')
takeprofitLong = input.float(0.2, 'Take Profit Long', step=0.01)
takeprofitShort = input.float(0.15, 'Take Profit Short', step=0.01)
stoplossLong = input.float(0.1, 'Stop Loss Long', step=0.01)
stoplossShort = input.float(0.04, 'Stop Loss Short', step=0.01)
start = input(defval = timestamp("01 Jan 2016 00:00 +0000"), title = "Start Time")
end = input(defval = timestamp("31 Dec 2050 23:59 +0000"), title = "End Time")

supportTicker = request.security(supportSymbol, timeframe.period, supportSource, lookahead=barmerge.lookahead_off)  //input(close, title="Source")
supportLine = ta.wma(supportTicker, supportLength)

window() => true

if not window()
    strategy.cancel_all()

supportLongPrice = close
supportShortPrice = close

if strategy.position_size > 0
    supportLongPrice := supportLongPrice[1]
if strategy.position_size < 0
    supportShortPrice := supportShortPrice[1]

longCondition = ta.rising(supportLine, 5) and window() and strategy.position_size <= 0
shortCondition = ta.falling(supportLine, 5) and window() and window() and strategy.position_size > 0
takeprofitLongCondition = takeprofitLong > 0 and window() and strategy.position_size > 0 and supportTicker > supportLongPrice * (1 + takeprofitLong)
stoplossLongCondition = stoplossLong > 0 and window() and strategy.position_size > 0 and supportTicker < supportLongPrice * (1 - stoplossLong)
takeprofitShortCondition = takeprofitShort > 0 and window() and strategy.position_size < 0 and supportTicker > supportShortPrice * (1 + takeprofitShort)
stoplossShortCondition = stoplossShort > 0 and window() and strategy.position_size < 0 and supportTicker < supportShortPrice * (1 - stoplossShort)

if longCondition
    strategy.entry('Long', strategy.long)
    supportLongPrice := supportTicker

if shortCondition
    strategy.entry('Short', strategy.short)
    supportShortPrice := supportTicker

if takeprofitLongCondition
    strategy.close('Long')
if stoplossLongCondition
    strategy.close('Long')
if takeprofitShortCondition
    strategy.close('Short')
if stoplossShortCondition
    strategy.close('Short')

///////////////////
// MONTHLY TABLE //

new_month = month(time) != month(time[1])
new_year  = year(time)  != year(time[1])

eq = strategy.equity

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

cur_month_pnl = 0.0
cur_year_pnl  = 0.0
cur_month_bh = 0.0
cur_year_bh  = 0.0

// Current Monthly P&L
cur_month_pnl := new_month ? 0.0 : 
                 (1 + cur_month_pnl[1]) * (1 + bar_pnl) - 1 
cur_month_bh := new_month ? 0.0 : 
                 (1 + cur_month_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 Monthly P&Ls
var month_pnl  = array.new_float(0)
var month_time = array.new_int(0)
var month_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_month_pnl[1]) and (new_month or end_time))
    if (end_time[1])
        array.pop(month_pnl)
        array.pop(month_time)
        
    array.push(month_pnl , cur_month_pnl[1])
    array.push(month_time, time[1])
    array.push(month_bh , cur_month_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])

// Monthly P&L Table    
var monthly_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
    monthly_table := table.new(position.bottom_right, columns = 14, rows = array.size(year_pnl) + 1, border_width = 1)

    table.cell(monthly_table, 0,  0, "",     bgcolor = #cccccc)
    table.cell(monthly_table, 1,  0, "Jan",  bgcolor = #cccccc)
    table.cell(monthly_table, 2,  0, "Feb",  bgcolor = #cccccc)
    table.cell(monthly_table, 3,  0, "Mar",  bgcolor = #cccccc)
    table.cell(monthly_table, 4,  0, "Apr",  bgcolor = #cccccc)
    table.cell(monthly_table, 5,  0, "May",  bgcolor = #cccccc)
    table.cell(monthly_table, 6,  0, "Jun",  bgcolor = #cccccc)
    table.cell(monthly_table, 7,  0, "Jul",  bgcolor = #cccccc)
    table.cell(monthly_table, 8,  0, "Aug",  bgcolor = #cccccc)
    table.cell(monthly_table, 9,  0, "Sep",  bgcolor = #cccccc)
    table.cell(monthly_table, 10, 0, "Oct",  bgcolor = #cccccc)
    table.cell(monthly_table, 11, 0, "Nov",  bgcolor = #cccccc)
    table.cell(monthly_table, 12, 0, "Dec",  bgcolor = #cccccc)
    table.cell(monthly_table, 13, 0, "Year", bgcolor = #999999)


    for yi = 0 to array.size(year_pnl) - 1
        table.cell(monthly_table, 0,  yi + 1, str.tostring(year(array.get(year_time, yi))), bgcolor = #cccccc)
        
        y_color = getCellColor(array.get(year_pnl, yi), array.get(year_bh, yi))
        table.cell(monthly_table, 13, yi + 1, str.tostring(math.round(array.get(year_pnl, yi) * 100)) + " (" + str.tostring(math.round(array.get(year_bh, yi) * 100)) + ")", bgcolor = y_color)
        
    for mi = 0 to array.size(month_time) - 1
        m_row   = year(array.get(month_time, mi))  - year(array.get(year_time, 0)) + 1
        m_col   = month(array.get(month_time, mi)) 
        m_color = getCellColor(array.get(month_pnl, mi), array.get(month_bh, mi))
        
        table.cell(monthly_table, m_col, m_row, str.tostring(math.round(array.get(month_pnl, mi) * 100)) + " (" + str.tostring(math.round(array.get(month_bh, mi) * 100)) +")", bgcolor = m_color)

Mais.