Ide utama dari strategi ini adalah untuk mengidentifikasi arah tren pada jangka waktu yang lebih besar dan menemukan titik-titik breakout untuk masuk pada jangka waktu yang lebih kecil.
Strategi ini terutama didasarkan pada tiga indikator untuk penilaian.
Pertama, hitung siklus yang lebih lama (seperti harian) X-day simple moving average. Biarkan membeli hanya ketika harga di atas moving average ini. Ini dapat digunakan untuk menentukan arah tren keseluruhan dan menghindari periode osilasi perdagangan.
Kedua, hitung harga tertinggi Swing High dalam siklus yang lebih pendek (seperti 5 hari). Ketika harga memecahkan harga tertinggi ini, sinyal beli dipicu.
Setelah masuk ke posisi, garis stop loss dikunci pada harga terendah periode tertentu lbStop jauh dari titik terendah terbaru. Pada saat yang sama, atur garis rata-rata bergerak (seperti EMA 10 hari pada harian) sebagai mekanisme keluar. Keluar dari posisi ketika harga berada di bawah garis rata-rata bergerak ini.
Strategi ini juga menetapkan nilai ATR untuk menghindari membeli poin yang terlalu lama.
Pertimbangan interaksi dari tiga indikator di atas membentuk logika inti dari strategi ini.
Sebagai strategi pelacakan, ia memiliki keuntungan berikut:
Gunakan dua kerangka waktu untuk menghindari terperangkap dalam breakout palsu di pasar osilasi. kerangka waktu yang lebih lama menentukan tren keseluruhan, dan kerangka waktu yang lebih pendek menemukan titik masuk tertentu.
Gunakan titik-titik istirahat yang terbentuk oleh swing tinggi. Jenis istirahat ini memiliki inersia tertentu dan mudah untuk membentuk pelacakan.
Metode stop loss relatif ketat, melacak titik terendah terbaru dengan jarak buffer tertentu untuk menghindari tergores.
Menggunakan moving average sebagai mekanisme keluar untuk mengambil keuntungan secara fleksibel sesuai dengan kondisi pasar.
Indikator ATR menghindari risiko leverage yang berlebihan.
Kombinasi parameter yang berbeda dapat diatur untuk pengujian, dengan ruang optimasi yang besar.
Strategi ini juga memiliki beberapa risiko:
Ketika harga berosilasi ke atas dan ke bawah di sekitar garis rata-rata bergerak, mudah untuk beralih bolak-balik antara posisi masuk dan keluar.
Ketika titik break-in dekat dengan garis rata-rata bergerak, ada risiko pullback yang relatif besar.
Ketika tidak ada tren yang jelas di pasar, waktu penyimpanan mungkin terlalu lama, menghadapi risiko waktu.
Parameter ATR perlu diatur secara wajar. Jika ATR terlalu kecil, efek penyaringan lemah. Jika terlalu besar, peluang masuk akan berkurang.
Perlu untuk menguji dampak dari parameter lb yang berbeda pada hasil. parameter yang terlalu besar dapat kehilangan beberapa kesempatan, sementara parameter yang terlalu kecil dapat mengidentifikasi penyusutan palsu.
Pengurangan Risiko:
Strategi ini juga dapat dioptimalkan dalam dimensi berikut:
Uji kombinasi parameter rata-rata bergerak yang berbeda untuk menemukan parameter optimal.
Cobalah pengaturan parameter ATR yang berbeda untuk menyeimbangkan peluang masuk dan pengendalian risiko.
Mengoptimalkan parameter periode lookback lb untuk mengidentifikasi lebih efisien breakouts.
Cobalah untuk membangun stop loss dinamis berdasarkan volatilitas dan penurunan untuk mengendalikan risiko.
Menggabungkan faktor lain seperti volume perdagangan untuk menentukan efektivitas breakout.
Mengembangkan /
Coba Machine Learning untuk melatih parameter untuk parameter optimal
Secara keseluruhan, ini adalah strategi pelacakan breakout yang khas. Dilihat dari kerangka waktu ganda, menggunakan Swing High untuk mengidentifikasi waktu masuk, dan menggunakan garis stop loss dan mekanisme keluar asuransi rata-rata bergerak membentuk sistem logis yang lengkap. Karakteristik risiko dan pengembalian strategi ini jelas, cocok untuk pelacakan investor jangka menengah dan panjang. Meskipun ada risiko tertentu, mereka dapat dikurangi dengan mengoptimalkan parameter dan aturan. Strategi ini memiliki banyak ruang untuk perbaikan. Menggabungkan lebih banyak indikator dapat lebih meningkatkan efek strategi.
/*backtest start: 2023-01-24 00:00:00 end: 2024-01-30 00:00:00 period: 1d basePeriod: 1h exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ // This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/ // © millerrh // The intent of this strategy is to buy breakouts with a tight stop on smaller timeframes in the direction of the longer term trend. // Then use a trailing stop of a close below either the 10 MA or 20 MA (user choice) on that larger timeframe as the position // moves in your favor (i.e. whenever position price rises above the MA). // Option of using daily ATR as a measure of finding contracting ranges and ensuring a decent risk/reward. // (If the difference between the breakout point and your stop level is below a certain % of ATR, it could possibly find those consolidating periods.) //@version=4 strategy("Qullamaggie Breakout", overlay=true, initial_capital=10000, currency='USD', default_qty_type=strategy.percent_of_equity, default_qty_value=100, commission_type=strategy.commission.percent, commission_value=0.1) // === BACKTEST RANGE === Start = input(defval = timestamp("01 Jan 2019 06:00 +0000"), title = "Backtest Start Date", type = input.time) Finish = input(defval = timestamp("01 Jan 2100 00:00 +0000"), title = "Backtest End Date", type = input.time) // Inputs lb = input(defval = 3, title = "Lookback Period for Swing High", minval = 1, tooltip = "Lookback period for defining the breakout level.") lbStop = input(defval = 3, title = "Lookback Bars for Stop Level", minval = 1, tooltip = "Initial stop placement is the lowest low this many bars back. Allows for tighter stop placement than referencing swing lows.") htf = input(defval="D", title="Timeframe of Moving Averages", type=input.resolution, tooltip = "Allows you to set a different time frame for the moving averages. The default behavior is to identify good tightening setups on a larger timeframe (like daily) and enter the trade on a breakout occuring on a smaller timeframe, using the moving averages of the larger timeframe to trail your stop.") maType = input(defval="SMA", options=["EMA", "SMA"], title = "Moving Average Type") ma1Length = input(defval = 10, title = "1st Moving Average Length", minval = 1) ma2Length = input(defval = 20, title = "2nd Moving Average Length", minval = 1) ma3Length = input(defval = 50, title = "3rd Moving Average Length", minval = 1) useMaFilter = input(title = "Use 3rd Moving Average for Filtering?", type = input.bool, defval = true, tooltip = "Signals will be ignored when price is under this slowest moving average. The intent is to keep you out of bear periods and only buying when price is showing strength or trading with the longer term trend.") trailMaInput = input(defval="2nd Moving Average", options=["1st Moving Average", "2nd Moving Average"], title = "Trailing Stop") // MA Calculations ma(maType, src, length) => maType == "EMA" ? ema(src, length) : sma(src, length) //Ternary Operator (if maType equals EMA, then do ema calc, else do sma calc) ma1 = security(syminfo.tickerid, htf, ma(maType, close, ma1Length)) ma2 = security(syminfo.tickerid, htf, ma(maType, close, ma2Length)) ma3 = security(syminfo.tickerid, htf, ma(maType, close, ma3Length)) plot(ma1, color=color.purple, style=plot.style_line, title="MA1", linewidth=2, transp = 60) plot(ma2, color=color.yellow, style=plot.style_line, title="MA2", linewidth=2, transp = 60) plot(ma3, color=color.white, style=plot.style_line, title="MA3", linewidth=2, transp = 60) // === USE ATR FOR FILTERING === // The idea here is that you want to buy in a consolodating range for best risk/reward. So here you can compare the current distance between // support/resistance vs.the ATR and make sure you aren't buying at a point that is too extended from normal. useAtrFilter = input(title = "Use ATR for Filtering?", type = input.bool, defval = false, tooltip = "Signals will be ignored if the distance between support and resistance is larger than a user-defined percentage of Daily ATR. This allows the user to ensure they are not buying something that is too extended and instead focus on names that are consolidating more.") atrPerc = input(defval = 100, title = "% of Daily ATR Value", minval = 1) atrValue = security(syminfo.tickerid, "D", atr(14))*atrPerc*.01 // === PLOT SWING HIGH/LOW AND MOST RECENT LOW TO USE AS STOP LOSS EXIT POINT === // Change these values to adjust the look back and look forward periods for your swing high/low calculations pvtLenL = lb pvtLenR = lb // Get High and Low Pivot Points pvthi_ = pivothigh(high, pvtLenL, pvtLenR) pvtlo_ = pivotlow(low, pvtLenL, pvtLenR) // Force Pivot completion before plotting. Shunt = 1 //Wait for close before printing pivot? 1 for true 0 for flase maxLvlLen = 0 //Maximum Extension Length pvthi = pvthi_[Shunt] pvtlo = pvtlo_[Shunt] // Count How many candles for current Pivot Level, If new reset. counthi = barssince(not na(pvthi)) countlo = barssince(not na(pvtlo)) pvthis = fixnan(pvthi) pvtlos = fixnan(pvtlo) hipc = change(pvthis) != 0 ? na : color.maroon lopc = change(pvtlos) != 0 ? na : color.green // Display Pivot lines plot((maxLvlLen == 0 or counthi < maxLvlLen) ? pvthis : na, color=hipc, transp=0, linewidth=1, offset=-pvtLenR-Shunt, title="Top Levels") // plot((maxLvlLen == 0 or countlo < maxLvlLen) ? pvtlos : na, color=lopc, transp=0, linewidth=1, offset=-pvtLenR-Shunt, title="Bottom Levels") plot((maxLvlLen == 0 or counthi < maxLvlLen) ? pvthis : na, color=hipc, transp=0, linewidth=1, offset=0, title="Top Levels 2") // plot((maxLvlLen == 0 or countlo < maxLvlLen) ? pvtlos : na, color=lopc, transp=0, linewidth=1, offset=0, title="Bottom Levels 2") // BUY CONDITIONS stopLevelCalc = valuewhen(pvtlo_, low[pvtLenR], 0) //Stop Level at Swing Low buyLevel = valuewhen(pvthi_, high[pvtLenR], 0) //Buy level at Swing High plot(buyLevel, style=plot.style_line, color=color.blue, title = "Current Breakout Level", show_last=1, linewidth=1, transp=50, trackprice=true) // Conditions for entry and exit stopLevel = float(na) // Define stop level here as "na" so that I can reference it in the inPosition // variable and the ATR calculation before the stopLevel is actually defined. buyConditions = (useMaFilter ? buyLevel > ma3 : true) and (useAtrFilter ? (buyLevel - stopLevel[1]) < atrValue : true) // buySignal = high > buyLevel and buyConditions buySignal = crossover(high, buyLevel) and buyConditions trailMa = trailMaInput == "1st Moving Average" ? ma1 : ma2 sellSignal = crossunder(close, trailMa) // sellSignal = security(syminfo.tickerid, htf, close < trailMa) and security(syminfo.tickerid, htf, close[1] < trailMa) // STOP AND PRICE LEVELS inPosition = bool(na) inPosition := buySignal[1] ? true : sellSignal[1] ? false : low <= stopLevel[1] ? false : inPosition[1] lowDefine = lowest(low, lbStop) stopLevel := inPosition ? stopLevel[1] : lowDefine // plot(stopLevel) buyPrice = buyLevel buyPrice := inPosition ? buyPrice[1] : buyLevel plot(stopLevel, style=plot.style_line, color=color.orange, title = "Current Stop Level", show_last=1, linewidth=1, transp=50, trackprice=true) plot(inPosition ? stopLevel : na, style=plot.style_circles, color=color.orange, title = "Historical Stop Levels", transp=50, trackprice=false) // plot(buyPrice, style=plot.style_line, color=color.blue, linewidth=1, transp=50, trackprice=true) // (STRATEGY ONLY) Comment out for Study strategy.entry("Long", strategy.long, stop = buyLevel, when = buyConditions) strategy.exit("Exit Long", from_entry = "Long", stop=stopLevel[1]) if (low[1] > trailMa) strategy.close("Long", when = sellSignal) // if (low[1] > trailMa) // strategy.exit("Exit Long", from_entry = "Long", stop=trailMa) //to get this to work right, I need to reference highest highs instead of swing highs //because it can have me buy right back in after selling if the stop level is above the last registered swing high point.