Стратегия кроссовера стохастического RSI с несколькими таймфреймами

RSI STOCH RSI MTF TRENDING MARKETS STOP LOSS MULTI-STAGE TP
Дата создания: 2025-06-05 13:13:32 Последнее изменение: 2025-06-05 13:13:32
Копировать: 0 Количество просмотров: 336
2
Подписаться
319
Подписчики

Стратегия кроссовера стохастического RSI с несколькими таймфреймами Стратегия кроссовера стохастического RSI с несколькими таймфреймами

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

Многовременная стратегия скрещивания случайных относительно сильных и слабых индикаторов - это комплексная торговая система, основанная на стохастическом RSI, которая использует данные для создания и подтверждения торговых сигналов в течение двух временных периодов: 5 минут и 15 минут. Это полная торговая система, включающая четкие условия входа, контроль стоп-лосса и поэтапную схему получения прибыли.

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

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

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

  1. Первоначальный триггерный сигнал ((5 минут временной рамки)

    • Многоголовый сигнал: когда линия K на 5-минутном графике Stoch RSI пересекает линию D вверх, а значение K при пересечении ниже указанного уровня триггера ((stoch_5min_k_long_trigger))
    • Головной сигнал: когда K-линия Stoch RSI на 5-минутном графике пересекает D-линию вниз, и K-значение при пересечении превышает указанный уровень триггера ((stoch_5min_k_short_trigger) }}.
  2. Высокоуровневое подтверждение ((15-минутный промежуток времени))

    • После того, как 5-минутный начальный сигнал будет запущен, стратегия будет искать подтверждение 15-минутного временного фрейма в установленном окне ожидания (wait_window_5min_bars).
    • Многоголовое подтверждение: линия K 15-минутного Stoch RSI должна быть строго больше ее линии D, а значение K 15-минутного Stoch должно быть ниже установленного значения stoch_15min_long_entry_level.
    • Подтверждение: линия K 15-минутного Stoch RSI должна быть строго меньше, чем ее линия D, и значение K 15-минутного Stoch должно быть выше, чем установленное значение stoch_15min_short_entry_level.
  3. Повторяющаяся фильтрация

    • В стратегии применяется механизм охлаждения (min_bars_between_signals), при котором необходимо пройти определенное количество K-линий между сигналами в одном направлении, чтобы рассматривать новые сигналы.
  4. Управление позицией

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

    • Первый этап (TP1): ликвидация 50% позиций, которая может быть вызвана одним из двух способов:
      • Приоритетный способ A ((крайние значения K): если 5 минут или 15 минут Стох K значение превышает extreme_long_tp_level ((многоголовый) или ниже extreme_short_tp_level ((порог)) [2].
      • Приоритетный способ B ((условное 5-минутное пересечение + 15-минутное обращение вспять значения K): когда происходит 5-минутное пересечение K/D Stoch RSI ((вспять пересечение K вниз по D при многоголовом; вспять пересечение K вверх по D при воздушном), и подтверждается 15-минутное “пересечение” Stoch K ((вспять пересечение 15 минут K < предыдущих 15 минут K для многоголового; вспять пересечение 15 минут K > предыдущих 15 минут K для воздушного).
    • Второй этап (TP2): уравнение оставшихся 50% позиций, активируются только после того, как TP1 был активирован, и выполняются, когда 5 минут или 15 минут Стох K снова достигает того же крайнего уровня.

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

  1. Механизм подтверждения многовременных рамок

    • Эта стратегия уменьшает количество ложных сигналов и повышает качество торгов, используя в сочетании 5-минутные и 15-минутные временные рамки. Более короткие временные рамки обеспечивают возможность входа, а более длинные - подтверждение тренда, что эффективно фильтрует краткосрочный рыночный шум.
  2. Точное определение условий перекупа/перепродажи

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

    • Двухступенчатый стоп-механизм позволяет трейдеру блокировать часть прибыли, сохраняя при этом оставшуюся позицию, чтобы поймать более крупную рыночную ситуацию. Этот метод уравновешивает риски и выгоды и особенно подходит для рынков с высокой волатильностью.
  4. Настройки настройки

    • Параметры стратегии могут быть скорректированы, чтобы отразить предпочтения рынка (например, текущая стратегия более гибкая для многосторонних), что позволяет адаптироваться к различным рыночным условиям и торговым предпочтениям.
  5. Полное управление рисками

    • Четкий механизм остановки, основанный на предельных значениях входных K-линий, обеспечивает количественный контроль риска для каждой сделки. Проверка остановки убытков имеет приоритет перед проверкой прибыли, гарантируя, что контроль риска всегда является первостепенным фактором.
  6. Повторяющаяся фильтрация

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

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

  1. Параметр Чувствительность

    • Эта стратегия зависит от нескольких параметров отклонения, таких как различные уровни триггера и подтверждение отклонения. Неправильная настройка параметров может привести к избыточному количеству ложных сигналов или пропуску ключевых торговых возможностей. Эти параметры должны быть оптимизированы путем обратной проверки в различных рыночных условиях.
  2. Стоп-стоп может быть шире

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

    • Стохастический RSI хорошо работает на рынках с диапазоном колебаний, но может дать преждевременный обратный сигнал на рынке с сильным трендом. Эта стратегия может плохо работать в быстром одностороннем движении, потому что цены могут продолжаться в состоянии перекупа или перепродажи и не переворачиваться.
  4. Пристрастие к многоголосности

    • Текущая конфигурация стратегии демонстрирует предпочтение многоголовым сделкам, что может привести к чрезмерному или неуместному многоголовому сигналу в условиях медвежьего рынка. Параметры должны быть скорректированы в соответствии с рыночной обстановкой, чтобы сохранить баланс.
  5. Задержка подтверждения 15 минут

    • Ожидание подтверждения 15-минутных временных рамок может привести к задержкам входа, а в быстрых рынках может быть пропущена идеальная точка входа. В крайне волатильных рынках эта задержка может значительно повлиять на эффективность стратегии.

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

  1. Динамический тормозной механизм

    • Текущие фиксированные стоп-проценты могут быть модернизированы в динамические стопы на основе ATR (Average True Range) или внедрены механизмы стоп-следов, чтобы поймать больше прибыли в трендовых условиях. Особенно для стопов второго этапа, подумайте о том, чтобы использовать уровень стоп-стопов, скорректированный на волатильность или силу тренда.
  2. Рынок адаптируется

    • Внедрение механизмов обнаружения состояния рынка (например, индикатор ADX, оценивающий силу тренда), позволяющего стратегии автоматически корректировать параметры в зависимости от различных рыночных условий. Например, ослабление условий обратного хода на рынке с сильной тенденцией и ужесточение этих условий на рынке с волатильностью.
  3. Многопоказательная синхронизация

    • Интеграция дополнительных технических показателей, таких как MACD, ленты Бринга или движущиеся средние, в качестве вспомогательного инструмента подтверждения. Многопоказательная резонансная частота может повысить надежность сигнала и уменьшить количество ложных прорывов.
  4. Оптимизация выхода из риска

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

    • Подумайте о добавлении третьих временных рамок (например, 1 час или 4 часа), чтобы обеспечить более высокий уровень анализа рынка, особенно для подтверждения тенденций и определения основных уровней поддержки/сопротивления.
  6. Фильтрация по времени сделки

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

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

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

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

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

Исходный код стратегии
/*backtest
start: 2024-06-05 00:00:00
end: 2025-06-04 00:00:00
period: 2d
basePeriod: 2d
exchanges: [{"eid":"Futures_Binance","currency":"DOGE_USDT"}]
*/

// This Pine Script® code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Archertoria

//@version=6
strategy("System 0530 - Stoch RSI Strategy v13 SL-Priority TP-Reversal", 
         overlay=true, 
         default_qty_type=strategy.percent_of_equity, 
         default_qty_value=100, 
         calc_on_order_fills=false, 
         process_orders_on_close=true,
         margin_short=50) 

// --- Original Indicator Input Parameters ---
g_stoch = "Stochastic RSI Parameters"
rsi_len = input.int(14, "RSI Period", minval=1, group=g_stoch)
stoch_rsi_len = input.int(14, "Stochastic of RSI Period (K Period for Stoch)", minval=1, group=g_stoch)
stoch_k_smooth = input.int(3, "Stochastic %K Smoothing (D Period for Stoch)", minval=1, group=g_stoch)
stoch_d_smooth = input.int(3, "Stochastic %D Smoothing (Smoothing for final D)", minval=1, group=g_stoch)

g_signal = "Signal Trigger and Confirmation Parameters"
stoch_5min_k_long_trigger = input.float(40.0, "5-min Stoch K Long Trigger Level (K must be ≤ this value)", minval=0, maxval=100, step=0.1, group=g_signal, tooltip="On the 5-minute chart, when the K line crosses above the D line, the K value at that time must be less than or equal to this setting to initiate a long signal wait.")
stoch_5min_k_short_trigger = input.float(70.0, "5-min Stoch K Short Trigger Level (K must be ≥ this value)", minval=0, maxval=100, step=0.1, group=g_signal, tooltip="On the 5-minute chart, when the K line crosses below the D line, the K value at that time must be greater than or equal to this setting to initiate a short signal wait.")
stoch_15min_long_entry_level = input.int(50, "15-min Stoch K Long Confirmation Threshold (K must be below this value)", minval=0, maxval=100, group=g_signal, tooltip="On the 15-minute chart, for final long confirmation, the 15-minute K line value must be below this setting.")
stoch_15min_short_entry_level = input.int(70, "15-min Stoch K Short Confirmation Threshold (K must be above this value)", minval=0, maxval=100, group=g_signal, tooltip="On the 15-minute chart, for final short confirmation, the 15-minute K line value must be above this setting.")
wait_window_5min_bars = input.int(7, "Number of 5-min bars to wait for 15-min signal", minval=1, group=g_signal, tooltip="After a 5-minute signal is issued, wait for 15-minute signal confirmation within the next N 5-minute bars.")

g_repeat_filter = "Duplicate Signal Filtering Settings"
use_signal_cooldown_filter = input.bool(true, title="Enable Duplicate Signal Filter", group=g_repeat_filter, tooltip="Filters out duplicate signals in the same direction within a short period.")
min_bars_between_signals = input.int(12, title="Minimum Bars Between Same-Direction Signals", minval=1, group=g_repeat_filter, tooltip="After a signal is issued, at least this many bars must pass before another signal in the same direction can be issued.")

// --- Take Profit Parameters ---
g_tp_params = "Take Profit Parameters"
extreme_long_tp_level = input.float(95.0, "Extreme Long TP Level (Stoch K >)", minval=50, maxval=100, step=0.1, group=g_tp_params, tooltip="Direct TP for longs if 5-min OR 15-min Stoch K exceeds this.")
extreme_short_tp_level = input.float(5.0, "Extreme Short TP Level (Stoch K <)", minval=0, maxval=50, step=0.1, group=g_tp_params, tooltip="Direct TP for shorts if 5-min OR 15-min Stoch K is below this.")

// --- Strategy Specific Input Parameters ---
g_strategy = "Strategy Parameters"
leverage_multiplier = input.float(1.0, "Leverage Multiplier (Affects theoretical position size only)", minval=1.0, step=0.1, group=g_strategy, tooltip="Note: TradingView strategies do not directly simulate margin account liquidation. This leverage is used to calculate theoretical position size. Actual leverage effects must be realized with a broker that supports leverage.")

// --- Function: Calculate Stochastic RSI ---
getStochasticRSI(src, rsiLen, stochLen, kSmooth, dSmooth) =>
    rsi_val = ta.rsi(src, rsiLen)
    stoch_rsi_k_raw = ta.stoch(rsi_val, rsi_val, rsi_val, stochLen) // Stoch of RSI
    stoch_rsi_k = ta.sma(stoch_rsi_k_raw, kSmooth)
    stoch_rsi_d = ta.sma(stoch_rsi_k, dSmooth)
    [stoch_rsi_k, stoch_rsi_d]

// --- Helper Function to get only K-series for Stochastic RSI (RE-ADDED for 15-min prev K) ---
getStochKSeriesOnly(src, rsiLen, stochLen, kSmooth, dSmooth) =>
    rsi_val = ta.rsi(src, rsiLen)
    stoch_rsi_k_raw = ta.stoch(rsi_val, rsi_val, rsi_val, stochLen)
    stoch_rsi_k = ta.sma(stoch_rsi_k_raw, kSmooth)
    stoch_rsi_k // Return only the K series

// --- Time Series Data Fetching and Stochastic RSI Calculation ---
[stoch_k_15min_val, stoch_d_15min_val] = request.security(syminfo.tickerid, "15", getStochasticRSI(close, rsi_len, stoch_rsi_len, stoch_k_smooth, stoch_d_smooth), lookahead=barmerge.lookahead_off)
// RE-ADDED: K value of the PREVIOUS 15-minute bar's Stochastic RSI
stoch_k_15min_prev_tf_bar = request.security(syminfo.tickerid, "15", nz(getStochKSeriesOnly(close, rsi_len, stoch_rsi_len, stoch_k_smooth, stoch_d_smooth)[1]), lookahead=barmerge.lookahead_off)
[stoch_k_5min_val, stoch_d_5min_val] = getStochasticRSI(close, rsi_len, stoch_rsi_len, stoch_k_smooth, stoch_d_smooth)

// --- Signal Logic State Variables ---
var bool waiting_for_15m_long_confirm = false
var bool waiting_for_15m_short_confirm = false
var int bars_elapsed_in_wait_state = 0
var int last_long_signal_bar_idx = -min_bars_between_signals 
var int last_short_signal_bar_idx = -min_bars_between_signals

// --- Variables to store SL reference points from ENTRY bar ---
var float entry_bar_low_for_sl = na
var float entry_bar_high_for_sl = na

// --- Take Profit Logic State Variables ---
var bool first_tp_long_taken = false
var bool first_tp_short_taken = false
// RE-ADDED: State variables for pending TP confirmation on 15-min reversal
var bool pending_long_tp_on_15m_reversal = false
var bool pending_short_tp_on_15m_reversal = false

// --- Detect 5-minute Stochastic RSI crossover events for ENTRY ---
bool stoch_5min_crossed_up_prev_bar = ta.crossover(stoch_k_5min_val[1], stoch_d_5min_val[1])
bool stoch_5min_crossed_down_prev_bar = ta.crossunder(stoch_k_5min_val[1], stoch_d_5min_val[1])
bool condition_5min_k_level_for_long_trigger = stoch_k_5min_val[1] <= stoch_5min_k_long_trigger
bool condition_5min_k_level_for_short_trigger = stoch_k_5min_val[1] >= stoch_5min_k_short_trigger

// --- Specific 5-minute Stochastic RSI crossover for Take Profit (current bar) ---
bool stoch_5min_k_cross_under_d_tp = ta.crossunder(stoch_k_5min_val, stoch_d_5min_val) // For Long TP trigger
bool stoch_5min_k_cross_over_d_tp  = ta.crossover(stoch_k_5min_val, stoch_d_5min_val)  // For Short TP trigger

// --- RE-ADDED: 15-minute Reversal Confirmation for Take Profit ---
bool confirm_15m_reversal_for_long_tp = stoch_k_15min_val < stoch_k_15min_prev_tf_bar
bool confirm_15m_reversal_for_short_tp = stoch_k_15min_val > stoch_k_15min_prev_tf_bar

// --- Manage waiting state and tolerance period for ENTRY ---
if (strategy.position_size == 0)
    if (stoch_5min_crossed_up_prev_bar and condition_5min_k_level_for_long_trigger)
        can_trigger_new_long = not use_signal_cooldown_filter or (bar_index - last_long_signal_bar_idx >= min_bars_between_signals)
        if (can_trigger_new_long)
            waiting_for_15m_long_confirm := true
            waiting_for_15m_short_confirm := false 
            bars_elapsed_in_wait_state := 1
    else if (stoch_5min_crossed_down_prev_bar and condition_5min_k_level_for_short_trigger)
        can_trigger_new_short = not use_signal_cooldown_filter or (bar_index - last_short_signal_bar_idx >= min_bars_between_signals)
        if (can_trigger_new_short)
            waiting_for_15m_short_confirm := true
            waiting_for_15m_long_confirm := false 
            bars_elapsed_in_wait_state := 1
    else if (waiting_for_15m_long_confirm or waiting_for_15m_short_confirm)
        bars_elapsed_in_wait_state += 1
    
    if (bars_elapsed_in_wait_state > wait_window_5min_bars)
        waiting_for_15m_long_confirm := false
        waiting_for_15m_short_confirm := false
        bars_elapsed_in_wait_state := 0 
else 
    waiting_for_15m_long_confirm := false
    waiting_for_15m_short_confirm := false
    bars_elapsed_in_wait_state := 0

// --- 15-minute Stochastic RSI confirmation conditions for ENTRY (Strict Crossover) ---
bool confirm_15min_long_stoch_kd_cond = stoch_k_15min_val > stoch_d_15min_val // K must be strictly greater than D
bool confirm_15min_short_stoch_kd_cond = stoch_k_15min_val < stoch_d_15min_val // K must be strictly less than D
bool filter_15min_stoch_level_long = stoch_k_15min_val < stoch_15min_long_entry_level
bool filter_15min_stoch_level_short = stoch_k_15min_val > stoch_15min_short_entry_level

// --- Main Signal Determination (for strategy logic) ---
entry_long_signal = false
entry_short_signal = false

if (strategy.position_size == 0) 
    if (waiting_for_15m_long_confirm and bars_elapsed_in_wait_state <= wait_window_5min_bars)
        if (confirm_15min_long_stoch_kd_cond and filter_15min_stoch_level_long)
            can_confirm_new_long = not use_signal_cooldown_filter or (bar_index - last_long_signal_bar_idx >= min_bars_between_signals)
            if (can_confirm_new_long)
                entry_long_signal := true
    if (waiting_for_15m_short_confirm and bars_elapsed_in_wait_state <= wait_window_5min_bars)
        if (confirm_15min_short_stoch_kd_cond and filter_15min_stoch_level_short)
            can_confirm_new_short = not use_signal_cooldown_filter or (bar_index - last_short_signal_bar_idx >= min_bars_between_signals)
            if (can_confirm_new_short)
                entry_short_signal := true

// --- Strategy Execution Logic ---
// Reset SL ref and TP flags if position just closed
if (strategy.position_size == 0 and strategy.position_size[1] != 0) 
    first_tp_long_taken := false
    first_tp_short_taken := false
    entry_bar_low_for_sl := na 
    entry_bar_high_for_sl := na 
    pending_long_tp_on_15m_reversal := false // Reset pending TP flag
    pending_short_tp_on_15m_reversal := false // Reset pending TP flag

if (entry_long_signal) 
    strategy.entry("LE", strategy.long, comment="Long Entry")
    last_long_signal_bar_idx := bar_index 
    waiting_for_15m_long_confirm := false 
    bars_elapsed_in_wait_state := 0
    first_tp_long_taken := false 
    entry_bar_low_for_sl := low 
    entry_bar_high_for_sl := na 
    pending_long_tp_on_15m_reversal := false // Reset for new trade
    pending_short_tp_on_15m_reversal := false     

if (entry_short_signal) 
    strategy.entry("SE", strategy.short, comment="Short Entry")
    last_short_signal_bar_idx := bar_index 
    waiting_for_15m_short_confirm := false 
    bars_elapsed_in_wait_state := 0
    first_tp_short_taken := false  
    entry_bar_high_for_sl := high 
    entry_bar_low_for_sl := na    
    pending_short_tp_on_15m_reversal := false // Reset for new trade
    pending_long_tp_on_15m_reversal := false

// --- Stop Loss Logic (PRIORITY 1) ---
// Check and execute SL first. If SL triggers, position size becomes 0, preventing TP logic below from executing on the same bar.
bool sl_triggered_this_bar = false
if (strategy.position_size > 0) // If in a long trade
    if (not na(entry_bar_low_for_sl) and close < entry_bar_low_for_sl)
        strategy.close(id="LE", comment="SL Long")
        sl_triggered_this_bar := true
        pending_long_tp_on_15m_reversal := false // Ensure pending TP is cancelled if SL hits

if (strategy.position_size < 0) // If in a short trade
    if (not na(entry_bar_high_for_sl) and close > entry_bar_high_for_sl)
        strategy.close(id="SE", comment="SL Short")
        sl_triggered_this_bar := true
        pending_short_tp_on_15m_reversal := false // Ensure pending TP is cancelled if SL hits

// --- Take Profit Logic (PRIORITY 2 - only if SL did not trigger on this bar) ---
if (not sl_triggered_this_bar) // Only proceed with TP if SL hasn't already closed the position on this bar
    if (strategy.position_size > 0) // --- LONG TP LOGIC ---
        extreme_long_tp_condition = stoch_k_5min_val > extreme_long_tp_level or stoch_k_15min_val > extreme_long_tp_level
        if (extreme_long_tp_condition)
            if (not first_tp_long_taken)
                strategy.close(id="LE", comment="TP1 Long", qty_percent=50)
                first_tp_long_taken := true
            else 
                strategy.close(id="LE", comment="TP2 Long")
            pending_long_tp_on_15m_reversal := false // Reset pending state as this TP takes precedence
        else 
            // Conditional TP logic (5-min trigger + 15-min reversal)
            if (stoch_5min_k_cross_under_d_tp and not pending_long_tp_on_15m_reversal) // Set pending state
                pending_long_tp_on_15m_reversal := true
        
            if (pending_long_tp_on_15m_reversal and confirm_15m_reversal_for_long_tp) // Check for confirmation
                if (not first_tp_long_taken)
                    strategy.close(id="LE", comment="TP1 Long", qty_percent=50)
                    first_tp_long_taken := true
                else 
                    strategy.close(id="LE", comment="TP2 Long")
                pending_long_tp_on_15m_reversal := false // Reset after TP

    if (strategy.position_size < 0) // --- SHORT TP LOGIC ---
        extreme_short_tp_condition = stoch_k_5min_val < extreme_short_tp_level or stoch_k_15min_val < extreme_short_tp_level
        if (extreme_short_tp_condition)
            if (not first_tp_short_taken)
                strategy.close(id="SE", comment="TP1 Short", qty_percent=50)
                first_tp_short_taken := true
            else 
                strategy.close(id="SE", comment="TP2 Short")
            pending_short_tp_on_15m_reversal := false // Reset pending state
        else
            // Conditional TP logic (5-min trigger + 15-min reversal)
            if (stoch_5min_k_cross_over_d_tp and not pending_short_tp_on_15m_reversal) // Set pending state
                pending_short_tp_on_15m_reversal := true

            if (pending_short_tp_on_15m_reversal and confirm_15m_reversal_for_short_tp) // Check for confirmation
                if (not first_tp_short_taken)
                    strategy.close(id="SE", comment="TP1 Short", qty_percent=50)
                    first_tp_short_taken := true
                else 
                    strategy.close(id="SE", comment="TP2 Short")
                pending_short_tp_on_15m_reversal := false // Reset after TP