Корреляционная стратегия торговли криптовалютами "бычье/медвежье" на основе индекса Wall Street CCI

Автор:Чао Чжан, Дата: 2023-11-01 11:27:20
Тэги:

img

Обзор

Это автоматизированная стратегия торговли, которая генерирует длинные/короткие/близкие сигналы на целевую криптовалюту на основе рассчитанной тенденции криптовалюты-бейнчмарка, считающейся с ней коррелирующей, с использованием индекса Wall Street Chasing Ring.

С параметрами по умолчанию и ETH/USDT в качестве базового символа, стратегия показывает хорошие результаты бэкстеста на таких символах, как DENT/USDT, BTT/USDT, FTT/USDT, DOT/USDT и т. Д. Это имеет смысл, поскольку ETH довольно влиятелен на крипторынках, поэтому многие крипто имеют тенденцию следовать основным движениям ETH.

Примечание: стратегия с параметрами по умолчанию предназначена для временных рамок 4h. На других временных рамах попробуйте другую длину поддержки.

Как работает стратегия

  1. WMA рассчитывается на основе базового символа с длиной 200 по умолчанию.

  2. Когда WMA поднимается, иди длинным, когда падает, иди коротким.

  3. TakeProfit для Long/Short и StopLoss для Long/Short рассчитываются в процентах, так что 0,05 = 5% и т. д. Также TakeProfit/StopLoss рассчитываются на основе символа базы, а не символа графика.

  4. Стратегия использует рыночные ордера для входа и выхода на основе следующей логики:

    • При подъеме WMA и отсутствии позиции, длинный вход

    • При падении WMA и отсутствии позиции, короткий вход

    • Если прибыль от длинной позиции >= TakeProfitLong %, закрыть длинную

    • Если прибыль от короткой позиции >= TakeProfitShort %, закрыть короткую позицию

    • Если потеря длинной позиции >= Стоп-потеряДлинный процент, закрытие длинной позиции

    • Если убыток короткой позиции >= Стоп-Убыток, процент закрытия короткой позиции

  5. Цены TakeProfit и StopLoss обновляются в режиме реального времени на основе изменений цены базового символа.

Анализ преимуществ

  1. Стратегия очень адаптируема для использования на нескольких криптовалютах путем настройки параметров.

  2. Использование CCI Уолл-стрит для определения тренда позволяет избежать неправильных сделок, связанных с шумом.

  3. Включение TakeProfit и StopLoss позволяет следовать тренду при одновременном контроле потери на торговле.

  4. Полностью автоматизированная торговля без ручного вмешательства позволяет работать 24 часа в сутки.

Анализ рисков

  1. Риск отсоединения целевой криптоцены от базовой криптографии, что приводит к неудаче стратегии. Можно оптимизировать, используя несколько базовых криптографий и выбирая наиболее коррелированный.

  2. Риск внезапной волатильности, останавливающей позиции.

  3. Риск TakeProfit процент слишком мал, чтобы захватить достаточные прибыли от тренда.

  4. Риск ложного прорыва, ведущего к выходу стоп-лосса, может настраивать параметры CCI или добавлять логику повторного входа.

Руководство по оптимизации

  1. Использовать корреляционный анализ в нескольких базовых криптовалютах и комбинировать индикаторы для снижения риска одного базового крипто.

  2. Добавить отслеживание тренда для динамической корректировки TakeProfit/StopLoss на основе волатильности.

  3. Добавьте поэтапные остановки, чтобы предотвратить экстремальные движения, останавливающие позиции.

  4. Добавить логику повторного входа, чтобы не упустить дальнейшие тенденции после выхода стоп-лосса.

  5. Оптимизировать параметры и настройки CCI для повышения эффективности сигнала.

  6. Оптимизировать параметры отдельно для каждого целевого крипто для улучшения адаптивности.

  7. Оптимизируйте размер позиций на основе размера счета.

Резюме

В целом, это типичная тенденция, следующая за стратегией. Основная идея заключается в определении направления тренда криптовалюты с использованием Wall Street CCI и соответствующей торговле целевой криптографией. Стратегия имеет некоторые преимущества, но также и риски.


/*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)

Больше