Strategi Purata Tangga Arah Aliran: Bagaimana untuk "Berbaring Mendatar" Secara Elegan Apabila Pasaran Mengiring?

ADX EMA ATR DI
Tarikh penciptaan: 2025-10-09 14:28:37 Akhirnya diubah suai: 2025-10-09 14:28:37
Salin: 0 Bilangan klik: 268
2
fokus pada
319
Pengikut

Strategi Purata Tangga Arah Aliran: Bagaimana untuk “Berbaring Mendatar” Secara Elegan Apabila Pasaran Mengiring? Strategi Purata Tangga Arah Aliran: Bagaimana untuk “Berbaring Mendatar” Secara Elegan Apabila Pasaran Mengiring?

Mengapa strategi trend-following tradisional sering ‘berbalik arah’ dalam keadaan yang bergolak?

Sebagai seorang trader kuantitatif, saya sering ditanya soalan ini: mengapa strategi yang berkinerja baik dalam pasaran yang sedang tren mula berundur dengan ketara apabila berlaku kejutan?

Jawapannya adalah mudah: kebanyakan strategi trend-following mengalami “kecenderungan obsesif” - mereka sentiasa berusaha untuk mengekalkan frekuensi perdagangan yang tinggi dalam apa jua keadaan pasaran, tetapi mengabaikan satu fakta asas:Pasaran berada dalam keadaan goyah 70% masa

Strategi rata-rata tangga trend yang akan kita bincangkan hari ini menawarkan penyelesaian yang menarik untuk masalah ini:Berpegang teguh dalam pasaran yang sedang tren, “berbaring dengan elegan” dalam pasaran yang bergolak

Apakah maksud rata-rata tangga dan bagaimana ia boleh mentakrifkan semula trend-tracking?

Strategi purata bergerak tradisional mempunyai kelemahan yang mematikan: mereka sentiasa berubah. Sama ada pasaran adalah trend yang kuat atau pergerakan yang berliku, garis purata akan sentiasa disesuaikan dengan turun naik harga, yang menyebabkan banyak isyarat palsu.

Ini adalah idea utama dari Ladder Average:“Beku” garis rata dalam keadaan tertentu

Logik pelaksanaan adalah seperti berikut:

  1. Pengesanan status trendMenerusi indikator ADX untuk menilai kekuatan trend pasaran:

    • ADX > 25: Pasaran trend kuat
    • Rata-rata kemerosotan < 0.3%: pasaran mendatar
  2. Dinamik Linear

    • Apabila trend kuat: mengikuti EMA secara normal 21
    • Apabila bertabung: garis rata “beku” dalam kedudukan mendatar, membentuk sokongan / rintangan

Ini adalah reka bentuk yang menarik kerana:Ia membolehkan strategi menunjukkan “sifat” yang berbeza dalam keadaan pasaran yang berbeza.Ia juga boleh digunakan untuk membasmi virus dan membasmi virus.

Bagaimana anda boleh menggunakan sistem Trend Capture?

Selain daripada mekanisme purata tangga asas, strategi ini juga menggabungkan modul “mengambil trend”, yang saya anggap sebagai bahagian yang paling inovatif:

Mekanisme pembalikan pantas

  • Apabila trend yang baru sahaja dirundingkan muncul,
  • Menubuhkan kedudukan baru dengan cepat dalam 3 kitaran
  • Syarat: ADX > 30 dan perbezaan DI+ dan DI- > 10

Reka bentuk ini menyelesaikan masalah utama strategi tradisional:Bagaimana untuk menyesuaikan kedudukan anda dengan cepat pada permulaan perubahan trend

Bayangkan satu senario: anda baru sahaja menebus banyak kedudukan teratas kerana stop loss, dan hasilnya pasaran segera mengalami tren turun yang kuat. Strategi tradisional mungkin memerlukan menunggu pengesahan isyarat baru, tetapi sistem “pemangkasan trend” ini dapat membangunkan kedudukan kosong dengan cepat dalam 3 kitaran.

Pengurusan Risiko: Mengapa membezakan keadaan pasaran?

Yang paling menarik dari strategi ini ialah:Mekanisme pengurusan risiko yang berbeza

