Chiến lược theo xu hướng dựa trên sự đột phá trung bình động

Tác giả:ChaoZhang, Ngày: 2023-10-30 12:22:28
Tags:

img

Tổng quan

Ý tưởng cốt lõi của chiến lược này là theo dõi xu hướng bằng cách phát hiện sự đột phá của các đường trung bình động trên các khung thời gian cao hơn. Khi giá phá vỡ trên hoặc phá vỡ dưới đường trung bình động trên một khung thời gian cao hơn, nó báo hiệu sự khởi đầu tiềm năng của một xu hướng mới, cho phép các nhà giao dịch có vị trí phù hợp.

Chiến lược logic

Chiến lược được phát triển trong Pine Script và bao gồm các thành phần chính sau:

  1. Các đầu vào

    Định nghĩa thời gian tham số đầu vào là thời gian trung bình động, mặc định là 200; và khung thời gian là khung thời gian thanh, mặc định là D (các thanh hàng ngày).

  2. Trung bình di chuyển

    Tính toán trung bình động theo cấp số nhân (EMA) bằng cách sử dụng hàm ta.ema.

  3. Khám phá đột phá

    Xác định sự cố và sự cố bằng cách sử dụng các hàm ta.crossover và ta.crossunder.

  4. Kế hoạch tín hiệu

    Định hướng mũi tên lên và xuống trên các thanh khi xảy ra sự đột phá.

  5. Nhập và xuất thương

    Tham gia giao dịch trên tín hiệu đột phá và ra khỏi khi giá đạt khoảng cách dừng lỗ 2x.

Chiến lược này chủ yếu tận dụng khả năng theo dõi xu hướng của đường trung bình động trên các khung thời gian cao hơn. Nó thực hiện logic đột phá đơn giản cho giao dịch xu hướng, làm cho nó trở thành một chiến lược đột phá thông thường.

Phân tích lợi thế

Những lợi thế chính của chiến lược này bao gồm:

  1. Logic đơn giản, dễ hiểu và thành thạo.

  2. Chỉ phụ thuộc vào một chỉ số, với điều chỉnh tham số tối thiểu.

  3. Các tín hiệu đột phá có xu hướng phù hợp với xu hướng, tránh giao dịch quá mức.

  4. Các khung thời gian cao hơn thể hiện rõ các xu hướng chính mà không gây ồn.

  5. Kết hợp khung thời gian linh hoạt phục vụ các sản phẩm khác nhau.

  6. Dễ dàng mở rộng trên các sản phẩm, tránh rút đồng thời.

Phân tích rủi ro

Những rủi ro tiềm ẩn là:

  1. Các tín hiệu đột phá có thể trở thành tín hiệu sai, không thể lọc tiếng ồn thị trường hiệu quả.

  2. Không thể tận dụng các cơ hội ngắn hạn.

  3. Mất rất nhiều nếu xu hướng lớn sai.

  4. Sự không phù hợp khung thời gian giữa đường trung bình động và khung thời gian giao dịch có thể dẫn đến giao dịch quá mức hoặc mất lợi nhuận.

  5. Thiếu stop loss thời gian thực có thể dẫn đến tổn thất phóng đại.

Các giải pháp có thể bao gồm kết hợp với các chỉ số theo xu hướng, thêm các bộ lọc, rút ngắn thời gian giữ, thực hiện stop loss động v.v.

Cơ hội gia tăng

Chiến lược có thể được cải thiện trong các khía cạnh sau:

  1. Thêm các chỉ số theo xu hướng như MACD, KD để tăng độ tin cậy đột phá.

  2. Thêm các bộ lọc dựa trên khối lượng hoặc Bollinger Bands để tránh đột phá sai.

  3. Tối ưu hóa điều chỉnh tham số để phù hợp với thời gian giữ với chu kỳ xu hướng.

  4. Tích hợp stop loss thời gian thực để kiểm soát lỗ giao dịch duy nhất.

  5. Khám phá các kỹ thuật học máy để tối ưu hóa tham số động.

  6. Kiểm tra các kết hợp phân bổ tài sản khác nhau để tăng cường sự ổn định tổng thể.

Kết luận

Tóm lại, đây là một chiến lược đơn giản và thực tế để theo dõi xu hướng thông qua các đột phá trung bình động. Nó dễ hiểu và thực hiện, phục vụ như một chiến lược giới thiệu tốt cho giao dịch algo. Nhưng nó cũng có một số lỗ hổng cần phải được giải quyết thông qua sự kết hợp của các chỉ số, điều chỉnh tham số, dừng mất động v.v. Vẫn còn nhiều chỗ cho cải tiến và mở rộng.


