This overlay strategy plots a two-timeframe Ichimoku setup on the price chart, with Tenkan, Kijun, Chikou, and Kumo from a base higher timeframe and an optional highest-timeframe cloud.
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// https://www.tradingview.com/script/UhhFWEus-MTF-Ichimoku-Takazudo/
//@version=4
//@author=Takazudo
strategy("2Tier Ichimoku Pyramiding [Takazudo]",
pyramiding=2,
overlay=true,
default_qty_type=strategy.fixed,
initial_capital=0,
currency=currency.USD)
//============================================================================
// consts, inputs
//============================================================================
// colors
var COLOR_KIJUN = color.new(#fcb103, 20)
var COLOR_TENKAN = color.new(#f57f17, 20)
var COLOR_CHIKOU = color.new(#ffffff, 50)
var COLOR_KUMO_BASEHTF_BULL = color.new(#315F2E, 60)
var COLOR_KUMO_BASEHTF_BEAR = color.new(#802A1C, 60)
var COLOR_KUMO_HIGHESTTF_BULL = color.new(#1D4F8A, 60)
var COLOR_KUMO_HIGHESTTF_BEAR = color.new(#6B2B55, 60)
var COLOR_SENKOUA_BASEHTF = color.new(#315F2E, 30)
var COLOR_SENKOUB_BASEHTF = color.new(#802A1C, 30)
var COLOR_SENKOUA_HIGHESTTF = color.new(#1D4F8A, 30)
var COLOR_SENKOUB_HIGHESTTF = color.new(#6B2B55, 30)
var COLOR_CROSS_POINT_BULL = color.new(#315F2E, 20)
var COLOR_CROSS_POINT_BEAR = color.new(#802A1C, 20)
var COLOR_CHIKOU_CROSS_POINT_BULL = color.new(#315F2E, 20)
var COLOR_CHIKOU_CROSS_POINT_BEAR = color.new(#802A1C, 20)
var COLOR_CHIKOU_KUMO_BREAKOUT_BULL = color.new(#315F2E, 0)
var COLOR_CHIKOU_KUMO_BREAKOUT_BEAR = color.new(#802A1C, 0)
var COLOR_CHIKOU_HINT_BULL = color.new(#315F2E, 0)
var COLOR_CHIKOU_HINT_BEAR = color.new(#802A1C, 0)
var COLOR_SENKOU_CROSS_HINT_BULL = color.new(#315F2E, 0)
var COLOR_SENKOU_CROSS_HINT_BEAR = color.new(#802A1C, 0)
var COLOR_TENKAN_CROSS_BG = color.new(#f2931d, 90)
var COLOR_CHIKOU_BREAKOUT_BG = color.new(#656565, 90)
var COLOR_SENKOU_CROSS_BG = color.new(#7a73d8, 90)
var COLOR_GAP_KUMO = color.new(#FCC02C, 97)
var COLOR_RANGE_EDGE = color.new(#43A6F5, 30)
var COLOR_RESISTANCE_PRICE_LINE = color.new(#e0f64d, 20)
var COLOR_TRANSPARENT = color.new(#000000, 100)
// HTF
var _1 = input(true, "═════════ HTF ══════════")
var config_baseHtf = input("D", "Base Higher Timeframe", type = input.resolution)
var config_useHighestTf = input(true, "use Highest Timeframe (Kumo only)")
var config_highestTf= input("W", "Highest Timeframe", type = input.resolution)
var _2 = input(true, "═════════ Ichimoku ══════════")
var config_tenkanSen = input(9, minval=1, title="Tenkan-Sen Bars")
var config_kijunSen = input(26, minval=1, title="Kijun-Sen Bars")
var config_senkouSpanB = input(52, minval=1, title="Senkou-Span B Bars")
var config_chikouSpan = input(26, minval=1, title="Chikou-Span Offset")
var config_senkouSpan = input(26, minval=1, title="Senkou-Span Offset")
var _3 = input(true, "═════════ Smooth Line ══════════")
var config_useSmooth = input(true, "enable smooth line")
var config_smoothFactor = input(2, minval=2, title="smooth factor")
var _4 = input(true, "═════════ MTF stuff ══════════")
var config_autoSwitchToHtf = input(true, "avoid to refer lower resolution indicator")
var config_avoidTooHighResolution = input(true, "avoid to refer too high resolution indicator")
var config_useGapKumo = input(true, "use Gap Kumo")
var _5 = input(true, "═════════ etc ══════════")
var config_bullDetectBars = input(defval = 3, title = "bull detection min bar count", minval = 1)
var config_rangeDetectBars = input(defval = 200, title = "range detection bar count", minval = 1)
var config_recentBars = input(defval = 50, title = "recent bar count for SL", minval = 1)
var config_atrLength = input(4, title = "Trailing stop ATR Length")
var config_atrSlMult = input(1, title = "Trailing stop ATR Multiple factor", type=input.float)
var config_atrEntryPaddingMult = input(0.5, title = "Entry padding ATR Multiple factor", type=input.float)
var config_atrEntryPaddingLength = input(10, title = "Entry padding ATR Length")
var config_extraEntryStopDetectBars = input(defval = 10, title = "Pyramiding entry recent detect bar count", minval = 1)
var _6 = input(true, "═════════ Backtesting range ══════════")
// From Date Inputs
fromYear = input(defval = 2019, title = "From Year", minval = 1970)
fromMonth = input(defval = 1, title = "From Month", minval = 1, maxval = 12)
fromDay = input(defval = 1, title = "From Day", minval = 1, maxval = 31)
// To Date Inputs
toYear = input(defval = 2021, title = "To Year", minval = 1970)
toMonth = input(defval = 3, title = "To Month", minval = 1, maxval = 12)
toDay = input(defval = 10, title = "To Day", minval = 1, maxval = 31)
//============================================================================
// MTF Selection Framework
// http://www.pinecoders.com/faq_and_code/#other-intervals-mtf
//============================================================================
// ————— Converts current "timeframe.multiplier" plus the TF into minutes of type float.
f_resInMinutes() =>
_resInMinutes = timeframe.multiplier * (
timeframe.isseconds ? 1. / 60. :
timeframe.isminutes ? 1. :
timeframe.isdaily ? 1440. :
timeframe.isweekly ? 10080. :
timeframe.ismonthly ? 43800. : na)
// ————— Returns resolution of _resolution period in minutes.
f_tfResInMinutes(_res) =>
// _res: resolution of any TF (in "timeframe.period" string format).
security(syminfo.tickerid, _res, f_resInMinutes())
// ————— Given current resolution, returns next step of HTF.
f_resNextStep(_res) =>
// _res: current TF in fractional minutes.
_res <= 1 ? "15" :
_res <= 5 ? "60" :
_res <= 30 ? "240" :
_res <= 60 ? "1D" :
_res <= 360 ? "3D" :
_res <= 1440 ? "1W" :
_res <= 10080 ? "1M" : "12M"
// ————— Returns a multiple of current resolution as a string in "timeframe.period" format usable with "security()".
f_multipleOfRes(_res, _mult) =>
// _res: current resolution in minutes, in the fractional format supplied by f_resInMinutes() companion function.
// _mult: Multiple of current TF to be calculated.
// Convert current float TF in minutes to target string TF in "timeframe.period" format.
_targetResInMin = _res * max(_mult, 1)
// Find best string to express the resolution.
_targetResInMin <= 0.083 ? "5S" :
_targetResInMin <= 0.251 ? "15S" :
_targetResInMin <= 0.501 ? "30S" :
_targetResInMin <= 1440 ? tostring(round(_targetResInMin)) :
_targetResInMin <= 43800 ? tostring(round(min(_targetResInMin / 1440, 365))) + "D" :
tostring(round(min(_targetResInMin / 43800, 12))) + "M"
// ————— Converts a resolution expressed in float minutes into a string usable by "security()".
// See our FAQ & Code for an example of using this function: http://www.pinecoders.com/faq_and_code/#how-can-i-convert-a-resolution-in-float-minutes-into-a-string-usable-with-security
f_resFromMinutes(_minutes) =>
_minutes <= 0.0167 ? "1S" :
_minutes <= 0.0834 ? "5S" :
_minutes <= 0.2500 ? "15S" :
_minutes <= 0.5000 ? "30S" :
_minutes <= 1440 ? tostring(round(_minutes)) :
_minutes <= 43800 ? tostring(round(min(_minutes / 1440, 365))) + "D" :
tostring(round(min(_minutes / 43800, 12))) + "M"
// Returns the theoretical numbers of current chart bars in the given target HTF resolution (note that this number maybe very different from actual number on certain symbols).
f_theoreticalDilationOf(_res) =>
// _res: resolution of any TF (in "timeframe.period" string format).
f_tfResInMinutes(_res) / f_resInMinutes()
// Returns the average number of current chart bars in the given target HTF resolution (this reflects the dataset's history).
f_avgDilationOf(_res) =>
// _res: resolution of any TF (in "timeframe.period" string format).
b = barssince(change(time(_res)))
cumTotal = cum(b == 0 ? b[1] + 1 : 0)
cumCount = cum(b == 0 ? 1 : 0)
cumTotal / cumCount
// ————— Print a label at end of chart.
f_htfLabel(_txt, _y, _color, _offsetLabels) =>
_t = int(time + (f_resInMinutes() * _offsetLabels * 60000))
// Create the label on the dataset's first bar.
var _lbl = label.new(_t, _y, _txt, xloc.bar_time, yloc.price, #00000000, label.style_none, color.gray, size.large)
if barstate.islast
// Rather than delete and recreate the label on every realtime bar update,
// simply update the label's information; it's more efficient.
label.set_xy(_lbl, _t, _y)
label.set_text(_lbl, _txt)
label.set_textcolor(_lbl, _color)
// }
//============================================================================
// utils, setup
//============================================================================
// initialize
var tenkanLine_baseHtf = 0.0
var kijunLine_baseHtf = 0.0
var senkouALine_baseHtf = 0.0
var senkouBLine_baseHtf = 0.0
var tenkanLine_highestTf = 0.0
var kijunLine_highestTf = 0.0
var senkouALine_highestTf = 0.0
var senkouBLine_highestTf = 0.0
var gapKumo_high = 0.0
var gapKumo_low = 0.0
f_isUsingHtf() =>
_current = f_resInMinutes()
_target = f_tfResInMinutes(config_baseHtf)
_current < _target
f_isOverHtf() =>
_current = f_resInMinutes()
_target = f_tfResInMinutes(config_baseHtf)
_current > _target
f_isOverHighestTf() =>
_current = f_resInMinutes()
_target = f_tfResInMinutes(config_highestTf)
_current >= _target
f_shouldAvoidHighestTf(barsMultipiller) =>
// it the resolution was too high, requested candle sticks
// hit the limit of trading view.
// this function detects the limit
config_avoidTooHighResolution and barsMultipiller > 150
var useSmooth = f_isUsingHtf() and config_useSmooth
f_smooth(_series) =>
_f = config_smoothFactor
// Tricky part. the lines that refers higher Timeframe got zig-zag
// because the granularity of the value per bar is the same
// inside the higher timeframe's one bar length.
// This smooth factor blends the value with previous values using ema.
_smoothed = ema(ema(ema(_series, _f), _f), _f)
useSmooth ? _smoothed : _series
lostPositionsInPrevBar = strategy.position_size == 0 and (strategy.position_size[0] != strategy.position_size[1])
// remember entry price
var previousEntryPrice = hl2
//============================================================================
// entry quantity caliculation
// wider SL = less quantities
//============================================================================
f_calcQtyForInitialEntry(_percentage) =>
if _percentage < 1
10000
else if _percentage < 2
8000
else if _percentage < 3
6000
else
4000
f_calcQtyForExtraEntry(_percentage) =>
if _percentage < 1
5000
else if _percentage < 2
4000
else if _percentage < 3
3000
else
2000
//============================================================================
// candle actions
//============================================================================
f_isUpDoji() =>
fullPriceHeight = high-low
bodyPriceHeight = abs(close-open)
(bodyPriceHeight < fullPriceHeight * 1/7) and (max(open, close) > (low + (high-low) * 2/3))
f_isDownDoji() =>
fullPriceHeight = high-low
bodyPriceHeight = abs(close-open)
(bodyPriceHeight < fullPriceHeight * 1/7) and (min(open, close) < (high - (high-low) * 2/3))
f_isLastCandleUp() =>
result = false
(close > open) or f_isUpDoji()
f_isLastCandleDown() =>
result = false
(close < open) or f_isDownDoji()
//============================================================================
// Ichimoku calcs
//============================================================================
f_donchian(len) =>
avg(lowest(len), highest(len))
f_tenkan() =>
f_donchian(config_tenkanSen)
f_kijun() =>
f_donchian(config_kijunSen)
f_senkouA(_tenkan, _kijun) =>
avg(_tenkan, _kijun)
f_senkouB() =>
f_donchian(config_senkouSpanB)
barsMultipiller_baseHtf = f_isOverHtf() ? 1 : f_theoreticalDilationOf(config_baseHtf)
barsMultipiller_highestTf = f_isOverHighestTf() ? 1 : f_theoreticalDilationOf(config_highestTf)
shouldAvoidHighestTf = f_shouldAvoidHighestTf(barsMultipiller_highestTf)
f_calcUseHighestTf() =>
_result = true
if shouldAvoidHighestTf
_result := false
else
if config_useHighestTf
if f_isOverHighestTf()
_result := false
else
_result := true
_result
var useHighestTf = f_calcUseHighestTf()
senkouOffset = config_senkouSpan - 1
chikouOffset = -config_chikouSpan + 1
senkouOffset_baseHtf = round((config_senkouSpan - 1) * barsMultipiller_baseHtf)
chikouOffset_baseHtf = round((config_chikouSpan - 1) * barsMultipiller_baseHtf)
senkouOffsetForPlot_baseHtf = round(senkouOffset * barsMultipiller_baseHtf)
chikouOffsetForPlot_baseHtf = round(-chikouOffset_baseHtf)
senkouOffset_highestTf = useHighestTf ? round((config_senkouSpan - 1) * barsMultipiller_highestTf) : 0
chikouOffset_highestTf = useHighestTf ? round((config_chikouSpan - 1) * barsMultipiller_highestTf) : 0
senkouOffsetForPlot_highestTf = useHighestTf ? round(senkouOffset * barsMultipiller_highestTf) : 0
chikouOffsetForPlot_highestTf = useHighestTf ? round(-chikouOffset_highestTf) : 0
senkouSpanIndexDiff = senkouOffsetForPlot_highestTf - senkouOffsetForPlot_baseHtf
// not sure why but it says negative index was detected
if senkouSpanIndexDiff < 0
senkouSpanIndexDiff := 0
if not useHighestTf or not config_useGapKumo
senkouSpanIndexDiff := 0
f_calcIchimoku_baseHtf() =>
_useCurrentRes = config_autoSwitchToHtf and f_isOverHtf()
_tenkan = f_tenkan()
_kijun = f_kijun()
_senkouA = f_senkouA(_tenkan[0], _kijun[0])
_senkouB = f_senkouB()
_htfTenkan = _useCurrentRes ? _tenkan : security(syminfo.tickerid, config_baseHtf, _tenkan)
_htfKijun = _useCurrentRes ? _kijun : security(syminfo.tickerid, config_baseHtf, _kijun)
_htfSenkouA = _useCurrentRes ? _senkouA : security(syminfo.tickerid, config_baseHtf, _senkouA)
_htfSenkouB = _useCurrentRes ? _senkouB : security(syminfo.tickerid, config_baseHtf, _senkouB)
[_htfTenkan, _htfKijun, _htfSenkouA, _htfSenkouB]
f_calcIchimoku_highestTf() =>
_tenkan = f_tenkan()
_kijun = f_kijun()
_senkouA = f_senkouA(_tenkan[0], _kijun[0])
_senkouB = f_senkouB()
_highestTfTenkan = useHighestTf ? security(syminfo.tickerid, config_highestTf, _tenkan) : _tenkan
_highestTfKijun = useHighestTf ? security(syminfo.tickerid, config_highestTf, _kijun) : _kijun
_highestTfSenkouA = useHighestTf ? security(syminfo.tickerid, config_highestTf, _senkouA) : _senkouA
_highestTfSenkouB = useHighestTf ? security(syminfo.tickerid, config_highestTf, _senkouB) : _senkouB
[_highestTfTenkan, _highestTfKijun, _highestTfSenkouA, _highestTfSenkouB]
//--------------------------------------
// HTF Ichimoku values
[_htfTenkan, _htfKijun, _htfSenkouA, _htfSenkouB] = f_calcIchimoku_baseHtf()
tenkanLine_baseHtf := _htfTenkan
kijunLine_baseHtf := _htfKijun
senkouALine_baseHtf := _htfSenkouA
senkouBLine_baseHtf := _htfSenkouB
//--------------------------------------
// Highest TF Ichimoku values
[_highestTfTenkan, _highestTfKijun, _highestTfSenkouA, _highestTfSenkouB] = f_calcIchimoku_highestTf()
tenkanLine_highestTf := _highestTfTenkan
kijunLine_highestTf := _highestTfKijun
senkouALine_highestTf := _highestTfSenkouA
senkouBLine_highestTf := _highestTfSenkouB
f_calcIchimokuSignals_baseHtf() =>
var _chikouAboveCandle = false
var _chikouBelowCandle = false
var _chikouAboveKumo = false
var _chikouBelowKumo = false
_kumoColor_bull = senkouALine_baseHtf > senkouBLine_baseHtf
_senkouCross_bull = crossover(senkouALine_baseHtf, senkouBLine_baseHtf)
_senkouCross_bear = crossover(senkouBLine_baseHtf, senkouALine_baseHtf)
_senkouSpanHigh = max(senkouALine_baseHtf[senkouOffset_baseHtf], senkouBLine_baseHtf[senkouOffset_baseHtf])
_senkouSpanLow = min(senkouALine_baseHtf[senkouOffset_baseHtf], senkouBLine_baseHtf[senkouOffset_baseHtf])
_chikouKumoHigh = max(senkouALine_baseHtf[senkouOffset_baseHtf+chikouOffset_baseHtf], senkouBLine_baseHtf[senkouOffset_baseHtf+chikouOffset_baseHtf])
_chikouKumoLow = min(senkouALine_baseHtf[senkouOffset_baseHtf+chikouOffset_baseHtf], senkouBLine_baseHtf[senkouOffset_baseHtf+chikouOffset_baseHtf])
_tenkanCross_bull = crossover(tenkanLine_baseHtf, kijunLine_baseHtf)
_tenkanCross_bear = crossover(kijunLine_baseHtf, tenkanLine_baseHtf)
_tenkanAboveKijun = tenkanLine_baseHtf > kijunLine_baseHtf
_tenkanBelowKijun = tenkanLine_baseHtf < kijunLine_baseHtf
_chikouAboveCandle := close > close[chikouOffset_baseHtf]
_chikouBelowCandle := close < close[chikouOffset_baseHtf]
_chikouCross_bull = _chikouAboveCandle and not _chikouAboveCandle[1]
_chikouCross_bear = _chikouBelowCandle and not _chikouBelowCandle[1]
_chikouAboveKumo := close > _chikouKumoHigh
_chikouBelowKumo := close < _chikouKumoLow
_currentInKumo = (_senkouSpanLow <= close) and (close <= _senkouSpanHigh)
_currentTouchingKumo = not _currentInKumo and
(((low <= _senkouSpanHigh) and (low >= _senkouSpanLow)) or
((high >= _senkouSpanLow) and (high <= _senkouSpanHigh)))
_currentAboveKumo = close > _senkouSpanHigh
_currentBelowKumo = close < _senkouSpanLow
_chikouInKumo = (_chikouKumoLow <= close) and (close <= _chikouKumoHigh)
_chikouTouchingKumo = not _chikouInKumo and
(((low <= _chikouKumoHigh) and (low >= _chikouKumoLow)) or
((high >= _chikouKumoLow) and (high <= _chikouKumoHigh)))
_chikouKumoBreakout_bull = _chikouAboveKumo and not _chikouAboveKumo[1]
_chikouKumoBreakout_bear = _chikouBelowKumo and not _chikouBelowKumo[1]
[_currentInKumo, _currentTouchingKumo, _kumoColor_bull, _senkouCross_bull, _senkouCross_bear,
_senkouSpanHigh, _senkouSpanLow,
_chikouKumoHigh, _chikouKumoLow,
_chikouAboveCandle, _chikouBelowCandle,
_tenkanCross_bull, _tenkanCross_bear,
_tenkanAboveKijun, _tenkanBelowKijun,
_chikouCross_bull, _chikouCross_bear,
_chikouAboveKumo, _chikouBelowKumo,
_chikouKumoBreakout_bull, _chikouKumoBreakout_bear,
_currentAboveKumo, _currentBelowKumo,
_chikouInKumo, _chikouTouchingKumo]
f_calcIchimokuSignals_highestTf() =>
var _chikouAboveCandle = false
var _chikouBelowCandle = false
var _chikouAboveKumo = false
var _chikouBelowKumo = false
_kumoColor_bull = senkouALine_highestTf > senkouBLine_highestTf
_senkouCross_bull = crossover(senkouALine_highestTf, senkouBLine_highestTf)
_senkouCross_bear = crossover(senkouBLine_highestTf, senkouALine_highestTf)
_senkouSpanCurrentHigh = max(senkouALine_highestTf[senkouOffset_highestTf], senkouBLine_highestTf[senkouOffset_highestTf])
_senkouSpanCurrentLow = min(senkouALine_highestTf[senkouOffset_highestTf], senkouBLine_highestTf[senkouOffset_highestTf])
_chikouKumoHigh = max(senkouALine_highestTf[senkouOffset_highestTf+chikouOffset_highestTf], senkouBLine_highestTf[senkouOffset_highestTf+chikouOffset_highestTf])
_chikouKumoLow = min(senkouALine_highestTf[senkouOffset_highestTf+chikouOffset_highestTf], senkouBLine_highestTf[senkouOffset_highestTf+chikouOffset_highestTf])
_tenkanCross_bull = crossover(tenkanLine_highestTf, kijunLine_highestTf)
_tenkanCross_bear = crossover(kijunLine_highestTf, tenkanLine_highestTf)
_chikouAboveCandle := close > close[chikouOffset_highestTf]
_chikouBelowCandle := close < close[chikouOffset_highestTf]
_chikouCross_bull = _chikouAboveCandle and not _chikouAboveCandle[1]
_chikouCross_bear = _chikouBelowCandle and not _chikouBelowCandle[1]
_chikouAboveKumo := close > _chikouKumoHigh
_chikouBelowKumo := close < _chikouKumoLow
_chikouKumoBreakout_bull = _chikouAboveKumo and not _chikouAboveKumo[1]
_chikouKumoBreakout_bear = _chikouBelowKumo and not _chikouBelowKumo[1]
_currentAboveKumo = close > _senkouSpanCurrentHigh
_currentBelowKumo = close < _senkouSpanCurrentLow
[_kumoColor_bull, _senkouCross_bull, _senkouCross_bear,
_senkouSpanCurrentHigh, _senkouSpanCurrentLow,
_chikouKumoHigh, _chikouKumoLow,
_chikouAboveCandle, _chikouBelowCandle,
_tenkanCross_bull, _tenkanCross_bear,
_chikouCross_bull, _chikouCross_bear,
_chikouAboveKumo, _chikouBelowKumo,
_chikouKumoBreakout_bull, _chikouKumoBreakout_bear,
_currentAboveKumo, _currentBelowKumo]
f_calcGapKumo(_tf1_senkouA, _tf1_senkouB, _tf2_senkouA, _tf2_senkouB) =>
_max = max(_tf1_senkouA, _tf1_senkouB, _tf2_senkouA, _tf2_senkouB)
_tf1IsHigher = (_tf1_senkouA == _max) or (_tf1_senkouB == _max)
_kumoA_max = _tf1IsHigher ? max(_tf1_senkouA, _tf1_senkouB) : max(_tf2_senkouA, _tf2_senkouB)
_kumoA_min = _tf1IsHigher ? min(_tf1_senkouA, _tf1_senkouB) : min(_tf2_senkouA, _tf2_senkouB)
_kumoB_max = _tf1IsHigher ? max(_tf2_senkouA, _tf2_senkouB) : max(_tf1_senkouA, _tf1_senkouB)
_kumoB_min = _tf1IsHigher ? min(_tf2_senkouA, _tf2_senkouB) : min(_tf1_senkouA, _tf1_senkouB)
_kumoCrossed = false
_gapKumo_high = max(_kumoA_max, _kumoB_max)
_gapKumo_low = _gapKumo_high
if _kumoA_max > _kumoB_max
if _kumoA_min < _kumoB_max
_kumoCrossed := true
else
_gapKumo_high := _kumoA_min
_gapKumo_low := _kumoB_max
else
if _kumoB_min < _kumoA_max
_kumoCrossed := true
else
_gapKumo_high := _kumoB_min
_gapKumo_low := _kumoA_max
[_kumoCrossed, _gapKumo_high, _gapKumo_low]
//============================================================================
// calc Ichimoku values for plot
//============================================================================
//--------------------------------------
// HTF Ichimoku signals
[currentInKumo_baseHtf, _, kumoColor_bull_baseHtf, _, _,
senkouSpanHigh_baseHtf, senkouSpanLow_baseHtf,
_, _,
chikouAboveCandle_baseHtf, chikouBelowCandle_baseHtf,
_, _,
tenkanAboveKijun_baseHtf, tenkanBelowKijun_baseHtf,
_, _,
chikouAboveKumo_baseHtf, chikouBelowKumo_baseHtf,
_, _,
currentAboveKumo_baseHtf, currentBelowKumo_baseHtf,
_, _] = f_calcIchimokuSignals_baseHtf()
//--------------------------------------
// Highest TF Ichimoku signals
[kumoColor_bull_highestTf, senkouCross_bull_highestTf, senkouCross_bear_highestTf,
senkouSpanHigh_highestTf, senkouSpanLow_highestTf,
_, _,
_, _,
tenkanCross_bull_highestTf, tenkanCross_bear_highestTf,
chikouCross_bull_highestTf, chikouCross_bear_highestTf,
_, _,
chikouKumoBreakout_bull_highestTf, chikouKumoBreakout_bear_highestTf,
currentAboveKumo_highestTf, currentBelowKumo_highestTf] = f_calcIchimokuSignals_highestTf()
//--------------------------------------
// smooth lines
smooth_tenkanLine_baseHtf = f_smooth(tenkanLine_baseHtf)
smooth_kijunLine_baseHtf = f_smooth(kijunLine_baseHtf)
smooth_senkouALine_baseHtf = f_smooth(senkouALine_baseHtf)
smooth_senkouBLine_baseHtf = f_smooth(senkouBLine_baseHtf)
//smooth_tenkanLine_highestTf = f_smooth(tenkanLine_highestTf)
//smooth_kijunLine_highestTf = f_smooth(kijunLine_highestTf)
smooth_senkouALine_highestTf = f_smooth(senkouALine_highestTf)
smooth_senkouBLine_highestTf = f_smooth(senkouBLine_highestTf)
//--------------------------------------
// gap kumo
//max_bars_back(senkouALine_highestTf, 600)
//max_bars_back(senkouBLine_highestTf, 600)
[_, _gapKumo_high, _gapKumo_low] = f_calcGapKumo(
senkouALine_baseHtf,
senkouBLine_baseHtf,
senkouALine_highestTf[senkouSpanIndexDiff],
senkouBLine_highestTf[senkouSpanIndexDiff])
gapKumo_high := _gapKumo_high
gapKumo_low := _gapKumo_low
smooth_gapKumo_high = f_smooth(gapKumo_high)
smooth_gapKumo_low = f_smooth(gapKumo_low)
//============================================================================
// plot stuffs
//============================================================================
// gap kumo
val_gapKumo_high = useHighestTf and config_useGapKumo ? smooth_gapKumo_high : na
val_gapKumo_low = useHighestTf and config_useGapKumo ? smooth_gapKumo_low : na
plot_gapKumo_high = plot(val_gapKumo_high,
offset=senkouOffsetForPlot_baseHtf,
color=COLOR_TRANSPARENT,
transp=0,
linewidth=1,
title="Gap Kumo High")
plot_gapKumo_low = plot(val_gapKumo_low,
offset=senkouOffsetForPlot_baseHtf,
color=COLOR_TRANSPARENT,
transp=0,
linewidth=1,
title="Gap Kumo LOW")
fill(plot_gapKumo_high, plot_gapKumo_low,
color=COLOR_GAP_KUMO,
transp=0,
title="Gap Kumo")
// kumo HighestTF
plotVal_senkouA_highestTf = useHighestTf ? smooth_senkouALine_highestTf : na
plotVal_senkouB_highestTf = useHighestTf ? smooth_senkouBLine_highestTf : na
color_kumo_highestTf = kumoColor_bull_highestTf ? COLOR_KUMO_HIGHESTTF_BULL : COLOR_KUMO_HIGHESTTF_BEAR
plot_senkouA_highestTf = plot(plotVal_senkouA_highestTf,
offset=senkouOffsetForPlot_highestTf,
color=COLOR_SENKOUA_HIGHESTTF,
transp=0,
linewidth=1,
title="Highest TFSenkou-Span A")
plot_senkouB_highestTf = plot(plotVal_senkouB_highestTf,
offset=senkouOffsetForPlot_highestTf,
color=COLOR_SENKOUB_HIGHESTTF,
transp=0,
linewidth=1,
title="Highest TFSenkou-Span B")
fill(plot_senkouA_highestTf, plot_senkouB_highestTf,
color=color_kumo_highestTf,
transp=0,
title="Highest TF Kumo")
// kumo HTF
color_kumo_baseHtf = kumoColor_bull_baseHtf ? COLOR_KUMO_BASEHTF_BULL : COLOR_KUMO_BASEHTF_BEAR
plot_senkouA_baseHtf = plot(smooth_senkouALine_baseHtf,
offset=senkouOffsetForPlot_baseHtf,
color=COLOR_SENKOUA_BASEHTF,
transp=0,
linewidth=1,
title="Base HTF: Senkou-Span A")
plot_senkouB_baseHtf = plot(smooth_senkouBLine_baseHtf,
offset=senkouOffsetForPlot_baseHtf,
color=COLOR_SENKOUB_BASEHTF,
transp=0,
linewidth=1,
title="Base HTF: Senkou-Span B")
fill(plot_senkouA_baseHtf, plot_senkouB_baseHtf,
color=color_kumo_baseHtf,
transp=0,
title="Base HTF Kumo")
// chikou
plot(close,
offset=chikouOffsetForPlot_baseHtf,
color=COLOR_CHIKOU,
linewidth=1,
transp=0,
title="Chikou-Span")
// tenkan & kijun
plot(smooth_tenkanLine_baseHtf,
color=COLOR_TENKAN,
linewidth=1,
transp=0,
title="Tenkan-Sen")
plot(smooth_kijunLine_baseHtf,
color=COLOR_KIJUN,
linewidth=3,
transp=0,
title="Kijun-Sen")
//============================================================================
// backtest duration
//============================================================================
// Calculate start/end date and time condition
startDate = timestamp(fromYear, fromMonth, fromDay, 00, 00)
finishDate = timestamp(toYear, toMonth, toDay, 00, 00)
//============================================================================
// bullish / bearish detection
//============================================================================
var bullish = false
var bearish = false
// detect bullish or bearish by many incidents
bullish := kumoColor_bull_baseHtf and chikouAboveCandle_baseHtf and
tenkanAboveKijun_baseHtf and chikouAboveKumo_baseHtf and
currentAboveKumo_baseHtf and currentAboveKumo_highestTf
bearish := not kumoColor_bull_baseHtf and chikouBelowCandle_baseHtf and
tenkanBelowKijun_baseHtf and chikouBelowKumo_baseHtf and
currentBelowKumo_baseHtf and currentBelowKumo_highestTf
// calc continuous bullish or bearish
f_isContinuousBull() =>
inTrend = 0
for i = 0 to (config_bullDetectBars-1)
if bullish[i]
inTrend := inTrend + 1
inTrend == config_bullDetectBars
f_isContinuousBear() =>
inTrend = 0
for i = 0 to (config_bullDetectBars-1)
if bearish[i]
inTrend := inTrend + 1
inTrend == config_bullDetectBars
continuousBull = f_isContinuousBull()
continuousBear = f_isContinuousBear()
//============================================================================
// MACD
//============================================================================
f_isMacdUpTrend() =>
[_macdLine, _signalLine, _] = macd(close, 12, 26, 9)
_upTrend = _macdLine > _signalLine
// calc macd for entry
macdUpTrend = f_isMacdUpTrend()
macdDownTrend = not macdUpTrend
//============================================================================
// recent high / low
//============================================================================
f_calcRecentHigh() =>
startIndex = 1
highest = max(open[startIndex], close[startIndex])
for i = startIndex to (config_recentBars - 1)
current = max(open[i], close[i])
if highest < current
highest := current
highest
f_calcRecentLow() =>
startIndex = 1
lowest = min(open[startIndex], close[startIndex])
for i = startIndex to (config_recentBars - 1)
current = min(open[i], close[i])
if lowest > current
lowest := current
lowest
recentHigh = f_calcRecentHigh()
recentLow = f_calcRecentLow()
//============================================================================
// ATR based stuff
//============================================================================
entryPadding = config_atrEntryPaddingMult * atr(config_atrEntryPaddingLength)
sl_val = config_atrSlMult * atr(config_atrLength)
atrSl_long = low - sl_val
atrSl_short = high + sl_val
//============================================================================
// Kumo based SL
//============================================================================
kumoBasedSlLong = (senkouSpanHigh_baseHtf + atrSl_long) / 2
kumoBasedSlShort = (senkouSpanLow_baseHtf + atrSl_short) / 2
//============================================================================
// Mixed SL
//============================================================================
var initialEntryTpPrice_long = hl2
var initialEntryTpPrice_short = hl2
var mixedTrailingSl_long = hl2
var mixedTrailingSl_short = hl2
mixedSlLong = min(atrSl_long, kumoBasedSlLong, recentLow)
mixedSlShort = max(atrSl_short, kumoBasedSlShort, recentHigh)
//plot(mixedSlLong, color=color.green, linewidth=2)
//plot(mixedSlShort, color=color.red, linewidth=2)
//============================================================================
// Range Edge caliculation
//============================================================================
// calc range edge
f_calcRangeEdge_high() =>
//highest = high[3]
highest = max(open[3], close[3])
for i = 4 to (config_rangeDetectBars - 1)
//current = high[i]
current = max(open[i], close[i])
if highest < current
highest := current
highest
f_calcRangeEdge_low() =>
//lowest = low[3]
lowest = min(open[3], close[3])
for i = 4 to (config_rangeDetectBars - 1)
//current = low[i]
current = min(open[i], close[i])
if lowest > current
lowest := current
lowest
entryLimitHigh = f_calcRangeEdge_high()
entryLimitLow = f_calcRangeEdge_low()
plot(entryLimitHigh, color=COLOR_RANGE_EDGE, linewidth=1)
plot(entryLimitLow, color=COLOR_RANGE_EDGE, linewidth=1)
//============================================================================
// entry timing judge
//============================================================================
f_trendStatsChanged() =>
var trendStats = 0
var kumoBull = false
var kumoBear = false
var kumoRanged = false
kumoBull := currentAboveKumo_baseHtf and currentAboveKumo_highestTf
kumoBear := currentBelowKumo_baseHtf and currentBelowKumo_highestTf
kumoRanged := not kumoBull and not kumoBear
if kumoRanged
trendStats := 0
// respect recent bullish or bearish
if kumoBull[1] or kumoBull[2] or kumoBull[3] or kumoBear[1] or kumoBear[2] or kumoBear[3]
trendStats := trendStats[1]
if kumoBull
trendStats := 1
if kumoBear
trendStats := -1
trendStats[1] != trendStats[0]
trendStatsChanged = f_trendStatsChanged()
var isFirstEntry = true
var resistancePrice = hl2
var rangeBreakSignalDetected = false
var rangeBreakMacdReversalDetected = false
var rangeBreakConfirmed = false
//--------------------------------------
// reset flags
// if trend stats changed, reset flags
if trendStatsChanged
isFirstEntry := true
rangeBreakSignalDetected := false
rangeBreakMacdReversalDetected := false
rangeBreakConfirmed := false
else
// if has no positions
if strategy.position_size == 0
isFirstEntry := isFirstEntry[1]
// if lost positions in prev bar
if lostPositionsInPrevBar
rangeBreakSignalDetected := false
rangeBreakConfirmed := false
else
rangeBreakSignalDetected := rangeBreakSignalDetected[1]
rangeBreakConfirmed := rangeBreakConfirmed[1]
// if has any position
else
isFirstEntry := false // no more first entry
resistancePrice := hl2 // no resistance price
//--------------------------------------
// 1st entry confirmation
var firstReverseAfterTrendChange = false
var trendConfirmed = false
// this operation is for the 1st entry
if isFirstEntry
if bullish
// wait for the short reversal for confirmation
if not firstReverseAfterTrendChange and not rangeBreakMacdReversalDetected
if macdDownTrend
rangeBreakMacdReversalDetected := true
if rangeBreakMacdReversalDetected
if macdUpTrend
trendConfirmed := true
if bearish
if not firstReverseAfterTrendChange and not rangeBreakMacdReversalDetected
if macdUpTrend
rangeBreakMacdReversalDetected := true
if rangeBreakMacdReversalDetected
if macdDownTrend
trendConfirmed := true
else
trendConfirmed := false
firstReverseAfterTrendChange := false
if (bullish[0] != bullish[1]) or (bearish[0] != bearish[1])
trendConfirmed := false
// plot trend confirmation
if (trendConfirmed[0] == true) and (trendConfirmed[1] == false)
if bullish
label.new(bar_index, low, 'Trend Confirmed', style=label.style_triangleup, size=size.tiny, color=#ffffff, textcolor=#ffffff)
else
label.new(bar_index, high, 'Trend Confirmed', style=label.style_triangledown, size=size.tiny, color=#ffffff, textcolor=#ffffff)
//--------------------------------------
// later entry confirmation
if strategy.position_size == 0
// this operation is for later entry
if isFirstEntry
resistancePrice := hl2
else
// if range break was detected, set flag
if not rangeBreakSignalDetected and continuousBull and entryLimitHigh < close
rangeBreakSignalDetected := true
if not rangeBreakSignalDetected and continuousBear and close < entryLimitLow
rangeBreakSignalDetected := true
// after range break, wait for short MACD reversal.
// after this confirmation, make stop entry
if rangeBreakSignalDetected
if senkouSpanHigh_baseHtf < close
resistancePrice := entryLimitHigh
if macdDownTrend
rangeBreakConfirmed := true
if senkouSpanLow_baseHtf > close
resistancePrice := entryLimitLow
if macdUpTrend
rangeBreakConfirmed := true
// plot rangebreak detection
if (rangeBreakSignalDetected[0] == true) and (rangeBreakSignalDetected[1] == false)
if bullish
label.new(bar_index, low, 'Rangebreak detected', style=label.style_triangleup, size=size.tiny, color=#ffffff, textcolor=#ffffff)
else
label.new(bar_index, high, 'Rangebreak detected', style=label.style_triangledown, size=size.tiny, color=#ffffff, textcolor=#ffffff)
// plot resistance price line
resitancePriceColor = rangeBreakConfirmed and strategy.position_size == 0 ? COLOR_RESISTANCE_PRICE_LINE : COLOR_TRANSPARENT
plot(resistancePrice, linewidth=4, color=resitancePriceColor)
//============================================================================
// Pyramiding entry judge
//============================================================================
f_calcExtraEntryStopForShort() =>
startIndex = 2
highest = max(open[startIndex], close[startIndex])
for i = startIndex to (config_extraEntryStopDetectBars - 1)
current = max(open[i], close[i])
if highest < current
highest := current
highest
f_calcExtraEntryStopForLong() =>
startIndex = 2
lowest = min(open[startIndex], close[startIndex])
for i = startIndex to (config_extraEntryStopDetectBars - 1)
current = min(open[i], close[i])
if lowest > current
lowest := current
lowest
extraEntryStopLong = f_calcExtraEntryStopForLong() + entryPadding
extraEntryStopShort = f_calcExtraEntryStopForShort() - entryPadding
extraEntryStop = bullish ? extraEntryStopLong :
bearish ? extraEntryStopShort :
hl2
extraEntryStopColor = (bullish or bearish) ? color.green : COLOR_TRANSPARENT
// plot as line
plot(extraEntryStop, color=extraEntryStopColor, linewidth=2)
//============================================================================
// entry, TP, SL
//============================================================================
shouldMakeEntryLong = continuousBull and ((isFirstEntry and trendConfirmed) or (rangeBreakConfirmed and close > resistancePrice))
shouldMakeEntryShort = continuousBear and ((isFirstEntry and trendConfirmed) or (rangeBreakConfirmed and close < resistancePrice))
// TP caliculation
if strategy.position_size == 0
initialEntryTpPrice_long := entryLimitHigh + (hl2 - extraEntryStopLong)
initialEntryTpPrice_short := entryLimitLow - (extraEntryStopShort - hl2)
// SL caliculation
mixedTrailingSl_long := if ((strategy.position_size == 0) and shouldMakeEntryLong) or ((strategy.position_size > 0) and (mixedTrailingSl_long < mixedSlLong))
mixedSlLong
else if (strategy.position_size == 0) or (strategy.position_size < 0)
hl2
else
mixedTrailingSl_long[1]
mixedTrailingSl_short := if ((strategy.position_size == 0) and shouldMakeEntryShort) or ((strategy.position_size < 0) and (mixedTrailingSl_short > mixedSlShort))
mixedSlShort
else if (strategy.position_size == 0) or (strategy.position_size > 0)
hl2
else
mixedTrailingSl_short[1]
// final entry price
initialEntryStopPrice_long = entryLimitHigh + entryPadding
initialEntryStopPrice_short = entryLimitLow - entryPadding
extraEntryLimitPrice_long = extraEntryStopLong
extraEntryLimitPrice_short = extraEntryStopShort
extraEntryTpPrice_long = entryLimitHigh + entryPadding
extraEntryTpPrice_short = entryLimitLow - entryPadding
//============================================================================
// Quantitiy caliculation
//============================================================================
var initialQty = 0
slPercentage = bullish ? abs(mixedTrailingSl_long-hl2)/hl2*100 : abs(mixedTrailingSl_short-hl2)/hl2*100
qtyForInitialEntry = f_calcQtyForInitialEntry(slPercentage)
qtyForExtraEntry = f_calcQtyForExtraEntry(slPercentage)
//============================================================================
// Pyramiding judge
//============================================================================
var anyTpTriggered = false
var hasAnyPositions = false
if strategy.position_size != 0 and strategy.position_size[1] == 0
hasAnyPositions := true
if strategy.position_size == 0 and strategy.position_size[1] != 0
hasAnyPositions := false
anyTpTriggered := false
if hasAnyPositions and not anyTpTriggered and (abs(strategy.position_size) < initialQty)
anyTpTriggered := true
pyramidingReady =
(anyTpTriggered and bullish and (extraEntryStopLong > previousEntryPrice) and f_isLastCandleUp()) or
(anyTpTriggered and bearish and (extraEntryStopShort < previousEntryPrice) and f_isLastCandleDown())
//============================================================================
// make entries
//============================================================================
if (time >= startDate and time <= finishDate)
if strategy.position_size == 0
if shouldMakeEntryLong
initialQty := qtyForInitialEntry
strategy.entry(id="Long", long=true, stop=initialEntryStopPrice_long, qty=initialQty)
previousEntryPrice := entryLimitHigh
if shouldMakeEntryShort
initialQty := qtyForInitialEntry
strategy.entry(id="Short", long=false, stop=initialEntryStopPrice_short, qty=initialQty)
previousEntryPrice := entryLimitLow
// Long pyramiding
if (strategy.position_size > 0) and pyramidingReady
previousEntryPrice := extraEntryStopLong
strategy.entry(id="LongExtra", long=true, limit=extraEntryLimitPrice_long, qty=qtyForExtraEntry)
else
strategy.cancel(id="LongExtra")
// Short pyramiding
if (strategy.position_size < 0) and pyramidingReady
previousEntryPrice := extraEntryStopShort
strategy.entry(id="ShortExtra", long=false, limit=extraEntryLimitPrice_short, qty=qtyForExtraEntry)
else
strategy.cancel(id="ShortExtra")
// cancel stop entries
if not continuousBull
strategy.cancel(id="Long")
strategy.cancel(id="LongExtra")
if not continuousBear
strategy.cancel(id="Short")
strategy.cancel(id="ShortExtra")
// TP, SL
strategy.exit('Long-TP', 'Long', stop=mixedTrailingSl_long, limit=initialEntryTpPrice_long, qty=(initialQty/2))
strategy.exit('Long-SL', 'Long', stop=mixedTrailingSl_long)
strategy.exit('LongExtra-SL/TP', 'LongExtra', stop=mixedTrailingSl_long, limit=extraEntryTpPrice_long)
strategy.exit('Short-TP', 'Short', stop=mixedTrailingSl_short, limit=initialEntryTpPrice_short, qty=(initialQty/2))
strategy.exit('Short-SL', 'Short', stop=mixedTrailingSl_short)
strategy.exit('ShortExtra-SL/TP', 'ShortExtra', stop=mixedTrailingSl_short, limit=extraEntryTpPrice_short)
//============================================================================
// plot SL, TP
//============================================================================
sl = if strategy.position_size > 0
mixedTrailingSl_long
else if strategy.position_size < 0
mixedTrailingSl_short
else
na
tp = if hasAnyPositions and not anyTpTriggered
strategy.position_size > 0 ? initialEntryTpPrice_long : initialEntryTpPrice_short
else
na
plot(sl, color=color.red, style=plot.style_cross, linewidth=2, title="SL")
plot(tp, color=color.blue, style=plot.style_cross, linewidth=2, title="T")
//============================================================================
// debug
//============================================================================
// continuous bull / bear check
value_bgcolor = continuousBull ? color.green : continuousBear ? color.red: color.new(#000000, 100)
// MACD up or down check
//value_bgcolor = macdUpTrend ? color.green : color.red
// both kumo bull
//value_bgcolor = (kumoColor_bull_baseHtf and kumoColor_bull_highestTf) ? color.green:
// (not kumoColor_bull_baseHtf and not kumoColor_bull_highestTf) ? color.red: color.new(#000000, 100)
// doji
//dojiUp = bullish and f_isUpDoji()
//dojiDown = bearish and f_isDownDoji()
//value_bgcolor = dojiUp ? color.green :
// dojiDown ? color.red :
// COLOR_TRANSPARENT
//value_bgcolor = f_isLastCandleUp() ? color.green : COLOR_TRANSPARENT
//value_bgcolor = pyramidingReady ? color.green : COLOR_TRANSPARENT
bgcolor(value_bgcolor, transp=95)
Expand (1085 lines)
Overview
2Tier Ichimoku Pyramiding [Takazudo] allows two entries in the same direction and uses ATR-based trailing stops plus ATR entry padding. Settings change Ichimoku lengths, line smoothing, gap-cloud use, bull and range detection, and the backtest start date. Exit logic beyond the trailing stop is not shown in the provided code.
The inputs you can change from the gear icon on the chart. Defaults are the author's.
Setting
Type
Default
Variable
═════════ HTF ══════════
bool
true
_1
Base Higher Timeframe
timeframe
D
config_baseHtf
use Highest Timeframe (Kumo only)
bool
true
config_useHighestTf
Highest Timeframe
timeframe
W
config_highestTf
═════════ Ichimoku ══════════
bool
true
_2
Tenkan-Sen Bars
int
9
config_tenkanSen
Kijun-Sen Bars
int
26
config_kijunSen
Senkou-Span B Bars
int
52
config_senkouSpanB
Chikou-Span Offset
int
26
config_chikouSpan
Senkou-Span Offset
int
26
config_senkouSpan
═════════ Smooth Line ══════════
bool
true
_3
enable smooth line
bool
true
config_useSmooth
Show all 33 settings
Setting
Type
Default
Variable
smooth factor
int
2
config_smoothFactor
═════════ MTF stuff ══════════
bool
true
_4
avoid to refer lower resolution indicator
bool
true
config_autoSwitchToHtf
avoid to refer too high resolution indicator
bool
true
config_avoidTooHighResolution
use Gap Kumo
bool
true
config_useGapKumo
═════════ etc ══════════
bool
true
_5
bull detection min bar count
int
3
config_bullDetectBars
range detection bar count
int
200
config_rangeDetectBars
recent bar count for SL
int
50
config_recentBars
Trailing stop ATR Length
int
4
config_atrLength
Trailing stop ATR Multiple factor
float
1
config_atrSlMult
Entry padding ATR Multiple factor
float
0.5
config_atrEntryPaddingMult
Entry padding ATR Length
int
10
config_atrEntryPaddingLength
Pyramiding entry recent detect bar count
int
10
config_extraEntryStopDetectBars
═════════ Backtesting range ══════════
bool
true
_6
From Year
int
2019
fromYear
From Month
int
1
fromMonth
From Day
int
1
fromDay
To Year
int
2021
toYear
To Month
int
3
toMonth
To Day
int
10
toDay
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.
This strategy plots VWMA-based Bollinger bands on the 1-minute ES futures price chart for volatility analysis and potential breakout identification. It calculates dynamic long and short stop loss and take profit levels using percentage inputs relative to entry
This strategy uses multiple VWAP anchors and a custom Lull indicator to generate buy and sell signals on the Nasdaq price chart. It plots the VWAP trend line and three VWAP anchors with customizable colors and mitigation methods. The Lull indicator produces si
This strategy implements a multi-stage trend following system inspired by John W. Seykota. It generates long and short entries when price breaks above or below Donchian channels of specified length. Each entry adds a unit sized to risk a fixed percentage of cu
Calculates upper and lower Donchian Channel bands over a customizable lookback length and plots them on the main price chart. At a specified exchange hour, the strategy places a long buy stop order at the upper Donchian Channel level. Unfilled pending orders a
This strategy combines moving averages, ATR volatility bands and ADX trend strength on the price chart. It calculates ADX from price data and adjusts the ATR multiplier dynamically based on whether ADX is rising or falling. Long and short entries are controlle
This trend-following strategy executes a classic Donchian channel breakout system designed to cross-validate backtest results against external framework benchmarks. It triggers a long entry when the closing price breaks above the highest high of the prior entr