Chiến lược giao dịch theo thuật toán mô hình đột phá và ngập

Tác giả:ChaoZhang, Ngày: 2024-01-30 17:20:59
Tags:

img

Tổng quan

Bài viết này giới thiệu một chiến lược giao dịch thuật toán xác định các cơ hội lợi nhuận thông qua các mô hình hấp thụ và sử dụng giá chéo với trung bình động như các tín hiệu đầu vào. Kết hợp phân tích kỹ thuật với các phương pháp theo xu hướng, chiến lược này nhằm mục đích kiếm lợi nhuận tại các điểm củng cố và đảo ngược xu hướng.

Nguyên tắc

Lý thuyết cốt lõi của chiến lược này dựa trên sự hội tụ của hai chỉ số không liên quan:

  1. Mô hình nuốt: Một mô hình đảo ngược hai nến trong đó cơ thể của nến thứ hai hoàn toàn nguồn cơ thể của nến đầu tiên, được sử dụng để xác định các cơ hội đảo ngược.

  2. Crossover giá với Moving Average: Một tín hiệu mua được tạo ra khi giá vượt trên đường trung bình động từ dưới; Một tín hiệu bán là khi giá vượt dưới đường trung bình động từ trên.

Bằng cách đánh giá thời gian đảo ngược thị trường tiềm năng với các mô hình bao trùm và sử dụng giá chéo với đường trung bình động như các tín hiệu xác nhận, xác suất lợi nhuận có thể được cải thiện.

Cụ thể, chiến lược này theo dõi ba loại mô hình ngập - tăng, giảm và không ngập bóng để xác định khả năng củng cố và đảo ngược. Cùng với tín hiệu chéo vàng và chéo chết của giá và chéo trung bình động, hướng mở các vị trí cuối cùng được xác định.

Ưu điểm

Lợi thế lớn nhất của chiến lược này là sử dụng sự hội tụ của các chỉ số không liên quan để cải thiện hiệu quả ra quyết định. Các mô hình ngập xác định thời gian và xác suất đảo ngược thị trường; trong khi giá chéo với đường trung bình động xác minh hướng và động lực của sự đảo ngược. Cả hai đều xác nhận lẫn nhau và có thể làm giảm hiệu quả tổn thất giao dịch do tín hiệu sai.

Một lợi thế khác là tính linh hoạt của cài đặt tham số. Người dùng có thể đặt các tham số như thời gian trung bình động và phạm vi dừng lỗ để tối ưu hóa chiến lược của chính họ.

Rủi ro

Mặc dù sử dụng nhiều chỉ số cải thiện phán đoán, nhưng vẫn có một số rủi ro của tín hiệu sai trong chiến lược này. Các mô hình ngập không phải là tín hiệu đảo ngược đáng tin cậy 100%, và các kịch bản thất bại cũng tồn tại trong giao thoa giá với đường trung bình động. Tất cả những điều này có thể dẫn đến tổn thất từ các vị trí mở sớm.

Hơn nữa, giống như hầu hết các chiến lược phân tích kỹ thuật, nó cũng hoạt động kém trong các thị trường xu hướng mâu thuẫn như dao động và hợp nhất.

Để kiểm soát rủi ro, các thông số như thời gian trung bình động và phạm vi dừng lỗ có thể được điều chỉnh phù hợp.

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

Các lĩnh vực sau đây có thể được tối ưu hóa cho chiến lược này:

  1. Kiểm tra nhiều loại trung bình động hơn để tìm các tập tham số tối ưu, như trung bình động cân nhắc, trung bình động trơn gấp đôi vv

  2. Thêm các chỉ số đánh giá xu hướng để tránh mở các vị trí trên thị trường bên.

  3. Tối ưu hóa các phương pháp dừng lỗ để cải thiện hiệu quả.

  4. Tăng các phương pháp học máy để đánh giá các mẫu nến và cải thiện độ chính xác nhận dạng ngập.

  5. Thêm các chức năng tối ưu hóa tham số để điều chỉnh thích nghi.

Kết luận

