
Chiến lược đường xu hướng tức thời của Ehlers được đề xuất bởi John Ehlers trong bài phân tích kiểm soát của ông về cổ phiếu và hợp đồng tương lai. Chiến lược này sử dụng các chỉ số kỹ thuật để xác định xu hướng tức thời của một cổ phiếu hoặc hợp đồng tương lai và mở vị trí khi xu hướng đảo ngược.
Cốt lõi của chiến lược này là tính toán đường xu hướng tức thời. Công thức tính toán của đường IT như sau:
it := (a-((a*a)/4.0))*src+0.5*a*a*src[1]-(a-0.75*a*a)*src[2]+2*(1-a )*it[1]-(1-a )*(1-a )*it[2]
Trong đó src đại diện cho giá, a là yếu tố mịn, giá trị mặc định là 0,07. Công thức này là một bộ lọc thứ hai, có thể làm mịn giá và tạo xu hướng.
Một chỉ số quan trọng khác là dòng trễ ((lag), và công thức tính toán là:
lag = 2.0 * it - nz(it[2])
Đường này tụt lại phía sau đường IT một chu kỳ. Khi giá vượt qua đường tụt lại phía trên, đại diện cho xu hướng đảo ngược, làm nhiều; khi giá vượt qua đường tụt lại phía dưới, đại diện cho xu hướng đảo ngược, làm trống.
Ngoài ra, chiến lược cũng đặt ra các đơn dừng lỗ để kiểm soát rủi ro.
Chiến lược này có những ưu điểm sau:
Chiến lược này cũng có một số rủi ro:
Những rủi ro này có thể được giảm thiểu bằng cách:
Chiến lược này có thể được tối ưu hóa theo các hướng sau:
Nhìn chung, chiến lược đường xu hướng tức thời của Ellers sử dụng các chỉ số kỹ thuật để xác định xu hướng thời gian thực của cổ phiếu / hợp đồng tương lai và mở vị trí khi xu hướng đảo ngược. Nó có các ưu điểm như lọc nhiễu hiệu quả, khả năng điều chỉnh tham số cao, logic tạo tín hiệu rõ ràng và kiểm soát rủi ro tích hợp. Chiến lược này có thể đạt được hiệu suất tốt hơn bằng cách tối ưu hóa thêm các tham số chọn tín hiệu, lọc, kích thước vị trí và điều chỉnh dừng lỗ. Cấu trúc mã rõ ràng cũng giúp dễ hiểu và sửa đổi.
/*backtest
start: 2022-12-13 00:00:00
end: 2023-12-19 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/
//@version=3
strategy("Ehlers Instantaneous Trendline Strategy", shorttitle = "Ehlers Instantaneous Trendline Strategy", overlay = true, default_qty_type = strategy.percent_of_equity, default_qty_value = 100.0, pyramiding = 1, backtest_fill_limits_assumption = 1)
src = input(hl2, title="Source")
a = input(0.07, title="Alpha", step=0.01)
fr = input(false, title="Fill Trend Region")
it = na
if (na(it[2]) or na(it[1]))
it := (src + 2 * src[1] + src[2]) / 4.0
else
it := (a-((a*a)/4.0))*src+0.5*a*a*src[1]-(a-0.75*a*a)*src[2]+2*(1-a )*it[1]-(1-a )*(1-a )*it[2]
lag = 2.0 * it - nz(it[2])
rngFrac = input(0.35)
revPct = input(0.015)
stopType = input(title="Stop type", defval = "stop-order", options = ["stop-order", "market-order", "None"])
diff = input(0.5, title = "Spread")
LongPrice(p) =>
LongPrice = diff == 0 ? p : floor(p / diff) * diff
ShortPrice(p) =>
ShortPrice = diff == 0 ? p : ceil(p / diff) * diff
strategy.cancel_all()
reverseTrade = false
if stopType == "market-order"
if strategy.position_size > 0 and close < strategy.position_avg_price * (1 - revPct)
strategy.order("StopLoss open short", strategy.short, 2 * strategy.position_size, limit = close - 2 * diff)
reverseTrade := true
if strategy.position_size < 0 and close > strategy.position_avg_price * (1 + revPct)
strategy.order("StopLoss open long", strategy.long, -2 * strategy.position_size, limit = close + 2 * diff)
reverseTrade := true
if lag > it and not reverseTrade
price = LongPrice(max(close - (high - low) * rngFrac, low))
if strategy.position_size <= 0
strategy.order("Open long", strategy.long, strategy.equity / price - strategy.position_size, limit = price)
if stopType == "stop-order"
strategy.order("StopLoss open long", strategy.short, 2 * strategy.equity / price, stop = ShortPrice(price * (1 - revPct)))
else
if stopType == "stop-order"
strategy.order("StopLoss open short", strategy.short, 2 * strategy.position_size, stop = ShortPrice(strategy.position_avg_price * (1 - revPct)))
if lag < it and not reverseTrade
price = ShortPrice(min(close - (high - low) * rngFrac, high))
if strategy.position_size >= 0
strategy.order("Open short", strategy.short, strategy.equity / price + strategy.position_size, limit = price)
if stopType == "stop-order"
strategy.order("StopLoss open short", strategy.long, 2 * strategy.equity / price, stop = LongPrice(price * (1 + revPct)))
else
if stopType == "stop-order"
strategy.order("StopLoss open long", strategy.long, -2 * strategy.position_size, stop = LongPrice(strategy.position_avg_price * (1 + revPct)))
itPlot=plot(it, color=red, linewidth=1, title="Trend")
lagPlot=plot(lag, color=blue, linewidth=1, title="Trigger")
fill(itPlot, lagPlot, it < lag ? green : red, transp=70)
// === Backtesting Dates ===
testPeriodSwitch = input(false, "Custom Backtesting Dates")
testStartYear = input(2018, "Backtest Start Year")
testStartMonth = input(9, "Backtest Start Month")
testStartDay = input(1, "Backtest Start Day")
testStartHour = input(0, "Backtest Start Hour")
testPeriodStart = timestamp(testStartYear,testStartMonth,testStartDay,testStartHour,0)
testStopYear = input(2018, "Backtest Stop Year")
testStopMonth = input(12, "Backtest Stop Month")
testStopDay = input(14, "Backtest Stop Day")
testStopHour = input(14, "Backtest Stop Hour")
testPeriodStop = timestamp(testStopYear,testStopMonth,testStopDay,testStopHour,0)
testPeriod() =>
time >= testPeriodStart and time <= testPeriodStop ? true : false
isPeriod = testPeriodSwitch == true ? testPeriod() : true
// === /END
if not isPeriod
strategy.cancel_all()
strategy.close_all()