/*backtest
start: 2023-09-29 00:00:00
end: 2023-10-29 00:00:00
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

// @version=5
// Open-Range-Breakout strategy
// No license. Free and Open Source.    

strategy('Strategy: ORB', shorttitle="ORB", overlay=true , currency=currency.NONE, initial_capital=100000)

// Inputs
period = input.int(defval=15, title="TimeRange", tooltip="The range in minutes (default: 15m)")
sessionInput = input(defval="0915-0930", title="Time Range", group="ORB settings", tooltip='What is the timeperiod (default 9:15AM to 9:30AM, exchange timezone')
hide = input.bool(defval = false, title="Hide ORB Range", group="ORB setting", tooltip = 'Hide the ORB range drawing')

// SL Related
slAtrLen = input.int(defval=14, title="ATR Period for placing SL", group="StopLoss settings")
showSLLines = input.bool(defval=false, title="Show SL lines in chart", tooltip="Show SL lines also as dotted lines in chart. Note: chart may look untidy.", group="StopLoss settings")

// Further Filtering
ignoreMementumVolume = input.bool(defval=false, title="Ignore Momentum & Volume", tooltip="Ignore Momentum & Volume to find out trades", group="Strengh Settings")
rsiLen = input.int(defval=14, title="Momentum Period", group="Strengh Settings", tooltip = 'To determine the momentum, RSI period is set default to 100')
rsiBullish = input.int(defval=50, step=1, title="Bullish Momentum", group="Strengh Settings", tooltip = 'Bullish Momentum, default set to RSI as 50')
rsiBearish = input.int(defval=50, step=1, title="Bearish Momentum", group="Strengh Settings", tooltip = 'Bearish Momentum, default set to RSI as 50')
volAvg = input.int(defval=20, step=1, title="Volume Average Period", group="Strengh Settings", tooltip = 'To calculate average volume, how many historical bars are considered. Default: 20.')
volThreshold = input.float(defval=1, step=0.1, title="Volume Strengh", group="Strengh Settings", tooltip = 'Multiplier: How big the current bar volume compared to average of last 20')

trendPeriod = input.int(defval=200, step=1, title="Trend Period", group="Trend Settings", tooltip = 'To calculate trend, what period is considered. Default: 200.')
hideTrend = input.bool(defval = false, title="Hide the trend line", group="Trend Settings", tooltip = 'Hide the trend')

hidePDHCL = input.bool(defval = false, title="Hide the PDHCL (prev day High Close Low range)", tooltip = 'Hide the Previous Day High, Close, Low lines')

hideTable = input.bool(defval = false, title="Hide the Summary Table", tooltip = 'Hide the summary table.')

// Trade related
rrRatio = input.float(title='Risk:Reward', step=0.1, defval=2.0, group="Trade settings")
endOfDay = input.int(defval=1500, title="Close all trades, default is 3:00 PM, 1500 hours (integer)", group="Trade settings")
mktAlwaysOn = input.bool(defval=true, title="Markets that never closed (Crypto, Forex, Commodity)", tooltip="Some markers never closes. For those cases, make this checked.", group="Trade settings")
lotSize = input.int(title='Lot Size', step=1, defval=1, group="Trade settings")

// Util method

is_newbar(res) => 
	timeframe.change(time(res)) != 0

// print table
printTable(txt) =>
    var table t = table.new(position.bottom_right, 1, 1)
    table.cell(t, 0, 0, txt, text_halign = text.align_left, bgcolor = color.lime)
	
// globals
t = time(timeframe.period, sessionInput + ":1234567") // everyday
in_session = not na(t)
is_first = in_session and not in_session[1]
is_end_session = in_session[1] and not in_session
green(open, close) => close > open ? true : false
red(open, close) => close < open ? true : false

var float orb_high = na
var float orb_low = na
if is_first
    orb_high := high
    orb_low := low
else
    orb_high := orb_high[1]
    orb_low := orb_low[1]
if high > orb_high and in_session
    orb_high := high
if low < orb_low and in_session
    orb_low := low

plot(hide ? na : orb_high, style=plot.style_line, color=orb_high[1] != orb_high ? na : color.green, title="ORB High", linewidth=2)
plot(hide ? na : orb_low, style=plot.style_line, color=orb_low[1] != orb_low ? na : color.red, title="ORB Low", linewidth=2)



// PDHCL (Previous Day High Close Low)
[dh,dl,dc] = request.security(syminfo.ticker, "D", [high[1],low[1], close[1]], lookahead=barmerge.lookahead_on)
plot(hidePDHCL ? na : dh, title="Prev High",  color=color.red,  linewidth=2, trackprice=true, show_last = 1)
plot(hidePDHCL ? na : dl, title="Prev Low",  color=color.green,  linewidth=2, trackprice=true, show_last = 1)
plot(hidePDHCL ? na : dc, title="Prev Close",  color=color.black,  linewidth=2, trackprice=true, show_last = 1)
plot(hidePDHCL ? na : ta.vwap(close), title="Prev VWAP",  color=color.fuchsia,  linewidth=2, trackprice=true, show_last = 1)

var l1 = label.new(bar_index, hidePDHCL ? na : dh, 'PDH', style=label.style_label_right)

// Previous Day WWAP


// For SL calculation
atr = ta.atr(slAtrLen)	
highestHigh = ta.highest(high, 7)
lowestLow = ta.lowest(low, 7)
longStop = showSLLines ? lowestLow - (atr * 1) : na
shortStop = showSLLines ? highestHigh + (atr * 1) : na
plot(longStop, title="Buy SL", color=color.green, style=plot.style_cross)
plot(shortStop, title="Sell SL", color=color.red, style=plot.style_cross)

// Momentum: rsi
rsi = ta.rsi(close, rsiLen)

// trend: EMA200
ema = ta.ema(close, trendPeriod)
plot(hideTrend ? na : ema, "EMA Trend", color=close > ema ? color.green : color.red, linewidth = 1)

// Volume-Weighed Moving Average calculation
vwmaAvg = ta.vwma(close, volAvg)
vwma_latest = volume
// plotshape((barstate.isconfirmed and (vwma_latest > (vwmaAvg * volThreshold))), title='VolumeData', text='', location=location.abovebar, style=shape.diamond, color=color.gray, textcolor=color.gray, size=size.tiny)

// Trade signals

longCond = barstate.isconfirmed and (ta.crossover(close, orb_high) or ta.crossover(close, dh)) and green(open, close) and (ignoreMementumVolume ? true : rsi > rsiBullish and (vwma_latest > (vwmaAvg * volThreshold)))
shortCond = barstate.isconfirmed and (ta.crossunder(close, orb_low) or ta.crossunder(close, dl)) and red(open, close) and (ignoreMementumVolume ? true : rsi < rsiBearish and (vwma_latest > (vwmaAvg * volThreshold)))

plotshape(longCond, title='Breakout', text='BO', location=location.belowbar, style=shape.triangleup, color=color.green, textcolor=color.green)
plotshape(shortCond, title='Breakout', text='BD', location=location.abovebar, style=shape.triangledown, color=color.red, textcolor=color.red)


// Trade execute
h = hour(time('1'), syminfo.timezone)
m = minute(time('1'), syminfo.timezone)
hourVal = h * 100 + m
totalTrades = strategy.opentrades + strategy.closedtrades
if (mktAlwaysOn or (hourVal < endOfDay))
    // Entry
    var float sl = na
    var float target = na
    if (longCond)
        strategy.entry("enter long", strategy.long, lotSize, limit=na, stop=na, comment="Enter Long")
        sl := longStop
        target := close + ((close - longStop) * rrRatio)
        alert('Buy:' + syminfo.ticker + ' ,SL:' + str.tostring(math.floor(sl)) + ', Target:' + str.tostring(target), alert.freq_once_per_bar)
    if (shortCond)
        strategy.entry("enter short", strategy.short, lotSize, limit=na, stop=na, comment="Enter Short")
        sl := shortStop
        target := close - ((shortStop - close) * rrRatio)
        alert('Sell:' + syminfo.ticker + ' ,SL:' + str.tostring(math.floor(sl)) + ', Target:' + str.tostring(target), alert.freq_once_per_bar)

    // Exit: target or SL
    if ((close >= target) or (close <= sl))
        strategy.close("enter long", comment=close < sl ? "Long SL hit" : "Long target hit")
    if ((close <= target) or (close >= sl))
        strategy.close("enter short", comment=close > sl ? "Short SL hit" : "Short target hit")
else if (not mktAlwaysOn)
    // Close all open position at the end if Day
    strategy.close_all(comment = "Close all entries at end of day.")


// Plotting table
if (not hideTable and is_end_session)
    message =  syminfo.ticker + " :\n\nORB Upper: " + str.tostring(math.round(orb_high)) + "\nORB Lower: " + str.tostring(math.round(orb_low)) + "\nPDH: " + str.tostring(math.round(dh)) + "\nPDC: " + str.tostring(math.round(dc)) + "\nPDL: " + str.tostring(math.round(dl)) + "\nVWAP: " + str.tostring(math.round(ta.vwap(close)))   
    printTable(message)
    alert(message, alert.freq_once_per_bar_close)



Thêm nữa