Kawalan risiko dalam pasaran horizontal

  • Stop loss disesuaikan dengan garis rata tangga
  • Menurunkan ATR dan mengetatkan stop loss
  • Tetapan bit sasaran lebih konservatif

Kawalan risiko dalam pasaran trend

  • Pengecutan dengan ATR standard
  • Mengaktifkan penghentian bergerak tangga
  • Membiarkan ruang harga yang lebih besar

Reka bentuk ini mencerminkan falsafah perdagangan yang penting:Persekitaran pasaran yang berbeza memerlukan pilihan risiko yang berbezaDalam pasaran yang berlainan arah, kita perlu lebih berhati-hati; dalam pasaran yang berlainan arah, kita perlu memberi lebih banyak ruang kepada keuntungan.

Stop Loss Mobile Ladder: Bagaimana untuk Mengimbangi Perlindungan Keuntungan dan Pemantauan Trend?

Hentian bergerak tradisional sering menjadi terlalu mekanikal, sama ada terlalu ketat menyebabkan penyingkiran awal, atau terlalu santai tidak dapat melindungi keuntungan dengan berkesan. Hentian bergerak bertingkat dalam strategi ini menawarkan penyelesaian yang lebih bijak:

Logik tetapan tangga

  • Jarak tangga berdasarkan ATR dinamik
  • Tetapkan sehingga 5 tahap tangga
  • Setiap satu tangga yang dilalui, Stop Loss akan dinaikkan.

Kelebihan reka bentuk ini ialah:Ia boleh melindungi keuntungan dan memberi trend ruang yang mencukupi untuk berkembang.

Apa yang perlu diperhatikan dalam aplikasi praktikal?

Berdasarkan pengalaman saya di lapangan, beberapa perkara perlu diperhatikan semasa menggunakan strategi seperti ini:

  1. Perangkap pengoptimuman parameterJangan terlalu mengoptimumkan ADX, nilai antara 25-30 stabil di kebanyakan pasaran

  2. Kesesuaian pasaranStrategi ini lebih sesuai untuk pasaran sederhana yang tidak menentu dan mungkin memerlukan penyesuaian ATR dalam keadaan yang sangat bergelombang

  3. Pengurusan wangIa disyorkan untuk tidak mengambil lebih daripada 10% daripada jumlah dana, terutamanya apabila trend capture diaktifkan.

  4. Trap pengesananBerhati-hati dengan kesan slippage dan yuran, terutamanya dalam perdagangan yang kerap berlaku di pasaran yang bergolak

Di mana nilai inovasi dalam strategi ini?

Dari segi perkembangan strategi kuantitatif, strategi ini mewakili satu arah evolusi yang penting:Peralihan dari logik tunggal ke adaptasi pelbagai keadaan

Strategi tradisional sering cuba menangani semua keadaan pasaran dengan satu set logik yang tetap, dan strategi ini menunjukkan kebijaksanaan yang sesuai dengan lokasi:

  • Berlakon sebagai trend follower yang radikal dalam pasaran trend
  • Berlaku seperti peniaga rantau yang konservatif dalam pasaran yang bergolak

Idea reka bentuk ini memberi inspirasi penting kepada pembangun strategi:Kita perlu membuat strategi yang mempunyai keupayaan untuk “mengesan pasaran” dan tidak mengikut logik yang tetap secara buta.

Akhirnya, perlu ditekankan bahawa tidak ada strategi yang boleh digunakan untuk semua. Strategi purata tangga ini, walaupun dalam teori yang elegan, masih perlu disesuaikan dengan keadaan pasaran tertentu dan keutamaan risiko peribadi dalam aplikasi praktikal.Strategi terbaik adalah yang paling sesuai untuk anda.

Kod sumber strategi
/*backtest
start: 2024-10-09 00:00:00
end: 2025-10-07 08:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Futures_Binance","currency":"SOL_USDT","balance":500000}]
*/

//@version=5
strategy("Trend Following Ladder Average Strategy", overlay=true, default_qty_type=strategy.percent_of_equity, default_qty_value=10)

// ═══════════════════════════════════════════════════════════════════════════════
// SETTINGS AND PARAMETERS
// ═══════════════════════════════════════════════════════════════════════════════

// Ladder Average Settings
ma_length = input.int(title="Average Period", defval=21, minval=5)
ma_type = input.string(title="Average Type", defval="EMA", options=["SMA", "EMA", "WMA"])

