TrendHunter w/MF Chiến lược xu hướng nhiều khung thời gian

Tác giả:ChaoZhang, Ngày: 2024-03-15 16:01:54
Tags:

img

Tổng quan

Chiến lược xu hướng đa khung thời gian TrendHunter w/MF là một chiến lược theo xu hướng dựa trên phân tích toàn diện của nhiều chỉ số kỹ thuật trên nhiều khung thời gian. Chiến lược này tính đến các yếu tố như Ichimoku Cloud, Moving Averages, SuperTrend, WaveTrend và MoneyFlow, sử dụng các điều kiện nghiêm ngặt để xác định các điểm nhập cảnh và nắm bắt các xu hướng chính của thị trường.

Nguyên tắc chiến lược

Nguyên tắc cốt lõi của chiến lược này là phân tích toàn diện về nhiều chỉ số kỹ thuật trong nhiều khung thời gian.

  1. Ichimoku Cloud: Bằng cách phân tích vị trí tương đối của giá và đám mây, cũng như vị trí tương đối của đường trung bình động và đám mây, xu hướng thị trường hiện tại được xác định. Khi giá trên đám mây và đường trung bình động cũng trên đám mây, nó được coi là xu hướng tăng; nếu không, nó được coi là xu hướng giảm.

  2. SuperTrend: Bằng cách phân tích vị trí tương đối của giá và SuperTrend, xu hướng thị trường hiện tại được xác nhận. Khi giá vượt quá SuperTrend, nó được coi là xu hướng tăng; nếu không, nó được coi là xu hướng giảm.

  3. WaveTrend: Bằng cách phân tích hướng và vị trí của chỉ số WaveTrend, xu hướng thị trường hiện tại được xác định. Khi WaveTrend đang tăng và chưa đạt đến vùng mua quá mức, nó được coi là xu hướng tăng; khi WaveTrend đang giảm và chưa đạt đến vùng bán quá mức, nó được coi là xu hướng giảm.

  4. Dòng tiền: Bằng cách phân tích trạng thái của chỉ số Dòng tiền, xu hướng thị trường hiện tại được xác nhận. Khi Dòng tiền dương tính, nó được coi là xu hướng tăng; nếu không, nó được coi là xu hướng giảm.

Đối với các vị trí dài, chiến lược đòi hỏi giá phải ở trên đám mây, trung bình động ở trên đám mây, siêu xu hướng tăng, xu hướng sóng tăng và không ở trong vùng mua quá mức, và dòng tiền tích cực. Điều ngược lại áp dụng cho các vị trí ngắn. Việc lọc chặt chẽ dựa trên nhiều chỉ số trên nhiều khung thời gian có thể tránh giao dịch thường xuyên trên các thị trường giới hạn phạm vi, do đó cải thiện sự ổn định và độ tin cậy của chiến lược.

Phân tích lợi thế

  1. Phán quyết toàn diện dựa trên nhiều chỉ số, độ tin cậy cao: Chiến lược này xem xét toàn diện nhiều chỉ số kỹ thuật, bổ sung lẫn nhau trong các điều kiện thị trường khác nhau, cung cấp một sự phản ánh toàn diện về xu hướng thị trường và tránh các lỗi có thể xảy ra với một chỉ số duy nhất.

  2. Điều kiện nhập cảnh nghiêm ngặt, tránh giao dịch thường xuyên: Chiến lược đặt ra các điều kiện nhập cảnh nghiêm ngặt, yêu cầu nhiều chỉ số phải được đáp ứng đồng thời trước khi nhập vào một vị trí, có hiệu quả tránh giao dịch thường xuyên trên các thị trường giới hạn phạm vi và giảm sự cạn kiệt của chiến lược.

  3. Phân tích nhiều khung thời gian, nắm bắt xu hướng lớn: Chiến lược thực hiện phân tích trên nhiều khung thời gian, giúp chiến lược nắm bắt các xu hướng chính của thị trường từ góc độ rộng hơn, tránh sự can thiệp của tiếng ồn ngắn hạn.

  4. Chiến lược dừng lỗ rõ ràng, rủi ro có thể kiểm soát được: Chiến lược sử dụng SuperTrend như một điều kiện dừng lỗ. Một khi xu hướng thị trường thay đổi, chiến lược có thể dừng lỗ kịp thời, giữ lỗ trong phạm vi chấp nhận được.

