Join useThinkScript to post your question to a community of 21,000+ developers and traders.
# MTF CHART ANALYZER: DAILY REGIME + DAILY 60-DAY RANGE + 4H LEVELS
# Designed for 5-minute and 15-minute execution charts
# ANTWERKS 08/17/2026
declare upper;
input dailySwingLookback = 60;
input dailyFastEMALength = 20;
input dailySlowEMALength = 50;
input dailyADXLength = 14;
input dailyTrendADXMinimum = 20.0;
input fourHourLookback = 30;
input showDailyLevels = yes;
input showFourHourLevels = yes;
input showLabels = yes;
input colorPriceByDailyRegime = no;
input showTradePlan = yes;
input minimumRewardRisk = 2.0;
input fourHourATRLength = 14;
input stopBufferATR = 0.75;
input entryProximityATR = 0.30;
input retestToleranceATR = 0.15;
input tradeBoxBars = 15;
Assert(GetAggregationPeriod() <= AggregationPeriod.FOUR_HOURS,
"Use this study on a 4-hour or lower chart. TOS cannot request 4-hour data from a higher chart aggregation.");
Assert(dailySwingLookback > 1,
"dailySwingLookback must be greater than 1");
Assert(fourHourLookback > 1,
"fourHourLookback must be greater than 1");
# ==================================================
# DAILY DATA
# ==================================================
def dHigh = high(period = AggregationPeriod.DAY);
def dLow = low(period = AggregationPeriod.DAY);
def dClose = close(period = AggregationPeriod.DAY);
# Completed daily bars are used so the levels do not move with today's
# developing daily high and low.
def dailySwingHigh = Highest(dHigh[1], dailySwingLookback);
def dailySwingLow = Lowest(dLow[1], dailySwingLookback);
def dailyRangeMid = (dailySwingHigh + dailySwingLow) / 2;
plot DailyHighLine =
if showDailyLevels then dailySwingHigh else Double.NaN;
DailyHighLine.SetDefaultColor(Color.BLUE);
DailyHighLine.SetLineWeight(3);
DailyHighLine.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
DailyHighLine.HideBubble();
plot DailyLowLine =
if showDailyLevels then dailySwingLow else Double.NaN;
DailyLowLine.SetDefaultColor(Color.BLUE);
DailyLowLine.SetLineWeight(3);
DailyLowLine.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
DailyLowLine.HideBubble();
# ==================================================
# DAILY REGIME ENGINE
# Trend requires directional price structure plus ADX confirmation.
# ==================================================
def dailyFastEMA = ExpAverage(dClose, dailyFastEMALength);
def dailySlowEMA = ExpAverage(dClose, dailySlowEMALength);
def dailyTrueRange =
Max(dHigh - dLow,
Max(AbsValue(dHigh - dClose[1]),
AbsValue(dLow - dClose[1])));
def dailyUpMove = dHigh - dHigh[1];
def dailyDownMove = dLow[1] - dLow;
def dailyPlusDM =
if dailyUpMove > dailyDownMove and dailyUpMove > 0
then dailyUpMove
else 0;
def dailyMinusDM =
if dailyDownMove > dailyUpMove and dailyDownMove > 0
then dailyDownMove
else 0;
def dailyATR = WildersAverage(dailyTrueRange, dailyADXLength);
def dailyPlusDI =
if dailyATR > 0
then 100 * WildersAverage(dailyPlusDM, dailyADXLength) / dailyATR
else 0;
def dailyMinusDI =
if dailyATR > 0
then 100 * WildersAverage(dailyMinusDM, dailyADXLength) / dailyATR
else 0;
def dailyDISum = dailyPlusDI + dailyMinusDI;
def dailyDX =
if dailyDISum > 0
then 100 * AbsValue(dailyPlusDI - dailyMinusDI) / dailyDISum
else 0;
def dailyADX = WildersAverage(dailyDX, dailyADXLength);
def dailyTrendingUp =
dailyADX >= dailyTrendADXMinimum and
dClose > dailyFastEMA and
dailyFastEMA > dailySlowEMA and
dailyPlusDI > dailyMinusDI;
def dailyTrendingDown =
dailyADX >= dailyTrendADXMinimum and
dClose < dailyFastEMA and
dailyFastEMA < dailySlowEMA and
dailyMinusDI > dailyPlusDI;
def dailyRangebound = !dailyTrendingUp and !dailyTrendingDown;
# ==================================================
# FOUR-HOUR MAJOR SUPPORT AND RESISTANCE
# These are completed-bar range boundaries, not discretionary S/R.
# ==================================================
def h4High = high(period = AggregationPeriod.FOUR_HOURS);
def h4Low = low(period = AggregationPeriod.FOUR_HOURS);
def h4Close = close(period = AggregationPeriod.FOUR_HOURS);
def fourHourResistance = Highest(h4High[1], fourHourLookback);
def fourHourSupport = Lowest(h4Low[1], fourHourLookback);
plot FourHourResistanceLine =
if showFourHourLevels then fourHourResistance else Double.NaN;
FourHourResistanceLine.SetDefaultColor(Color.RED);
FourHourResistanceLine.SetStyle(Curve.SHORT_DASH);
FourHourResistanceLine.SetLineWeight(2);
FourHourResistanceLine.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
FourHourResistanceLine.HideBubble();
plot FourHourSupportLine =
if showFourHourLevels then fourHourSupport else Double.NaN;
FourHourSupportLine.SetDefaultColor(Color.RED);
FourHourSupportLine.SetStyle(Curve.SHORT_DASH);
FourHourSupportLine.SetLineWeight(2);
FourHourSupportLine.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
FourHourSupportLine.HideBubble();
# ==================================================
# LABELS
# ==================================================
AddLabel(showLabels,
if dailyTrendingUp then "DAILY REGIME: TRENDING UP"
else if dailyTrendingDown then "DAILY REGIME: TRENDING DOWN"
else "DAILY REGIME: RANGEBOUND",
if dailyTrendingUp then Color.GREEN
else if dailyTrendingDown then Color.RED
else Color.YELLOW);
AddLabel(showLabels,
"D60 HIGH: " + Round(dailySwingHigh, 2) +
" | LOW: " + Round(dailySwingLow, 2),
Color.BLUE);
AddLabel(showLabels,
"4H R: " + Round(fourHourResistance, 2) +
" | S: " + Round(fourHourSupport, 2),
Color.RED);
AddLabel(showLabels,
if close > fourHourResistance then "LOCATION: ABOVE 4H RANGE"
else if close < fourHourSupport then "LOCATION: BELOW 4H RANGE"
else if close >= dailyRangeMid then "LOCATION: UPPER DAILY RANGE"
else "LOCATION: LOWER DAILY RANGE",
if close > fourHourResistance then Color.GREEN
else if close < fourHourSupport then Color.RED
else Color.GRAY);
# ==================================================
# TRADE SETUP ANALYZER
# Only trend-aligned plans qualify. The target must be an existing
# Daily or 4H level and must provide at least the selected reward/risk.
# Stops are placed beyond the structural level by a 4H ATR buffer.
# ==================================================
def h4TrueRange =
Max(h4High - h4Low,
Max(AbsValue(h4High - h4Close[1]),
AbsValue(h4Low - h4Close[1])));
def h4ATR = Average(h4TrueRange, fourHourATRLength);
def safeH4ATR = if h4ATR > 0 then h4ATR else TickSize();
def stopBuffer = stopBufferATR * safeH4ATR;
# If price has already broken the 4H boundary, plan its retest.
# Otherwise, plan a trend-aligned trade from the opposite 4H boundary.
def longBreakoutRetest = close > fourHourResistance;
def shortBreakoutRetest = close < fourHourSupport;
def longEntryCandidate =
if longBreakoutRetest
then fourHourResistance
else fourHourSupport;
def longStopCandidate = longEntryCandidate - stopBuffer;
def longTargetCandidate =
if longBreakoutRetest
then dailySwingHigh
else fourHourResistance;
def shortEntryCandidate =
if shortBreakoutRetest
then fourHourSupport
else fourHourResistance;
def shortStopCandidate = shortEntryCandidate + stopBuffer;
def shortTargetCandidate =
if shortBreakoutRetest
then dailySwingLow
else fourHourSupport;
def longRisk = longEntryCandidate - longStopCandidate;
def longReward = longTargetCandidate - longEntryCandidate;
def longRewardRisk =
if longRisk > 0 and longReward > 0
then longReward / longRisk
else 0;
def shortRisk = shortStopCandidate - shortEntryCandidate;
def shortReward = shortEntryCandidate - shortTargetCandidate;
def shortRewardRisk =
if shortRisk > 0 and shortReward > 0
then shortReward / shortRisk
else 0;
def qualifiedLongPlan =
dailyTrendingUp and
longRewardRisk >= minimumRewardRisk;
def qualifiedShortPlan =
dailyTrendingDown and
shortRewardRisk >= minimumRewardRisk;
def entryProximity = entryProximityATR * safeH4ATR;
def retestTolerance = retestToleranceATR * safeH4ATR;
# A retest candle must trade into the level's tolerance zone and close
# back on the correct side. The following candle must then break the
# retest candle in the trade direction.
def longRetestHold =
qualifiedLongPlan and
low <= longEntryCandidate + retestTolerance and
high >= longEntryCandidate - retestTolerance and
close > longEntryCandidate;
def shortRetestHold =
qualifiedShortPlan and
high >= shortEntryCandidate - retestTolerance and
low <= shortEntryCandidate + retestTolerance and
close < shortEntryCandidate;
def longConfirmedNow =
qualifiedLongPlan and
longRetestHold[1] and
close > high[1] and
close > longEntryCandidate;
def shortConfirmedNow =
qualifiedShortPlan and
shortRetestHold[1] and
close < low[1] and
close < shortEntryCandidate;
# Keep a confirmed trade active until its target, stop, regime or
# minimum reward/risk condition is invalidated.
rec confirmedTradeDirection = CompoundValue(1,
if longConfirmedNow then 1
else if shortConfirmedNow then -1
else if confirmedTradeDirection[1] == 1 and
qualifiedLongPlan and
close > longStopCandidate and
close < longTargetCandidate then 1
else if confirmedTradeDirection[1] == -1 and
qualifiedShortPlan and
close < shortStopCandidate and
close > shortTargetCandidate then -1
else 0,
0);
def longNearEntry =
qualifiedLongPlan and
AbsValue(close - longEntryCandidate) <= entryProximity;
def shortNearEntry =
qualifiedShortPlan and
AbsValue(close - shortEntryCandidate) <= entryProximity;
# Freeze the current plan and display it over the latest chart bars.
def lastChartBar = !IsNaN(close) and IsNaN(close[-1]);
def lastChartBarNumber =
HighestAll(if !IsNaN(close) then BarNumber() else 0);
def displayWindow =
BarNumber() >= lastChartBarNumber - tradeBoxBars and
!IsNaN(close);
def planDirection = HighestAll(
if lastChartBar then
if qualifiedLongPlan then 1
else if qualifiedShortPlan then -1
else 0
else Double.NaN);
def planConfirmedDirection = HighestAll(
if lastChartBar then confirmedTradeDirection
else Double.NaN);
def planEntry = HighestAll(
if lastChartBar and qualifiedLongPlan then longEntryCandidate
else if lastChartBar and qualifiedShortPlan then shortEntryCandidate
else Double.NaN);
def planStop = HighestAll(
if lastChartBar and qualifiedLongPlan then longStopCandidate
else if lastChartBar and qualifiedShortPlan then shortStopCandidate
else Double.NaN);
def planTarget = HighestAll(
if lastChartBar and qualifiedLongPlan then longTargetCandidate
else if lastChartBar and qualifiedShortPlan then shortTargetCandidate
else Double.NaN);
plot TradeTargetLine =
if showTradePlan and displayWindow and planDirection != 0
then planTarget
else Double.NaN;
TradeTargetLine.SetDefaultColor(Color.GREEN);
TradeTargetLine.SetLineWeight(2);
TradeTargetLine.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
TradeTargetLine.AssignValueColor(
if planConfirmedDirection != 0 then Color.GREEN
else Color.YELLOW);
plot TradeEntryLine =
if showTradePlan and displayWindow and planDirection != 0
then planEntry
else Double.NaN;
TradeEntryLine.SetDefaultColor(Color.WHITE);
TradeEntryLine.SetLineWeight(3);
TradeEntryLine.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
TradeEntryLine.AssignValueColor(
if planConfirmedDirection != 0 then Color.WHITE
else Color.YELLOW);
plot TradeStopLine =
if showTradePlan and displayWindow and planDirection != 0
then planStop
else Double.NaN;
TradeStopLine.SetDefaultColor(Color.RED);
TradeStopLine.SetLineWeight(2);
TradeStopLine.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
TradeStopLine.AssignValueColor(
if planConfirmedDirection != 0 then Color.RED
else Color.ORANGE);
# HYPOTHETICAL PLAN
# Yellow = projected reward; orange = projected risk.
AddCloud(
if showTradePlan and displayWindow and
planDirection == 1 and planConfirmedDirection == 0
then TradeTargetLine else Double.NaN,
if showTradePlan and displayWindow and
planDirection == 1 and planConfirmedDirection == 0
then TradeEntryLine else Double.NaN,
Color.YELLOW,
Color.YELLOW);
AddCloud(
if showTradePlan and displayWindow and
planDirection == 1 and planConfirmedDirection == 0
then TradeEntryLine else Double.NaN,
if showTradePlan and displayWindow and
planDirection == 1 and planConfirmedDirection == 0
then TradeStopLine else Double.NaN,
Color.ORANGE,
Color.ORANGE);
AddCloud(
if showTradePlan and displayWindow and
planDirection == -1 and planConfirmedDirection == 0
then TradeEntryLine else Double.NaN,
if showTradePlan and displayWindow and
planDirection == -1 and planConfirmedDirection == 0
then TradeTargetLine else Double.NaN,
Color.YELLOW,
Color.YELLOW);
AddCloud(
if showTradePlan and displayWindow and
planDirection == -1 and planConfirmedDirection == 0
then TradeStopLine else Double.NaN,
if showTradePlan and displayWindow and
planDirection == -1 and planConfirmedDirection == 0
then TradeEntryLine else Double.NaN,
Color.ORANGE,
Color.ORANGE);
# CONFIRMED TRADE
# Green = confirmed reward; red = confirmed risk.
AddCloud(
if showTradePlan and displayWindow and
planDirection == 1 and planConfirmedDirection == 1
then TradeTargetLine else Double.NaN,
if showTradePlan and displayWindow and
planDirection == 1 and planConfirmedDirection == 1
then TradeEntryLine else Double.NaN,
Color.DARK_GREEN,
Color.DARK_GREEN);
AddCloud(
if showTradePlan and displayWindow and
planDirection == 1 and planConfirmedDirection == 1
then TradeEntryLine else Double.NaN,
if showTradePlan and displayWindow and
planDirection == 1 and planConfirmedDirection == 1
then TradeStopLine else Double.NaN,
Color.DARK_RED,
Color.DARK_RED);
AddCloud(
if showTradePlan and displayWindow and
planDirection == -1 and planConfirmedDirection == -1
then TradeEntryLine else Double.NaN,
if showTradePlan and displayWindow and
planDirection == -1 and planConfirmedDirection == -1
then TradeTargetLine else Double.NaN,
Color.DARK_GREEN,
Color.DARK_GREEN);
AddCloud(
if showTradePlan and displayWindow and
planDirection == -1 and planConfirmedDirection == -1
then TradeStopLine else Double.NaN,
if showTradePlan and displayWindow and
planDirection == -1 and planConfirmedDirection == -1
then TradeEntryLine else Double.NaN,
Color.DARK_RED,
Color.DARK_RED);
plot ConfirmedLongArrow =
if showTradePlan and longConfirmedNow then low else Double.NaN;
ConfirmedLongArrow.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
ConfirmedLongArrow.SetDefaultColor(Color.GREEN);
ConfirmedLongArrow.SetLineWeight(3);
plot ConfirmedShortArrow =
if showTradePlan and shortConfirmedNow then high else Double.NaN;
ConfirmedShortArrow.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
ConfirmedShortArrow.SetDefaultColor(Color.RED);
ConfirmedShortArrow.SetLineWeight(3);
AddLabel(showLabels,
if confirmedTradeDirection == 1 then
"TRADE: LONG ACTIVE - RETEST CONFIRMED"
else if confirmedTradeDirection == -1 then
"TRADE: SHORT ACTIVE - RETEST CONFIRMED"
else if qualifiedLongPlan and close < longEntryCandidate - retestTolerance then
"PLAN: WAIT FOR LONG RECLAIM"
else if qualifiedShortPlan and close > shortEntryCandidate + retestTolerance then
"PLAN: WAIT FOR SHORT RECLAIM"
else if longRetestHold then
"PLAN: LONG RETEST HELD - WAIT CONFIRMATION"
else if shortRetestHold then
"PLAN: SHORT RETEST HELD - WAIT CONFIRMATION"
else if longNearEntry then "PLAN: LONG RETEST IN PROGRESS"
else if shortNearEntry then "PLAN: SHORT RETEST IN PROGRESS"
else if qualifiedLongPlan then "PLAN: WAIT FOR LONG RETEST"
else if qualifiedShortPlan then "PLAN: WAIT FOR SHORT RETEST"
else if dailyRangebound then "TRADE: NONE - DAILY RANGEBOUND"
else "TRADE: NONE - R:R BELOW " + minimumRewardRisk,
if confirmedTradeDirection == 1 then Color.GREEN
else if confirmedTradeDirection == -1 then Color.RED
else if qualifiedLongPlan or qualifiedShortPlan then Color.YELLOW
else Color.GRAY);
AddLabel(showLabels and qualifiedLongPlan,
"LONG E " + Round(longEntryCandidate, 2) +
" | S " + Round(longStopCandidate, 2) +
" | T " + Round(longTargetCandidate, 2) +
" | R:R " + Round(longRewardRisk, 2),
if confirmedTradeDirection == 1 then Color.GREEN else Color.YELLOW);
AddLabel(showLabels and qualifiedShortPlan,
"SHORT E " + Round(shortEntryCandidate, 2) +
" | S " + Round(shortStopCandidate, 2) +
" | T " + Round(shortTargetCandidate, 2) +
" | R:R " + Round(shortRewardRisk, 2),
if confirmedTradeDirection == -1 then Color.RED else Color.YELLOW);
AssignPriceColor(
if !colorPriceByDailyRegime then Color.CURRENT
else if dailyTrendingUp then Color.GREEN
else if dailyTrendingDown then Color.RED
else Color.GRAY);
| Thread starter | Similar threads | Forum | Replies | Date |
|---|---|---|---|---|
| S | Support Resistance Levels script testing | Playground | 19 | |
| R | ToS Trade Button script? | Playground | 5 | |
| R | Script makes chart get stuck. What is the problem? | Playground | 1 | |
| A | Migration Script from ToS to Python or JavaScript | Playground | 1 | |
| M | Entry and exit timer script for ThinkorSwim | Playground | 5 |
Start a new thread and receive assistance from our community.
useThinkScript is the #1 community of stock market investors using indicators and other tools to power their trading strategies. Traders of all skill levels use our forums to learn about scripting and indicators, help each other, and discover new ways to gain an edge in the markets.
We get it. Our forum can be intimidating, if not overwhelming. With thousands of topics, tens of thousands of posts, our community has created an incredibly deep knowledge base for stock traders. No one can ever exhaust every resource provided on our site.
If you are new, or just looking for guidance, here are some helpful links to get you started.