
Strategi perdagangan arbitrage adalah sistem perdagangan frekuensi tinggi harian yang didasarkan pada indikator oscillator stochastic, yang menggunakan dua parameter yang berbeda untuk menghasilkan dan mengkonfirmasi sinyal perdagangan dalam jangka waktu 15 detik. Logika utamanya adalah untuk mengidentifikasi titik masuk potensial melalui persimpangan antara% K dan% D dari indikator acak utama, sambil merujuk nilai% D dari indikator acak sekunder sebagai filter status pasar, menggabungkan rata-rata bergerak dan kondisi penyaringan waktu pasar, untuk membangun sistem perdagangan dengan mekanisme konfirmasi bertingkat.
Strategi ini menggunakan dua sistem indikator seismik acak, masing-masing disebut indikator utama dan indikator referensi:
Pengaturan indikator seismik acak utama:
Pengaturan indikator seismik acak:
Logika input dirancang dengan baik, dan validasi sinyal dilakukan pada beberapa tingkatan:
Syarat masuk:
Syarat untuk masuk dengan kepala kosong:
Logika keluar berdasarkan kombinasi waktu dan sinyal teknis:
Strategi ini juga mengintegrasikan fitur pengenalan bentuk:
Mekanisme konfirmasi multi-lapisan: Mengkonfirmasi satu sama lain melalui dua indikator getaran acak yang berbeda, mengurangi sinyal palsu yang dihasilkan oleh satu indikator, meningkatkan keandalan sinyal.
Aturan masuk dan keluar yang tepatStrategi ini mendefinisikan persyaratan masuk dan keluar yang jelas, menghilangkan subjektivitas dalam keputusan perdagangan, dan memungkinkan perdagangan yang sepenuhnya sistematis.
Kemampuan untuk mengenali bentukIni adalah kemampuan untuk mengidentifikasi bentuk “higher low” dan “lower high” di pasar, dan menangkap peluang untuk melanjutkan tren, yang tidak dapat dicapai oleh banyak strategi sederhana.
Filter waktuDengan membatasi waktu perdagangan pada jam pasar biasa, menghindari periode likuiditas rendah dan berfluktuasi tinggi sebelum buka dan tutup, mengurangi slippage dan biaya.
Filter rata-rata bergerakOpsi penyaringan rata-rata bergerak menambahkan lapisan konfirmasi tren untuk memastikan arah perdagangan sesuai dengan tren keseluruhan.
Perbedaan harga dan parameter perbedaan kapasitasStrategi ini memperkenalkan berbagai parameter untuk mengontrol amplitudo perubahan harga dan kisaran perbedaan indikator, yang secara efektif menyaring sinyal noise yang dihasilkan oleh fluktuasi kecil.
Konversi Logika DinamisSistem ini dapat menyesuaikan kondisi transisi dari multihead ke headless dan dari headless ke multiheadless berdasarkan kondisi pasar yang dinamis, dan lebih mudah beradaptasi.
Sistem Peringatan KomprehensifStrategi ini terintegrasi dengan kondisi peringatan yang kaya untuk memonitor dan melakukan transaksi secara real time.
Risiko perdagangan frekuensi tinggi dalam jangka waktu singkatStrategi: Menggunakan 15 detik waktu frame dapat menghasilkan terlalu banyak sinyal, menyebabkan perdagangan yang sering, meningkatkan biaya transaksi, dan dapat menghasilkan sejumlah besar sinyal palsu dalam situasi pasar yang berfluktuasi besar.
Kurangnya pengendalian kerugian: Tidak ada penghentian kerugian yang jelas dalam kode, risiko kerugian yang lebih besar dapat terjadi jika tren tiba-tiba berbalik. Kurangnya kontrol risiko adalah salah satu kelemahan utama strategi.
Parameter SensitivitasBeberapa parameter yang tepat digunakan dalam strategi (misalnya, batas diferensial 0,15 dan batas diferensial 0,1%) mungkin terlalu sensitif terhadap kondisi pasar yang berbeda dan perlu disesuaikan secara teratur.
Biaya kesempatan dari keterbatasan waktuPerdagangan hanya pada jam pasar biasa dapat melewatkan beberapa peluang penting sebelum dan sesudah perdagangan, terutama ketika pasar bereaksi setelah berita besar.
Ketergantungan pada likuiditasStrategi frekuensi tinggi mungkin mengalami masalah slippage di pasar yang kurang likuid, dan harga yang sebenarnya dieksekusi mungkin berbeda secara signifikan dari harga saat sinyal dihasilkan.
Penundaan indikator teknisIndikator pergerakan acak sendiri memiliki keterlambatan, terutama dalam pasar yang berbalik dengan cepat, dan mungkin tidak dapat menangkap titik-titik pergeseran tepat waktu.
Risiko overadaptasiPerbaikan parameter strategi dapat menyebabkan penyesuaian yang berlebihan terhadap data historis, yang dapat menyebabkan kinerja yang buruk dalam situasi pasar di masa depan.
Meningkatkan mekanisme penghentian kerugianOptimalisasi yang paling penting adalah menerapkan sistem stop loss cerdas, yang dapat mempertimbangkan strategi stop loss berdasarkan ATR, atau menggunakan tingkat teknologi sebagai titik stop loss untuk membatasi kerugian maksimum pada satu transaksi.
Memperkenalkan manajemen posisiSkala transaksi disesuaikan secara dinamis berdasarkan volatilitas pasar dan toleransi risiko akun, menggunakan konfigurasi posisi yang berbeda pada intensitas sinyal yang berbeda untuk mengoptimalkan tingkat pemanfaatan dana dan rasio keuntungan risiko.
Menambahkan konfirmasi pengirimanUntuk mengintegrasikan indikator lalu lintas ke dalam sistem, sinyal masuk yang penting harus memiliki dukungan lalu lintas yang cukup untuk menyaring sinyal yang tidak dapat diandalkan dalam lingkungan lalu lintas rendah.
Integrasi multi-indikatorPertimbangan: Menggabungkan indikator momentum dan tren lainnya seperti RSI, MACD, atau Bollinger Bands, untuk membangun perspektif pasar yang lebih komprehensif dan meningkatkan stabilitas sistem.
Pengoptimalan kerangka waktu: menguji berbagai kerangka waktu dasar, seperti 1 menit atau 5 menit, yang mungkin mengurangi kebisingan sambil mempertahankan peluang perdagangan yang cukup, untuk menemukan titik keseimbangan kualitas dan kuantitas sinyal yang optimal.
Menambahkan pelacakan statistik retrospektif: Mendapatkan indikator kinerja pelacakan yang lebih komprehensif, seperti pengembalian maksimum, rasio Sharpe, tingkat kemenangan, rasio kerugian, dll, untuk menilai kinerja strategi dengan lebih ilmiah.
Parameter adaptasi: mengubah parameter tetap menjadi parameter adaptif berdasarkan perubahan dinamika volatilitas pasar, sehingga strategi dapat beradaptasi dengan berbagai kondisi pasar.
Meningkatkan filter lingkungan pasar: Menambahkan VIX (Indeks Volatilitas) atau indikator serupa sebagai kondisi penyaring lingkungan pasar, menyesuaikan parameter strategi atau menghentikan perdagangan dalam lingkungan yang sangat berfluktuasi.
Strategi ini adalah sistem perdagangan frekuensi tinggi jangka pendek yang dirancang dengan baik, yang meningkatkan keandalan sinyal perdagangan melalui mekanisme konfirmasi berlapis seperti indikator getaran acak ganda, penyaringan rata-rata bergerak, dan penyaringan waktu. Strategi ini mengidentifikasi titik balik overbought dan oversold jangka pendek dan bentuk kelanjutan tren dalam waktu pasar reguler, sesuai untuk pasar yang memiliki likuiditas yang cukup dan volatilitas moderat.
Meskipun struktur desain strategi yang sempurna, masih ada kekurangan mekanisme manajemen risiko kunci seperti risiko yang melekat pada perdagangan frekuensi tinggi dan kurangnya stop loss. Untuk meningkatkan stabilitas strategi dan profitabilitas jangka panjang, disarankan untuk menambahkan langkah-langkah optimasi seperti mekanisme stop loss, sistem manajemen posisi, konfirmasi volume transaksi dan integrasi multi-indikator. Selain itu, mengubah parameter tetap menjadi parameter adaptif dan menambahkan pelacakan statistik pengembalian yang komprehensif akan membantu strategi untuk mempertahankan kinerja yang stabil dalam berbagai lingkungan pasar.
Dengan pemahaman yang mendalam dan pengoptimalan yang berkelanjutan dari para pedagang tentang strategi ini, sistem perdagangan ini berpotensi menjadi komponen yang efektif dalam kotak alat perdagangan intraday, terutama cocok untuk digunakan oleh para pedagang yang memiliki pemahaman yang mendalam tentang indikator teknis dan dapat memantau pasar secara tepat waktu.
/*backtest
start: 2025-01-01 00:00:00
end: 2025-06-17 00:00:00
period: 4h
basePeriod: 4h
exchanges: [{"eid":"Binance","currency":"ETH_USDT"}]
*/
//@version=6
strategy("Dual TF Stochastic Strategy", overlay=false)
// Input parameters with updated defaults
primaryLen = input.int(12, "Primary Stoch K Length", minval=1) // Changed from 14 to 12
primarySmooth = input.int(12, "Primary Stoch K Smoothing", minval=1) // Changed from 3 to 12
primaryDLen = input.int(12, "Primary Stoch D Length", minval=1) // Changed from 3 to 12
primaryRes = input.timeframe("15S", "Primary Timeframe") // Changed from "" to "15S"
refLen = input.int(12, "Reference Stoch K Length", minval=1) // Changed from 14 to 12
refSmooth = input.int(15, "Reference Stoch K Smoothing", minval=1) // Changed from 3 to 15
refDLen = input.int(30, "Reference Stoch D Length", minval=1) // Changed from 3 to 30
refRes = input.timeframe("15S", "Reference Timeframe") // Changed from "D" to "15S"
tolerance = input.float(0.1, "Ref D Tolerance %", minval=0.1, maxval=10.0, step=0.1) // Changed from 1.0 to 0.1
maxPriceDiff = input.float(0.1, "Maximum Price % Difference", minval=0.1, maxval=5.0, step=0.1) // Changed from 1.0 to 0.1
closeKThreshold = input.float(0.7, "Close %K Tolerance %", minval=0.1, maxval=10.0, step=0.1) // Changed from 5.0 to 0.7
minPriceDiffShort = input.float(0.1, "Min Price % Diff for Close %K Short", minval=0.1, maxval=5.0, step=0.1) // Changed from 0.5 to 0.1
showLabels = input.bool(true, "Show Crossover/Crossunder Labels")
// Time Filters (America/New_York timezone, UTC-4)
is_premarket = hour(time, "America/New_York") < 9
is_postmarket = hour(time, "America/New_York") >= 16
is_regular_hours = hour(time, "America/New_York") >= 9 and hour(time, "America/New_York") < 16
is_exit_time = hour(time, "America/New_York") >= 15 and minute(time, "America/New_York") >= 30 // 3:30 PM ET
// Moving Average Settings
useMAFilter = input.bool(true, "Use Moving Average Filter")
maLength = input.int(200, "Moving Average Length", minval=1)
maType = input.string("SMA", "Moving Average Type", options=["SMA", "EMA", "WMA", "VWMA"])
maTimeframe = input.timeframe("", "Moving Average Timeframe")
// Stochastic Calculations
primaryHighest = ta.highest(high, primaryLen)
primaryLowest = ta.lowest(low, primaryLen)
primaryK_raw = 100 * (close - primaryLowest) / (primaryHighest - primaryLowest)
primaryK = ta.sma(primaryK_raw, primarySmooth)
primaryD = ta.sma(primaryK, primaryDLen)
[primaryK_tf, primaryD_tf] = request.security(syminfo.tickerid, primaryRes, [primaryK, primaryD])
refHighest = ta.highest(high, refLen)
refLowest = ta.lowest(low, refLen)
refK_raw = 100 * (close - refLowest) / (refHighest - refLowest)
refK = ta.sma(refK_raw, refSmooth)
refD = ta.sma(refK, refDLen)
[refK_tf, refD_tf] = request.security(syminfo.tickerid, refRes, [refK, refD])
// Calculate Moving Average
var float ma = na
if useMAFilter
if maType == "SMA"
ma := request.security(syminfo.tickerid, maTimeframe, ta.sma(close, maLength))
else if maType == "EMA"
ma := request.security(syminfo.tickerid, maTimeframe, ta.ema(close, maLength))
else if maType == "WMA"
ma := request.security(syminfo.tickerid, maTimeframe, ta.wma(close, maLength))
else if maType == "VWMA"
ma := request.security(syminfo.tickerid, maTimeframe, ta.vwma(close, maLength))
// Price relative to MA
priceAboveMA = not useMAFilter or close > ma
priceBelowMA = not useMAFilter or close < ma
// Crossover Detection and Tracking
crossOver = ta.crossover(primaryK_tf, primaryD_tf)
crossUnder = ta.crossunder(primaryK_tf, primaryD_tf)
// Separate tracking for crossover and crossunder %K and price
var float lastCrossOverK = na
var float lastCrossOverPrice = na
var float currentCrossOverK = na
var float currentCrossOverPrice = na
var float lastCrossUnderK = na
var float lastCrossUnderPrice = na
var float currentCrossUnderK = na
var float currentCrossUnderPrice = na
// Update crossover tracking variables
if crossOver
lastCrossOverK := nz(currentCrossOverK, primaryK_tf[1])
lastCrossOverPrice := nz(currentCrossOverPrice, close[1])
currentCrossOverK := primaryK_tf
currentCrossOverPrice := close
// Update crossunder tracking variables
if crossUnder
lastCrossUnderK := nz(currentCrossUnderK, primaryK_tf[1])
lastCrossUnderPrice := nz(currentCrossUnderPrice, close[1])
currentCrossUnderK := primaryK_tf
currentCrossUnderPrice := close
// Calculate differences separately
crossOverPriceDiffPercent = math.abs((currentCrossOverPrice - lastCrossOverPrice) / lastCrossOverPrice * 100)
crossOverKDiffPercent = math.abs((currentCrossOverK - lastCrossOverK) / lastCrossOverK * 100)
crossUnderPriceDiffPercent = math.abs((currentCrossUnderPrice - lastCrossUnderPrice) / lastCrossUnderPrice * 100)
crossUnderKDiffPercent = math.abs((currentCrossUnderK - lastCrossUnderK) / lastCrossUnderK * 100)
isKCloseCrossUnder = crossUnderKDiffPercent <= closeKThreshold and not na(lastCrossUnderK)
// New condition for long entry based on %K and refD_tf difference
kAndRefDDiffClose = crossOver and math.abs(currentCrossOverK - refD_tf) <= 0.15
// Labels for crossover and crossunder (optional)
if showLabels
if crossOver
diffKandRefD = math.abs(currentCrossOverK - refD_tf)
label.new(bar_index, 50, "CrossOver\nDiff K-RefD: " + str.tostring(diffKandRefD, "#.###"), color=color.green, textcolor=color.black, style=label.style_label_up)
if crossUnder
diffKandRefD = math.abs(currentCrossUnderK - refD_tf)
label.new(bar_index, 50, "CrossUnder\nDiff K-RefD: " + str.tostring(diffKandRefD, "#.###"), color=color.red, textcolor=color.black, style=label.style_label_down)
// Entry Conditions
longKCondition = crossOver and (na(lastCrossOverK) or currentCrossOverK > lastCrossOverK)
shortKCondition = crossUnder and (crossUnderPriceDiffPercent <= maxPriceDiff)
closeKShortCondition = crossUnder and isKCloseCrossUnder and (crossUnderPriceDiffPercent > minPriceDiffShort)
crossUnderBetween50and45 = crossUnder and currentCrossUnderK <= 50 and currentCrossUnderK > 45
// Long to Short if crossunder %K > 80 OR < 60
longToShortCondition = crossUnder and (currentCrossUnderK > 80 or currentCrossUnderK < 60) and strategy.position_size > 0 and is_regular_hours
upperLimit = refD_tf * (1 + tolerance/100)
lowerLimit = refD_tf * (1 - tolerance/100)
withinToleranceLong = primaryK_tf >= lowerLimit and primaryK_tf <= upperLimit
withinToleranceShort = primaryK_tf >= lowerLimit and primaryK_tf <= upperLimit
// Final Entry Conditions with MA filter
longCondition = ((longKCondition and (refD_tf >= 50 or refD_tf < 20)) or kAndRefDDiffClose) and is_regular_hours and not is_exit_time and priceAboveMA
shortCondition = (shortKCondition or (crossUnder and withinToleranceShort and (crossUnderPriceDiffPercent <= maxPriceDiff)) or closeKShortCondition or longToShortCondition or crossUnderBetween50and45) and is_regular_hours and not is_exit_time and priceBelowMA
// Short-to-Long Transition Condition with MA filter
shortToLongCondition = crossOver and currentCrossOverK < 25 and strategy.position_size < 0 and is_regular_hours and not is_exit_time and priceAboveMA
// Tracking for %K crossing under refD_tf
var float lastPrimaryKCrossUnderRefD = na
var float currentPrimaryKCrossUnderRefD = na
var bool isPrimaryKCrossUnderRefD = false
// Check if primary %K crosses under reference %D
isPrimaryKCrossUnderRefD := ta.crossunder(primaryK_tf, refD_tf)
// Update tracking for %K crossing under refD
if isPrimaryKCrossUnderRefD
lastPrimaryKCrossUnderRefD := currentPrimaryKCrossUnderRefD
currentPrimaryKCrossUnderRefD := primaryK_tf
// Exit Conditions
if is_exit_time
strategy.close("Long")
strategy.close("Short")
else if isPrimaryKCrossUnderRefD and not na(lastPrimaryKCrossUnderRefD) and currentPrimaryKCrossUnderRefD < lastPrimaryKCrossUnderRefD
strategy.close("Long")
else if (ta.crossunder(primaryK_tf, primaryD_tf) and primaryK_tf < refD_tf and refD_tf < 60)
strategy.close("Long")
if (ta.crossover(primaryK_tf, primaryD_tf) and primaryK_tf > refD_tf and refD_tf > 20) and not is_exit_time
strategy.close("Short")
// Track if crossunder happens above 85
var bool crossUnderAbove85 = false
// Detect crossunder above 85
if crossUnder and currentCrossUnderK > 85
crossUnderAbove85 := true
// Reset condition if %K crosses over %D
if ta.crossover(primaryK_tf, primaryD_tf)
crossUnderAbove85 := false
// Track previous crossover/crossunder values for Higher Low/Lower High detection
var float prevCrossOverK = na
var float prevCrossUnderK = na
// Update previous values on new crossovers/crossunders
if crossOver
prevCrossOverK := currentCrossOverK
if crossUnder
prevCrossUnderK := currentCrossUnderK
// Higher Low and Lower High conditions
higherLowCondition = crossOver and not na(prevCrossOverK) and currentCrossOverK > prevCrossOverK
lowerHighCondition = crossUnder and not na(prevCrossUnderK) and currentCrossUnderK < prevCrossUnderK
// Strategy Entries and Transitions
if longCondition
strategy.entry("Long", strategy.long)
if shortCondition
if strategy.position_size > 0 // If in a long position, close it first
strategy.close("Long")
strategy.entry("Short", strategy.short)
if shortToLongCondition
strategy.close("Short")
if ((longKCondition and (refD_tf >= 50 or refD_tf < 20)) or kAndRefDDiffClose) // Check full longCondition minus time (already checked)
strategy.entry("Long", strategy.long)
// Add label for Short to Long Transition
if shortToLongCondition
label.new(bar_index, na, "T", color=color.green, textcolor=color.white, style=label.style_label_up)
// Add label for Long to Short Transition
if longToShortCondition
label.new(bar_index, na, "T", color=color.red, textcolor=color.white, style=label.style_label_down)
// Plotting
plot(primaryK_tf, "Primary %K", color=color.white, linewidth=1)
plot(primaryD_tf, "Primary %D", color=color.orange, linewidth=1)
plot(refK_tf, "Reference %K", color=color.navy, linewidth=1)
plot(refD_tf, "Reference %D", color=color.rgb(33, 233, 243), linewidth=2)
// Plot current and last %K only for crossUnder when isKCloseCrossUnder is true and currentCrossUnderK < lastCrossUnderK
plot(crossUnder and isKCloseCrossUnder and currentCrossUnderK < lastCrossUnderK ? currentCrossUnderK : na, "Current CrossUnder %K (Close)", color=color.green, style=plot.style_cross, linewidth=2)
plot(crossUnder and isKCloseCrossUnder and currentCrossUnderK < lastCrossUnderK ? lastCrossUnderK : na, "Last CrossUnder %K (Close)", color=color.red, style=plot.style_cross, linewidth=2)
h0 = hline(85, "Upper Band", color=color.rgb(242, 187, 21))
hline(50, "Middle Band", color=#eaff04)
h1 = hline(20, "Lower Band", color=color.rgb(242, 187, 21))
h2 = hline(40, "Lower Band", color=#787B86)
h3 = hline(60, "Lower Band", color=#787B86)
h = hline(0, "Lower Band", color=#787B86)
h5 = hline(100, "Lower Band", color=#787B86)
fill(h0, h1, color=color.rgb(33, 150, 243, 90), title="Background")
fill(h, h1, color=#1be2781d, title="Background")
fill(h0, h5, color=#e21b742d, title="Background")
// Plot the MA if enabled
plot(useMAFilter ? ma : na, "Moving Average", color=color.yellow, linewidth=2)
// Add plot for visualization (optional)
plot(isPrimaryKCrossUnderRefD ? primaryK_tf : na, "Primary %K CrossUnder RefD", color=color.purple, style=plot.style_cross, linewidth=2)
plot(isPrimaryKCrossUnderRefD and not na(lastPrimaryKCrossUnderRefD) ? lastPrimaryKCrossUnderRefD : na, "Last Primary %K CrossUnder RefD", color=color.fuchsia, style=plot.style_cross, linewidth=2)
// Add new alert conditions
alertcondition(higherLowCondition, title="Stoch Higher Low", message="Stoch Higher Low Pattern Detected")
alertcondition(lowerHighCondition, title="Stoch Lower High", message="Stoch Lower High Pattern Detected")
// Plot markers for Higher Low and Lower High patterns
plot(higherLowCondition ? currentCrossOverK : na, "Higher Low", color=color.green, style=plot.style_cross, linewidth=2)
plot(lowerHighCondition ? currentCrossUnderK : na, "Lower High", color=color.red, style=plot.style_cross, linewidth=2)
// Alert conditions
alertcondition(crossOver, title="Stochastic %K Crossed Over %D", message="Stochastic %K crossed over %D")
alertcondition(crossUnder, title="Stochastic %K Crossed Under %D", message="Stochastic %K crossed under %D")
alertcondition(crossOver and primaryK_tf > 50, title="Stochastic %K Crossed Over %D Above 50", message="Stochastic %K crossed over %D above 50")
alertcondition(crossOver and primaryK_tf > refD_tf, title="Stochastic %K Crossed Over %D Above Reference %D", message="Stochastic %K crossed over %D above Reference %D")
alertcondition(longCondition, title="Long Entry Signal", message="Long entry signal triggered")
alertcondition(shortCondition, title="Short Entry Signal", message="Short entry signal triggered")
alertcondition(shortToLongCondition, title="Short to Long Transition", message="Short to Long transition triggered")
alertcondition(longToShortCondition, title="Long to Short Transition", message="Long to Short transition triggered")
alertcondition(isPrimaryKCrossUnderRefD, title="Primary %K Crossed Under Reference %D", message="Primary %K crossed under Reference %D")
alertcondition(crossOver and primaryK_tf > refD_tf, title="Bullish Crossover Above Ref %D", message="Bull: Dual Stoch")
alertcondition(crossUnder and primaryK_tf < refD_tf, title="Bearish Crossunder Below Ref %D", message="Bear: Dual Stoch")