// Trend Strength Settings
adx_length = input.int(title="Trend Strength Period (ADX)", defval=14, minval=5)
trend_threshold = input.float(title="Trend Strength Threshold", defval=25.0, minval=10.0, step=5.0)
sideways_slope_threshold = input.float(title="Sideways Market Slope Threshold", defval=0.3, minval=0.1, step=0.1)

// Trend Catching Settings
enable_trend_catch = input.bool(title="Trend Catching System", defval=true)
trend_catch_adx_threshold = input.float(title="Trend Catch ADX Threshold", defval=30.0, minval=20.0, step=5.0)
trend_catch_di_diff = input.float(title="DI+ DI- Difference Threshold", defval=10.0, minval=5.0, step=2.5)
quick_entry_bars = input.int(title="Quick Entry Waiting Bars", defval=3, minval=1, maxval=10)

// ATR and Volatility Settings
atr_length = input.int(title="ATR Period", defval=14, minval=1)
atr_multiplier = input.float(title="ATR Multiplier", defval=2.0, minval=0.1, step=0.1)

// Ladder Trailing Stop Settings
ladder_step = input.float(title="Ladder Step Size (%)", defval=1.0, minval=0.1, step=0.1)
max_ladders = input.int(title="Maximum Ladder Count", defval=5, minval=2, maxval=10)

// Stop Loss and Take Profit Settings
use_stop_loss = input.bool(title="Use Stop Loss", defval=false)
use_take_profit = input.bool(title="Use Take Profit", defval=false)
use_trailing_stop = input.bool(title="Use Trailing Stop", defval=true)

sl_type = input.string(title="Stop Loss Type", defval="ATR", options=["ATR", "Percent", "Points"])
sl_atr_multiplier = input.float(title="SL ATR Multiplier", defval=2.0, minval=0.5, step=0.1)
sl_percent = input.float(title="SL Percent (%)", defval=2.0, minval=0.1, step=0.1)
sl_points = input.float(title="SL Points", defval=100, minval=1)

tp_type = input.string(title="Take Profit Type", defval="ATR", options=["ATR", "Percent", "Points", "Risk/Reward"])
tp_atr_multiplier = input.float(title="TP ATR Multiplier", defval=3.0, minval=0.5, step=0.1)
tp_percent = input.float(title="TP Percent (%)", defval=3.0, minval=0.1, step=0.1)
tp_points = input.float(title="TP Points", defval=150, minval=1)
tp_risk_reward = input.float(title="Risk/Reward Ratio", defval=2.0, minval=0.5, step=0.1)

// Horizontal Level Settings
horizontal_lookback = input.int(title="Horizontal Level Stabilization Period", defval=10, minval=3)

// ═══════════════════════════════════════════════════════════════════════════════
// INDICATORS AND CALCULATIONS
// ═══════════════════════════════════════════════════════════════════════════════

// ATR calculation
atr_value = ta.atr(atr_length)

// Moving Average calculation
ma_value = ma_type == "SMA" ? ta.sma(close, ma_length) : ma_type == "EMA" ? ta.ema(close, ma_length) : ma_type == "WMA" ? ta.wma(close, ma_length) : ta.ema(close, ma_length)

// ADX (Trend Strength) calculation - Manual calculation
tr = math.max(high - low, math.max(math.abs(high - close[1]), math.abs(low - close[1])))
plus_dm = high - high[1] > low[1] - low ? math.max(high - high[1], 0) : 0
minus_dm = low[1] - low > high - high[1] ? math.max(low[1] - low, 0) : 0
plus_di = 100 * ta.rma(plus_dm, adx_length) / ta.rma(tr, adx_length)
minus_di = 100 * ta.rma(minus_dm, adx_length) / ta.rma(tr, adx_length)
adx_value = 100 * ta.rma(math.abs(plus_di - minus_di) / (plus_di + minus_di), adx_length)

// MA slope calculation (for sideways market detection)
ma_slope = (ma_value - ma_value[5]) / ma_value[5] * 100

// Trend state detection
is_strong_trend = adx_value > trend_threshold
is_sideways_by_slope = math.abs(ma_slope) < sideways_slope_threshold
is_sideways = not is_strong_trend or is_sideways_by_slope

