Strategi Purata Bergerak Adaptif Saluran Gaussian

Penulis:ChaoZhang, Tarikh: 2024-03-28 18:08:18
Tag:

img

Ringkasan

Gaussian Channel Adaptive Moving Average Strategy adalah strategi perdagangan kuantitatif yang menggunakan teknik penapisan Gaussian dan tetapan parameter adaptif. Berdasarkan teori penapisan Gaussian yang dicadangkan oleh John Ehlers, strategi ini menjana isyarat perdagangan yang lancar dan adaptif dengan menggunakan beberapa pengiraan purata bergerak eksponensial kepada data harga. Inti strategi adalah untuk membina saluran harga yang disesuaikan secara dinamik, dengan jalur atas dan bawah yang diperoleh dengan menambah dan mengurangkan julat sebenar yang ditapis dari harga yang ditapis oleh Gaussian. Apabila harga memecahkan di atas jalur atas, kedudukan panjang dimasukkan, dan apabila ia memecahkan di bawah jalur bawah, kedudukan pendek dimasukkan.

Prinsip Strategi

Prinsip-prinsip strategi purata bergerak adaptif Saluran Gaussian adalah seperti berikut:

  1. Mengira nilai penapis Gaussian harga. Berdasarkan tempoh pengambilan sampel yang ditakrifkan oleh pengguna dan bilangan kutub, parameter Beta dan Alpha dikira, dan kemudian data harga menjalani penapis Gaussian pelbagai peringkat untuk mendapatkan siri harga yang halus.
  2. Mengira nilai penapis Gaussian julat sebenar. Proses penapis Gaussian yang sama digunakan untuk julat sebenar harga, menghasilkan siri julat yang halus.
  3. Membina saluran Gaussian. Harga yang disaring Gaussian berfungsi sebagai jalur tengah, jalur atas dibentuk dengan menambahkan hasil julat sebenar yang disaring dan pengganda yang ditakrifkan pengguna ke jalur tengah, dan jalur bawah dibentuk dengan mengurangkan nilai ini dari jalur tengah, mewujudkan saluran dinamik.
  4. Menghasilkan isyarat dagangan. Apabila harga memecahkan band atas saluran, isyarat beli dihasilkan; apabila harga memecahkan band bawah, isyarat jual dihasilkan.
  5. Memperkenalkan parameter tempoh masa. Pengguna boleh menetapkan waktu permulaan dan akhir untuk pelaksanaan strategi, dan strategi hanya akan beroperasi berdasarkan isyarat perdagangan dalam tempoh masa yang ditentukan ini.

Analisis Kelebihan

Strategi purata bergerak adaptif Saluran Gaussian mempunyai kelebihan berikut:

  1. Kemudahan penyesuaian yang kuat. Strategi menggunakan parameter yang disesuaikan secara dinamik yang dapat menyesuaikan diri dengan keadaan pasaran dan instrumen perdagangan yang berbeza tanpa memerlukan penyesuaian manual yang kerap.
  2. Kemampuan mengikuti trend yang baik. Dengan membina saluran harga, strategi dapat menangkap dan mengikuti trend pasaran dengan berkesan, mengelakkan isyarat palsu di pasaran yang bergolak.
  3. Teknik penapisan Gaussian digunakan untuk meluruskan data harga beberapa kali, menghapuskan kebanyakan bunyi pasaran dan menjadikan isyarat perdagangan lebih boleh dipercayai.
  4. Pengguna boleh menyesuaikan parameter strategi mengikut keperluan mereka, seperti tempoh pengambilan sampel, bilangan tiang, pengganda julat, dan lain-lain, untuk mengoptimumkan prestasi strategi.
  5. Kepraktisan yang kuat: Pengenalan parameter tempoh masa membolehkan strategi dijalankan dalam julat masa yang ditentukan, memudahkan aplikasi dunia sebenar dan penyelidikan backtesting.

Analisis Risiko

Walaupun banyak kelebihan, Strategi Purata Bergerak Adaptif Saluran Gaussian masih membawa risiko tertentu:

  1. Risiko penetapan parameter: Tetapan parameter yang tidak sesuai boleh menyebabkan strategi tidak berkesan atau prestasi yang buruk, yang memerlukan ujian berulang dan pengoptimuman dalam aplikasi praktikal.
  2. Risiko kejadian tiba-tiba: Menghadapi beberapa peristiwa besar tiba-tiba, strategi mungkin tidak dapat bertindak balas dengan betul dalam masa yang tepat, mengakibatkan kerugian.
  3. Risiko overfitting: Jika tetapan parameter terlalu rapat dengan data sejarah, strategi mungkin berfungsi dengan buruk pada masa akan datang, yang memerlukan pertimbangan kedua-dua prestasi dalam sampel dan di luar sampel.
  4. Risiko arbitrase: Strategi ini terutamanya sesuai untuk pasaran yang sedang berkembang, dan perdagangan yang kerap di pasaran yang bergolak mungkin menghadapi risiko arbitrase yang besar.

Arahan pengoptimuman

