Стратегия отслеживания прорыва Куламагги

Автор:Чао Чжан, Дата: 2024-01-31 17:06:36
Тэги:

img

Обзор

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

Принцип стратегии

Эта стратегия основывается на трех показателях для оценки.

Во-первых, вычислить более длительный цикл (например, ежедневный) X-дневная простая скользящая средняя. Позволить покупать только тогда, когда цена выше этой скользящей средней. Это может быть использовано для определения общего направления тренда и избежать торговли колеблющихся периодов.

Во-вторых, вычислить самую высокую цену Swing High в более коротком цикле (например, 5 дней). Когда цена пробивается через эту самую высокую цену, запускается сигнал покупки.

В-третьих, установить линию стоп-лосса. После входа в позицию, линия стоп-лосса блокируется на самой низкой цене за определенный период lbStop от самой последней низкой точки. В то же время, установить линию скользящей средней (такую как 10-дневная EMA на сутки) в качестве механизма выхода. Выйти из позиции, когда цена ниже этой скользящей средней линии.

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

Суждение о взаимодействии трех вышеупомянутых индикаторов составляет основную логику этой стратегии.

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

Как стратегия отслеживания прорыва, она имеет следующие преимущества:

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

  2. Используйте точки прорыва, сформированные высокими колебаниями. Этот тип прорыва имеет определенную инерцию и легко формирует отслеживание. Параметр периода просмотра lb также можно настроить, чтобы найти действительно эффективные прорывы.

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

  4. Использовать скользящую среднюю в качестве механизма выхода, чтобы гибко получать прибыль в соответствии с рыночными условиями.

  5. Показатель ATR позволяет избежать риска чрезмерного использования кредитных инструментов.

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

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

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

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

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

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

  4. Параметр ATR должен быть установлен разумно. Если ATR слишком маленький, эффект фильтрации слабый. Если он слишком большой, возможности входа уменьшатся.

  5. Необходимость проверить влияние различных параметров на результаты. Чрезмерно большие параметры могут упустить некоторые возможности, в то время как слишком маленькие параметры могут выявить ложные прорывы.

Уменьшение риска:

  1. Соответственно корректировать параметры скользящей средней для повышения способности фильтрации.
  2. Оптимизировать параметры ATR, дополненные визуальным суждением.
  3. Настроить период просмотра фунтов, чтобы найти оптимальные параметры.
  4. Приостановить торговлю во время колебаний рынков.

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

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

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

  2. Попробуйте различные параметры ATR, чтобы сбалансировать возможности входа и контроль рисков.

  3. Оптимизируйте параметр lb lookback period для выявления более эффективных прорывов.

  4. Постарайтесь создать динамический стоп-лосс, основанный на волатильности и снижении, чтобы контролировать риск.

  5. Для определения эффективности прорывов учитывать другие факторы, такие как объем торговли.

  6. Разработать/,< и другие методы поиска крайних точек в качестве ссылок.

  7. Попробуйте машинное обучение для обучения параметров для оптимальных параметров

Резюме

В целом, это типичная стратегия отслеживания прорыва. Судя по двойным временным рамкам, использование Swing High для определения времени входа, а также использование линии остановки потерь и механизмов выхода из двойного страхования движущейся средней составляют полную логическую систему. Характеристики риска и доходности этой стратегии ясны, подходят для средне- и долгосрочных инвесторов. Хотя существуют определенные риски, их можно уменьшить путем оптимизации параметров и правил. Стратегия имеет большое пространство для улучшения. Включение большего количества индикаторов может еще больше улучшить эффект стратегии.


