
Chiến lược này là một chiến lược giao dịch định lượng MACD ngược hai quỹ đạo. Nó lấy các chỉ số kỹ thuật được mô tả bởi William Blau trong cuốn sách của ông, Momentum, Direction and Divergence, và được mở rộng dựa trên đó. Chiến lược này cũng có chức năng phản hồi, có thể thêm các chức năng bổ sung như cảnh báo, bộ lọc, theo dõi dừng lỗ.
Chỉ số cốt lõi của chiến lược này là MACD. Nó tính toán đường trung bình di chuyển nhanh EMA ® và đường trung bình di chuyển chậm EMA (slowMALen) và sau đó tính toán chênh lệch của chúng là xmacd. Ngoài ra, tính toán đường trung bình di chuyển nhanh của xmacd (EMA (signalLength) để có được xMA_MACD.
Ngoài ra, chiến lược này cũng giới thiệu bộ lọc xu hướng. Khi phát ra nhiều tín hiệu, nếu bộ lọc xu hướng lạc quan được thiết lập, nó sẽ phát hiện ra liệu giá có đang tăng hay không; tương tự như vậy, tín hiệu phá giá sẽ phát hiện xu hướng giảm giá. Chỉ số RSI và chỉ số MFI cũng có thể được sử dụng để lọc cấu hình tín hiệu.
Ưu điểm lớn nhất của chiến lược này là tính năng đo đạc mạnh mẽ. Bạn có thể chọn các loại giao dịch khác nhau, thiết lập phạm vi thời gian đo đạc, tối ưu hóa chiến lược cho dữ liệu cụ thể. So với chiến lược MACD đơn giản, nó tăng xu hướng, đánh giá quá mua quá bán, có thể lọc một số tín hiệu đồng thuận.
Rủi ro của chiến lược này chủ yếu xuất phát từ tư tưởng giao dịch ngược. Mặc dù có thể có được một số cơ hội, tín hiệu ngược cũng có nghĩa là từ bỏ một số điểm mua và bán MACD truyền thống, điều này cần được đánh giá cẩn thận. Ngoài ra, bản thân MACD dễ gây ra các vấn đề về tín hiệu giả nhiều đầu.
Để giảm rủi ro, các tham số có thể được điều chỉnh thích hợp, tối ưu hóa chiều dài của đường trung bình di chuyển; kết hợp xu hướng và bộ lọc chỉ số, tránh phát sinh tín hiệu trong thị trường chấn động; nâng cao khoảng cách dừng lỗ thích hợp, đảm bảo kiểm soát thua lỗ giao dịch cá nhân.
Chiến lược này có thể được tối ưu hóa theo các khía cạnh sau:
Chiến lược định lượng MACD ngược hai chiều lấy ý tưởng từ chỉ số MACD cổ điển, được mở rộng và cải tiến dựa trên đó. Chiến lược này có các ưu điểm như cấu hình tham số linh hoạt, lựa chọn cơ chế lọc phong phú và tính năng phản hồi mạnh mẽ. Điều này cho phép nó được tối ưu hóa cá nhân cho các loại giao dịch khác nhau và là một chiến lược giao dịch định lượng tiềm năng đáng để khám phá.
/*backtest
start: 2023-11-20 00:00:00
end: 2023-12-20 00:00:00
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/
//@version = 3
////////////////////////////////////////////////////////////
// Copyright by HPotter v1.0 09/12/2016
// This is one of the techniques described by William Blau in his book
// "Momentum, Direction and Divergence" (1995). If you like to learn more,
// we advise you to read this book. His book focuses on three key aspects
// of trading: momentum, direction and divergence. Blau, who was an electrical
// engineer before becoming a trader, thoroughly examines the relationship
// between price and momentum in step-by-step examples. From this grounding,
// he then looks at the deficiencies in other oscillators and introduces some
// innovative techniques, including a fresh twist on Stochastics. On directional
// issues, he analyzes the intricacies of ADX and offers a unique approach to help
// define trending and non-trending periods.
// Blau`s indicator is like usual MACD, but it plots opposite of meaningof
// stndard MACD indicator.
//
// You can change long to short in the Input Settings
// Please, use it only for learning or paper trading. Do not for real trading.
//
//
// 2018-09 forked by Khalid Salomão
// - Backtesting
// - Added filters: RSI, MFI, Price trend
// - Trailing Stop Loss
// - Other minor adjustments
//
////////////////////////////////////////////////////////////
strategy(title="Ergotic MACD Backtester [forked from HPotter]", shorttitle="Ergotic MACD Backtester", overlay=true, pyramiding=0, default_qty_type=strategy.cash, default_qty_value=25000, initial_capital=50000, commission_type=strategy.commission.percent, commission_value=0.15, slippage=3)
// === BACKTESTING: INPUT BACKTEST RANGE ===
source = input(close)
strategyType = input(defval="Long Only", options=["Long & Short", "Long Only", "Short Only"])
FromMonth = input(defval = 7, title = "From Month", minval = 1, maxval = 12)
FromDay = input(defval = 1, title = "From Day", minval = 1, maxval = 31)
FromYear = input(defval = 2018, title = "From Year", minval = 2017)
ToMonth = input(defval = 12, title = "To Month", minval = 1, maxval = 12)
ToDay = input(defval = 1, title = "To Day", minval = 1, maxval = 31)
ToYear = input(defval = 2030, title = "To Year", minval = 2017)
start = timestamp(FromYear, FromMonth, FromDay, 00, 00)
finish = timestamp(ToYear, ToMonth, ToDay, 23, 59)
window() => true // window of time verification
// === STRATEGY ===
r = input(144, minval=1, title="R (32,55,89,100,144,200)") // default 32
slowMALen = input(6, minval=1) // default 32
signalLength = input(6, minval=1)
reverse = input(false, title="Trade reverse (long/short switch)")
//hline(0, color=blue, linestyle=line)
fastMA = ema(source, r)
slowMA = ema(source, slowMALen)
xmacd = fastMA - slowMA
xMA_MACD = ema(xmacd, signalLength)
pos = 0
pos := iff(xmacd < xMA_MACD, 1,
iff(xmacd > xMA_MACD, -1, nz(pos[1], 0)))
possig = 0
possig := iff(reverse and pos == 1, -1,
iff(reverse and pos == -1, 1, pos))
// === FILTER: price trend ====
trending_price_long = input(true, title="Long only if price has increased" )
trending_price_short = input(false, title="Short only if price has decreased" )
trending_price_length = input( 2, minval=1 )
trending_price_with_ema = input( false )
trending_price_ema = input( 3, minval=1 )
price_trend = trending_price_with_ema ? ema(source, trending_price_ema) : source
priceLongTrend() => (trending_price_long ? rising(price_trend, trending_price_length) : true)
priceShortTrend() => (trending_price_short ? falling(price_trend, trending_price_length) : true)
// === FILTER: RSI ===
rsi_length = input( 14, minval=1 )
rsi_overSold = input( 14, minval=0, title="RSI Sell Cutoff (Sell only if >= #)" )
rsi_overBought = input( 82, minval=0, title="RSI Buy Cutoff (Buy only if <= #)" )
vrsi = rsi(source, rsi_length)
rsiOverbought() => vrsi > rsi_overBought
rsiOversold() => vrsi < rsi_overSold
trending_rsi_long = input(false, title="Long only if RSI has increased" )
trending_rsi_length = input( 2 )
rsiLongTrend() => trending_rsi_long ? rising(vrsi, trending_rsi_length) : true
// === FILTER: MFI ===
mfi_length = input(14, minval=1)
mfi_lower = input(14, minval=0, maxval=50)
mfi_upper = input(82, minval=50, maxval=100)
upper_s = sum(volume * (change(source) <= 0 ? 0 : source), mfi_length)
lower_s = sum(volume * (change(source) >= 0 ? 0 : source), mfi_length)
mf = rsi(upper_s, lower_s)
mfiOverbought() => (mf > mfi_upper)
mfiOversold() => (mf < mfi_lower)
trending_mfi_long = input(false, title="Long only if MFI has increased" )
trending_mfi_length = input( 2 )
mfiLongTrend() => trending_mfi_long ? rising(mf, trending_mfi_length) : true
// === SIGNAL CALCULATION ===
long = window() and possig == 1 and rsiLongTrend() and mfiLongTrend() and not rsiOverbought() and not mfiOverbought() and priceLongTrend()
short = window() and possig == -1 and not rsiOversold() and not mfiOversold() and priceShortTrend()
// === trailing stop
tslSource=input(hlc3,title="TSL source")
//suseCurrentRes = input(true, title="Use current chart resolution for stop trigger?")
tslResolution = input(title="Use different timeframe for stop trigger? Uncheck box above.", defval="5")
tslTrigger = input(3.0) / 100
tslStop = input(0.6) / 100
currentPrice = request.security(syminfo.tickerid, tslResolution, tslSource, barmerge.gaps_off, barmerge.lookahead_off)
isLongOpen = false
isLongOpen := nz(isLongOpen[1], false)
entryPrice=0.0
entryPrice:= nz(entryPrice[1], 0.0)
trailPrice=0.0
trailPrice:=nz(trailPrice[1], 0.0)
// update TSL high mark
if (isLongOpen )
if (not trailPrice and currentPrice >= entryPrice * (1 + tslTrigger))
trailPrice := currentPrice
else
if (trailPrice and currentPrice > trailPrice)
trailPrice := currentPrice
if (trailPrice and currentPrice <= trailPrice * (1 - tslStop))
// FIRE TSL SIGNAL
short:=true // <===
long := false
// if short clean up
if (short)
isLongOpen := false
entryPrice := 0.0
trailPrice := 0.0
if (long)
isLongOpen := true
if (not entryPrice)
entryPrice := currentPrice
// === BACKTESTING: ENTRIES ===
if long
if (strategyType == "Short Only")
strategy.close("Short")
else
strategy.entry("Long", strategy.long, comment="Long")
if short
if (strategyType == "Long Only")
strategy.close("Long")
else
strategy.entry("Short", strategy.short, comment="Short")
//barcolor(possig == -1 ? red: possig == 1 ? green : blue )
//plot(xmacd, color=green, title="Ergotic MACD")
//plot(xMA_MACD, color=red, title="SigLin")
plotshape(trailPrice ? trailPrice : na, style=shape.circle, location=location.absolute, color=blue, size=size.tiny)
plotshape(long, style=shape.triangleup, location=location.belowbar, color=green, size=size.tiny)
plotshape(short, style=shape.triangledown, location=location.abovebar, color=red, size=size.tiny)
// === Strategy Alert ===
alertcondition(long, title='BUY - Ergotic MACD Long Entry', message='Go Long!')
alertcondition(short, title='SELL - Ergotic MACD Long Entry', message='Go Short!')
// === BACKTESTING: EXIT strategy ===
sl_inp = input(7, title='Stop Loss %', type=float)/100
tp_inp = input(1.8, title='Take Profit %', type=float)/100
stop_level = strategy.position_avg_price * (1 - sl_inp)
take_level = strategy.position_avg_price * (1 + tp_inp)
strategy.exit("Stop Loss/Profit", "Long", stop=stop_level, limit=take_level)