// Trend direction detection (DI+ vs DI-)
is_uptrend = plus_di > minus_di
is_downtrend = minus_di > plus_di
di_difference = math.abs(plus_di - minus_di)

// Strong trend momentum detection
strong_uptrend = adx_value > trend_catch_adx_threshold and plus_di > minus_di and di_difference > trend_catch_di_diff
strong_downtrend = adx_value > trend_catch_adx_threshold and minus_di > plus_di and di_difference > trend_catch_di_diff

// Position tracking system
var bool just_closed_long = false
var bool just_closed_short = false
var int bars_since_close = 0

// Position closure tracking - Fixed
if strategy.position_size == 0 and strategy.position_size[1] != 0
    if strategy.position_size[1] > 0
        just_closed_long := true
        just_closed_short := false
    else
        just_closed_short := true  
        just_closed_long := false
    bars_since_close := 0
else if strategy.position_size == 0
    bars_since_close += 1
    if bars_since_close > quick_entry_bars
        just_closed_long := false
        just_closed_short := false
else
    just_closed_long := false
    just_closed_short := false
    bars_since_close := 0

// Ladder Average System
var float ladder_ma = na
var float horizontal_level = na
var int sideways_count = 0

// Trend-following ladder average
if is_strong_trend and not is_sideways_by_slope
    // Normal MA tracking in strong trend
    ladder_ma := ma_value
    sideways_count := 0
else
    // When trend weakens or in sideways market
    sideways_count += 1
    if sideways_count >= horizontal_lookback or na(horizontal_level)
        horizontal_level := ma_value
    ladder_ma := horizontal_level

// Market state
market_state = is_strong_trend and not is_sideways_by_slope ? "TREND" : "SIDEWAYS"

// Volatility measurement
volatility = atr_value / close * 100

// ═══════════════════════════════════════════════════════════════════════════════
// STOP LOSS AND TAKE PROFIT CALCULATIONS
// ═══════════════════════════════════════════════════════════════════════════════

// Stop Loss calculation function
calculate_stop_loss(entry_price_val, is_long) =>
    sl_value = sl_type == "ATR" ? (is_long ? entry_price_val - (atr_value * sl_atr_multiplier) : entry_price_val + (atr_value * sl_atr_multiplier)) : sl_type == "Percent" ? (is_long ? entry_price_val * (1 - sl_percent / 100) : entry_price_val * (1 + sl_percent / 100)) : sl_type == "Points" ? (is_long ? entry_price_val - sl_points : entry_price_val + sl_points) : (is_long ? entry_price_val - (atr_value * sl_atr_multiplier) : entry_price_val + (atr_value * sl_atr_multiplier))
    sl_adjusted = if is_sideways
        is_long ? math.min(sl_value, ladder_ma - atr_value * 0.5) : math.max(sl_value, ladder_ma + atr_value * 0.5)
    else
        sl_value
    sl_adjusted

// Take Profit calculation function
calculate_take_profit(entry_price_val, stop_loss_val, is_long) =>
    tp_value = tp_type == "ATR" ? (is_long ? entry_price_val + (atr_value * tp_atr_multiplier) : entry_price_val - (atr_value * tp_atr_multiplier)) : tp_type == "Percent" ? (is_long ? entry_price_val * (1 + tp_percent / 100) : entry_price_val * (1 - tp_percent / 100)) : tp_type == "Points" ? (is_long ? entry_price_val + tp_points : entry_price_val - tp_points) : tp_type == "Risk/Reward" ? (is_long ? entry_price_val + (math.abs(entry_price_val - stop_loss_val) * tp_risk_reward) : entry_price_val - (math.abs(entry_price_val - stop_loss_val) * tp_risk_reward)) : (is_long ? entry_price_val + (atr_value * tp_atr_multiplier) : entry_price_val - (atr_value * tp_atr_multiplier))
    tp_adjusted = if is_sideways
        is_long ? math.max(tp_value, ladder_ma + atr_value * 1.5) : math.min(tp_value, ladder_ma - atr_value * 1.5)
    else
        tp_value
    tp_adjusted

var float current_sl = na
var float current_tp = na