Phân tích rủi ro

  1. Thiếu điều chỉnh năng động, khả năng đáp ứng với những thay đổi thị trường hạn chế: Các thiết lập tham số của chiến lược này là cố định và thiếu khả năng điều chỉnh năng động theo điều kiện thị trường. Khi điều kiện thị trường thay đổi đáng kể, chiến lược có thể thất bại.

  2. Các điều kiện nhập cảnh quá nghiêm ngặt có thể bỏ lỡ những cơ hội tốt: Các điều kiện nhập cảnh của chiến lược rất nghiêm ngặt, mặc dù nó có thể tránh giao dịch thường xuyên, nhưng cũng có thể dẫn đến chiến lược bỏ lỡ một số cơ hội nhập cảnh tốt.

  3. Không biết khả năng thích nghi với điều kiện thị trường cực đoan: Chiến lược hoạt động tốt trong điều kiện thị trường bình thường, nhưng khả năng thích nghi với một số điều kiện thị trường cực đoan, chẳng hạn như đảo ngược nhanh chóng và đáng kể, vẫn chưa được kiểm tra.

  4. Chiến lược stop-loss tương đối đơn giản, không gian tối ưu hóa: Hiện tại, chiến lược chỉ sử dụng SuperTrend như một điều kiện stop-loss. Mặc dù điều này đơn giản và đơn giản, nhưng có thêm không gian tối ưu hóa trong chiến lược stop-loss để kiểm soát tốt hơn rủi ro.

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

  1. Giới thiệu đánh giá điều kiện thị trường, điều chỉnh động các tham số: Xem xét việc giới thiệu một số chỉ số đánh giá điều kiện thị trường, chẳng hạn như chỉ số biến động, để điều chỉnh động các tham số chiến lược theo những thay đổi trong điều kiện thị trường để thích nghi với môi trường thị trường khác nhau.

  2. Tối ưu hóa các điều kiện nhập cảnh, cải thiện độ nhạy: Xem xét tối ưu hóa các điều kiện nhập cảnh, chẳng hạn như giới thiệu nhiều chỉ số xác nhận hơn, để cải thiện độ nhạy của chiến lược trong khi đảm bảo độ tin cậy, nắm bắt nhiều cơ hội giao dịch hơn.

  3. Thêm các biện pháp ứng phó cho các điều kiện thị trường cực đoan: Đối với một số điều kiện thị trường cực đoan, chẳng hạn như đảo ngược nhanh chóng và đáng kể, hãy xem xét việc đưa ra một số biện pháp ứng phó đặc biệt, chẳng hạn như tăng cường cường độ dừng lỗ hoặc đình chỉ giao dịch, để giảm rủi ro của chiến lược trong điều kiện thị trường cực đoan.

  4. Tối ưu hóa chiến lược dừng lỗ, cải thiện khả năng kiểm soát rủi ro: Xem xét giới thiệu nhiều điều kiện dừng lỗ hơn, chẳng hạn như dừng lỗ thời gian, dừng lỗ phạm vi, vv. Cũng xem xét giới thiệu một số chiến lược dừng lỗ năng động, chẳng hạn như dừng lỗ sau, để kiểm soát rủi ro tốt hơn.

Tóm lại

Chiến lược xu hướng đa khung thời gian TrendHunter w/MF là một chiến lược theo xu hướng dựa trên phân tích đa chỉ số, đa khung thời gian. Chiến lược này, thông qua việc xem xét toàn diện các yếu tố như Ichimoku Cloud, Moving Averages, SuperTrend, WaveTrend và MoneyFlow, cài đặt điều kiện nhập cảnh nghiêm ngặt và phân tích nhiều khung thời gian, có thể nắm bắt các xu hướng chính của thị trường tương đối đáng tin cậy, tránh giao dịch thường xuyên trên các thị trường giới hạn phạm vi, và có sự ổn định và độ tin cậy tốt.

Đồng thời, chiến lược này cũng có một số hạn chế và rủi ro, chẳng hạn như thiếu khả năng điều chỉnh năng động, các điều kiện nhập cảnh có khả năng quá nghiêm ngặt, khả năng thích nghi với điều kiện thị trường cực đoan không rõ, và một chiến lược dừng lỗ tương đối đơn giản.

Nhìn chung, TrendHunter w/MF Multi-Timeframe Trend Strategy là một chiến lược theo xu hướng với tiềm năng tốt. Khi sử dụng chiến lược này, các nhà giao dịch nên hiểu đầy đủ các nguyên tắc, lợi thế và rủi ro của nó và thực hiện các điều chỉnh và tối ưu hóa cần thiết theo sở thích rủi ro và phong cách giao dịch của riêng họ. Đồng thời, họ cũng nên theo dõi chặt chẽ những thay đổi trong điều kiện thị trường và điều chỉnh chiến lược một cách kịp thời để thích nghi với những thay đổi trên thị trường. Chỉ dựa trên sự hiểu biết sâu sắc và sử dụng thận trọng, chiến lược này có thể phát huy đầy đủ những lợi thế tiềm năng của nó và mang lại lợi nhuận ổn định cho các nhà giao dịch.