/*backtest
start: 2023-01-24 00:00:00
end: 2024-01-30 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/
// © millerrh

// The intent of this strategy is to buy breakouts with a tight stop on smaller timeframes in the direction of the longer term trend.
// Then use a trailing stop of a close below either the 10 MA or 20 MA (user choice) on that larger timeframe as the position 
// moves in your favor (i.e. whenever position price rises above the MA).
// Option of using daily ATR as a measure of finding contracting ranges and ensuring a decent risk/reward.
// (If the difference between the breakout point and your stop level is below a certain % of ATR, it could possibly find those consolidating periods.)

//@version=4
strategy("Qullamaggie Breakout", overlay=true, initial_capital=10000, currency='USD', 
   default_qty_type=strategy.percent_of_equity, default_qty_value=100, commission_type=strategy.commission.percent, commission_value=0.1)
   
// === BACKTEST RANGE ===
Start = input(defval = timestamp("01 Jan 2019 06:00 +0000"), title = "Backtest Start Date", type = input.time)
Finish = input(defval = timestamp("01 Jan 2100 00:00 +0000"), title = "Backtest End Date", type = input.time)

// Inputs
lb = input(defval = 3, title = "Lookback Period for Swing High", minval = 1,
   tooltip = "Lookback period for defining the breakout level.")
lbStop = input(defval = 3, title = "Lookback Bars for Stop Level", minval = 1,
   tooltip = "Initial stop placement is the lowest low this many bars back. Allows for tighter stop placement than referencing swing lows.")  
htf = input(defval="D", title="Timeframe of Moving Averages", type=input.resolution,
  tooltip = "Allows you to set a different time frame for the moving averages. The default behavior is to identify good tightening setups on a larger timeframe
  (like daily) and enter the trade on a breakout occuring on a smaller timeframe, using the moving averages of the larger timeframe to trail your stop.")
maType = input(defval="SMA", options=["EMA", "SMA"], title = "Moving Average Type")
ma1Length = input(defval = 10, title = "1st Moving Average Length", minval = 1)
ma2Length = input(defval = 20, title = "2nd Moving Average Length", minval = 1)
ma3Length = input(defval = 50, title = "3rd Moving Average Length", minval = 1)
useMaFilter = input(title = "Use 3rd Moving Average for Filtering?", type = input.bool, defval = true,
  tooltip = "Signals will be ignored when price is under this slowest moving average.  The intent is to keep you out of bear periods and only
             buying when price is showing strength or trading with the longer term trend.")
trailMaInput = input(defval="2nd Moving Average", options=["1st Moving Average", "2nd Moving Average"], title = "Trailing Stop")

// MA Calculations
ma(maType, src, length) =>
    maType == "EMA" ? ema(src, length) : sma(src, length) //Ternary Operator (if maType equals EMA, then do ema calc, else do sma calc)
ma1 = security(syminfo.tickerid, htf, ma(maType, close, ma1Length))
ma2 = security(syminfo.tickerid, htf, ma(maType, close, ma2Length))
ma3 = security(syminfo.tickerid, htf, ma(maType, close, ma3Length))

plot(ma1, color=color.purple, style=plot.style_line, title="MA1", linewidth=2, transp = 60)
plot(ma2, color=color.yellow, style=plot.style_line, title="MA2", linewidth=2, transp = 60)
plot(ma3, color=color.white, style=plot.style_line, title="MA3", linewidth=2, transp = 60)

// === USE ATR FOR FILTERING ===
// The idea here is that you want to buy in a consolodating range for best risk/reward. So here you can compare the current distance between 
// support/resistance vs.the ATR and make sure you aren't buying at a point that is too extended from normal.
useAtrFilter = input(title = "Use ATR for Filtering?", type = input.bool, defval = false,
  tooltip = "Signals will be ignored if the distance between support and resistance is larger than a user-defined percentage of Daily ATR. 
             This allows the user to ensure they are not buying something that is too extended and instead focus on names that are consolidating more.")
atrPerc = input(defval = 100, title = "% of Daily ATR Value", minval = 1)
atrValue = security(syminfo.tickerid, "D", atr(14))*atrPerc*.01

// === PLOT SWING HIGH/LOW AND MOST RECENT LOW TO USE AS STOP LOSS EXIT POINT ===
// Change these values to adjust the look back and look forward periods for your swing high/low calculations
pvtLenL = lb
pvtLenR = lb

// Get High and Low Pivot Points
pvthi_ = pivothigh(high, pvtLenL, pvtLenR)
pvtlo_ = pivotlow(low, pvtLenL, pvtLenR)

// Force Pivot completion before plotting.
Shunt = 1 //Wait for close before printing pivot? 1 for true 0 for flase
maxLvlLen = 0 //Maximum Extension Length
pvthi = pvthi_[Shunt]
pvtlo = pvtlo_[Shunt]

// Count How many candles for current Pivot Level, If new reset.
counthi = barssince(not na(pvthi))
countlo = barssince(not na(pvtlo))
 
pvthis = fixnan(pvthi)
pvtlos = fixnan(pvtlo)
hipc = change(pvthis) != 0 ? na : color.maroon
lopc = change(pvtlos) != 0 ? na : color.green

// Display Pivot lines
plot((maxLvlLen == 0 or counthi < maxLvlLen) ? pvthis : na, color=hipc, transp=0, linewidth=1, offset=-pvtLenR-Shunt, title="Top Levels")
// plot((maxLvlLen == 0 or countlo < maxLvlLen) ? pvtlos : na, color=lopc, transp=0, linewidth=1, offset=-pvtLenR-Shunt, title="Bottom Levels")
plot((maxLvlLen == 0 or counthi < maxLvlLen) ? pvthis : na, color=hipc, transp=0, linewidth=1, offset=0, title="Top Levels 2")
// plot((maxLvlLen == 0 or countlo < maxLvlLen) ? pvtlos : na, color=lopc, transp=0, linewidth=1, offset=0, title="Bottom Levels 2")

// BUY CONDITIONS
stopLevelCalc = valuewhen(pvtlo_, low[pvtLenR], 0) //Stop Level at Swing Low
buyLevel = valuewhen(pvthi_, high[pvtLenR], 0) //Buy level at Swing High
plot(buyLevel, style=plot.style_line, color=color.blue, title = "Current Breakout Level", show_last=1, linewidth=1, transp=50, trackprice=true)

// Conditions for entry and exit
stopLevel = float(na) // Define stop level here as "na" so that I can reference it in the inPosition 
  // variable and the ATR calculation before the stopLevel is actually defined.
buyConditions = (useMaFilter ? buyLevel > ma3 : true) and
  (useAtrFilter ? (buyLevel - stopLevel[1]) < atrValue : true)
// buySignal = high > buyLevel and buyConditions
buySignal = crossover(high, buyLevel) and buyConditions
trailMa = trailMaInput == "1st Moving Average" ? ma1 : ma2
sellSignal = crossunder(close, trailMa)
// sellSignal = security(syminfo.tickerid, htf, close < trailMa) and security(syminfo.tickerid, htf, close[1] < trailMa)


// STOP AND PRICE LEVELS
inPosition = bool(na)
inPosition := buySignal[1] ? true : sellSignal[1] ? false : low <= stopLevel[1] ? false : inPosition[1]

lowDefine = lowest(low, lbStop)
stopLevel := inPosition ? stopLevel[1] : lowDefine
// plot(stopLevel)

buyPrice = buyLevel
buyPrice := inPosition ? buyPrice[1] : buyLevel
plot(stopLevel, style=plot.style_line, color=color.orange, title = "Current Stop Level", show_last=1, linewidth=1, transp=50, trackprice=true)
plot(inPosition ? stopLevel : na, style=plot.style_circles, color=color.orange, title = "Historical Stop Levels", transp=50, trackprice=false)
// plot(buyPrice, style=plot.style_line, color=color.blue, linewidth=1, transp=50, trackprice=true)

// (STRATEGY ONLY) Comment out for Study
strategy.entry("Long", strategy.long, stop = buyLevel, when = buyConditions)
strategy.exit("Exit Long", from_entry = "Long", stop=stopLevel[1])
if (low[1] > trailMa)
    strategy.close("Long", when = sellSignal)
// if (low[1] > trailMa)
//     strategy.exit("Exit Long", from_entry = "Long", stop=trailMa) //to get this to work right, I need to reference highest highs instead of swing highs
    //because it can have me buy right back in after selling if the stop level is above the last registered swing high point.

Больше