// ═══════════════════════════════════════════════════════════════════════════════
// ENTRY SIGNALS
// ═══════════════════════════════════════════════════════════════════════════════

// Normal entry conditions
normal_long = strategy.position_size == 0 and ((is_strong_trend and close > ladder_ma and close[1] <= ladder_ma[1]) or (is_sideways and close < ladder_ma and close > ladder_ma - atr_value))
normal_short = strategy.position_size == 0 and ((is_strong_trend and close < ladder_ma and close[1] >= ladder_ma[1]) or (is_sideways and close > ladder_ma and close < ladder_ma + atr_value))

// Trend catching entry conditions
trend_catch_long = enable_trend_catch and strategy.position_size == 0 and just_closed_short and bars_since_close <= quick_entry_bars and strong_uptrend and close > close[1] and close > ladder_ma
trend_catch_short = enable_trend_catch and strategy.position_size == 0 and just_closed_long and bars_since_close <= quick_entry_bars and strong_downtrend and close < close[1] and close < ladder_ma

// Strong momentum entry conditions (even if no position closed, but strong trend exists)
momentum_long = enable_trend_catch and strategy.position_size == 0 and strong_uptrend and close > ladder_ma and close > close[1] and close > open
momentum_short = enable_trend_catch and strategy.position_size == 0 and strong_downtrend and close < ladder_ma and close < close[1] and close < open

// Combined entry conditions
long_condition = normal_long or trend_catch_long or momentum_long
short_condition = normal_short or trend_catch_short or momentum_short

// Entry type determination
entry_type = if trend_catch_long or trend_catch_short
    "TREND_CATCH"
else if momentum_long or momentum_short
    "MOMENTUM"
else
    market_state

// ═══════════════════════════════════════════════════════════════════════════════
// LADDER TRAILING STOP SYSTEM
// ═══════════════════════════════════════════════════════════════════════════════

var float[] ladder_levels = array.new<float>()
var float current_trailing_stop = na
var float entry_price = na

// Calculate ladder levels function
calculate_ladder_levels(entry_price_val, is_long) =>
    ladder_array = array.new<float>()
    base_level = ladder_ma
    for i = 1 to max_ladders
        level_value = if is_long
            base_level + (atr_value * atr_multiplier * i * ladder_step / 100)
        else
            base_level - (atr_value * atr_multiplier * i * ladder_step / 100)
        array.push(ladder_array, level_value)
    ladder_array

// Trailing stop update function
update_trailing_stop(entry_price_val, current_price, is_long) =>
    stop_level = if is_long
        initial_stop = is_sideways ? ladder_ma - atr_value : entry_price_val - (atr_value * atr_multiplier)
        new_stop = initial_stop
        if array.size(ladder_levels) > 0
            for i = 0 to array.size(ladder_levels) - 1
                level_value = array.get(ladder_levels, i)
                if current_price >= level_value
                    adjusted_stop = is_sideways ? ladder_ma : entry_price_val + (atr_value * atr_multiplier * (i + 1) * 0.3)
                    if adjusted_stop > new_stop
                        new_stop := adjusted_stop
        new_stop
    else
        initial_stop = is_sideways ? ladder_ma + atr_value : entry_price_val + (atr_value * atr_multiplier)
        new_stop = initial_stop
        if array.size(ladder_levels) > 0
            for i = 0 to array.size(ladder_levels) - 1
                level_value = array.get(ladder_levels, i)
                if current_price <= level_value
                    adjusted_stop = is_sideways ? ladder_ma : entry_price_val - (atr_value * atr_multiplier * (i + 1) * 0.3)
                    if adjusted_stop < new_stop
                        new_stop := adjusted_stop
        new_stop
    stop_level

// ═══════════════════════════════════════════════════════════════════════════════
// POSITION MANAGEMENT
// ═══════════════════════════════════════════════════════════════════════════════

// Long position entry
if long_condition
    strategy.entry("Long", strategy.long, comment="Long: " + market_state)
    entry_price := close
    ladder_levels := calculate_ladder_levels(close, true)
    
    // Stop Loss calculation (only if active)
    if use_stop_loss
        current_sl := calculate_stop_loss(close, true)
    
    // Take Profit calculation (only if active)
    if use_take_profit
        temp_sl = use_stop_loss ? current_sl : close - (atr_value * sl_atr_multiplier)
        current_tp := calculate_take_profit(close, temp_sl, true)
    
    // Trailing stop initialization (only if active)
    if use_trailing_stop
        current_trailing_stop := is_sideways ? ladder_ma - atr_value : close - (atr_value * atr_multiplier)

