Количественная стратегия торговли, основанная на индикаторе супертенденции и кривой торговли акций

Автор:Чао Чжан, Дата: 2024-01-15 11:41:53
Тэги:

img

Обзор

Основная идея этой стратегии состоит в том, чтобы объединить индикатор Supertrend с торговлей кривой акций. Когда индикатор Supertrend генерирует сигнал покупки или продажи, мы не выполняем торговлю напрямую. Вместо этого мы проверяем, находится ли текущая крива акций ниже скользящей средней. Мы будем открывать позиции только тогда, когда крива акций выше скользящей средней. Когда крива акций ниже скользящей средней, мы остановим торговлю для текущей стратегии. Это может эффективно предотвратить расширение потерь.

Логика стратегии

Эта стратегия состоит главным образом из двух частей:

  1. Индикатор супертенденции
  2. Торговля кривой акций

Формула расчета индикатора Supertrend:

Верхний диапазон = исходная цена - мультипликатор ATR * ATR Нижняя полоса = исходная цена + мультипликатор ATR * ATR

где ATR означает средний истинный диапазон. индикатор Supertrend использует ATR для установки верхней и нижней полос. прорыв выше верхней полосы означает сигнал продажи, в то время как прорыв ниже нижней полосы означает сигнал покупки.

Идея торговли кривой акций заключается в том, что мы берем скользящую среднюю кривую акций стратегии. Когда кривая акций падает ниже скользящей средней, мы приостанавливаем торговлю для текущей стратегии и ждем, пока кривая акций восстановится выше скользящей средней, прежде чем возобновить торговлю.

Эта стратегия сочетает в себе два метода, так что после того, как индикатор Supertrend генерирует торговый сигнал, мы не вступаем непосредственно в сделки. Вместо этого мы проверяем, является ли текущая кривая акций выше своей скользящей средней. Только при выполнении обоих условий мы откроем позиции. Это может эффективно смягчить риски, присущие самому индикатору Supertrend, и предотвратить чрезмерные потери.

Преимущества

Основными преимуществами этой стратегии являются:

  1. Он может эффективно предотвратить риски индикатора Supertrend. Сам индикатор Supertrend не может эффективно сдерживать потери. Торговля кривой акций компенсирует этот недостаток.

  2. Когда торговля становится неблагоприятной, он останавливает торговлю, чтобы избежать чрезмерных потерь.

  3. Он может автоматически управлять позициями без ручного вмешательства. Торговля автоматически приостанавливается, когда кривая акций падает ниже скользящей средней, и возобновляется, когда кривая акций восстанавливается выше нее.

Риски

Эта стратегия также сопряжена с некоторыми рисками:

  1. Неправильные параметры могут привести к неэффективности торговли кривой акций.

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

  3. Она может упустить хорошие торговые возможности, ожидая отскока кривой акций.

Противодействие:

  1. Оптимизируйте параметры и выберите лучший период скользящей средней.

  2. Включить другие показатели для оценки тенденции и соответственно корректировать позиции.

  3. Сократить продолжительность приостановления торговли, чтобы снизить вероятность упущенных возможностей.

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

Мы можем оптимизировать стратегию из следующих аспектов:

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

  2. Попробуйте другие типы скользящих средних, как экспоненциальная скользящая средняя, Хулл скользящая средняя и т.д.

  3. Добавьте другие показатели для определения тенденции рынка и скорректируйте позиции при изменении тенденции.

  4. Оптимизируйте период скользящей средней, чтобы найти наилучший баланс: слишком длинные периоды могут упустить возможности, а слишком короткие могут слишком часто останавливаться.

  5. Оптимизируйте условия для приостановки торговли, например, устанавливайте порог стоп-лосса перед приостановкой.

Заключение

Эта стратегия умело сочетает в себе индикатор Supertrend с торговлей кривой акций, используя сильные стороны обеих методов. Результаты испытаний показывают, что в большинстве случаев применение кривой акций фактически снижает прибыльность. Таким образом, эта стратегия более подходит для оборонительных трейдеров. С параметром и оптимизацией логики она может стать очень практичной количественной торговой стратегией.


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

//@version=5
strategy('Supertrend & Equity curve with EMA', overlay=false, format=format.price, precision=2, initial_capital=100000)

eqlen = input.int(25, "EQ EMA len", group = "New Equity Curve Settings")
shEQandMA = input.bool(true, "Show Original Equity Curve and MA")
shEQfilt = input.bool(true, "Show Filtered Equity Curve by MA")

Periods = input(title='ATR Period', defval=10, group = "SuperTrend Settings")
src = input(hl2, title='Source', group = "SuperTrend Settings")
Multiplier = input.float(title='ATR Multiplier', step=0.1, defval=3.0, group = "SuperTrend Settings")
changeATR = input(title='Change ATR Calculation Method ?', defval=true, group = "SuperTrend Settings")

//SuperTrend Code
atr2 = ta.sma(ta.tr, Periods)
atr = changeATR ? ta.atr(Periods) : atr2
up = src - Multiplier * atr
up1 = nz(up[1], up)
up := close[1] > up1 ? math.max(up, up1) : up
dn = src + Multiplier * atr
dn1 = nz(dn[1], dn)
dn := close[1] < dn1 ? math.min(dn, dn1) : dn
trend = 1
trend := nz(trend[1], trend)
trend := trend == -1 and close > dn1 ? 1 : trend == 1 and close < up1 ? -1 : trend

// Strategy main code
buySignal = trend == 1 and trend[1] == -1
sellSignal = trend == -1 and trend[1] == 1
if buySignal
    strategy.entry('Long', strategy.long)
if sellSignal
    strategy.entry('Short', strategy.short)