Arah pengoptimuman untuk Strategi Purata Bergerak Adaptif Saluran Gaussian termasuk:

  1. Pengoptimuman parameter dinamik. Dengan memperkenalkan pembelajaran mesin dan teknik lain, mencapai pengoptimuman automatik dan pelarasan dinamik parameter strategi untuk meningkatkan kesesuaian.
  2. Penggabungan pelbagai faktor. Gabungkan penunjuk teknikal atau faktor lain yang berkesan dengan saluran Gaussian untuk membentuk isyarat perdagangan yang lebih kukuh.
  3. Mengoptimumkan pengurusan kedudukan: Masukkan peraturan pengurusan kedudukan dan pengurusan wang yang munasabah ke dalam strategi untuk mengawal pengeluaran dan risiko.
  4. Penyelarasan pelbagai instrumen: meluaskan strategi kepada pelbagai instrumen perdagangan yang berbeza dan mempelbagaikan risiko melalui peruntukan aset dan analisis korelasi.

Ringkasan

Strategi purata bergerak adaptif Saluran Gaussian adalah strategi perdagangan kuantitatif berdasarkan penapisan Gaussian dan parameter adaptif, yang menghasilkan isyarat perdagangan yang lancar dan boleh dipercayai dengan membina saluran harga secara dinamik. Strategi ini mempunyai kelebihan seperti kemampuan beradaptasi yang kuat, keupayaan mengikuti trend yang baik, kelancaran yang tinggi, fleksibiliti yang besar, dan kepraktisan yang kuat.


