Chiến lược theo dõi xu hướng kênh Gaussian


Ngày tạo: 2024-03-29 16:26:26 sửa đổi lần cuối: 2024-03-29 16:26:26
sao chép: 2 Số nhấp chuột: 1133
1
tập trung vào
1617
Người theo dõi

Chiến lược theo dõi xu hướng kênh Gaussian

Tổng quan

Chiến lược theo dõi xu hướng Gaussian Channel là một chiến lược giao dịch theo dõi xu hướng dựa trên chỉ số Gaussian Channel. Chiến lược này được thiết kế để nắm bắt xu hướng chính của thị trường, mua và giữ vị trí trong xu hướng tăng, và xem xét giảm giá trong xu hướng giảm. Chiến lược sử dụng chỉ số Gaussian Channel để xác định hướng và cường độ của xu hướng, xác định thời gian mua và bán bằng cách phân tích mối quan hệ giữa giá và đường mòn trên và dưới kênh. Mục tiêu chính của chiến lược là để có được lợi nhuận tối đa trong thời gian xu hướng kéo dài, đồng thời tránh giao dịch thường xuyên trong thị trường biến động.

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

Trung tâm của chiến lược theo dõi xu hướng Gaussian Channel là chỉ số Gaussian Channel, được đề xuất bởi Ehlers, là một công cụ phân tích xu hướng kết hợp công nghệ Gaussian Slip Wave với phạm vi thực (True Range). Chỉ số này trước tiên tính các giá trị β và α dựa trên chu kỳ lấy mẫu và số cực, sau đó xử lý dữ liệu theo slide, tạo ra đường cong mịn (trung tâm).

Lợi thế chiến lược

  1. Theo dõi xu hướng: Chiến lược này có khả năng nắm bắt các xu hướng chính của thị trường và đầu tư theo xu hướng, giúp thu được lợi nhuận ổn định lâu dài.
  2. Giảm tần suất giao dịch: Chiến lược chỉ tham gia khi xác nhận xu hướng và giữ vị trí khi xu hướng kéo dài, do đó giảm số lần giao dịch và chi phí giao dịch không cần thiết.
  3. Giảm độ trễ: Bằng cách giảm độ trễ và phản ứng nhanh, chiến lược có thể phản ứng kịp thời hơn với sự thay đổi của thị trường.
  4. Tính linh hoạt về tham số: Người dùng có thể điều chỉnh các tham số chính sách theo nhu cầu của mình, chẳng hạn như chu kỳ lấy mẫu, số điểm cực, số nhân phạm vi thực, v.v. để tối ưu hóa hiệu suất chính sách.

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 phù hợp có thể dẫn đến hiệu suất chiến lược kém. Cần tối ưu hóa tham số và kiểm tra lại trong các môi trường thị trường khác nhau để tìm ra sự kết hợp tham số tối ưu nhất.
  2. Rủi ro đảo chiều xu hướng: Khi xu hướng thị trường đột ngột đảo chiều, chiến lược có thể tạo ra sự rút lui lớn. Bạn có thể kiểm soát rủi ro bằng cách đặt lệnh dừng lỗ hoặc giới thiệu các chỉ số khác.
  3. Rủi ro thị trường chấn động: Trong thị trường chấn động, chiến lược có thể xuất hiện các tín hiệu giao dịch thường xuyên, dẫn đến tổn thất thu nhập. Các tín hiệu có thể được lọc bằng các tham số tối ưu hóa hoặc kết hợp với các chỉ số kỹ thuật khác.

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

  1. Thêm các chỉ số kỹ thuật khác: kết hợp với các chỉ số xu hướng hoặc dao động khác như MACD, RSI, v.v. để tăng độ chính xác và độ tin cậy của tín hiệu.
  2. Tối ưu hóa tham số động: Đổi ứng các tham số chiến lược động theo tình trạng thị trường thay đổi để phù hợp với 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 và dừng hợp lý, kiểm soát rủi ro giao dịch đơn lẻ và mức độ rút tiền 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 chu kỳ thời gian khác nhau, chẳng hạn như đường ngày, đường 4 giờ, để có được thông tin thị trường toàn diện hơn.

Tóm tắt

Chiến lược theo dõi xu hướng Gaussian Channel là một chiến lược giao dịch theo dõi xu hướng dựa trên công nghệ Gaussian Wave để thu được lợi nhuận ổn định lâu dài bằng cách nắm bắt xu hướng thị trường chính. Chiến lược sử dụng chỉ số Gaussian Channel để xác định hướng và cường độ của xu hướng, đồng thời cung cấp các chức năng giảm độ trễ và phản ứng nhanh.

Mã nguồn chiến lược
/*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")