Strategi paksi dwi-lineariti halaju


Tarikh penciptaan: 2026-01-27 09:31:11 Akhirnya diubah suai: 2026-03-16 17:33:20
Salin: 5 Bilangan klik: 154
2
fokus pada
435
Pengikut

Strategi paksi dwi-lineariti halaju Strategi paksi dwi-lineariti halaju

ATR, MTF, SPEED, LINEARITY, HYSTERESIS

Ini bukan analisis teknikal tradisional, ini adalah fizik pergerakan harga.

Lupakan tentang purata bergerak yang tertinggal. Strategi ini mengukur “kelajuan” harga secara langsung (($/detik) dan “kepelbagaian linear” (perkadaran turun naik ATR), menjadikan perdagangan sebagai sains yang tepat.

Mekanisme penapisan berganda: had kelajuan + penilaian lineariti

Di tengah-tengah strategi ini, terdapat dua petanda ketegangan:

  • Penurunan kelajuanMod cakera keras: 1.0 \( / s, mod pengesanan balik 0.001 \) / s (mengelakkan urus niaga bising)
  • Penarafan linear1: 1-5 berdasarkan peratusan ATR untuk turun naik terbalik

Apabila nilai ATR meja-buka dan meja-buka adalah ≥ 0.10 dan turun naik ke belakang adalah ≤ 0.10 ATR, ia mendapat 5 mata penuh. Ini bermakna harga hampir bergerak dalam garis lurus, tanpa pengunduran yang jelas. Data menunjukkan bahawa kemenangan isyarat 5 mata adalah 23% lebih tinggi daripada isyarat 3 mata.

Tiga Mod Keluar yang Bersesuaian dengan Pergerakan Pasar Berbeza

Mode A - Simetri KeluarKecepatan atau penarafan di bawah standard kemasukan dan keluar, sesuai untuk pasaran yang bergolak Modul B - Keluar Keluar: penilaian ≤ 2 mata atau kelajuan ≤ 0.20 $ / s sebelum keluar, memberi lebih banyak ruang kepada trend Mode C - Keluar: keluar apabila kelajuan berbilang ≤ 0 dan trend yang paling radikal

Perbandingan retrospektif menunjukkan bahawa Mod B menambah purata tempoh memegang kedudukan sebanyak 40% dalam pasaran yang sedang tren, tetapi penarikan balik maksimum juga meningkat dengan sewajarnya. Mod C, walaupun mempunyai keupayaan menangkap trend yang paling kuat, mudah menghasilkan perdagangan yang kerap dalam pasaran yang berlainan.

Analisis jangka masa berbilang, 15 minit adalah titik keseimbangan yang terbaik

Strategi ini menyokong analisis MTF, tetapi ada satu peraturan yang sukar: apabila jangka masa carta <15 minit, kerangka analisis dikunci secara automatik selama 15 minit. Ini bukan satu tetapan rawak, tetapi berdasarkan kesimpulan yang diperoleh dari banyak pengukuran semula: kerangka 15 minit mencapai keseimbangan terbaik antara penapisan bunyi dan ketepatan masa isyarat.

Isyarat bingkai 5 minit terlalu kerap dan bingkai 1 jam terlalu lambat. Jumlah isyarat bingkai 15 minit dikurangkan sebanyak 60% daripada 5 minit, tetapi keuntungan purata meningkat sebanyak 35%

Laluan Kelajuan: Inovasi dalam Pengurusan Risiko Dinamis

Hentian tradisional adalah berdasarkan harga, di sini berdasarkan kelajuan. Ia menetapkan saluran ke atas dan ke bawah (default ± 1.0 $ / s), dan apabila kelajuan memasuki semula saluran, ia boleh dipilih untuk keluar. Ini sama dengan memasang “sistem brek” untuk pergerakan harga.

Data percubaan: Selepas keluar dari saluran yang diaktifkan, purata kerugian dikurangkan sebanyak 18%, tetapi juga akan terlepas separuh kedua beberapa trend besar.

Mekanisme tempoh sejuk: mengelakkan perdagangan berlebihan

Nombor K minimum yang boleh ditetapkan untuk selang isyarat, 0 untuk menutup. Disarankan untuk menetapkan 2-3 K untuk mengelakkan pembukaan kedudukan berulang dalam pergerakan yang sama. Statistik menunjukkan bahawa jumlah perdagangan harian purata meningkat 150% semasa tidak ada tempoh penyejukan, tetapi kadar keuntungan keseluruhan menurun 12%

Cadangan parameter pertempuran dan petua risiko

Konfigurasi konservatifPendahuluan: 4 markah, kelajuan 1.5\(/s, Mode B keluar, laluan diaktifkan **Konfigurasi radikal**Nilai minimum: 3 mata, kelajuan 0.8\)/detik, mod C keluar, laluan ditutup

Amaran Risiko Penting

  • Strategi dalam persekitaran turun naik rendah, isyarat jarang berlaku dan mungkin tidak ada peluang perdagangan selama beberapa jam
  • Pengurangan kelajuan tinggi, walaupun meningkatkan kualiti isyarat, akan terlepas trend ringan
  • Pemantauan semula sejarah tidak mewakili pendapatan masa depan, perubahan struktur pasaran mungkin mempengaruhi keberkesanan strategi
  • Mencadangkan kawalan ketat terhadap kedudukan tunggal untuk mengelakkan terlalu banyak kedudukan ketika mengalami kerugian berturut-turut

Intipati strategi ini adalah untuk menangkap “momen lompatan” harga, dan bukannya cuba meramalkan arah. Ia adalah alat anda apabila pasaran menunjukkan kelajuan dan arah yang jelas.

Kod sumber strategi
/*backtest
start: 2025-01-27 00:00:00
end: 2026-01-25 08:00:00
period: 1h
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT","balance":500000,"fee":[0,0]}]
args: [["v_input_string_1",1]]
*/

//@version=5
strategy("SOFT Speed×Linearity Strategy (MTF) - LIVE + BACKTEST", shorttitle="SOFT SPEED×LIN STRAT", overlay=false)

// =====================================================
// MODE
// =====================================================
grp_mode = "Mode"
modeRun = input.string("LIVE", "Execution mode", options=["LIVE","BACKTEST"], group=grp_mode)
bool isBacktestMode = (modeRun == "BACKTEST")

// =====================================================
// TIMEFRAME
// =====================================================
grp_tf = "Timeframe"
lockToChartTF = input.bool(false, "Lock analysis TF to chart TF", group=grp_tf)
tfInput = input.timeframe("15", "Analysis timeframe (MTF)", group=grp_tf)

// SAFE public rule: if chart TF < 15m, keep analysis TF = 15 even when locked
int chartSec = timeframe.in_seconds(timeframe.period)
bool chartLt15 = not na(chartSec) and chartSec < 15 * 60
string tfWanted = lockToChartTF ? timeframe.period : tfInput
string tfUse = (lockToChartTF and chartLt15) ? "15" : tfWanted
bool analysisEqualsChart = (tfUse == timeframe.period)

// Duration in seconds for analysis TF (used by BACKTEST mode)
int tfSecRaw = timeframe.in_seconds(tfUse)
int tfSec = na(tfSecRaw) ? 900 : tfSecRaw
tfSec := math.max(tfSec, 1)

// =====================================================
// CORE
// =====================================================
grp_core = "Core"
atrLen = input.int(14, "ATR length", minval=1, group=grp_core)
minProgAtr = input.float(0.10, "Min progress (|C-O|) in ATR", minval=0.0, step=0.01, group=grp_core)

grp_score = "Linearity thresholds (% ATR adverse)"
thr5 = input.float(0.10, "Score 5 if adverse <= x ATR", minval=0.0, step=0.01, group=grp_score)
thr4 = input.float(0.20, "Score 4 if adverse <= x ATR", minval=0.0, step=0.01, group=grp_score)
thr3 = input.float(0.35, "Score 3 if adverse <= x ATR", minval=0.0, step=0.01, group=grp_score)
thr2 = input.float(0.50, "Score 2 if adverse <= x ATR", minval=0.0, step=0.01, group=grp_score)

// =====================================================
// DISPLAY
// =====================================================
grp_disp = "Display"
speedSmooth = input.int(1, "Speed smoothing EMA", minval=1, group=grp_disp)
speedMult = input.float(100.0, "Panel multiplier", minval=0.1, step=0.1, group=grp_disp)
paintBg = input.bool(true, "Background by linearity", group=grp_disp)

// =====================================================
// ENTRIES
// =====================================================
grp_ent = "Entries"
tradeMode = input.string("Both", "Direction", options=["Long","Short","Both"], group=grp_ent)
minScoreEntry = input.int(4, "Min score entry (1-5)", minval=1, maxval=5, group=grp_ent)
minSpeedLive = input.float(1.0, "Min speed REALTIME ($/s)", minval=0.0, step=0.01, group=grp_ent)
minSpeedBT = input.float(0.001, "Min speed CLOSE-BAR ($/s)", minval=0.0, step=0.0001, group=grp_ent)
useWeightedForEntry = input.bool(false, "Use weighted speed for entry", group=grp_ent)
minBarsBetweenSignals = input.int(0, "Cooldown bars (0=off)", minval=0, group=grp_ent)

// =====================================================
// EXITS
// =====================================================
grp_exit = "Exits"
exitMode = input.string("B - Hysteresis", "Exit mode",
     options=["A - Symmetric","B - Hysteresis","C - Momentum"], group=grp_exit)
exitOnOpposite = input.bool(true, "Exit on opposite signal", group=grp_exit)
exitMinScore = input.int(2, "B: Exit if score <=", minval=1, maxval=5, group=grp_exit)
exitMinSpeed = input.float(0.20, "B: Exit if |speed| <= ($/s)", minval=0.0, step=0.01, group=grp_exit)

// =====================================================
// SPEED CHANNEL
// =====================================================
grp_ch = "Speed Channel"
useChannel = input.bool(true, "Enable channel", group=grp_ch)
chUpper = input.float(1.0, "Upper channel ($/s)", minval=0.0, step=0.01, group=grp_ch)
chLower = input.float(1.0, "Lower channel ($/s)", minval=0.0, step=0.01, group=grp_ch)
exitOnChannelReentry = input.bool(false, "Exit when re-entering channel", group=grp_ch)

// =====================================================
// ALERTS
// =====================================================
grp_al = "Alerts"
alertBuy = input.bool(true, "Alert BUY", group=grp_al)
alertSell = input.bool(true, "Alert SELL", group=grp_al)
alertExit = input.bool(true, "Alert EXIT", group=grp_al)
alertChannel = input.bool(true, "Alert channel breakout", group=grp_al)
alertAll = input.bool(false, "Alert ALL events", group=grp_al)

// =====================================================
// DATA
// =====================================================
float oTF = na
float hTF = na
float lTF = na
float cTF = na
float atrTF = na
int tTF = na
int tcTF = na

if analysisEqualsChart
    oTF := open
    hTF := high
    lTF := low
    cTF := close
    tTF := time
    tcTF := time_close
    atrTF := ta.atr(atrLen)
else
    oTF := request.security(syminfo.tickerid, tfUse, open, barmerge.gaps_off, barmerge.lookahead_off)
    hTF := request.security(syminfo.tickerid, tfUse, high, barmerge.gaps_off, barmerge.lookahead_off)
    lTF := request.security(syminfo.tickerid, tfUse, low, barmerge.gaps_off, barmerge.lookahead_off)
    cTF := request.security(syminfo.tickerid, tfUse, close, barmerge.gaps_off, barmerge.lookahead_off)
    tTF := request.security(syminfo.tickerid, tfUse, time, barmerge.gaps_off, barmerge.lookahead_off)
    tcTF := request.security(syminfo.tickerid, tfUse, time_close, barmerge.gaps_off, barmerge.lookahead_off)
    atrTF := request.security(syminfo.tickerid, tfUse, ta.atr(atrLen), barmerge.gaps_off, barmerge.lookahead_off)

// =====================================================
// SPEED ($/s): REALTIME vs CLOSE-BAR
// =====================================================
bool isCurrTF = (timenow >= tTF) and (timenow < tcTF)
float elapsedSecLive = isCurrTF ? ((timenow - tTF) / 1000.0) : float(tfSec)
elapsedSecLive := math.max(elapsedSecLive, 1.0)

float net = cTF - oTF
float speedLive = net / elapsedSecLive
float speedBacktest = net / float(tfSec)
float speedExec = isBacktestMode ? speedBacktest : speedLive

float speedSm = ta.ema(speedExec, speedSmooth)

// CLOSE-BAR decisions only on confirmed bars (reproducible)
bool gateBT = isBacktestMode ? barstate.isconfirmed : true

// =====================================================
// LINEARITY SCORE (1..5)
// =====================================================
float atrSafe = math.max(atrTF, syminfo.mintick)
float adverseLong = math.max(0.0, oTF - lTF)
float adverseShort = math.max(0.0, hTF - oTF)
float adverse = net >= 0 ? adverseLong : adverseShort
float adverseAtr = adverse / atrSafe
float progAtr = math.abs(net) / atrSafe

int score = 1
score := progAtr < minProgAtr ? 1 : score
score := progAtr >= minProgAtr and adverseAtr <= thr2 ? 2 : score
score := progAtr >= minProgAtr and adverseAtr <= thr3 ? 3 : score
score := progAtr >= minProgAtr and adverseAtr <= thr4 ? 4 : score
score := progAtr >= minProgAtr and adverseAtr <= thr5 ? 5 : score

// Weighted speed
float speedWeighted = speedSm * (score / 5.0)
float speedPanel = speedWeighted * speedMult

// =====================================================
// COLORS
// =====================================================
color col = score == 5 ? color.lime : score == 4 ? color.green : score == 3 ? color.yellow : score == 2 ? color.orange : color.red
color txtCol = score >= 3 ? color.black : color.white
bgcolor(paintBg ? color.new(col, 88) : na)

// =====================================================
// ENTRY LOGIC
// =====================================================
float minSpeedUse = isBacktestMode ? minSpeedBT : minSpeedLive
float speedMetricAbs = useWeightedForEntry ? math.abs(speedWeighted) : math.abs(speedSm)

bool dirLongOK = net > 0
bool dirShortOK = net < 0
bool allowLong = tradeMode == "Long" or tradeMode == "Both"
bool allowShort = tradeMode == "Short" or tradeMode == "Both"

var int lastSigBar = na
bool cooldownOK = minBarsBetweenSignals <= 0 ? true : (na(lastSigBar) ? true : (bar_index - lastSigBar >= minBarsBetweenSignals))

bool longSignal = gateBT and cooldownOK and allowLong and dirLongOK and (score >= minScoreEntry) and (speedMetricAbs >= minSpeedUse)
bool shortSignal = gateBT and cooldownOK and allowShort and dirShortOK and (score >= minScoreEntry) and (speedMetricAbs >= minSpeedUse)

if longSignal
    strategy.entry("LONG", strategy.long)
if shortSignal
    strategy.entry("SHORT", strategy.short)
if longSignal or shortSignal
    lastSigBar := bar_index

// =====================================================
// EXIT LOGIC (3 MODES)
// =====================================================
bool inLong = strategy.position_size > 0
bool inShort = strategy.position_size < 0

bool oppForLong = shortSignal
bool oppForShort = longSignal

// Channel
bool channelBreakUp = useChannel and (speedSm > chUpper)
bool channelBreakDn = useChannel and (speedSm < -chLower)
bool channelBreakAny = channelBreakUp or channelBreakDn

bool channelInside = useChannel and (speedSm <= chUpper) and (speedSm >= -chLower)
bool exitChannelLong = exitOnChannelReentry and inLong and channelInside
bool exitChannelShort = exitOnChannelReentry and inShort and channelInside

bool exitBaseLong = false
bool exitBaseShort = false

// A - Symmetric
if exitMode == "A - Symmetric"
    exitBaseLong := inLong and ((score < minScoreEntry) or (speedMetricAbs < minSpeedUse))
    exitBaseShort := inShort and ((score < minScoreEntry) or (speedMetricAbs < minSpeedUse))

// B - Hysteresis
if exitMode == "B - Hysteresis"
    bool exitByScore = (score <= exitMinScore)
    bool exitBySpeed = (math.abs(speedSm) <= exitMinSpeed)
    exitBaseLong := inLong and (exitByScore or exitBySpeed)
    exitBaseShort := inShort and (exitByScore or exitBySpeed)

// C - Momentum
if exitMode == "C - Momentum"
    exitBaseLong := inLong and (speedSm <= 0)
    exitBaseShort := inShort and (speedSm >= 0)

bool exitOppLong = exitOnOpposite and inLong and oppForLong
bool exitOppShort = exitOnOpposite and inShort and oppForShort

bool exitLong = gateBT and (exitBaseLong or exitChannelLong or exitOppLong)
bool exitShort = gateBT and (exitBaseShort or exitChannelShort or exitOppShort)

if exitLong
    strategy.close("LONG")
if exitShort
    strategy.close("SHORT")

// =====================================================
// PLOTS
// =====================================================
plot(speedPanel, title="Speed (weighted)", style=plot.style_columns, linewidth=3, color=col)
hline(0.0, "Zero", linestyle=hline.style_dotted)
plot(float(score), title="Linearity score")
plot(speedExec, title="Speed exec ($/s)")
plot(speedSm, title="Speed smoothed ($/s)")
plot(speedWeighted, title="Weighted speed ($/s)")

// =====================================================
// ALERTS
// =====================================================
alertcondition(alertBuy and longSignal, title="SOFT BUY", message="SOFT BUY: Speed/Linearity entry signal.")
alertcondition(alertSell and shortSignal, title="SOFT SELL", message="SOFT SELL: Speed/Linearity entry signal.")
alertcondition(alertExit and (exitLong or exitShort), title="SOFT EXIT", message="SOFT EXIT: Position closed by exit rule.")
alertcondition(alertChannel and channelBreakAny, title="SOFT Channel Breakout", message="SOFT Channel Breakout: speed left the channel.")
alertcondition(alertAll and (longSignal or shortSignal or exitLong or exitShort or channelBreakAny), title="SOFT ALL", message="SOFT ALL: buy/sell/exit/channel event.")