Chiến lược này xác định thời gian đảo ngược với các mẫu ngập và xác minh hướng sử dụng chéo giá với trung bình động. Bằng cách cải thiện hiệu quả quyết định thông qua hội tụ chỉ số, đây là một phương pháp phân tích kỹ thuật. Ưu điểm bao gồm các chỉ số bổ sung và các tham số linh hoạt.


/*backtest
start: 2023-12-30 00:00:00
end: 2024-01-29 00:00:00
period: 3h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=4
//@author=Daveatt

StrategyName = "BEST Engulfing + MA"
ShortStrategyName = "BEST Engulfing + MA"

strategy(title=StrategyName, shorttitle=ShortStrategyName, overlay=true)

includeEngulfing = true

includeMA = true
source_ma = input(title="Source Price vs MA", type=input.source, defval=close)
typeofMA = input(title="Type of MA", defval="SMA", options=["RMA", "SMA", "EMA", "WMA", "VWMA", "SMMA", "KMA", "TMA", "HullMA", "DEMA", "TEMA"])
length_ma = input(32, title = "MA Length", type=input.integer)

// ---------- Candle components and states
GreenCandle = close > open
RedCandle = close < open
NoBody = close==open
Body = abs(close-open)


// bullish conditions
isBullishEngulfing1 = max(close[1],open[1]) < max(close,open) and min(close[1],open[1]) > min(close,open) and Body > Body[1] and GreenCandle and RedCandle[1]
isBullishEngulfing2 = max(close[1],open[1]) < max(close,open) and min(close[1],open[1]) <= min(close,open) and Body > Body[1] and GreenCandle and RedCandle[1]

// bearish conditions
isBearishEngulfing1 = max(close[1],open[1]) < max(close,open) and min(close[1],open[1]) > min(close,open) and Body > Body[1] and RedCandle and GreenCandle[1]
isBearishEngulfing2 = max(close[1],open[1]) >= max(close,open) and min(close[1],open[1]) > min(close,open) and Body > Body[1] and RedCandle and GreenCandle[1]

// consolidation of conditions
isBullishEngulfing = isBullishEngulfing1 or isBullishEngulfing2
isBearishEngulfing = isBearishEngulfing1 or isBearishEngulfing2

//isBullishEngulfing = max(close[1],open[1]) < max(close,open) and min(close[1],open[1]) > min(close,open) and Body > Body[1] and GreenCandle and RedCandle[1]
//isBearishEngulfing = max(close[1],open[1]) < max(close,open) and min(close[1],open[1]) > min(close,open) and Body > Body[1] and RedCandle and GreenCandle[1]

Engulf_curr = 0 - barssince(isBearishEngulfing) + barssince(isBullishEngulfing)
Engulf_Buy = Engulf_curr < 0 ? 1 : 0
Engulf_Sell = Engulf_curr > 0 ? 1 : 0


// Price vs MM


smma(src, len) =>
    smma = 0.0
    smma := na(smma[1]) ? sma(src, len) : (smma[1] * (len - 1) + src) / len
    smma

ma(smoothing, src, length) => 
    if smoothing == "RMA"
        rma(src, length)
    else
        if smoothing == "SMA"
            sma(src, length)
        else 
            if smoothing == "EMA"
                ema(src, length)
            else 
                if smoothing == "WMA"
                    wma(src, length)
				else
					if smoothing == "VWMA"
						vwma(src, length)
					else
						if smoothing == "SMMA"
						    smma(src, length)
						else
							if smoothing == "HullMA"
								wma(2 * wma(src, length / 2) - wma(src, length), round(sqrt(length)))
							else
								if smoothing == "LSMA"
									src
								else
								    if smoothing == "KMA"
								        xPrice = src
                                        xvnoise = abs(xPrice - xPrice[1])
                                        nfastend = 0.666
                                        nslowend = 0.0645
                                        nsignal = abs(xPrice - xPrice[length])
                                        nnoise = sum(xvnoise, length)
                                        nefratio = iff(nnoise != 0, nsignal / nnoise, 0)
                                        nsmooth = pow(nefratio * (nfastend - nslowend) + nslowend, 2) 
                                        nAMA = 0.0
                                        nAMA := nz(nAMA[1]) + nsmooth * (xPrice - nz(nAMA[1]))
                                        nAMA
								    else
								        if smoothing == "TMA"
									        sma(sma(close, length), length)
						                else
							                if smoothing == "DEMA"
							                    2 * src - ema(src, length)
							                else
							                    if smoothing == "TEMA"
							                        3 * (src - ema(src, length)) + ema(ema(src, length), length) 
							                    else
		    							            src
		    							                

MA = ma(typeofMA, source_ma, length_ma)

plot(MA, color=#006400FF, title="MA breakout", linewidth=3)

macrossover  = crossover (source_ma, MA)
macrossunder = crossunder(source_ma, MA)

since_ma_buy = barssince(macrossover)
since_ma_sell = barssince(macrossunder)
macross_curr = 0 - since_ma_sell + since_ma_buy
bullish_MA_cond = macross_curr < 0 ?  1 : 0
bearish_MA_cond = macross_curr > 0 ? 1  : 0

posUp = (Engulf_Buy ? 1 : 0) + (bullish_MA_cond ? 1 : 0) 
posDn = (Engulf_Sell ? 1 : 0) + (bearish_MA_cond ? 1 : 0) 

conditionUP = posUp == 2 and posUp[1] < 2
conditionDN = posDn == 2 and posDn[1] < 2


sinceUP = barssince(conditionUP)
sinceDN = barssince(conditionDN)

// primary-first signal of the trend
nUP = crossunder(sinceUP,sinceDN)
nDN = crossover(sinceUP,sinceDN)


// and the following secondary signals

// save of the primary signal
sinceNUP = barssince(nUP)
sinceNDN = barssince(nDN)

buy_trend   = sinceNDN > sinceNUP
sell_trend  = sinceNDN < sinceNUP

// engulfing by
barcolor(nUP ? color.orange : na, title="Bullish condition")
barcolor(nDN ? color.yellow : na, title="Bearish condition")

isLong  = nUP
isShort = nDN

long_entry_price    = valuewhen(nUP, close, 0)
short_entry_price   = valuewhen(nDN, close, 0)

longClose   = close[1] < MA
shortClose  = close[1] > MA

///////////////////////////////////////////////
//* Backtesting Period Selector | Component *//
///////////////////////////////////////////////


