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.
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:
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
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.
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ọ.
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.
Các lĩnh vực sau đây có thể được tối ưu hóa cho chiến lược này:
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
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.
Tối ưu hóa các phương pháp dừng lỗ để cải thiện hiệu quả.
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.
Thêm các chức năng tối ưu hóa tham số để điều chỉnh thích nghi.
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)