// Short position entry
if short_condition
    strategy.entry("Short", strategy.short, comment="Short: " + market_state)
    entry_price := close
    ladder_levels := calculate_ladder_levels(close, false)
    
    // Stop Loss calculation (only if active)
    if use_stop_loss
        current_sl := calculate_stop_loss(close, false)
    
    // Take Profit calculation (only if active)
    if use_take_profit
        temp_sl = use_stop_loss ? current_sl : close + (atr_value * sl_atr_multiplier)
        current_tp := calculate_take_profit(close, temp_sl, false)
    
    // Trailing stop initialization (only if active)
    if use_trailing_stop
        current_trailing_stop := is_sideways ? ladder_ma + atr_value : close + (atr_value * atr_multiplier)

// Position exit management
if strategy.position_size > 0  // Long position
    // If using fixed SL/TP
    if use_stop_loss and use_take_profit
        strategy.exit("Long Exit", "Long", stop=current_sl, limit=current_tp, comment="SL/TP")
    else if use_stop_loss and not use_take_profit
        strategy.exit("Long Exit", "Long", stop=current_sl, comment="SL Only")
    else if not use_stop_loss and use_take_profit
        strategy.exit("Long Exit", "Long", limit=current_tp, comment="TP Only")
    
    // If using trailing stop (optional)
    if use_trailing_stop
        current_trailing_stop := update_trailing_stop(entry_price, close, true)
        if close <= current_trailing_stop
            strategy.close("Long", comment="Trailing Stop")

if strategy.position_size < 0  // Short position
    // If using fixed SL/TP
    if use_stop_loss and use_take_profit
        strategy.exit("Short Exit", "Short", stop=current_sl, limit=current_tp, comment="SL/TP")
    else if use_stop_loss and not use_take_profit
        strategy.exit("Short Exit", "Short", stop=current_sl, comment="SL Only")
    else if not use_stop_loss and use_take_profit
        strategy.exit("Short Exit", "Short", limit=current_tp, comment="TP Only")
    
    // If using trailing stop (optional)
    if use_trailing_stop
        current_trailing_stop := update_trailing_stop(entry_price, close, false)
        if close >= current_trailing_stop
            strategy.close("Short", comment="Trailing Stop")



// ═══════════════════════════════════════════════════════════════════════════════
// VISUALIZATION
// ═══════════════════════════════════════════════════════════════════════════════

// Ladder Average plot
plot(ladder_ma, color=is_sideways ? color.orange : (ma_slope > 0 ? color.green : color.red), linewidth=3, title="Ladder Average")

// Horizontal level plot
plot(is_sideways ? horizontal_level : na, color=color.yellow, style=plot.style_circles, linewidth=2, title="Horizontal Level")

// ATR-based bands
upper_band = ladder_ma + atr_value
lower_band = ladder_ma - atr_value
plot(upper_band, color=color.new(color.blue, 70), title="Upper ATR Band")
plot(lower_band, color=color.new(color.blue, 70), title="Lower ATR Band")

// Stop Loss and Take Profit plots (only if active)
plot(strategy.position_size != 0 and use_stop_loss ? current_sl : na, color=color.red, style=plot.style_circles, linewidth=2, title="Stop Loss")
plot(strategy.position_size != 0 and use_take_profit ? current_tp : na, color=color.green, style=plot.style_circles, linewidth=2, title="Take Profit")

// Trailing stop plot (only if active)
plot(strategy.position_size > 0 and use_trailing_stop ? current_trailing_stop : na, color=color.orange, style=plot.style_stepline, linewidth=2, title="Long Trailing Stop")
plot(strategy.position_size < 0 and use_trailing_stop ? current_trailing_stop : na, color=color.orange, style=plot.style_stepline, linewidth=2, title="Short Trailing Stop")

// Market state background color
bgcolor(is_sideways ? color.new(color.yellow, 95) : (is_strong_trend ? color.new(color.green, 98) : color.new(color.gray, 98)), title="Market State")