The latest version of the Daily Range script on TradingView looks like this:
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/// © AndreSolbach//@version=5indicator(title="Daily Range", precision=2, overlay=true)days_used_for_calculation = input.int(defval=50, title="Days used for calculation", minval=1, tooltip="How many past days should be used to calculate the Daily Range", group="Settings")text_color = input.color(defval=color.rgb(233, 30, 99, 0), title="Text color", tooltip="Color of the Daily Range value", group="Settings")block_mult = 0.0var1 = falseif barstate.islastvar1 := trueif (syminfo.mintick == 0.00001) or ((syminfo.mintick == 0.001) and str.contains(syminfo.ticker, "JPY"))block_mult := syminfo.mintick * 10else if (syminfo.mintick == 0.01)block_mult := syminfo.mintick * 100else if (syminfo.mintick == 0.0000001)block_mult := syminfo.mintick * 10000000else if (syminfo.mintick == 1.0)block_mult := syminfo.mintick * 1elseblock_mult := syminfo.mintick / syminfo.mintickcalcResult_ = ((1 / block_mult) * (math.sum(high-low, days_used_for_calculation)) / (days_used_for_calculation))calcResult = request.security(syminfo.tickerid, "D", calcResult_[0] , barmerge.gaps_off, barmerge.lookahead_on)plot(var1 ? calcResult : na, color=text_color, display=display.status_line, editable=false)
The first step in rewriting it in Indie is to create a class Main (decorated with @indicator) for the main instrument and a function HighLowSma (decorated with @sec_context) for the 1-day time frame. Accordingly, the code that calculates calcResult_ should be placed in HighLowSma:
@sec_contextdef HighLowSma(self):# calculating calcResult_@indicator('Daily Range')class Main(MainContext):def __init__(self):self._high_low_sma = self.calc_on(time_frame=TimeFrame.from_str('1D'), sec_context=HighLowSma, lookahead=True)def calc(self):return self._high_low_sma[0]
Using Indie syntax, the body of HighLowSma becomes this:
def HighLowSma(self, days_used_for_calculation):block_mult = nanif self.is_last_bar:if self.info.tick_size == 0.00001 or (self.info.tick_size == 0.001 and 'JPY' in self.info.ticker):block_mult = self.info.tick_size * 10elif self.info.tick_size == 0.01:block_mult = self.info.tick_size * 100elif self.info.tick_size == 0.0000001:block_mult = self.info.tick_size * 10000000elif self.info.tick_size == 1.0:block_mult = self.info.tick_size * 1else:block_mult = self.info.tick_size / self.info.tick_sizereturn 1 / block_mult * Sum.new(MutSeriesF.new(self.high[0] - self.low[0]), days_used_for_calculation)[0] / days_used_for_calculation
After adding all the necessary decorators and imports, the code becomes this:
# indie:lang_version = 5from math import nanfrom indie import indicator, sec_context, param, format, MutSeriesF, param_ref, MainContext, TimeFrame, plot, colorfrom indie.algorithms import Sum@sec_context@param_ref('days_used_for_calculation')def HighLowSma(self, days_used_for_calculation):block_mult = nanif self.is_last_bar:if self.info.tick_size == 0.00001 or self.info.tick_size == 0.001 and 'JPY' in self.info.ticker:block_mult = self.info.tick_size * 10elif self.info.tick_size == 0.01:block_mult = self.info.tick_size * 100elif self.info.tick_size == 0.0000001:block_mult = self.info.tick_size * 10000000elif self.info.tick_size == 1.0:block_mult = self.info.tick_size * 1else:block_mult = self.info.tick_size / self.info.tick_sizereturn 1 / block_mult * Sum.new(MutSeriesF.new(self.high[0] - self.low[0]), days_used_for_calculation)[0] / days_used_for_calculation@indicator('Daily Range', format=format.PRICE, precision=2, overlay_main_pane=True)@param.int('days_used_for_calculation', default=50, min=1, title='Days used for calculation')@plot.line(color=color.rgba(233, 30, 99), display_options=plot.LineDisplayOptions(status_line=True))class Main(MainContext):def __init__(self):self._high_low_sma = self.calc_on(time_frame=TimeFrame.from_str('1D'), sec_context=HighLowSma, lookahead=True)def calc(self):return self._high_low_sma[0] if self.is_last_bar else nan
Note: This indicator requests daily data for 50 days, so on lower timeframes (e.g., 1 minute), there may not be enough historical bars, resulting in nan values in the indicator’s output data. On a 1-hour chart, however, the history depth should be sufficient to cover the requested period without issues.
In addition, the HighLowSma code can be simplified: all the if statements except the first one set block_mult to 1.0, and Sum.new(..., len)[0] / len can be rewritten as Sma.new(..., len)[0]. With a little refactoring, the code can become:
# indie:lang_version = 5from math import nanfrom indie import indicator, sec_context, param, format, MutSeriesF, param_ref, MainContext, TimeFrame, plot, colorfrom indie.algorithms import Sma@sec_context@param_ref('days_used_for_calculation')def HighLowSma(self, days_used_for_calculation):block_mult = nanif self.is_last_bar:block_mult = 1.0if self.info.tick_size == 0.00001 or self.info.tick_size == 0.001 and 'JPY' in self.info.ticker:block_mult = self.info.tick_size * 10return 1 / block_mult * Sma.new(MutSeriesF.new(self.high[0] - self.low[0]), days_used_for_calculation)[0]@indicator('Daily Range', format=format.PRICE, precision=2, overlay_main_pane=True)@param.int('days_used_for_calculation', default=50, min=1, title='Days used for calculation')@plot.line(color=color.rgba(233, 30, 99), display_options=plot.LineDisplayOptions(status_line=True))class Main(MainContext):def __init__(self):self._high_low_sma = self.calc_on(time_frame=TimeFrame.from_str('1D'), sec_context=HighLowSma, lookahead=True)def calc(self):return self._high_low_sma[0] if self.is_last_bar else nan
With that, the Daily Range indicator is fully ported to Indie. The final version is cleaner, easier to maintain, and uses Indie’s composable architecture for clarity and efficiency. Now it’s ready for production use or further customization.


Be the first to comment
Publish your first comment to unleash the wisdom of crowd.