Strategi Pengesanan Pelarian Qullamaggie

Penulis:ChaoZhang, Tarikh: 2024-01-31 17:06:36
Tag:

img

Ringkasan

Idea utama strategi ini adalah untuk mengenal pasti arah trend pada jangka masa yang lebih besar dan mencari titik pecah untuk memasuki dalam jangka masa yang lebih kecil.

Prinsip Strategi

Strategi ini terutamanya bergantung kepada tiga penunjuk untuk penilaian.

Pertama, mengira kitaran yang lebih lama (seperti harian) purata bergerak mudah X hari. Hanya membenarkan pembelian apabila harga di atas purata bergerak ini. Ini boleh digunakan untuk menentukan arah trend keseluruhan dan mengelakkan tempoh berayun perdagangan.

Kedua, mengira harga tertinggi Swing High dalam kitaran yang lebih pendek (seperti 5 hari). Apabila harga memecahkan harga tertinggi ini, isyarat beli dicetuskan.

Ketiga, tetapkan garis stop loss. Selepas memasuki kedudukan, garis stop loss dikunci pada harga terendah dalam tempoh tertentu lbStop jauh dari titik terendah terkini. Pada masa yang sama, tetapkan garis purata bergerak (seperti EMA 10 hari pada harian) sebagai mekanisme keluar. Keluar dari kedudukan apabila harga di bawah garis purata bergerak ini.

Strategi ini juga menetapkan nilai ATR untuk mengelakkan membeli mata yang terlalu panjang.

Penghakiman interaksi tiga penunjuk di atas membentuk logik teras strategi ini.

Analisis Kelebihan

Sebagai strategi pengesanan pelarian, ia mempunyai kelebihan berikut:

  1. Gunakan dua jangka masa untuk mengelakkan terperangkap dalam pecah palsu di pasaran berayun. jangka masa yang lebih lama menentukan trend keseluruhan, dan jangka masa yang lebih pendek mencari titik masuk tertentu.

  2. Gunakan titik pecah yang terbentuk oleh swing tinggi. Jenis pecah ini mempunyai inersia tertentu dan mudah untuk membentuk pengesanan. Parameter tempoh melihat balik lb juga boleh diselaraskan untuk mencari pecah yang benar-benar berkesan.

  3. Kaedah stop loss agak ketat, mengesan titik terendah terkini dengan jarak penyangga tertentu untuk mengelakkan mengikis.

  4. Gunakan purata bergerak sebagai mekanisme keluar untuk mengambil keuntungan secara fleksibel mengikut keadaan pasaran.

  5. Indikator ATR mengelakkan risiko leverage berlebihan.

  6. Kombinasi parameter yang berbeza boleh ditetapkan untuk ujian, dengan ruang pengoptimuman yang besar.

Analisis Risiko

Strategi ini juga mempunyai beberapa risiko:

  1. Apabila harga berayun ke atas dan ke bawah di sekitar garis purata bergerak, mudah untuk beralih ke hadapan dan ke belakang antara masuk dan keluar kedudukan.

  2. Apabila titik pecah berhampiran dengan garis purata bergerak, terdapat risiko menarik balik yang agak besar.

  3. Apabila tidak ada trend yang jelas di pasaran, masa penahan mungkin terlalu lama, menghadapi risiko masa.

  4. Parameter ATR perlu ditetapkan dengan munasabah. Jika ATR terlalu kecil, kesan penapisan lemah. Jika terlalu besar, peluang masuk akan berkurangan.

  5. Perlu menguji kesan parameter lb yang berbeza pada hasil. parameter yang terlalu besar mungkin kehilangan beberapa peluang, sementara parameter yang terlalu kecil boleh mengenal pasti pecah palsu.

Pengurangan Risiko:

  1. Sesuaikan parameter purata bergerak dengan betul untuk meningkatkan keupayaan penapisan.
  2. Mengoptimumkan parameter ATR, ditambah dengan penilaian visual.
  3. Sesuaikan tempoh 1 lb untuk mencari parameter yang optimum.
  4. Hentikan perdagangan semasa pasaran berayun.

Arahan pengoptimuman

Strategi ini juga boleh dioptimumkan dalam dimensi berikut:

  1. Uji kombinasi parameter purata bergerak yang berbeza untuk mencari parameter yang optimum.

  2. Cuba tetapan parameter ATR yang berbeza untuk mengimbangi peluang kemasukan dan kawalan risiko.

  3. Mengoptimumkan parameter tempoh melihat balik lb untuk mengenal pasti penembusan yang lebih cekap.

  4. Cuba membina stop loss dinamik berdasarkan turun naik dan penurunan untuk mengawal risiko.

  5. Menggabungkan faktor-faktor lain seperti jumlah dagangan untuk menentukan keberkesanan penembusan.

  6. Membangunkan /,< dan kaedah lain untuk mencari titik ekstrem sebagai rujukan.

  7. Cuba Machine Learning untuk melatih parameter untuk parameter optimum

Ringkasan

Secara keseluruhannya, ini adalah strategi penjejakan pecah biasa. Menghakimi dengan bingkai masa berganda, menggunakan Swing High untuk mengenal pasti masa kemasukan, dan menggunakan garis stop loss dan mekanisme keluar insurans purata bergerak berganda membentuk sistem logik yang lengkap. Ciri risiko dan pulangan strategi ini jelas, sesuai untuk pelabur penjejakan jangka menengah dan panjang. Walaupun terdapat risiko tertentu, mereka dapat dikurangkan dengan mengoptimumkan parameter dan peraturan. Strategi ini mempunyai ruang yang besar untuk peningkatan. Menggabungkan lebih banyak penunjuk boleh meningkatkan lagi kesan 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.

Lebih lanjut