//Equity Curve calcs
eq = strategy.netprofit
ch = ta.change(eq)
neq = ch != 0 ? eq : na
mova = ta.ema(neq,eqlen)

// New Equity Curve
var float neweq = 0
var int ttrades = 0
var int wintrades = 0
var int losetrades = 0

switch
    strategy.netprofit == strategy.netprofit[1]  => na
    strategy.netprofit < mova and strategy.netprofit[1] > mova  => neweq := neweq + ch
    strategy.netprofit < mova and strategy.netprofit[1] < mova => na
    strategy.netprofit > mova and strategy.netprofit[1] > mova => neweq := neweq + ch

newch = ta.change(neweq)
switch
    newch == 0 => na
    newch > 0 => 
        wintrades := wintrades +1
        ttrades := ttrades +1
    newch < 0 =>
        losetrades := losetrades +1
        ttrades := ttrades +1

//plot(eq, linewidth = 2)
//plot(mova, color=color.red)
//plot(neweq, color= color.green, linewidth = 3)


//Table 
var testTable = table.new(position = position.top_right, columns = 5, rows = 10, bgcolor = color.green, border_width = 1)
table.cell(table_id = testTable, column = 0, row = 0, text = "Strategy: ", bgcolor=color.white)     
table.cell(table_id = testTable, column = 1, row = 0, text = "Original: ", bgcolor=color.white)     
table.cell(table_id = testTable, column = 2, row = 0, text = "Equity Curve EMA: ", bgcolor=color.white)     

table.cell(table_id = testTable, column = 0, row = 1, text = "Total Trades: ", bgcolor=color.white)     
table.cell(table_id = testTable, column = 0, row = 2, text = "Win Trades: ", bgcolor=color.white)     
table.cell(table_id = testTable, column = 0, row = 3, text = "Lose Trades: ", bgcolor=color.white)     
table.cell(table_id = testTable, column = 0, row = 4, text = "Win Rate: ", bgcolor=color.white)     
table.cell(table_id = testTable, column = 0, row = 5, text = "Net Profit: ", bgcolor=color.white)     

//Equity Curve EMA stat
table.cell(table_id = testTable, column = 2, row = 1, text = str.tostring(ttrades), bgcolor=color.white)     
table.cell(table_id = testTable, column = 2, row = 2, text = str.tostring(wintrades), bgcolor=color.white)
table.cell(table_id = testTable, column = 2, row = 3, text = str.tostring(losetrades), bgcolor=color.white)
table.cell(table_id = testTable, column = 2, row = 4, text = str.tostring(math.round(100*wintrades/ttrades,2)), bgcolor=color.white)
table.cell(table_id = testTable, column = 2, row = 5, text = str.tostring(math.round(neweq)), bgcolor=color.white)

//Original Strategy stat
// table.cell(table_id = testTable, column = 1, row = 1, text = str.tostring(strategy.closedtrades), bgcolor=color.white)     
// table.cell(table_id = testTable, column = 1, row = 2, text = str.tostring(strategy.wintrades), bgcolor=color.white)
// table.cell(table_id = testTable, column = 1, row = 3, text = str.tostring(strategy.losstrades), bgcolor=color.white)
// table.cell(table_id = testTable, column = 1, row = 4, text = str.tostring(math.round(100*strategy.wintrades/strategy.closedtrades,2)), bgcolor=color.white)
// table.cell(table_id = testTable, column = 1, row = 5, text = str.tostring(math.round(strategy.netprofit)), bgcolor=color.white)




//New Equity curve
var newcurve = array.new_float(0)
var int ida = 0
var bool printEQ = false
if newch !=0 
    array.push(newcurve, neweq)
if bar_index > last_bar_index - array.size(newcurve) - 1 - 20  and array.size(newcurve) > 20 
    printEQ := true
else
    printEQ := false

plot(printEQ and ida < strategy.closedtrades and shEQfilt ? array.get(newcurve, ida) : na, color=color.green, linewidth = 2)

if printEQ
    ida := ida + 1
if ida >= array.size(newcurve) and printEQ
    ida := array.size(newcurve) -1



//Original Equity curve
var newcurve2 = array.new_float(0)
var int ida2 = 0
var bool printEQ2 = false
if ch !=0 
    array.push(newcurve2, eq)
if bar_index > last_bar_index - array.size(newcurve2) - 1 - 20  and array.size(newcurve2) > 20 
    printEQ2 := true
else
    printEQ2 := false

plot(printEQ2 and ida2 < strategy.closedtrades and shEQandMA  ? array.get(newcurve2, ida2) : na, color=color.blue, linewidth = 2)

if printEQ2
    ida2 := ida2 + 1
if ida2 >= array.size(newcurve2) and printEQ2
    ida2 := array.size(newcurve2) -1



//Moving Average Array
var marray = array.new_float(0)
if ch
    array.push(marray, mova)

plot(printEQ2 and  array.size(marray) > 40 and shEQandMA ? array.get(marray, ida2-1) : na, color=color.red, linewidth = 1)

hline(0,"0 line", color=color.black, linestyle = hline.style_dotted)


if (last_bar_index-1) and array.size(newcurve2) > 20 and array.size(newcurve) > 20
    l = label.new(bar_index+2, array.get(newcurve2, array.size(newcurve2)-1), "Original Equity Curve", color=color.rgb(33, 149, 243, 85), textcolor = color.black, style = label.style_label_left)
    label.delete(l[1])
    f = label.new(bar_index+2, array.get(newcurve, array.size(newcurve)-1), "Filtered Equity Curve", color=color.rgb(69, 238, 97, 85), textcolor = color.black, style = label.style_label_left)
    label.delete(f[1])

Больше