StartYear = input(2017, "Backtest Start Year",minval=1980)
StartMonth = input(1, "Backtest Start Month",minval=1,maxval=12)
StartDay = input(1, "Backtest Start Day",minval=1,maxval=31)
testPeriodStart = timestamp(StartYear,StartMonth,StartDay,0,0)

StopYear = input(2020, "Backtest Stop Year",minval=1980)
StopMonth = input(12, "Backtest Stop Month",minval=1,maxval=12)
StopDay = input(31, "Backtest Stop Day",minval=1,maxval=31)
testPeriodStop = timestamp(StopYear,StopMonth,StopDay,0,0)

testPeriod() => true


//////////////////////////
//* Profit Component *//
//////////////////////////

input_tp_pips = input(600, "Backtest Profit Goal (in USD)",minval=0)
input_sl_pips = input(300, "Backtest STOP Goal (in USD)",minval=0)


tp = buy_trend? long_entry_price + input_tp_pips : short_entry_price - input_tp_pips
sl = buy_trend? long_entry_price - input_sl_pips : short_entry_price + input_sl_pips


long_TP_exit  = buy_trend and high >= tp
short_TP_exit = sell_trend and low <= tp

plot(tp, title="TP", style=plot.style_circles, linewidth=3, color=color.blue)
plot(sl, title="SL", style=plot.style_circles, linewidth=3, color=color.red)

if testPeriod()
    strategy.entry("Long", 1, when=isLong)
    strategy.close("Long", when=longClose )
    strategy.exit("XL","Long", limit=tp,  when=buy_trend, stop=sl)


if testPeriod()
    strategy.entry("Short", 0,  when=isShort)
    strategy.close("Short", when=shortClose )
    strategy.exit("XS","Short", when=sell_trend, limit=tp, stop=sl)


Thêm nữa