/*backtest
start: 2023-03-22 00:00:00
end: 2024-03-27 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=4
strategy(title="Gaussian Channel Strategy v1.0", overlay=true, calc_on_every_tick=false, initial_capital=10000, default_qty_type=strategy.percent_of_equity, default_qty_value=100, commission_type=strategy.commission.percent, commission_value=0.1)

// Date condition inputs
startDate = input(title="Date Start", type=input.time, defval=timestamp("1 Jan 2018 00:00 +0000"), group="Dates")
endDate = input(title="Date End", type=input.time, defval=timestamp("31 Dec 2060 23:59 +0000"), group="Dates")
timeCondition = true

// This study is an experiment utilizing the Ehlers Gaussian Filter technique combined with lag reduction techniques and true range to analyze trend activity.
// Gaussian filters, as Ehlers explains it, are simply exponential moving averages applied multiple times.
// First, beta and alpha are calculated based on the sampling period and number of poles specified. The maximum number of poles available in this script is 9.
// Next, the data being analyzed is given a truncation option for reduced lag, which can be enabled with "Reduced Lag Mode".
// Then the alpha and source values are used to calculate the filter and filtered true range of the dataset.
// Filtered true range with a specified multiplier is then added to and subtracted from the filter, generating a channel.
// Lastly, a one pole filter with a N pole alpha is averaged with the filter to generate a faster filter, which can be enabled with "Fast Response Mode". 

//Custom bar colors are included.

//Note: Both the sampling period and number of poles directly affect how much lag the indicator has, and how smooth the output is.
//      Larger inputs will result in smoother outputs with increased lag, and smaller inputs will have noisier outputs with reduced lag.
//      For the best results, I recommend not setting the sampling period any lower than the number of poles + 1. Going lower truncates the equation.

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Updates:
// Huge shoutout to @e2e4mfck for taking the time to improve the calculation method!
// -> migrated to v4
// -> pi is now calculated using trig identities rather than being explicitly defined.
// -> The filter calculations are now organized into functions rather than being individually defined.
// -> Revamped color scheme.

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Functions - courtesy of @e2e4mfck
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
 
//Filter function 
f_filt9x (_a, _s, _i) => 
    int _m2 = 0, int _m3 = 0, int _m4 = 0, int _m5 = 0, int _m6 = 0, 
    int _m7 = 0, int _m8 = 0, int _m9 = 0, float _f = .0, _x = (1 - _a)
    // Weights. 
    // Initial weight _m1 is a pole number and equal to _i
    _m2 := _i == 9 ? 36  : _i == 8 ? 28 : _i == 7 ? 21 : _i == 6 ? 15 : _i == 5 ? 10 : _i == 4 ? 6 : _i == 3 ? 3 : _i == 2 ? 1 : 0
    _m3 := _i == 9 ? 84  : _i == 8 ? 56 : _i == 7 ? 35 : _i == 6 ? 20 : _i == 5 ? 10 : _i == 4 ? 4 : _i == 3 ? 1 : 0
    _m4 := _i == 9 ? 126 : _i == 8 ? 70 : _i == 7 ? 35 : _i == 6 ? 15 : _i == 5 ? 5  : _i == 4 ? 1 : 0
    _m5 := _i == 9 ? 126 : _i == 8 ? 56 : _i == 7 ? 21 : _i == 6 ? 6  : _i == 5 ? 1  : 0 
    _m6 := _i == 9 ? 84  : _i == 8 ? 28 : _i == 7 ? 7  : _i == 6 ? 1  : 0 
    _m7 := _i == 9 ? 36  : _i == 8 ? 8  : _i == 7 ? 1  : 0 
    _m8 := _i == 9 ? 9   : _i == 8 ? 1  : 0 
    _m9 := _i == 9 ? 1   : 0
    // filter
    _f :=   pow(_a, _i) * nz(_s) + 
      _i  *     _x      * nz(_f[1])      - (_i >= 2 ? 
      _m2 * pow(_x, 2)  * nz(_f[2]) : 0) + (_i >= 3 ? 
      _m3 * pow(_x, 3)  * nz(_f[3]) : 0) - (_i >= 4 ? 
      _m4 * pow(_x, 4)  * nz(_f[4]) : 0) + (_i >= 5 ? 
      _m5 * pow(_x, 5)  * nz(_f[5]) : 0) - (_i >= 6 ? 
      _m6 * pow(_x, 6)  * nz(_f[6]) : 0) + (_i >= 7 ? 
      _m7 * pow(_x, 7)  * nz(_f[7]) : 0) - (_i >= 8 ? 
      _m8 * pow(_x, 8)  * nz(_f[8]) : 0) + (_i == 9 ? 
      _m9 * pow(_x, 9)  * nz(_f[9]) : 0)

//9 var declaration fun
f_pole (_a, _s, _i) =>
    _f1 =            f_filt9x(_a, _s, 1),      _f2 = (_i >= 2 ? f_filt9x(_a, _s, 2) : 0), _f3 = (_i >= 3 ? f_filt9x(_a, _s, 3) : 0)
    _f4 = (_i >= 4 ? f_filt9x(_a, _s, 4) : 0), _f5 = (_i >= 5 ? f_filt9x(_a, _s, 5) : 0), _f6 = (_i >= 6 ? f_filt9x(_a, _s, 6) : 0)
    _f7 = (_i >= 2 ? f_filt9x(_a, _s, 7) : 0), _f8 = (_i >= 8 ? f_filt9x(_a, _s, 8) : 0), _f9 = (_i == 9 ? f_filt9x(_a, _s, 9) : 0)
    _fn = _i == 1 ? _f1 : _i == 2 ? _f2 : _i == 3 ? _f3 :
      _i == 4     ? _f4 : _i == 5 ? _f5 : _i == 6 ? _f6 :
      _i == 7     ? _f7 : _i == 8 ? _f8 : _i == 9 ? _f9 : na
    [_fn, _f1]

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Inputs
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------

//Source
src = input(defval=hlc3, title="Source")

//Poles
int N = input(defval=4, title="Poles", minval=1, maxval=9)

//Period
int per = input(defval=144, title="Sampling Period", minval=2)

//True Range Multiplier
float mult = input(defval=1.414, title="Filtered True Range Multiplier", minval=0)

//Lag Reduction
bool modeLag  = input(defval=false, title="Reduced Lag Mode")
bool modeFast = input(defval=false, title="Fast Response Mode")

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Definitions
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------

//Beta and Alpha Components
beta  = (1 - cos(4*asin(1)/per)) / (pow(1.414, 2/N) - 1)
alpha = - beta + sqrt(pow(beta, 2) + 2*beta)

//Lag
lag = (per - 1)/(2*N)

//Data
srcdata = modeLag ? src + (src - src[lag]) : src
trdata  = modeLag ? tr(true) + (tr(true) - tr(true)[lag]) : tr(true)

//Filtered Values
[filtn, filt1]     = f_pole(alpha, srcdata, N)
[filtntr, filt1tr] = f_pole(alpha, trdata,  N)

//Lag Reduction
filt   = modeFast ? (filtn + filt1)/2 : filtn
filttr = modeFast ? (filtntr + filt1tr)/2 : filtntr

//Bands
hband = filt + filttr*mult
lband = filt - filttr*mult

// Colors
color1   = #0aff68
color2   = #00752d
color3   = #ff0a5a
color4   = #990032
fcolor   = filt > filt[1] ? #0aff68 : filt < filt[1] ? #ff0a5a : #cccccc
barcolor = (src > src[1]) and (src > filt) and (src < hband) ? #0aff68 : (src > src[1]) and (src >= hband) ? #0aff1b : (src <= src[1]) and (src > filt) ? #00752d : 
           (src < src[1]) and (src < filt) and (src > lband) ? #ff0a5a : (src < src[1]) and (src <= lband) ? #ff0a11 : (src >= src[1]) and (src < filt) ? #990032 : #cccccc

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Outputs
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------

//Filter Plot
filtplot = plot(filt, title="Filter", color=fcolor, linewidth=3)

//Band Plots
hbandplot = plot(hband, title="Filtered True Range High Band", color=fcolor)
lbandplot = plot(lband, title="Filtered True Range Low Band", color=fcolor)

//Channel Fill
fill(hbandplot, lbandplot, title="Channel Fill", color=fcolor, transp=80)

//Bar Color
barcolor(barcolor)


longCondition = crossover(close, hband) and timeCondition
closeAllCondition = crossunder(close, hband) and timeCondition

if longCondition
    strategy.entry("long", strategy.long)

if closeAllCondition
    strategy.close("long")

Lebih lanjut