Стратегия захвата тренда разворота объема

SMA ATR VOLUME ETH RTH TP SL
Дата создания: 2025-05-13 10:39:29 Последнее изменение: 2025-05-13 10:39:29
Копировать: 1 Количество просмотров: 346
2
Подписаться
319
Подписчики

Стратегия захвата тренда разворота объема Стратегия захвата тренда разворота объема

Обзор стратегии

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

Стратегический принцип

Основные принципы этой стратегии основаны на обратном тренде после необычного объема торгов на рынке. Конкретная логика действий следующая:

  1. Выявление аномального объема транзакцийСистема обнаруживает, имеет ли предыдущая K-линия значительно более высокий, чем средний, объем сделок. В обычные торговые периоды (RTH) объем сделок должен быть в 3 раза больше, чем средний объем сделок за последнее время (регулируемый); в послеобеденные или специальные периоды (ETH) - более чем в 5 раз.

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

  3. Определение направления: определение направления тренда путем сравнения цены закрытия до K-линии сверхнормального объема торгов с отношением к SMA (простой движущейся средней).

  4. Сигнал обратного входа

    • Повышение сигнала: когда аномальный объем торгов на K-линии предшествует понижению тренда (закрытие ниже SMA), а текущий объем торгов на K-линии снижается.
    • Сигналы прорыва: когда аномальный объем торгов на K-линии предшествует тенденции к повышению позиций ((закрытие цены выше SMA), а текущий объем торгов на K-линии снижается。
  5. Вход в систему

    • Сделать больше: установить лимитную плату за минимальную цену на линии K с необычным объемом сделки.
    • Сделать пустоту: установить лимитную цену на наивысшую цену на линии K с необычным объемом сделки.
  6. Управление рискамиВ зависимости от особенностей разных сортов, система предлагает два варианта параметров остановки/остановки:

    • Для конкретных сортов (например, NQ): с использованием фиксированной точки настройки стоп-лосса и стоп-утилизации.
    • Для других сортов: можно выбрать динамический стоп/стоп на основе ATR, или использовать фиксированное количество баллов.
  7. Фильтр времени: Стратегия может выборочно фильтровать торговые сигналы в течение первых и последних 15 минут RTH и всегда фильтровать сигналы в период после закрытия торгового дня (в 4-6 часов вечера) и в период до закрытия торгового дня в воскресенье.

Стратегические преимущества

  1. Поймать ключевые моментыСтратегия ориентирована на захват рыночных поворотных точек, которые сопровождаются аномальными объемами сделок, которые обычно представляют собой значительные изменения в настроениях рынка и обеспечивают более высокие шансы на выигрыш.

  2. Точное место входа: повышение точности входа, обеспечивая торговлю на технически важном уровне цен, с использованием ограничительных цен в высоких/низких точках по линии K с необычным объемом торгов.

  3. Количество самостоятельной идентификацииСтратегия: Динамическая корректировка критериев определения объема необычных сделок в зависимости от различных торговых периодов (обычные торговые часы против после закрытия / особых периодов), чтобы соответствовать реальным условиям рынка.

  4. Гибкое управление рисками: Предоставляет опции остановки/остановки на основе фиксированного балла и ATR, индивидуальные настройки могут быть сделаны в зависимости от характеристик и волатильности различных сортов.

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

  6. Ясный визуальный отзывСтратегия: обеспечивает интуитивно понятные визуальные указания на графике, включая необычные торговые K-линии, трендовые SMA-линии, стоп-стоп-линии, для удобства мониторинга и анализа.

  7. Автоматизация исполненияПри выполнении условий система автоматически выполняет ограничительные и стоп-стоп-установки, сокращая вмешательство человека и поддерживая дисциплину торговли.

Стратегический риск

  1. Риск ложного проникновенияДля смягчения этого риска можно рассмотреть возможность добавления подтверждающих показателей, таких как подтверждение RSI опережения/перепродажи или требование продолжительности прорыва.

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

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

  4. Риск невыполнения ценовой лимиты: Если цена не достигнет установленного предельного уровня на следующей K-линии, торговый сигнал может быть недействителен. Можно рассмотреть возможность установления максимального срока действия или перейти к исполнению по рыночной цене при определенных условиях.

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

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

Направление оптимизации стратегии

  1. Подтверждение многократного цикла: добавление фильтра трендов с более высокими временными циклами, чтобы обеспечить более высокую выигрышную вероятность в более крупном трендовом направлении. Например, можно проверить направление тренда солнечной линии и играть только в том случае, если он соответствует тренду солнечной линии.

  2. Оценка качества объемов сделокПомимо чистого объема, можно рассмотреть возможность увеличения количества сделок с помощью качественной оценки, например, отклонения от средней цены, взвешенной по объему сделок (VWAP), чтобы лучше понять поведение рынка за большим количеством сделок.

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

  4. Фильтрация корреляцииДля соответствующих видов (например, фондовый индекс, фьючерсы и наличные, золото и серебро и т. д.) добавление подтверждающих индикаторов соответствующих видов повышает качество сигнала. Сигнал может быть более надежным, когда несколько соответствующих видов одновременно имеют аномальный объем торговли и поведение цен.

  5. Оптимизация машинного обучения: Анализ наиболее успешных аномальных моделей объема сделок в исторических данных с помощью алгоритмов машинного обучения, динамическая корректировка условий и параметров входа. Например, можно использовать деревья решений или случайные леса для прогнозирования наилучших действий при данных аномальных характеристиках объема сделок.

  6. Корректировка колебаний: в зависимости от текущего состояния волатильности рынка корректировать критерии определения аномального объема торговли и уровень остановки / остановки. В условиях высокой волатильности повышение аномального объема может определить порог и снизить расстояние остановки; в условиях низкой волатильности наоборот.

  7. Добавить базовые фильтрыВ день публикации важных экономических данных или в день ежеквартального финансового отчета следует сезонно корректировать параметры стратегии или приостановить торговлю, чтобы избежать ложных сигналов, вызванных помехами в новостях.

Подвести итог

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

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

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

В целом, стратегия захвата обратных тенденций в объеме торгов предоставляет трейдерам торговую систему, основанную на принципах поведения рынка и психологии, которая особенно подходит для волатильных рынков и колебаний в диапазоне. При разумной настройке и постоянной оптимизации эта стратегия может стать эффективным инструментом в торговом портфеле.

Исходный код стратегии
/*backtest
start: 2024-05-13 00:00:00
end: 2025-05-11 08:00:00
period: 1h
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=5
// Strategy Title Reflects Latest Logic
strategy(title="Middle Finger Trading Strategy",
         shorttitle="Middle_Finger",
         overlay=true,
         pyramiding=0, // Only one entry at a time
         default_qty_type=strategy.percent_of_equity,
         default_qty_value=1, // Trade 1% of equity
         commission_value=0.04, // Example commission (adjust as needed)
         commission_type=strategy.commission.percent,
         initial_capital = 10000, // Example starting capital
         process_orders_on_close=false // Important for limit orders to potentially fill intra-bar
         )

// --- Inputs ---

// Volume Settings Group
grp_vol = "Volume Settings"
float rthHugeVolMultiplier = input.float(3.0, title="1. RTH Huge Vol. Multiplier (> Avg)", minval=1.1, step=0.1, group=grp_vol, tooltip="Multiplier for core RTH (9:45-15:44 ET)")
float ethHugeVolMultiplier = input.float(5.0, title="2. ETH/Excluded Huge Vol. Multiplier (> Avg)", minval=1.1, step=0.1, group=grp_vol, tooltip="Multiplier for ETH and first/last 15min RTH (default 5x)")
int   volLookback         = input.int(20, title="3. Volume SMA Lookback", minval=1, group=grp_vol, tooltip="Lookback for calculating the filtered average volume (Used ONLY for identifying the HUGE spike)")
// Removed normalVolMultiplier as it's no longer used for entry confirmation

// Trend Settings Group
grp_trend = "Trend Settings"
int   trendLookback       = input.int(20, title="1. Trend SMA Lookback", minval=2, group=grp_trend, tooltip="Lookback period for the Simple Moving Average used to determine the trend before the spike")

// Risk Management Group
grp_risk = "Risk Management (SL/TP)"
string nqTargetTickerId   = input.string("CME:NQ1!", title="1. Target Ticker ID for Fixed NQ Points", group=grp_risk, tooltip="Specify the exact Ticker ID (e.g., CME:NQ1!, TVC:NDX) for fixed SL/TP. Found in Symbol Info.")
float nqFixedStopPoints   = input.float(20.0, title="2. Fixed SL Points (for Target Ticker)", group=grp_risk, minval=0.1, step=0.1)
float nqFixedTpPoints     = input.float(50.0, title="3. Fixed TP Points (for Target Ticker)", group=grp_risk, minval=0.1, step=0.1)

// General SL/TP Settings (used if NOT the target ticker)
bool  useAtrStops         = input.bool(true, title="4. Use ATR for SL/TP (Other Tickers)?", group=grp_risk)
int   atrLookback         = input.int(14, title="5. ATR Lookback", group=grp_risk, inline="atr_other")
float atrStopMultiplier   = input.float(2.0, title="6. ATR SL Multiplier", group=grp_risk, inline="atr_other", minval=0.1, step=0.1)
float atrTpMultiplier     = input.float(4.0, title="7. ATR TP Multiplier", group=grp_risk, inline="atr_other", minval=0.1, step=0.1)
float fixedStopPoints     = input.float(100.0, title="6. Fixed SL Points (Other Tickers)", group=grp_risk, inline="fixed_other", minval=1)
float fixedTpPoints       = input.float(200.0, title="7. Fixed TP Points (Other Tickers)", group=grp_risk, inline="fixed_other", minval=1)

// Time Filter Settings Group
grp_time = "Time Filter (ET)"
bool  enableEntryFilterRthEdges = input.bool(true, title="1. Filter Entries First/Last 15 Min RTH (ET)?", group=grp_time, tooltip="If checked, ignores entries from 9:30-9:44 ET and 15:45-15:59 ET. Avg Vol calc *always* filters these times, 4-6PM ET, and Sun pre-6PM ET.")
string targetTimezone     = "America/New_York" // Specify Eastern Time zone

// --- Time Calculation Function ---
isTimeInSession(t, tz, sessionString) =>
    not na(time(timeframe.period, sessionString, tz))

// --- Time Context Functions ---
getTimeContext(t, tz) =>
    h = hour(t, tz)
    m = minute(t, tz)
    d = dayofweek(t, tz)

    // Core RTH: 9:45 AM to 15:44 PM ET (Mon-Fri)
    bool isCoreRTH = d >= dayofweek.monday and d <= dayofweek.friday and
       ((h == 9 and m >= 45) or (h >= 10 and h <= 14) or (h == 15 and m <= 44))

    // Excluded RTH Edges: 9:30-9:44 ET and 15:45-15:59 ET (Mon-Fri)
    bool isExcludedRTH = d >= dayofweek.monday and d <= dayofweek.friday and
       ((h == 9 and m >= 30 and m <= 44) or (h == 15 and m >= 45))

    // After Hours Closed: 4:00 PM to 5:59 PM ET (Mon-Fri)
    bool isAfterHoursClosed = d >= dayofweek.monday and d <= dayofweek.friday and
       (h >= 16 and h < 18)

    // Sunday Pre-Market: Sunday before 6:00 PM ET
    bool isSundayPreMarket = d == dayofweek.sunday and h < 18

    // Combine ALL periods where activity should be ignored or volume excluded from avg
    bool isExcludedPeriod = isExcludedRTH or isAfterHoursClosed or isSundayPreMarket

    [isCoreRTH, isExcludedRTH, isAfterHoursClosed, isSundayPreMarket, isExcludedPeriod]

// --- Get Time Context for Current and Previous Bar ---
[isCurrentBarCoreRTH, isCurrentBarExcludedRTH, isCurrentBarAfterHoursClosed, isCurrentBarSundayPreMarket, isCurrentBarExcludedPeriod] = getTimeContext(time, targetTimezone)
[isPreviousBarCoreRTH, isPreviousBarExcludedRTH, isPreviousBarAfterHoursClosed, isPreviousBarSundayPreMarket, isPreviousBarExcludedPeriod] = getTimeContext(time[1], targetTimezone)

// --- Calculations ---

// Volume Averaging: Exclude RTH edges, 4-6 PM ET, and Sunday Pre-6 PM ET ALWAYS
// This average is *only* used to define the huge volume spike threshold
bool excludeCurrentVolFromAvg = isCurrentBarExcludedPeriod
float volumeForAvgCalc = excludeCurrentVolFromAvg ? na : volume
float avgVolume = ta.sma(volumeForAvgCalc, volLookback)

// Dynamic Huge Volume Multiplier: Based on *previous* bar's time (Core RTH or not)
float activeHugeVolMultiplier = isPreviousBarCoreRTH ? rthHugeVolMultiplier : ethHugeVolMultiplier
// Use avgVolume[1] as current avgVolume excludes current bar, and we compare previous volume to avg *before* it
float hugeVolThreshold   = nz(avgVolume[1]) * activeHugeVolMultiplier

// --- MODIFIED Volume Conditions ---
// 1. Check if the *previous* bar had huge volume compared to its preceding average
bool isHugeVolumePrevBar = volume[1] > hugeVolThreshold and hugeVolThreshold > 0
// 2. Check if the *current* bar's volume is simply lower than the previous (huge) bar's volume
bool isVolumeLowerThanSpike = volume < volume[1]

// Trend Condition
float priceSma = ta.sma(close, trendLookback)
// Ensure trend condition uses close[2] vs sma[2] (trend state *before* the spike bar)
bool isBullishTrendBeforeSpike = close[2] > nz(priceSma[2])
bool isBearishTrendBeforeSpike = close[2] < nz(priceSma[2])

// --- Entry Time Filtering ---
// Always filter After Hours Closed and Sunday Pre-Market.
// Optionally filter RTH Edges based on input.
bool shouldFilterRthEdges = enableEntryFilterRthEdges and isCurrentBarExcludedRTH
bool isIgnoreEntryTime = shouldFilterRthEdges or isCurrentBarAfterHoursClosed or isCurrentBarSundayPreMarket

// --- MODIFIED Base Conditions ---
// Uses the simplified `isVolumeLowerThanSpike` check
bool baseLongCondition = isBearishTrendBeforeSpike and isHugeVolumePrevBar and isVolumeLowerThanSpike
bool baseShortCondition = isBullishTrendBeforeSpike and isHugeVolumePrevBar and isVolumeLowerThanSpike

// Final Conditions (Apply Time Filter)
bool finalLongCondition = baseLongCondition and not isIgnoreEntryTime
bool finalShortCondition = baseShortCondition and not isIgnoreEntryTime

// --- Stop Loss & Take Profit Calculation (Conditional Logic) ---
// This part remains the same
float atrValue = ta.atr(atrLookback)
float tickValue = syminfo.mintick
int stopLossTicks = 100 // Default fallback SL ticks
int takeProfitTicks = 200 // Default fallback TP ticks

// Check if the current symbol matches the target ticker ID
bool isTargetTicker = str.upper(syminfo.tickerid) == str.upper(nqTargetTickerId) // Case-insensitive comparison

if (isTargetTicker and tickValue > 0)
    // --- Target Ticker Logic (e.g., NQ Fixed Points) ---
    float ticksPerPoint = 1.0 / tickValue
    stopLossTicks := math.max(1, math.round(nqFixedStopPoints * ticksPerPoint))
    takeProfitTicks := math.max(1, math.round(nqFixedTpPoints * ticksPerPoint))
else if tickValue > 0 // Use only if tickValue is valid
    // --- Standard Logic (Other Tickers: ATR or Fixed) ---
    float stopLossDistance = useAtrStops ? atrValue * atrStopMultiplier : fixedStopPoints * tickValue
    float takeProfitDistance = useAtrStops ? atrValue * atrTpMultiplier : fixedTpPoints * tickValue

    // Calculate ticks, ensuring it's at least 1 tick
    stopLossTicks := na(stopLossDistance) ? 100 : math.max(1, math.round(stopLossDistance / tickValue))
    takeProfitTicks := na(takeProfitDistance) ? 200 : math.max(1, math.round(takeProfitDistance / tickValue))

// Final check to ensure SL/TP are not na
stopLossTicks := nz(stopLossTicks, 100)
takeProfitTicks := nz(takeProfitTicks, 200)


// --- Strategy Execution ---
// Uses Limit Orders based on previous bar's low/high - Remains the same
float limitEntryPriceLong = low[1]  // Target entry at the low of the huge volume bar
float limitEntryPriceShort = high[1] // Target entry at the high of the huge volume bar

if (finalLongCondition and strategy.position_size == 0)
    strategy.cancel("S") // Cancel any pending short limit order first
    strategy.entry("L", strategy.long, limit = limitEntryPriceLong)
    strategy.exit("L SL/TP", from_entry="L", loss=stopLossTicks, profit=takeProfitTicks)

if (finalShortCondition and strategy.position_size == 0)
    strategy.cancel("L") // Cancel any pending long limit order first
    strategy.entry("S", strategy.short, limit = limitEntryPriceShort)
    strategy.exit("S SL/TP", from_entry="S", loss=stopLossTicks, profit=takeProfitTicks)


// --- Plotting & Visuals ---
plot(avgVolume, title="Filtered Avg Volume", color=color.new(color.blue, 60), style=plot.style_line)
// Removed the plot for the normal volume threshold as it's no longer used

// Highlight huge volume bar (previous bar that triggered the signal)
bgcolor(isHugeVolumePrevBar[1] ? color.new(color.yellow, 85) : na, title="Huge Volume Bar [-1]")

// Highlight bars excluded from volume average calculation
bgcolor(excludeCurrentVolFromAvg ? color.new(color.teal, 90) : na, title="Vol Excluded from Avg Calc")

// Highlight bars where entries are ignored due to time filters
bgcolor(isIgnoreEntryTime and (baseLongCondition or baseShortCondition) ? color.new(color.gray, 75) : na, title="Entry Time Filtered Bar")

// --- MODIFIED Highlight base conditions met ---
// Reflects the updated base conditions using isVolumeLowerThanSpike
bgcolor(baseLongCondition and not isIgnoreEntryTime ? color.new(color.green, 90) : na, title="Base Long Condition Met")
bgcolor(baseShortCondition and not isIgnoreEntryTime ? color.new(color.red, 90) : na, title="Base Short Condition Met")

plot(priceSma, title="Trend SMA", color=color.gray)

// Plot SL/TP levels for visualization - Remains the same
var float entryPrice = na
var float slLevel = na
var float tpLevel = na

if (strategy.opentrades > 0 and strategy.opentrades[1] == 0) // Just entered a trade
    entryPrice := strategy.opentrades.entry_price(0)
    if (strategy.position_size > 0) // Long
        slLevel := entryPrice - stopLossTicks * tickValue
        tpLevel := entryPrice + takeProfitTicks * tickValue
    else // Short
        slLevel := entryPrice + stopLossTicks * tickValue
        tpLevel := entryPrice - takeProfitTicks * tickValue
else if (strategy.opentrades == 0 and strategy.opentrades[1] > 0) // Position closed
    entryPrice := na
    slLevel := na
    tpLevel := na
else if (strategy.opentrades > 0) // Position still open
    entryPrice := strategy.opentrades.entry_price(0)
    if (strategy.position_size > 0) // Long
        slLevel := entryPrice - stopLossTicks * tickValue
        tpLevel := entryPrice + takeProfitTicks * tickValue
    else // Short
        slLevel := entryPrice + stopLossTicks * tickValue
        tpLevel := entryPrice - takeProfitTicks * tickValue

plot(strategy.opentrades > 0 ? slLevel : na, title="Stop Loss Level", color=color.red, style=plot.style_linebr)
plot(strategy.opentrades > 0 ? tpLevel : na, title="Take Profit Level", color=color.green, style=plot.style_linebr)

// Optional Debugging Plots
// plotchar(isHugeVolumePrevBar, "HugeVol[1]", "H", location.bottom, color.yellow, size=size.tiny)
// plotchar(isVolumeLowerThanSpike, "VolLow", "v", location.bottom, color.purple, size=size.tiny) // Changed char
// plotchar(finalLongCondition, "FinalLong", "L", location.top, color.green, size=size.tiny)
// plotchar(finalShortCondition, "FinalShort", "S", location.top, color.red, size=size.tiny)
// plot(finalLongCondition ? limitEntryPriceLong : na, "Long Limit Target", color.lime, style=plot.style_circles, linewidth=2)
// plot(finalShortCondition ? limitEntryPriceShort : na, "Short Limit Target", color.fuchsia, style=plot.style_circles, linewidth=2)