멀티타임프레임 트렌드 헌터 전략 (Multitimeframe Trend Hunter Strategy) 은 자동 거래 신호를 생성하기 위해 여러 지표를 활용하는 전략이다. 이 전략은 트렌드 방향을 결정하고 잠재적 인 거래 기회를 발견하기 위해 여러 시간 프레임에 걸쳐 이동 평균, 슈퍼 트렌드 지표, 이치모쿠 클라우드 및 기타를 포함합니다.
이 전략의 핵심 논리는 높은 및 낮은 시간 프레임에서 동시다발적으로 트렌드 방향을 판단하는 것입니다. 전략은 먼저 높은 시간 프레임에서 주요 이동 평균, 슈퍼 트렌드 라인, 이치모쿠 변환 및 기본 라인 등을 계산합니다. 다음에는 낮은 시간 프레임에서 슈퍼 트렌드 라인을 계산합니다. 두 시간 프레임에서 슈퍼 트렌드 방향이 정렬되면 전체 트렌드 방향이 확인됩니다. 또한, 전략은 추세 신뢰성을 추가로 검증하기 위해 가격이 이동 평균 또는 이치모쿠 클라우드를 통과하는지 여부를 검사합니다.
특정 기준이 충족되면 전략은 구매 또는 판매 신호를 생성합니다. 사용자는 자신의 필요에 따라 장기 또는 단위 또는 둘 다만 거래를 선택할 수 있습니다. 사용자는 또한 이동 평균, 슈퍼 트렌드, 이치모쿠 등과 같은 매개 변수를 최적화하여 전략 성능을 향상시킬 수 있습니다.
이 전략의 가장 큰 장점은 여러 시간 프레임과 지표의 조합으로 트렌드 정확성을 크게 향상시키고 역전 기회를 적시에 감지합니다. 구체적인 장점은 다음과 같습니다.
주요 위험은 과도한 거래 또는 놓친 기회로 이어지는 잘못된 매개 변수 설정입니다. 지표의 잘못된 신호는 손실을 유발할 수도 있습니다. 특정 위험과 해결책:
이 전략을 최적화 할 수있는 더 많은 공간이 있습니다.
결론적으로, 멀티타임프레임 트렌드 헌터 전략은 트렌드를 결정하고 적시에 반전을 포착하기 위해 시간 프레임에 걸쳐 여러 지표를 활용합니다. 그것은 광범위한 응용 프로그램과 미래 최적화에 대한 많은 공간이있는 효과적인 양 거래 전략이며 양 거래자가 지속적으로 연구하고 적용하는 것이 가치가 있습니다.
/*backtest start: 2024-01-01 00:00:00 end: 2024-01-31 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/ //@version=5 strategy("TrendHunter [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. // Higher Time Frame Selection HTF_TimeFrame = input.timeframe(title='Higher Time Frame', defval='60', group = '== Timeframe ==', tooltip = "Select Chart for standard functionality") // 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 ==') Multiplier = input.float(title='ATR Multiplier', step=0.1, defval=3.0, group = '== Supertrend ==') Src = input.source(title='Source', defval=hl2, group = '== Supertrend ==') // Ichimoku conversionPeriods = input.int(9, minval=1, title='Conversion Line Periods', group = '== Ichimoku ==') basePeriods = input.int(26, minval=1, title='Base Line Periods', group = '== Ichimoku ==') laggingSpan2Periods = input.int(52, minval=1, title='Lagging Span 2 Periods', group = '== Ichimoku ==') displacement = input.int(26, minval=1, title='Displacement', group = '== Ichimoku ==') // Ichimoku Display Options isActiveConversion = input(false, 'Conversion Line', group = '== Ichimoku ==', inline = 'lines1') isActiveBase = input(false, 'Base Line', group = '== Ichimoku ==', inline = 'lines1') isActiveLagging = input(false, 'Lagging Span', group = '== Ichimoku ==', inline = 'lines2') isActiveCloud = input(true, 'Cloud', group = '== Ichimoku ==', inline = 'lines2') // ================ // Strategy Options // ================ bTable = input.bool(true, 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') bPriceCloudBody = input.bool(false, title='Full Body', group='== Strategy Options ==', inline='PriceCloud', tooltip = 'Only trade when price action outside the cloud.\nLongs when price action above the cloud.\nShort when price action below the cloud') bPriceEMA = input.bool(false, title='Price above/below EMA', group='== Strategy Options ==', inline='PriceEMA') bPriceEMABody = input.bool(false, title='Full Body', group='== Strategy Options ==', inline='PriceEMA', tooltip = 'Longs when price action above the EMA.\nShort when price action below the EMA') bSuper = input.bool(true, title='Supertrend transistions', group='== Strategy Options ==', tooltip = "Trade in direction of the supertrend transitions") bLTF = input.bool(false, title='LTF/HTF Supertrend alignment', group='== Strategy Options ==', tooltip = "Utilise a dual supertrends, chart and defined higher time frame") 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") bExitHTFTrail = input.bool(true, title='Super Trend Exits: HTF', group='== Strategy Options ==', inline = 'Exits') bExitLTFTrail = input.bool(true, title='LTF', group='== Strategy Options ==', inline = 'Exits', tooltip = 'Exit trades when price crosses the supertrend line\nIf neither selected trade closes when opposite trade opens\nIf using LTF closes turn on HTF/LTF alignment') // =========================== // EMA Functions and Plotting // =========================== // Calculate EMA ema = ta.ema(close, len) emaSmooth = request.security(syminfo.tickerid, HTF_TimeFrame, 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] // Calculate SuperTrend for the current time frame [up, dn, trend] = calcSuperTrend(Src, Periods, Multiplier) // Plotting for the current time frame plot(trend == 1 ? up : dn, title='LTF Supertrend', color=trend == 1 ?color.green : color.red, linewidth=1, style = plot.style_stepline) // Fetching the higher time frame data [HTF_up, HTF_dn, HTF_trend] = request.security(syminfo.tickerid, HTF_TimeFrame, 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(HTF_TimeFrame) // ————— 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') // =============================== // Strategy Entries // =============================== // Checks whether price is inside the Ichimoku cloud f_PriceCloud(dir) => _enter = false if bPriceCloud if bLong and dir == 1 if bPriceCloudBody _enter := close > math.max(SSA[Displacement], SSB[Displacement]) and open > math.max(SSA[Displacement], SSB[Displacement]) else _enter := close > math.max(SSA[Displacement], SSB[Displacement]) if bShort and dir == 2 if bPriceCloudBody _enter := close < math.min(SSA[Displacement], SSB[Displacement]) and open < math.min(SSA[Displacement], SSB[Displacement]) else _enter := close < 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 if bPriceEMABody _enter := close > emaSmooth and open > emaSmooth else _enter := close > emaSmooth if bShort and dir == 2 if bPriceEMABody _enter := close < emaSmooth and open < emaSmooth else _enter := close < emaSmooth 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 LTF supertrend direction f_LTF(dir) => _enter = false if bLTF if bLong and dir == 1 _enter := trend == 1 and HTF_trend == 1 if bShort and dir == 2 _enter := trend == -1 and 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 // 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_LTF(dir)) and na(f_EMACloud1(dir)) and na(f_EMACloud2(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_LTF(dir)) and f_NATrue(f_EMACloud1(dir)) and f_NATrue(f_EMACloud2(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)) or (bExitLTFTrail and (close < up or trend == -1)) exitShort = (bExitHTFTrail and (close > HTF_dn or HTF_trend == 1)) or (bExitLTFTrail and (close > dn or 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 = 9, bgcolor=color.new(color.white, 50), border_width = 1) table.cell(tbl, 1, 0, "Selected") table.cell(tbl, 2, 0, "Long", bgcolor=na(bLong) ? color.gray : bShort ? color.rgb(4, 112, 8) : color.rgb(100, 7, 7)) table.cell(tbl, 3, 0, "Short", bgcolor=na(bShort) ? color.gray : bShort ? color.rgb(4, 112, 8) : color.rgb(100, 7, 7)) table.cell(tbl, 0, 1, "Entry") table.cell(tbl, 2, 1, str.tostring(longCondition), bgcolor=longCondition ? color.green : color.red) table.cell(tbl, 3, 1, str.tostring(shortCondition), bgcolor=shortCondition ? color.green : color.red) table.cell(tbl, 0, 3, "Price Cloud") table.cell(tbl, 1, 3, str.tostring(bPriceCloud), bgcolor=na(bPriceCloud) ? color.gray : bPriceCloud ? color.green : color.red) table.cell(tbl, 2, 3, str.tostring(f_PriceCloud(1)), bgcolor=na(f_PriceCloud(1)) ? color.gray : f_PriceCloud(1) ? color.green : color.red) table.cell(tbl, 3, 3, str.tostring(f_PriceCloud(2)), bgcolor=na(f_PriceCloud(2)) ? color.gray : f_PriceCloud(2) ? color.green : color.red) table.cell(tbl, 0, 4, "Price EMA") table.cell(tbl, 1, 4, str.tostring(bPriceEMA), bgcolor=na(bPriceEMA) ? color.gray : bPriceEMA ? color.green : color.red) table.cell(tbl, 2, 4, str.tostring(f_PriceEMA(1)), bgcolor=na(f_PriceEMA(1)) ? color.gray : f_PriceEMA(1) ? color.green : color.red) table.cell(tbl, 3, 4, str.tostring(f_PriceEMA(2)), bgcolor=na(f_PriceEMA(2)) ? color.gray : f_PriceEMA(2) ? color.green : color.red) table.cell(tbl, 0, 5, "SuperTrend") table.cell(tbl, 1, 5, str.tostring(bSuper), bgcolor=na(bSuper) ? color.gray : bSuper ? color.green : color.red) table.cell(tbl, 2, 5, str.tostring(f_Super(1)), bgcolor=na(f_Super(1)) ? color.gray : f_Super(1) ? color.green : color.red) table.cell(tbl, 3, 5, str.tostring(f_Super(2)), bgcolor=na(f_Super(2)) ? color.gray : f_Super(2) ? color.green : color.red) table.cell(tbl, 0, 6, "HTF/LTF") table.cell(tbl, 1, 6, str.tostring(bLTF), bgcolor=na(bLTF) ? color.gray : bLTF ? color.green : color.red) table.cell(tbl, 2, 6, str.tostring(f_LTF(1)), bgcolor=na(f_LTF(1)) ? color.gray : f_LTF(1) ? color.green : color.red) table.cell(tbl, 3, 6, str.tostring(f_LTF(2)), bgcolor=na(f_LTF(2)) ? color.gray : f_LTF(2) ? color.green : color.red) table.cell(tbl, 0, 7, "EMA Outside Cloud") table.cell(tbl, 1, 7, str.tostring(bEMACloud1), bgcolor=na(bEMACloud1) ? color.gray : bEMACloud1 ? color.green : color.red) table.cell(tbl, 2, 7, str.tostring(f_EMACloud1(1)), bgcolor=na(f_EMACloud1(1)) ? color.gray : f_EMACloud1(1) ? color.green : color.red) table.cell(tbl, 3, 7, str.tostring(f_EMACloud1(2)), bgcolor=na(f_EMACloud1(2)) ? color.gray : f_EMACloud1(2) ? color.green : color.red) table.cell(tbl, 0, 8, "EMA Above/Below Cloud") table.cell(tbl, 1, 8, str.tostring(bEMACloud2), bgcolor=na(bEMACloud2) ? color.gray : bEMACloud2 ? color.green : color.red) table.cell(tbl, 2, 8, str.tostring(f_EMACloud2(1)), bgcolor=na(f_EMACloud2(1)) ? color.gray : f_EMACloud2(1) ? color.green : color.red) table.cell(tbl, 3, 8, str.tostring(f_EMACloud2(2)), bgcolor=na(f_EMACloud2(2)) ? color.gray : f_EMACloud2(2) ? color.green : color.red)