/*backtest
start: 2024-02-01 00:00:00
end: 2024-02-29 23:59:59
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © godzcopilot / blockybears

// Thanks to anthonyf50 for his MTF Ichimoku https://www.tradingview.com/script/Pw9cBFma/
// Thanks to KivancOzbilgic for his SuperTrend https://www.tradingview.com/script/r6dAP7yi/
// Thanks to ZenAndTheArtOfTrading / PineScriptMastery for their Higher Timeframe EMA https://www.tradingview.com/script/Vh3XG9sD-Higher-Timeframe-EMA/
//  Thanks to LazyBear for WaveTrend Oscillator https://www.tradingview.com/script/2KE8wTuF-Indicator-WaveTrend-Oscillator-WT/
//  Thanks to andreholanda73 for MFI+RSI Area https://www.tradingview.com/script/UlGZzUAr/

//@version=5
strategy("TrendHunter w/MF [Blocky]", overlay=true, default_qty_type=strategy.percent_of_equity, default_qty_value=80, initial_capital=1000, pyramiding=0)

// ================
// Strategy Inputs
// ================

// Defines user inputs for configuring the strategy.

// Inputs for EMA
len     = input.int(title="EMA Length", defval=200, group ='== EMA ==')
col     = input.bool(title="Colour EMA", defval=true, group ='== EMA ==')

// SuperTrend
Periods = input(title='ATR: Period', defval=10, group = '== Supertrend ==', inline = 'atr')
Multiplier = input.float(title='Mult', step=0.1, defval=3.0, group = '== Supertrend ==', inline = 'atr')
Src = input.source(title='Src', defval=hl2, group = '== Supertrend ==', inline = 'atr')

// Ichimoku
conversionPeriods = input.int(9, minval=1, title='Conversion', group = '== Ichimoku ==', inline = 'ich1')
basePeriods = input.int(26, minval=1, title='Base', group = '== Ichimoku ==', inline = 'ich1')
laggingSpan2Periods = input.int(52, minval=1, title='Lagging', group = '== Ichimoku ==', inline = 'ich2')
displacement = input.int(26, minval=1, title='Displacement', group = '== Ichimoku ==', inline = 'ich2')

// Ichimoku Display Options
isActiveConversion = input(false, 'Conversion', group = '== Ichimoku ==', inline = 'lines1')
isActiveBase = input(false, 'Base', group = '== Ichimoku ==', inline = 'lines1')
isActiveLagging = input(false, 'Lagging', group = '== Ichimoku ==', inline = 'lines1')
isActiveCloud = input(true, 'Cloud', group = '== Ichimoku ==', inline = 'lines1')


// Input for WaveTrend
n1 = input(9, 'Channel Length', group = '== WaveTrend ==', inline = 'wt1')
n2 = input(12, 'Average Length', group = '== WaveTrend ==', inline = 'wt1')

obLevel = input(60, 'Over Bought', group = '== WaveTrend ==', inline = 'wt2')
osLevel = input(-60, 'Over Sold', group = '== WaveTrend ==', inline = 'wt2')

// Input for Money Flow
rsiMFIperiod = input(60, 'Money Flow Length', group = '== Money Flow ==', inline = 'mf')
rsiMFIMultiplier = input(190, 'RSI+MFI Area multiplier', group = '== Money Flow ==', inline = 'mf')
MFRSIMA = input.string(defval='SMA', title='Money Flow MA Type', options=['RMA', 'SMA', 'EMA', 'WMA', 'VWMA'], group = '== Money Flow ==', inline = 'mf')


// ================
// Strategy Options
// ================

bTable = input.bool(false, title='Trade Table', group='== Strategy Options ==', tooltip = "Show table that shows current selected options and trade trade entry parameters")

bLong = input.bool(true, title='Enter Longs', group='== Strategy Options ==', inline = 'LongShort')
bShort = input.bool(true, title='Enter Shorts', group='== Strategy Options ==', inline = 'LongShort', tooltip = "Filter long / short trade signals")

bPriceCloud = input.bool(true, title='Price outside cloud', group='== Strategy Options ==', inline='PriceCloud')
priceActionOption = input.string(title="", defval="Close", options=["Close", "Candle Body", "Full Candle"], group = "== Strategy Options ==", inline='PriceCloud')

bPriceEMA = input.bool(false, title='Price above/below EMA', group='== Strategy Options ==', inline='PriceEMA')
priceEMAOption = input.string(title="", defval="Close", options=["Close", "Candle Body", "Full Candle"], group = "== Strategy Options ==", inline='PriceEMA')

bSuper = input.bool(true, title='Supertrend transistions', group='== Strategy Options ==', tooltip = "Trade in direction of the supertrend transitions")

bEMACloud1 = input.bool(true, title='EMA Outside Cloud', group='== Strategy Options ==', tooltip = "EMA must be outside the ichimoku cloud")
bEMACloud2 = input.bool(false, title='EMA above/below Cloud', group='== Strategy Options ==', tooltip = "Longs when EMA above the cloud.\nShort when EMA below the cloud")

bMFI = input.bool(false, title='Money Flow', group='== Strategy Options ==', tooltip = "Money Flow Green for Long\nMoney Flow Red for Short")
bWT = input.bool(false, title='Wavetrend', group='== Strategy Options ==', inline = 'WT')
bWTOB = input.bool(false, title='Overbought/sold', group='== Strategy Options ==', tooltip = "Longs when WT Rising\nShort when WT Falling\n\nRestrict entries if in overbough or oversold levels",inline = 'WT')

bExitHTFTrail = input.bool(true, title='Super Trend Exits', group='== Strategy Options ==', inline = 'Exits')


// ===========================
// EMA Functions and Plotting
// ===========================

// Calculate EMA
ema = ta.ema(close, len)
emaSmooth = request.security(syminfo.tickerid, "", ema[barstate.isrealtime ? 1 : 0], gaps=barmerge.gaps_on)[barstate.isrealtime ? 0 : 1]


// Draw EMA
plot(emaSmooth, color=col ? (close > emaSmooth ? color.rgb(76, 163, 175) : color.rgb(6, 23, 173)) : color.black, linewidth=2, title="HTF EMA")


// ==================================
// Supertrend Functions and Plotting
// ==================================

// Function to calculate SuperTrend
calcSuperTrend(src, atrPeriods, multiplier) =>
    atr = ta.atr(atrPeriods)
    up = src - multiplier * atr
    up1 = nz(up[1], up)
    up := close[1] > up1 ? math.max(up, up1) : up
    dn = src + multiplier * atr
    dn1 = nz(dn[1], dn)
    dn := close[1] < dn1 ? math.min(dn, dn1) : dn
    trend = 1
    trend := nz(trend[1], trend)
    trend := trend == -1 and close > dn1 ? 1 : trend == 1 and close < up1 ? -1 : trend
    [up, dn, trend]


// Fetching the higher time frame data
[HTF_up, HTF_dn, HTF_trend] = request.security(syminfo.tickerid, "", calcSuperTrend(hl2, Periods, Multiplier), lookahead=barmerge.lookahead_on)

// Plotting for the higher time frame
plot(HTF_trend == 1 ? HTF_up : HTF_dn, title='HTF Up Trend', color= HTF_trend == 1 ? color.green : color.red, linewidth=4)


// ===============================
// Ichimoku Functions and Plotting
// ===============================

// Function to convert timeframe to hours
f_convertTimeframeToHours(tf) =>
    val = 0.0
    if tf == "1S" or tf == "S"
        val := 1.0 / 3600.0
    else if str.contains(tf, "S")
        val := str.tonumber(str.replace(tf, "S", "")) / 3600.0
    else if tf == "1D" or tf == "D"
        val := 24.0
    else if str.contains(tf, "D")
        val := str.tonumber(str.replace(tf, "D", "")) * 24.0
    else if tf == "1W" or tf == "W"
        val := 24.0 * 7.0
    else if str.contains(tf, "W")
        val := str.tonumber(str.replace(tf, "W", "")) * 24.0 * 7.0
    else if tf == "1M" or tf == "M"
        val := 24.0 * 30.0  // Approximation for a month
    else if str.contains(tf, "M")
        val := str.tonumber(str.replace(tf, "M", "")) * 24.0 * 30.0  // Approximation for months
    else
        // Default to minutes
        val := str.tonumber(tf) / 60.0
    val

// Time
timeOffset = time - time[1]


// Returns the displacement based on the chart / HTF resolution
f_getDisplacement(_res) =>
    _res == '' ? displacement : math.round(f_convertTimeframeToHours(_res) / f_convertTimeframeToHours(timeframe.period) * displacement)
    //f_avgDilationOf(_res) * displacement

// Returns average value between lowest and highest
f_avgLH(_len) =>
    math.avg(ta.lowest(_len), ta.highest(_len))

// Returns f_donchian data 
f_donchian(_tf, _src) =>
    request.security(syminfo.tickerid, _tf, _src, barmerge.gaps_off, barmerge.lookahead_on)

// Returns ichimoku data
f_ichimokuData(_tf) =>
    _isShow = _tf == '' or f_convertTimeframeToHours(_tf) >= f_convertTimeframeToHours(timeframe.period)
    _displacement = _isShow ? f_getDisplacement(_tf) : na
    _Conversion = _isShow ? f_donchian(_tf, f_avgLH(conversionPeriods)) : na
    _Base = _isShow ? f_donchian(_tf, f_avgLH(basePeriods)) : na
    _Lagging = _isShow ? f_donchian(_tf, close) : na
    _SSA = _isShow ? math.avg(_Conversion, _Base) : na
    _SSB = _isShow ? f_donchian(_tf, f_avgLH(laggingSpan2Periods)) : na
    _middleCloud = _isShow ? _SSA[0] > _SSB[0] ? _SSA[0] - math.abs(_SSA[0] - _SSB[0]) / 2 : _SSA[0] + math.abs(_SSA[0] - _SSB[0]) / 2 : na
    [_displacement, _Conversion, _Base, _Lagging, _SSA, _SSB, _middleCloud]

// Plotting ichimoku data

[Displacement, Conversion, Base, Lagging, SSA, SSB, fisrtMiddleCloud] = f_ichimokuData("")

// ————— Conversion
plot(isActiveConversion ? Conversion : na, color=color.new(color.blue, 0), title=' Conversion', linewidth=1)
// ————— Base
plot(isActiveBase ? Base : na, color=color.new(color.fuchsia, 0), title=' Base', linewidth=2)
// ————— Lagging
plot(isActiveLagging ? Lagging : na, offset=-Displacement, color=color.new(color.green, 0), title=' Lagging')

// ————— SSA + SSB
ssa = plot(isActiveCloud ? SSA : na, offset=Displacement, color=color.new(color.green, 0), title=' SSA', linewidth=1)
ssb = plot(isActiveCloud ? SSB : na, offset=Displacement, color=color.new(color.red, 0), title=' SSB', linewidth=1)
fill(ssa, ssb, color=color.new(SSA > SSB ? color.green : color.red , 80), title=' Cloud')


// ===============================
// Makret Cypher Additions
// ===============================


// WaveTrend calculations
ap = hlc3
esa = ta.ema(ap, n1)
d = ta.ema(math.abs(ap - esa), n1)
ci = (ap - esa) / (0.015 * d)
tci = ta.ema(ci, n2)

wt1 = tci
wt2 = ta.sma(wt1, 3)

// WaveTrend plotting
//plot(0, color=color.rgb(120, 123, 134), title='Zero Line')
//plot(emaSmooth + wt1, color=color.rgb(191, 228, 255), style=plot.style_linebr, title='WaveTrend 1')
//plot(emaSmooth + wt2, color=color.rgb(56, 56, 56, 40), style=plot.style_linebr, title='WaveTrend 2')

// WaveTrend shapes
plotshape(ta.crossover(wt1, wt2) and wt2[2] < osLevel ? close : na, title='Pos Crossover', location=location.belowbar, style=shape.cross, size=size.small, color=color.rgb(63, 255, 0, 60))
plotshape(ta.crossover(wt2, wt1) and wt1[2] > osLevel ? close : na, title='Neg Crossover', location=location.abovebar, style=shape.cross, size=size.small, color=color.rgb(255, 82, 82, 60))
plotshape(ta.crossover(wt1, wt2) and osLevel ? close : na, title='Positive Crossover', location=location.belowbar, style=shape.triangleup, size=size.tiny, color=color.rgb(63, 255, 0, 60))
plotshape(ta.crossover(wt2, wt1) and obLevel ?  close : na, title='Negative Crossover', location=location.abovebar, style=shape.triangledown, size=size.tiny, color=color.rgb(255, 82, 82, 60))

// Function to determine WaveTrend direction and steepness
isWaveTrendUp() =>
    wt1Slope = wt1 - wt1[1]
    wt2Slope = wt2 - wt2[1]
    if wt1 > wt2 // wt1Slope > 0 and wt2Slope > 0
        1  // Both are going up
    else if wt1 < wt2 // wt1Slope < 0 and wt2Slope < 0
        2 // Both are going down
    else
        na  // Trends are not in the same direction



ma(matype, src, length) =>
    if matype == 'RMA'
        ta.rma(src, length)
    else
        if matype == 'SMA'
            ta.sma(src, length)
        else
            if matype == 'EMA'
                ta.ema(src, length)
            else
                if matype == 'WMA'
                    ta.wma(src, length)
                else
                    if matype == 'VWMA'
                        ta.vwma(src, length)
                    else
                        src

// Money Flow calculations
candleValue = (close - open) / (high - low)
MVC = ma(MFRSIMA, candleValue, rsiMFIperiod)
MVC := MVC * rsiMFIMultiplier
mfi_transp = math.abs(MVC) > 35 ? 0 : math.abs(MVC) > 30 ? 20 : math.abs(MVC) > 25 ? 30 : math.abs(MVC) > 20 ? 40 : math.abs(MVC) > 15 ? 50 : math.abs(MVC) > 10 ? 60 : math.abs(MVC) > 5 ? 65 : math.abs(MVC) > 2 ? 70 : 80
color_area = MVC > 0 ? color.rgb(76, 255, 80, mfi_transp) : color.rgb(255, 82, 82, mfi_transp)

// Money Flow plotting
// RSIMFIplot = plot(MVC * rsiMFIMultiplier, title='Money Flow', color=color_area, style=plot.style_area)
// fill(RSIMFIplot, plot(0), color_area)

plotshape(MVC > 0 ? true : na, title='MFI', location=location.top, style=shape.labeldown, size= size.tiny, color=color_area)
plotshape(MVC < 0 ? true : na, title='MFI', location=location.top, style= shape.labelup, size= size.tiny, color=color_area)




// ===============================
// Strategy Entries
// ===============================

// Checks whether price is inside the Ichimoku cloud
f_PriceCloud(dir) =>
    _enter = false
    if bPriceCloud
        if bLong and dir == 1
            _enter := switch priceActionOption
                "Close" => close > math.max(SSA[Displacement], SSB[Displacement])
                "Candle Body" => open > math.max(SSA[Displacement], SSB[Displacement]) and close > math.max(SSA[Displacement], SSB[Displacement])
                "Full Candle" => low > math.max(SSA[Displacement], SSB[Displacement]) and high > math.max(SSA[Displacement], SSB[Displacement]) 
        if bShort and dir == 2
            _enter := switch priceActionOption
                "Close" => close < math.min(SSA[Displacement], SSB[Displacement])
                "Candle Body" => open < math.min(SSA[Displacement], SSB[Displacement]) and close < math.min(SSA[Displacement], SSB[Displacement])
                "Full Candle" => low < math.min(SSA[Displacement], SSB[Displacement]) and high < math.min(SSA[Displacement], SSB[Displacement]) 
    else
        _enter := na
    _enter

// Checks whether price is above / below the ema
f_PriceEMA(dir) =>
    _enter = false
    if bPriceEMA
        if bLong and dir == 1
            _enter := switch priceEMAOption
                "Close" => close > math.max(SSA[Displacement], SSB[Displacement])
                "Candle Body" => open > math.max(SSA[Displacement], SSB[Displacement]) and close > math.max(SSA[Displacement], SSB[Displacement])
                "Full Candle" => low > math.max(SSA[Displacement], SSB[Displacement]) and high > math.max(SSA[Displacement], SSB[Displacement]) 
        if bShort and dir == 2
            _enter := switch priceEMAOption
                "Close" => close < math.min(SSA[Displacement], SSB[Displacement])
                "Candle Body" => open < math.min(SSA[Displacement], SSB[Displacement]) and close < math.min(SSA[Displacement], SSB[Displacement])
                "Full Candle" => low < math.min(SSA[Displacement], SSB[Displacement]) and high < math.min(SSA[Displacement], SSB[Displacement]) 
    else
        _enter := na
    _enter

// Checks HTF supertrend direction
f_Super(dir) =>
    _enter = false
    if bSuper
        if bLong and dir == 1
            _enter := HTF_trend == 1
        if bShort and dir == 2
            _enter := HTF_trend == -1
    else
        _enter := na

    _enter

// Checks whether ema is inside the Ichimoku cloud
f_EMACloud1(dir) =>
    _enter = false
    if bEMACloud1
        if bLong and dir == 1
            _enter := (emaSmooth > math.max(SSA[Displacement], SSB[Displacement])) or (emaSmooth < math.min(SSA[Displacement], SSB[Displacement]))
        if bShort and dir == 2
            _enter := (emaSmooth > math.max(SSA[Displacement], SSB[Displacement])) or (emaSmooth < math.min(SSA[Displacement], SSB[Displacement]))
    else
        _enter := na
    _enter

// Checks whether ema is above/below Ichimoku cloud
f_EMACloud2(dir) =>
    _enter = false
    if bEMACloud2
        if bLong and dir == 1
            _enter := emaSmooth > math.max(SSA[Displacement], SSB[Displacement])
        if bShort and dir == 2
            _enter := emaSmooth < math.min(SSA[Displacement], SSB[Displacement])
    else
        _enter := na
    _enter

// Checks whether moneyflow is positive
f_MFI(dir) =>
    _enter = false
    if bMFI
        if bLong and dir == 1
            _enter := MVC > 0
        if bShort and dir == 2
            _enter := MVC < 0
    else
        _enter := na
    _enter


// Checks whether wavetrend is rising or falling
f_WT(dir) =>
    _enter = false
    if bWT
        if bLong and dir == 1
            _enter := isWaveTrendUp() == dir
        if bShort and dir == 2
            _enter := isWaveTrendUp() == dir
    else
        _enter := na
    _enter


f_WTOB(dir) =>
    _enter = false
    if bWT and bWTOB
        if bLong and dir == 1
            _enter := wt1 < obLevel
        if bShort and dir == 2
            _enter := wt1 > osLevel
    else
        _enter := na
    _enter


// Check if a value is 'na' or true.
f_NATrue(val) =>
    _enter = false
    if na(val)
        _enter := true
    if val
        _enter := true
    _enter   
    

// Consolidates entry conditions.
f_checkCondition(dir) =>
    _enter = false
    if na(f_PriceCloud(dir)) and na(f_PriceEMA(dir)) and na(f_Super(dir)) and na(f_EMACloud1(dir)) and na(f_EMACloud2(dir)) and na(f_MFI(dir)) and na(f_WT(dir)) and na(f_WTOB(dir))
        _enter := false
    else if f_NATrue(f_PriceCloud(dir)) and f_NATrue(f_PriceEMA(dir)) and f_NATrue(f_Super(dir)) and f_NATrue(f_EMACloud1(dir)) and f_NATrue(f_EMACloud2(dir)) and f_NATrue(f_MFI(dir)) and f_NATrue(f_WT(dir)) and f_NATrue(f_WTOB(dir))
        _enter := true
    _enter

        
// Execute long trade entries
longCondition = bLong and f_checkCondition(1)
if (longCondition)
    strategy.entry("Long", strategy.long)

// Execute short trade entries
shortCondition = bShort and f_checkCondition(2)
if (shortCondition)
    strategy.entry("Short", strategy.short)

// Excute trade exits
exitLong = (bExitHTFTrail and (close < HTF_up or HTF_trend == -1))
exitShort = (bExitHTFTrail and (close > HTF_dn or HTF_trend == 1))

if exitLong
    strategy.close("Long")

if exitShort
    strategy.close("Short")

// Creates a table shoing all the user options and their current status for entering a trade
if bTable
    // Create a table
    tbl = table.new(position = position.bottom_right, columns = 4, rows = 11, bgcolor=color.new(color.black,100), border_width = 0, frame_width = 0)

    table.cell(tbl, 1, 0, "Selected", text_halign = text.align_center, text_size = size.small, text_color = color.rgb(207, 207, 207))
    table.cell(tbl, 2, 0, "Long", bgcolor=na(bLong) ? color.new(color.black,100) : bShort ? color.rgb(4, 112, 8) : color.rgb(100, 7, 7), text_halign = text.align_center, text_size = size.small, text_color = color.rgb(207, 207, 207))
    table.cell(tbl, 3, 0, "Short", bgcolor=na(bShort) ? color.new(color.black,100) : bShort ? color.rgb(4, 112, 8) : color.rgb(100, 7, 7), text_halign = text.align_center, text_size = size.small, text_color = color.rgb(207, 207, 207))

    table.cell(tbl, 0, 1, "Entry", text_halign = text.align_left, text_size = size.small, text_color = color.rgb(207, 207, 207))
    table.cell(tbl, 2, 1, longCondition  ? "✓" : "✗", bgcolor=longCondition ? color.green : color.red, text_halign = text.align_center, text_size = size.small, text_color = color.rgb(207, 207, 207))
    table.cell(tbl, 3, 1, shortCondition  ? "✓" : "✗", bgcolor=shortCondition ? color.green : color.red, text_halign = text.align_center, text_size = size.small, text_color = color.rgb(207, 207, 207))


    table.cell(tbl, 0, 3, "Price Cloud", text_halign = text.align_left, text_size = size.small, text_color = color.rgb(207, 207, 207))
    table.cell(tbl, 1, 3, bPriceCloud ? "✓" : "✗", bgcolor=na(bPriceCloud) ? color.new(color.black,100) : bPriceCloud ? color.green : color.red, text_halign = text.align_center, text_size = size.small, text_color = color.rgb(207, 207, 207))
    table.cell(tbl, 2, 3, f_PriceCloud(1) ? "✓" : "✗", bgcolor=na(f_PriceCloud(1)) ? color.new(color.black,100) : f_PriceCloud(1) ? color.green : color.red, text_halign = text.align_center, text_size = size.small, text_color = color.rgb(207, 207, 207))
    table.cell(tbl, 3, 3, f_PriceCloud(2)  ? "✓" : "✗", bgcolor=na(f_PriceCloud(2)) ? color.new(color.black,100) : f_PriceCloud(2) ? color.green : color.red, text_halign = text.align_center, text_size = size.small, text_color = color.rgb(207, 207, 207))

    table.cell(tbl, 0, 4, "Price EMA", text_halign = text.align_left, text_size = size.small, text_color = color.rgb(207, 207, 207))
    table.cell(tbl, 1, 4, bPriceEMA ? "✓" : "✗", bgcolor=na(bPriceEMA) ? color.new(color.black,100) : bPriceEMA ? color.green : color.red, text_halign = text.align_center, text_size = size.small, text_color = color.rgb(207, 207, 207))
    table.cell(tbl, 2, 4, f_PriceEMA(1) ? "✓" : "✗", bgcolor=na(f_PriceEMA(1)) ? color.new(color.black,100) : f_PriceEMA(1) ? color.green : color.red, text_halign = text.align_center, text_size = size.small, text_color = color.rgb(207, 207, 207))
    table.cell(tbl, 3, 4, f_PriceEMA(2) ? "✓" : "✗", bgcolor=na(f_PriceEMA(2)) ? color.new(color.black,100) : f_PriceEMA(2) ? color.green : color.red, text_halign = text.align_center, text_size = size.small, text_color = color.rgb(207, 207, 207))

    table.cell(tbl, 0, 5, "SuperTrend", text_halign = text.align_left, text_size = size.small, text_color = color.rgb(207, 207, 207))
    table.cell(tbl, 1, 5, bSuper ? "✓" : "✗", bgcolor=na(bSuper) ? color.new(color.black,100) : bSuper ? color.green : color.red, text_halign = text.align_center, text_size = size.small, text_color = color.rgb(207, 207, 207))
    table.cell(tbl, 2, 5, f_Super(1) ? "✓" : "✗", bgcolor=na(f_Super(1)) ? color.new(color.black,100) : f_Super(1) ? color.green : color.red, text_halign = text.align_center, text_size = size.small, text_color = color.rgb(207, 207, 207))
    table.cell(tbl, 3, 5, f_Super(2) ? "✓" : "✗", bgcolor=na(f_Super(2)) ? color.new(color.black,100) : f_Super(2) ? color.green : color.red, text_halign = text.align_center, text_size = size.small, text_color = color.rgb(207, 207, 207))

    table.cell(tbl, 0, 6, "EMA Outside Cloud", text_halign = text.align_left, text_size = size.small, text_color = color.rgb(207, 207, 207))
    table.cell(tbl, 1, 6, bEMACloud1 ? "✓" : "✗", bgcolor=na(bEMACloud1) ? color.new(color.black,100) : bEMACloud1 ? color.green : color.red, text_halign = text.align_center, text_size = size.small, text_color = color.rgb(207, 207, 207))
    table.cell(tbl, 2, 6, f_EMACloud1(1) ? "✓" : "✗", bgcolor=na(f_EMACloud1(1)) ? color.new(color.black,100) : f_EMACloud1(1) ? color.green : color.red, text_halign = text.align_center, text_size = size.small, text_color = color.rgb(207, 207, 207))
    table.cell(tbl, 3, 6, f_EMACloud1(2) ? "✓" : "✗", bgcolor=na(f_EMACloud1(2)) ? color.new(color.black,100) : f_EMACloud1(2) ? color.green : color.red, text_halign = text.align_center, text_size = size.small, text_color = color.rgb(207, 207, 207))

    table.cell(tbl, 0, 7, "EMA Above/Below Cloud", text_halign = text.align_left, text_size = size.small, text_color = color.rgb(207, 207, 207))
    table.cell(tbl, 1, 7, bEMACloud2 ? "✓" : "✗", bgcolor=na(bEMACloud2) ? color.new(color.black,100) : bEMACloud2 ? color.green : color.red, text_halign = text.align_center, text_size = size.small, text_color = color.rgb(207, 207, 207))
    table.cell(tbl, 2, 7, f_EMACloud2(1) ? "✓" : "✗", bgcolor=na(f_EMACloud2(1)) ? color.new(color.black,100) : f_EMACloud2(1) ? color.green : color.red, text_halign = text.align_center, text_size = size.small, text_color = color.rgb(207, 207, 207))
    table.cell(tbl, 3, 7, f_EMACloud2(2) ? "✓" : "✗", bgcolor=na(f_EMACloud2(2)) ? color.new(color.black,100) : f_EMACloud2(2) ? color.green : color.red, text_halign = text.align_center, text_size = size.small, text_color = color.rgb(207, 207, 207))

    table.cell(tbl, 0, 8, "Moneyflow", text_halign = text.align_left, text_size = size.small, text_color = color.rgb(207, 207, 207))
    table.cell(tbl, 1, 8, bMFI ? "✓" : "✗", bgcolor=na(bMFI) ? color.new(color.black,100) : bMFI ? color.green : color.red, text_halign = text.align_center, text_size = size.small, text_color = color.rgb(207, 207, 207))
    table.cell(tbl, 2, 8, f_MFI(1) ? "✓" : "✗", bgcolor=na(f_MFI(1)) ? color.new(color.black,100) : f_MFI(1) ? color.green : color.red, text_halign = text.align_center, text_size = size.small, text_color = color.rgb(207, 207, 207))
    table.cell(tbl, 3, 8, f_MFI(2) ? "✓" : "✗", bgcolor=na(f_MFI(2)) ? color.new(color.black,100) : f_MFI(2) ? color.green : color.red, text_halign = text.align_center, text_size = size.small, text_color = color.rgb(207, 207, 207))

    table.cell(tbl, 0, 9, "WaveTrend", text_halign = text.align_left, text_size = size.small, text_color = color.rgb(207, 207, 207))
    table.cell(tbl, 1, 9, bWT ? "✓" : "✗", bgcolor=na(bWT) ? color.new(color.black,100) : bWT ? color.green : color.red, text_halign = text.align_center, text_size = size.small, text_color = color.rgb(207, 207, 207))
    table.cell(tbl, 2, 9, f_WT(1) ? "✓" : "✗", bgcolor=na(f_WT(1)) ? color.new(color.black,100) : f_WT(1) ? color.green : color.red, text_halign = text.align_center, text_size = size.small, text_color = color.rgb(207, 207, 207))
    table.cell(tbl, 3, 9, f_WT(2) ? "✓" : "✗", bgcolor=na(f_WT(2)) ? color.new(color.black,100) : f_WT(2) ? color.green : color.red, text_halign = text.align_center, text_size = size.small, text_color = color.rgb(207, 207, 207))

    table.cell(tbl, 0, 10, "Overbought/Sold  " + str.tostring(wt1, '#.#'), text_halign = text.align_left, text_size = size.small, text_color = color.rgb(207, 207, 207))
    table.cell(tbl, 1, 10, bWTOB ? "✓" : "✗", bgcolor=na(bWTOB) ? color.new(color.black,100) : bWTOB ? color.green : color.red, text_halign = text.align_center, text_size = size.small, text_color = color.rgb(207, 207, 207))
    table.cell(tbl, 2, 10, f_WTOB(1) ? "✓" : "✗", bgcolor=na(f_WTOB(1)) ? color.new(color.black,100) : f_WTOB(1) ? color.green : color.red, text_halign = text.align_center, text_size = size.small, text_color = color.rgb(207, 207, 207))
    table.cell(tbl, 3, 10, f_WTOB(2) ? "✓" : "✗", bgcolor=na(f_WTOB(2)) ? color.new(color.black,100) : f_WTOB(2) ? color.green : color.red, text_halign = text.align_center, text_size = size.small, text_color = color.rgb(207, 207, 207))


Thêm nữa