Xu hướng kênh Gaussian theo chiến lược

Tác giả:ChaoZhang, Ngày: 2024-03-29 16:26:26
Tags:

img

Tổng quan

Gaussian Channel Trend Following Strategy là một chiến lược giao dịch theo xu hướng dựa trên chỉ số Gaussian Channel. Chiến lược này nhằm mục đích nắm bắt các xu hướng chính trên thị trường, mua và giữ các vị trí trong xu hướng tăng và đóng các vị trí trong xu hướng giảm. Nó sử dụng chỉ số Gaussian Channel để xác định hướng và sức mạnh của xu hướng bằng cách phân tích mối quan hệ giữa giá và các dải trên và dưới của kênh. Mục tiêu chính của chiến lược là tối đa hóa lợi nhuận trong các xu hướng bền vững trong khi giảm thiểu tần suất giao dịch trong các thị trường giới hạn phạm vi.

Nguyên tắc chiến lược

Lòng cốt của Gaussian Channel Trend Following Strategy là chỉ số Gaussian Channel, được đề xuất bởi Ehlers. Nó kết hợp các kỹ thuật lọc Gaussian với True Range để phân tích hoạt động xu hướng. Chỉ số đầu tiên tính toán giá trị beta và alpha dựa trên thời gian lấy mẫu và số cột, sau đó áp dụng bộ lọc cho dữ liệu để có được đường cong mượt (đường trung). Tiếp theo, chiến lược nhân True Range mượt bằng một trình nhân để tạo các kênh trên và dưới. Khi giá vượt qua trên / dưới kênh trên / dưới, nó tạo ra tín hiệu mua / bán. Ngoài ra, chiến lược cung cấp các tính năng để giảm độ trễ của chỉ số và chế độ phản hồi nhanh.

Ưu điểm chiến lược

  1. Tiếp theo xu hướng: Chiến lược xuất sắc trong việc nắm bắt các xu hướng chính trên thị trường, đầu tư theo hướng xu hướng, giúp đạt được lợi nhuận ổn định dài hạn.
  2. Tỷ lệ giao dịch giảm: Chiến lược chỉ đi vào các vị trí khi một xu hướng được xác nhận và duy trì các vị trí trong thời gian xu hướng, do đó giảm chi phí giao dịch và giao dịch không cần thiết.
  3. Giảm chậm trễ: Thông qua chế độ chậm trễ giảm và chế độ phản ứng nhanh, chiến lược có thể phản ứng nhanh hơn với những thay đổi trên thị trường.
  4. Các thông số linh hoạt: Người dùng có thể điều chỉnh các thông số chiến lược theo nhu cầu của họ, chẳng hạn như thời gian lấy mẫu, số cột, nhân True Range, v.v., để tối ưu hóa hiệu suất chiến lược.

Rủi ro chiến lược

  1. Rủi ro tối ưu hóa tham số: Cài đặt tham số không chính xác có thể dẫn đến hiệu suất chiến lược kém.
  2. Rủi ro đảo ngược xu hướng: Khi xu hướng thị trường đột ngột đảo ngược, chiến lược có thể trải qua sự rút ngắn đáng kể. Điều này có thể được giảm thiểu bằng cách thiết lập dừng lỗ hoặc giới thiệu các chỉ số khác để kiểm soát rủi ro.
  3. Rủi ro thị trường giới hạn phạm vi: Trong các thị trường giới hạn phạm vi, chiến lược có thể tạo ra các tín hiệu giao dịch thường xuyên, dẫn đến lợi nhuận giảm. Điều này có thể được giải quyết bằng cách tối ưu hóa các thông số hoặc kết hợp với các chỉ số kỹ thuật khác để lọc tín hiệu.

Hướng dẫn tối ưu hóa chiến lược

  1. Kết hợp các chỉ số kỹ thuật khác: Kết hợp với các chỉ số theo xu hướng hoặc dao động khác, chẳng hạn như MACD, RSI, v.v., để cải thiện độ chính xác và độ tin cậy của tín hiệu.
  2. Tối ưu hóa tham số động: Điều chỉnh động các tham số chiến lược dựa trên những thay đổi trong điều kiện thị trường để thích nghi với các môi trường thị trường khác nhau.
  3. Thêm mô-đun kiểm soát rủi ro: Thiết lập các quy tắc dừng lỗ và lấy lợi nhuận hợp lý để kiểm soát rủi ro giao dịch cá nhân và mức thu hút tổng thể.
  4. Phân tích nhiều khung thời gian: Kết hợp các tín hiệu từ các khung thời gian khác nhau, chẳng hạn như biểu đồ hàng ngày và 4 giờ, để có được thông tin thị trường toàn diện hơn.

Tóm lại

Chiến lược theo dõi xu hướng kênh Gaussian là một chiến lược giao dịch theo xu hướng dựa trên kỹ thuật lọc Gaussian, nhằm mục đích nắm bắt các xu hướng thị trường chính để có lợi nhuận ổn định dài hạn. Chiến lược sử dụng chỉ số kênh Gaussian để xác định hướng và sức mạnh xu hướng trong khi cung cấp các tính năng để giảm chậm trễ và cung cấp phản ứng nhanh.


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

//@version=5
strategy(title="Gaussian Channel Strategy v2.0", overlay=true, calc_on_every_tick=false, initial_capital=1000, default_qty_type=strategy.percent_of_equity, default_qty_value=100, commission_type=strategy.commission.percent, commission_value=0.1, slippage=3)

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
// Gaussian Channel Indicaor - courtesy of @DonovanWall
//----------------------------------------------------------------------------------------------------------------------------------------------------------------- 

// Date condition inputs
startDate = input(timestamp("1 January 2018 00:00 +0000"), "Date Start", group="Main Algo Settings")
endDate = input(timestamp("1 January 2060 00:00 +0000"), "Date Start", group="Main Algo Settings")
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 :=   math.pow(_a, _i) * nz(_s) + 
      _i  *     _x      * nz(_f[1])      - (_i >= 2 ? 
      _m2 * math.pow(_x, 2)  * nz(_f[2]) : 0) + (_i >= 3 ? 
      _m3 * math.pow(_x, 3)  * nz(_f[3]) : 0) - (_i >= 4 ? 
      _m4 * math.pow(_x, 4)  * nz(_f[4]) : 0) + (_i >= 5 ? 
      _m5 * math.pow(_x, 5)  * nz(_f[5]) : 0) - (_i >= 6 ? 
      _m6 * math.pow(_x, 6)  * nz(_f[6]) : 0) + (_i >= 7 ? 
      _m7 * math.pow(_x, 7)  * nz(_f[7]) : 0) - (_i >= 8 ? 
      _m8 * math.pow(_x, 8)  * nz(_f[8]) : 0) + (_i == 9 ? 
      _m9 * math.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.int(defval=4, title="Poles", minval=1, maxval=9)

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

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

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

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

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

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

// Data
srcdata = modeLag ? src + (src - src[lag]) : src
trdata  = modeLag ? ta.tr(true) + (ta.tr(true) - ta.tr(true)[lag]) : ta.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=color.new(fcolor, 80))

// Bar Color
barcolor(barcolor)

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

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

if closeAllCondition
    strategy.close("long")

Thêm nữa