Chiến lược giao dịch định lượng ERGOTIC 2 đường ray ngược MACD

Tác giả:ChaoZhang, Ngày: 2023-12-21 11:07:51
Tags:

img

Tổng quan

Chiến lược này là một chiến lược giao dịch định lượng MACD ngược hai đường ray. Nó dựa trên 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à mở rộng chúng. Chiến lược cũng có khả năng kiểm tra lại và có thể kết hợp các tính năng bổ sung như cảnh báo, bộ lọc, dừng lỗ, vv.

Nguyên tắc

Chỉ số cốt lõi của chiến lược này là MACD. Nó tính toán EMA chuyển động nhanh và EMA chuyển động chậm (slowMALen), sau đó tính toán sự khác biệt của chúng xmacd. Nó cũng tính toán EMA (signalLength) của xmacd để có được xMA_MACD. Một tín hiệu dài được kích hoạt khi xmacd vượt qua trên xMA_MACD, và một tín hiệu ngắn được kích hoạt trên đường chéo bên dưới.

Ngoài ra, chiến lược bao gồm các bộ lọc xu hướng. Khi tín hiệu dài được bắn, nếu bộ lọc xu hướng tăng được cấu hình, nó sẽ kiểm tra xem giá có tăng hay không. Tương tự, tín hiệu ngắn kiểm tra xu hướng giảm giá. Các chỉ số RSI và MFI cũng có thể được sử dụng để lọc các tín hiệu. Một cơ chế dừng lỗ được bao gồm để ngăn chặn tổn thất vượt quá ngưỡng.

Phân tích lợi thế

Lợi thế lớn nhất của chiến lược này là khả năng backtesting mạnh mẽ. Bạn có thể chọn các công cụ giao dịch khác nhau, đặt khung thời gian backtest và tối ưu hóa các thông số chiến lược dựa trên dữ liệu cụ thể của công cụ. So với một chiến lược MACD đơn giản, nó kết hợp xu hướng và phân tích mua quá mức / bán quá mức để lọc ra một số tín hiệu giống hệt nhau.

Phân tích rủi ro

Rủi ro chính của chiến lược này đến từ logic giao dịch ngược. Trong khi tín hiệu ngược có thể nắm bắt một số cơ hội bị bỏ lỡ bởi các tín hiệu truyền thống, nó cũng có nghĩa là mất một số điểm nhập MACD thông thường, đòi hỏi phải đánh giá cẩn thận. Hơn nữa, chính MACD có xu hướng tạo ra các tín hiệu tăng giả. Chiến lược có thể dẫn đến giao dịch quá mức và tăng chi phí trong các thị trường hỗn loạn, không có hướng.

Để giảm thiểu rủi ro, các tham số có thể được tối ưu hóa - điều chỉnh chiều dài trung bình động; kết hợp xu hướng và bộ lọc chỉ số tránh tín hiệu trong thị trường hỗn loạn; nâng khoảng cách dừng lỗ đảm bảo lỗ giới hạn trên các giao dịch riêng lẻ.

Hướng dẫn tối ưu hóa

Chiến lược có thể được cải thiện trong một số khía cạnh:

  1. Điều chỉnh các thông số đường ray nhanh và chậm, tối ưu hóa chiều dài trung bình chuyển động, backtest để tìm các bộ thông số tối ưu cho các thiết bị cụ thể
  2. Thêm hoặc điều chỉnh các bộ lọc xu hướng, đánh giá từ kết quả backtest cho dù nó cải thiện lợi nhuận
  3. Kiểm tra các cơ chế dừng mất mát khác nhau, cố định hoặc theo dõi để xác định hiệu suất tốt hơn
  4. Hãy thử kết hợp các chỉ số khác như KD, Bollinger Bands để thiết lập điều kiện lọc bổ sung và đảm bảo chất lượng tín hiệu

Tóm lại

Chiến lược định lượng MACD ngược hai đường ray dựa trên chỉ số MACD cổ điển với các mở rộng và cải tiến. Với cấu hình tham số linh hoạt, lựa chọn bộ lọc phong phú và chức năng kiểm tra ngược mạnh mẽ, nó có thể được điều chỉnh để phù hợp với các công cụ giao dịch khác nhau. Do đó, nó là một chiến lược giao dịch định lượng hấp dẫn và hứa hẹn xứng đáng được khám phá thêm.


/*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)

Thêm nữa