Pine Script Boilerplate ExampleI frequently receive questions about my coding style and logic, so I decided to publish a simple indicator that draws the OHLC of a higher timeframe as an example of my coding style. This example will also explain my approach to writing indicators.
This indicator showcases how I use Types and Methods to structure my code and maintain clarity in logic. It demonstrates how I collect input data, organize the flow of the code, and utilize the TradingView method feature.
The example illustrates:
1. The use of input settings within a settings object to keep configurations grouped together.
2. The use of Types to create an object that consolidates relevant data.
3. The collection of objects to create, update, and render elements on the chart.
Pinecoders
price action reversion bands - [SigmaStreet]█ OVERVIEW
The "Price Action Reversion Bands" is designed to help traders identify potential reversal zones through the integration of polynomial regression, fractal analysis, and pinbar detection. This tool overlays directly onto the price chart, providing dynamic visual cues and signals for market reversals. Its unique synthesis of these methodologies offers traders a powerful, multifaceted approach to market analysis.
█ CONCEPTS
Polynomial Regression Bands:
What It Does:
Models the main trend using a polynomial equation to create a middle trend line with dynamic support and resistance bands.
How It Works:
Calculates polynomial coefficients to plot a regression line and adjusts the bands according to market volatility and conditions.
Fibonacci Retracement Levels:
What It Does:
Provides additional lines inside the regression bands at key Fibonacci ratios to identify potential support and resistance areas.
How It Works:
Calculates retracement levels by identifying high and low points over the same period used to calculate the regression bands, applying Fibonacci ratios to these points.
Fractal Analysis:
What It Does: Identifies natural resistance and support levels, indicating potential reversal zones.
How It Works: Detects fractals based on a specific pattern of price action, using Williams Fractal methodology.
Pinbar Detection:
What It Does: Signals potential price reversals through pinbar candlestick patterns.
How It Works: Analyzes
candlesticks to identify pinbars which show a rejection of prices, suggesting possible reversals.
█ ORIGINALITY AND USEFULNESS
The price action reversion bands distinguishes itself through its innovative integration of several advanced analytical methods, providing traders with a holistic view of potential market reversals:
Unique Combination:
While many tools use these techniques in isolation, this indicator synergistically combines polynomial regression, Fibonacci retracement levels, fractal analysis, and pinbar detection. This multi-faceted approach allows traders to assess strength, potential reversal zones, and price rejection more effectively than using traditional single-method indicators.
Advanced Polynomial Regression Application:
Unlike standard regression tools that offer static insights, this indicator dynamically adjusts its regression bands based on real-time market volatility, providing a more accurate reflection of market conditions.
Enhanced Signal Reliability:
By using fractals and pinbars in conjunction to validate each other, the indicator significantly increases the reliability of its reversal signals. This dual-validation method filters out less probable signals, focusing on high-probability trading opportunities.
Customization and Flexibility:
It offers unprecedented customization options, allowing traders to fine-tune the tool according to their trading style and market conditions. Traders can adjust the polynomial degree, the sensitivity of the Fibonacci retracements, and even the definition of what constitutes a significant pinbar, making it highly adaptable to various trading scenarios.
Educational Value:
The indicator not only aids in trading but also serves as an educational tool that helps traders understand the interaction between different types of market analysis techniques. This contributes to a deeper knowledge base and better trading decisions over time.
These distinctive features make the "Price Action Reversion Bands - " not just another indicator but a comprehensive trading tool that enhances decision-making through a well-rounded analysis of market dynamics.
█ HOW TO USE
Installation and Setup:
Apply the indicator to your TradingView chart from the "Indicators" menu.
Select either polynomial regression or Fibonacci retracement as the basis for the bands through the indicator settings.
Reading the Indicator:
Monitor the approach of price to the upper and lower bands which indicate potential reversal zones.
Look for fractal and pinbar formations near these bands for additional signal confirmation.
Customization:
Adjust settings such as the polynomial degree, data window length, and engagement zones to tailor the bands to your trading style.
Modify visual aspects like color and line type for better clarity and personal preference.
█ FEATURES
Dynamic Adjustment:
Bands adjust in real-time based on incoming price data and selected settings.
Multiple Analysis Techniques: Combines several analytical techniques to provide a comprehensive view of potential market movements. The integration of polynomial regression with Fibonacci levels, supplemented by fractal and pinbar analysis, marks this tool as particularly innovative, offering a level of synthesis that enhances predictive accuracy and usability.
User-Friendly Customization: Allows for extensive customization to suit individual trading strategies and preferences.
█ LIMITATIONS
Market Dependency:
Performance may vary significantly across different markets and conditions.
Parameter Sensitivity: Requires fine-tuning of parameters to ensure optimal performance, which might demand a steep learning curve for new users.
█ NOTES
For best results, combine this tool with other forms of analysis, such as fundamental analysis and other technical indicators, to confirm signals and enhance decision-making.
█ THANKS
Special thanks to the PineCoders community the Pine Coders themselves for their foundational contributions to the concepts used in this script. Their pioneering work in the fields of technical analysis and Pine Script development has been invaluable. This script is a testament to the collaborative spirit of the TradingView developer community, integrating analytical techniques with innovative approaches to offer a tool that is both modern and cutting-edge.
Information Entropy OscillatorHello Traders
This Trading Indicator / script is my interpritation of the use of shannons entropy in Trading, hope you find this usefull !!!
Information Entropy Oscillator :
In Physics, entropy is a concept and a measurable physical property that is most commonly associated with the state of disorder, randomness or uncertainty of a system. In the Thermodynamic field Entropy also describes how much energy is not available to do work, The more disordered a system and higher the entropy, the less of a system's energy is available to do work. This last definition is central to the idea of this trading idea, Briefly this is because the lower the information Entropy the “more predictable” is price movement which is characterized by a two states process up(h), and down(d) - (green and red candles), thus the more predictable a up or down move, Given the definition this also means more “energy” which can be thought of as the systems “predictive power” is available to do work, where work in this case to predict the likelihood of a trend continuation.
In Information Theory, the entropy of a random variable (A statistical term that describes either a discrete or continuous event with a respective (discrete or continuous) probability, where the latter is expressed via a CDF - cumulative distribution function) is the average level of "information", "surprise", or "uncertainty" inherent to the variable's possible outcomes. note : this is the definition for Entropy that this script is built upon
Formual Derivation :
Interpretations of Information Entropy Values (Polar approach)
when , …
H(x) = 0 Max-Information gain (purity of knowledge available)
H(x) = 1 No INformation gain, When both states probabilities are equal, i.e. H = T = 0.5, the function yields maximum uncertainty and therefore maximum entropy. This reflects
When Information gain is nearing 0, thus low, the script attempts to predict the proceeding trend direction, for example when entropy is low and all bars preceding the real market / time bars have all been positive and the real time bar closes as a red candle (close < yesterday's open) the script takes this as a high information gain signal, “predicting” a Bearish trend.
The Script Also comes with a Information Entropy heat map to plot entropy (inspired by Oppenheimer and Barbie lol), to see this turn off all candle plots, plots in the Chart settings, under the symbol header .
Dynamic Trailing Support & ResistanceDynamic Trailing Support & Resistance (DTSR) :
Hello Traders !!
DTSR is an objective dynamic support and resistance zone channel, Unlike subjective technical analysis DTSR finds S&R zones by calculating a range threshold within a given range over a specified lookback. FIB (Fibonacci) 38.2% and 61.8% retracement zones are also plotted for intermediate zones of resistance / support within the main resistance / support zones.
Plots
▾ <=> Close or high >= Trailing Resistance
▴ <=> Close or low <= Trailing Support
HH = The Highest High over the given Lookback period
LL = Lowest Low over the given Lookback period
Proximal Lines = The trailing S&R zones over the given lookback
Distal Lines = The HH or LL over the given lookback
DTSR Formula
note : This idea is not original to me, and was inspired by another creators work
New York, London and custom trading sessionsHi Traders
The script :
The Time sessions script plots the trading sessions of both New York and London markets (background fills), In addition to the above the script also plots a user defined trading session period (vertical lines). All plots may be toggled true or false inorder to ensure you can focus on the respective market / markets / custom session.
Market sessions are useful for technical or quantitative analysis, as the majority of trading activity and net daily volume occurs in these zones, in fact the U.S./London market overlap tends to have the greatest volume accumulation across that range of time / bars than that range at any other time within the daily session. For FX traders it may also be important to take into account for many currency pairs the average exchange rate pip movement is greatest within these zones.
The custom session, is intended to be used for traders who trade only within specific intervals within the market session or day for 24/7 traded asset classes
Additional notes :
Not as of now, I have only added three optional trading sessions. If you would like to change the sessions, copy the scripts code and change the "ctm_session" default time range value, insuring the second time value is 1 min > than the first.
As always i Hope this is a useful script, and I will be updating this script in the near future.
Volatility Weighted Moving Average + Session Average linesHi Traders !
Just finished my Y2 university finals exams, and thought I would cook up a quick and hopefully useful script.
VWAP + Session Average Lines :
Volatility Weighted Average Price in the standard case is a trading indicator that measures the average trading price for the user defined period, usually a standard session (D timeframe), & is used by traders as a trend confirmation tool.
This VWAP script allows for altering of the session to higher dimensions (D, W, M) or those of lower dimension (H4, or even H1 timeframes), furthermore this script allows the lookback of data to be switched from the standard session to a user defined amount of bars (e.g. the VWAP of 200 bars as opposed to the VWAP of a standard session which contains 95 bars in M15 timeframe for 24/7 traded assets e.g. BTCUSD), lastly this script plots Session VWAP Average Lines (if true in settings) so tradaes can gauge the area of highest liquidity within a session, this can be interpreted as the fair price within a session. If Average lines are increasing and decreasing consistently like a monotonic function this singles traders interest is at higher / lower prices respectively (Bullish / Bearish bias respectively ?), However if Average lines are centered around the same zones without any major fluctuations this signals a ranging market.
VWAP calculation :
VWAP is derived from the ratio of the assets value to total volume of transactions where value is the product of typical price (Average of high, low and close bars / candles) and corresponding bar volume, value can be thought of as the dollar value traded per bar.
How is VWAP used by Institutions / Market movers :
For some context and general information, VWAP is typically used by Market movers (e.g. Hedge funds, Mutual funds ,..., ...) in their trade execution, as trading at the VWAP equals the area of highest market volume, trading in line with the volume of the market reduces transaction costs by minimizing market impact (extra liquidity lowers spreads and lag time between order fills), this overall improves market efficiency.
In my opinion the script is best used with its standard settings on the M15 timeframe, note as of now the script is not functional on certain timeframes, however this script is not intended to be used in these timeframes, i will try fix this code bug as soon as possible.
Gaussian Fisher Transform Price Reversals - FTRHello Traders !
Looking for better trading results ?
"This indicator shows you how to identify price reversals in a timely manner." John F. Ehlers
Introduction :
The Gaussian Fisher Transform Price Reversals indicator, dubbed FTR for short, is a stat based price reversal detection indicator inspired by and based on the work of the electrical engineer now private trader John F. Ehlers.
The Fisher Transform :
It is a common assumption that prices have a gaussian / normal probability density function(PDF), i.e. a sample of n close prices would be normally distributed if the probability of observing a price value say at any given standard deviation range is equal to that probability in the case of the normal distribution, e.g. 68% off all samples fell within one standard deviation around the mean, which is what we would expect if the data was normal.
However Price Action is not normally distributed and thus can not be conventionally interpreted in this way, Formally the Fisher Transform, transforms the distribution of bounded ranging price action (were price action takes values in a range from -1 to 1) into that of a normal distribution, alternatively it may be said the Fisher Transform changes the PDF of any waveform so that the transformed output has n approximately Gaussian PDF, It does so through the following equations. taken directly from the work of John F. Ehlers - Using The Fisher Transform
By substituting price data in the above formulas, bounded ranging price actions (over a given user defined period lookback - this determines the range price ranges in, see the Intermediate formula above) distribution is transformed to that in the normal case. This means when the input, the Intermediate ,(the Midpoint - see formula above) approaches either limit within the range the outputs are greatly amplified, this amplification accentuates /puts more weight on the larger deviations or limits within the range, conversely when price action is varying round the mean of the range the output is approximately equal to unity (the input is approximately equal to the input, the intermediate)
The inputs (Intermediates) are converted to normal outputs and the nonlinear Transfer of the Fisher Transform with varying senesitivity's (gammas) can be seen in the graph / image above. Although sensitivity adjustments are not currently available in this script (I forgot to add it) the outputs may be greatly amplified as gamma (the coefficient of the Fisher Transformation - see Fish equation) approaches 1. the purple line show this graphically, as a higher gamma leads to a greater amplification than in the standard case (the red line which is the standard fisher transformation, the black plot is the Fish with a gamma of 1, which is unity sensativity)
Reversal plots and Breakouts :
- Support lines are plotted with their corresponding Fish value when there is a crossover of the Fish and Fish SMA <= a given standard deviation of Fish
- Resistance lines are plotted with their corresponding Fish value when there is a crossunder of the Fish and Fish SMA >= a given standard deviation of Fish
- Reversals are these support and resistance line plots
Breakouts and Volume bars :
Breakouts cause the reversal lines to break (when the high/low is above the resistance/support), Breakouts are more "high quality" when they occur conditional on high volume, the highlighted bars represent volume standard deviations ranging from -3 to 3. When breakouts occure on high volume this may be a sign of the continutaion of the trend (reversals would signify the start of a new trend).
Hope you enjoy, Happy Trading !
(be sure to rocket the script if you liked it, this helps me know which of my scripts are the most useful)
TASC 2023.03 Every Little Bit Helps - Special EditionMy first Published contribution.
Gracious thank you to all Pine Coders,
this has subtle features that have multiple shifts based on inputs.
with some experimentation, one might try pushing other sources
at the hue dials and see more dynamic indication.
for John Ehlers article
TASC Magazine This Month.
- Special Edition.
Number Formatting Indian/USAThis is a Pine script that helps traders format numbers in different ways to make it easier to read and display big numbers on TradingView.
this script is specifically to help other fellow pinecoder. Its not a indicator.
The above code is an example of how to format numbers in TradingView using two different formats: Indian and USA. The code defines a function called `formatNumber()` which takes two arguments: num (the number to format) and format (the format to use - either "Indian" or "USA").
If the "Indian" format is selected, the function rounds the number to the nearest crore, lakh or thousand and adds the appropriate suffix (i.e. "Cr", "Lac" or "K"). If the "USA" format is selected, the function rounds the number to the nearest billion, million or thousand and adds the appropriate suffix (i.e. "B", "M" or "K").
In both cases, the function then adds commas to the formatted number. The example usage shows how to call the `formatNumber()` function with a given number and format, and then plot the formatted number as a label on the chart.
Symbol InfoFor those who likes clean chart:
Adjustable Symbol ticker and timeframe( AKA watermark) script is here.
1: You can place Symbol ticker and timeframe info anywhere on the chart.
Also you can hide one of them or both.
Position:
Horizontal options: Left Center Right
Vertical options: Top Middle Bottom
Size: Tiny Smal Normal Large Huge Auto
Color is adjustable. Background is optional too.
2: Even more cool part is you can add 2 different custom texts that can switch. (Idea from Pinecoders original script)
You don't have to use text function and reposition it everytime, your message will always stays at one place.
Let the chart deliver your message.
I put my favourite trading slangs there:
1. Do Your Own Research (DYOR)
2. Not a Financial Advice ( NFA)
TimeLockedMALibrary "TimeLockedMA"
Library & function(s) which generates a moving average that stays locked to users desired time preference.
TODO - Add functionality for more moving average types. IE: smooth, weighted etc...
Example:
time_locked_ma(close, length=1, timeframe='days', type='ema')
Will generate a 1 day exponential moving average that will stay consistent across all chart intervals.
Error Handling
On small time frames with large moving averages (IE: 1min chart with a 50 week moving average), you'll get a study error that says "(function "sma") references too many candles in history" .
To fix this, make sure you have timeframe="" as an indicator() header. Next, in the indicator settings, increase the timeframe from to a higher interval until the error goes away.
By default, it's set to "Chart". Bringing the interval up to 1hr will usually solve the issue.
Furthermore, adding timeframe_gaps=false to your indicator() header will give you an approximation of real-time values.
Misc Info
For time_lock_ma() setting type='na' will return the relative length value that adjusts dynamically to user's chart time interval.
This is good for plugging into other functions where a lookback or length is required. (IE: Bollinger Bands)
time_locked_ma(source, length, timeframe, type) Creates a moving average that is locked to a desired timeframe
Parameters:
source : float, Moving average source
length : int, Moving average length
timeframe : string, Desired timeframe. Use: "minutes", "hours", "days", "weeks", "months", "chart"
type : string, string Moving average type. Use "SMA" (default) or "EMA". Value of "NA" will return relative lookback length.
Returns: moving average that is locked to desired timeframe.
timeframe_convert(t, a, b) Converts timeframe to desired timeframe. From a --> b
Parameters:
t : int, Time interval
a : string, Time period
b : string, Time period to convert to
Returns: Converted timeframe value
chart_time(timeframe_period, timeframe_multiplier) Separates timeframe.period function and returns chart interval and period
Parameters:
timeframe_period : string, timeframe.period
timeframe_multiplier : int, timeframe.multiplier
Enjoy :)
RKs Notepad++ Pine Script V5█ OVERVIEW
After reading all the new names and renames that Pine Script V5 brought to us, I knew that my old Notepad++ User Defined Language (UDL) would need a big update, so I decided to do a complete remake using the same Dark color scheme theme of the Pine Editor.
Then, I create a Notepad++ Theme and the Auto-Completion file with the Parameter hints for every built-in function to make everything look nicer
█ IMPORTANT
This is not an indicator!!
These are 3 XML files to copy and paste inside the Notepad++ folder.
You can use any Notepad Software to create the XML files.
The main Notepad++ folder is normally on %AppData%\Notepad++\
To avoid mistakes, always make a Backup of your files before anything.
█ INSTALLATION
Just follow these steps:
1. open a New Document File;
2. Copy everything between ↓↓↓ and ↑↑↑ symbols to this new document;
3. Remove the "//" of every single line;
4. Save each document with the correct name in the right folder;
5. Restart the Notepad++
█ NOTES:
If you have some problem installing, ask me, and I will try to help you.
But, in any case, here is the link to these files on my GitHub:
smfLibrary "smf"
f_strLeft(string, int) Function returning the leftmost `_n` characters in `_str`.
Parameters:
string : _str: source string.
int : _n : number of leftmost characters to return.
f_strRight(string, int) Function returning the rightmost `_n` characters in `_str`.
Parameters:
string : _str: source string.
int : _n : number of rightmost characters to return.
f_strMid(string, int, int) Function returning the substring of `_str` from character position `_from` to `_to` inclusively.
Parameters:
string : _str : source string.
int : _from: left character position. The first character's position is 0.
int : _to : right character position.
f_strLeftOf(string, string) Function returning the sub-string of `_str` to the left of the `_of` separating character.
Parameters:
string : _str: string to separate.
string : _op : separator character.
f_strRightOf(string, string) Function returning the sub-string of `_str` to the right of the `_of` separating character.
Parameters:
string : _str: string to separate.
string : _op : separator character.
f_strCharPos(string, string) Function returning the position of the first occurrence of `_chr` in `_str`, where the first character position is 0. Returns -1 if the character is not found.
Parameters:
string : _str: string to search.
string : _chr: character to search for in `_str`.
f_strReplace(string, int, string) Function that replaces a character at position `_pos` in the `_src` string with the `_str` character or string.
Parameters:
string : _src : source string.
int : _pos : position of character to be replaced. The first character's position is 0.
string : _str : replacement character or string.
f_tickFormat() Function returning a format string usable with `tostring()` to round a value to the symbol's tick precision.
f_tostringPad(float, string) Function returning a string representation of a numeric `_val` using a special `_fmt` string allowing all strings to be of the same width, to help align columns of values.
Parameters:
float : _val: string to separate.
string : _fmt: formatting string similar to those used in the `tostring()` format string, with "?" used to indicate padding,
f_print() Function prints a label on dataset's last bar.
Alma Moving Average Ribbon Reverse Length [DM]Greetings Colleagues
Following some recommendations and ideas I share this moving average, put all of them together
The length calculation is automatic there is only one input.
The length is inverse so it will wrap from the longest reference point, hence using phi
Moving averages will wrap around the price.
I've also added gradient color to plots and fill plots
There is an alert selector in case you are interested in a particular crossing, "remember that the order is reversed".
There is an alert visual plotshapes with offset signal.
Finally, after spending a few hours with the Williams alligator moving averages I found nothing special, but I added the individual offset adjustment for each moving average in case someone comes up with something.
Enjoy”
Some references about alma by "tradingview pinecoders"
What to look for
The Arnaud Legoux Moving Average has three elements to it:
Window: This element is the period. By default, the window is set to 9 periods, but it can be customized to fit any trading style.
Offset: This element is the Gaussian that is applied to the combo line and can be aligned to the current price. It’s default is set to 0.85, but by setting it to 1, you can make it align fully to the current price (similar to how an Exponential Moving Average (EMA) with a setting of 0 is like a Simple Moving Average (SMA)). 0.85 is what is recommended, however, you can customize it like with the window element.
Sigma: This element is a standard deviation that is applied to the combo line in order for it to appear more sharp. The default is set to 6 and it is not recommended to change the setting. The value of 6 is inspired by the Six Sigma process.
www.tradingview.com
RGB color check tool with RSI [DM]Greetings colleagues.
Here I share a tool that uses the color gradient provided by PineCoders and lucf.
This tool was made for the reason that whenever we start with an idea for a script, we end up consuming a lot of time in selecting suitable colors.
An RSI was taken as a reference for the signal
You have multiple switches for axes, fill, background and colors
You can also change the background so that you can check the contrast with the signals.
The mix of colors with 8 boxes (4 channels for each color as detailed below) for each color since RGB has been defined
Red= 0 a 255
Green= 0 a 255
Blue= 0 a 255
Transparency= 0 a 100
I hope you enjoy it. [ ;-)
Moving Average Ribbon [TheBearFighter]
This code was written using:
•Pine Script Coding Conventions.
This script provides a very useful tool for new community users and professionals. It puts at your disposal a Moving Average Ribbon by hand to graph and easily find the ones with the highest performance. The creation of this script was motivated because in free TradingView accounts there is a limit of 3 indicators by chart, and with this tool you can draw up to 32 MA's at the same time!
Choose one of 10 types of MA´s:
•KAMA Kaufman's moving average.
•HULL Hull moving average.
•TEMA Triple exponencial moving average.
•LSMA Least square moving average.
•DEMA Double exponencial moving average.
•ALMA Arnaud Legoux moving average.
•WMA Weighted moving average
•EMA Exponencial moving average.
•VWMA Volume Weighted moving average.
•SMA Simple moving average.
Use the tooltips to know the lengths of MA´s.
A main characteristic of the script is that the lengths are in days but when changing the lowest timeframes, the same daily resolution is maintained. This gives us extreme precision in intraday timeframes, e.g 30 minutes.
Once this is understood, we can turning the MA´s on/off, and changing the timeframe to our liking.
Available timeframes: M, W, D, 4H, 1H, 30m, 15m, 5m.
Also the MA´s are colored for easy visualization and know if they grow or decrease.
Thank´s to @midtownsk8rguy to let me know more about HEX colors.
Thank´s to @HPotter for his KAMA.
Using `varip` variables [PineCoders]█ OVERVIEW
The new varip keyword in Pine can be used to declare variables that escape the rollback process, which is explained in the Pine User Manual's page on the execution model . This publication explains how Pine coders can use variables declared with varip to implement logic that was impossible to code in Pine before, such as timing events during the realtime bar, or keeping track of sequences of events that occur during successive realtime updates. We present code that allows you to calculate for how much time a given condition is true during a realtime bar, and show how this can be used to generate alerts.
█ WARNINGS
1. varip is an advanced feature which should only be used by coders already familiar with Pine's execution model and bar states .
2. Because varip only affects the behavior of your code in the realtime bar, it follows that backtest results on strategies built using logic based on varip will be meaningless,
as varip behavior cannot be simulated on historical bars. This also entails that plots on historical bars will not be able to reproduce the script's behavior in realtime.
3. Authors publishing scripts that behave differently in realtime and on historical bars should imperatively explain this to traders.
█ CONCEPTS
Escaping the rollback process
Whereas scripts only execute once at the close of historical bars, when a script is running in realtime, it executes every time the chart's feed detects a price or volume update. At every realtime update, Pine's runtime normally resets the values of a script's variables to their last committed value, i.e., the value they held when the previous bar closed. This is generally handy, as each realtime script execution starts from a known state, which simplifies script logic.
Sometimes, however, script logic requires code to be able to save states between different executions in the realtime bar. Declaring variables with varip now makes that possible. The "ip" in varip stands for "intrabar persist".
Let's look at the following code, which does not use varip :
//@version=4
study("")
int updateNo = na
if barstate.isnew
updateNo := 1
else
updateNo := updateNo + 1
plot(updateNo, style = plot.style_circles)
On historical bars, barstate.isnew is always true, so the plot shows a value of "1". On realtime bars, barstate.isnew is only true when the script first executes on the bar's opening. The plot will then briefly display "1" until subsequent executions occur. On the next executions during the realtime bar, the second branch of the if statement is executed because barstate.isnew is no longer true. Since `updateNo` is initialized to `na` at each execution, the `updateNo + 1` expression yields `na`, so nothing is plotted on further realtime executions of the script.
If we now use varip to declare the `updateNo` variable, the script behaves very differently:
//@version=4
study("")
varip int updateNo = na
if barstate.isnew
updateNo := 1
else
updateNo := updateNo + 1
plot(updateNo, style = plot.style_circles)
The difference now is that `updateNo` tracks the number of realtime updates that occur on each realtime bar. This can happen because the varip declaration allows the value of `updateNo` to be preserved between realtime updates; it is no longer rolled back at each realtime execution of the script. The test on barstate.isnew allows us to reset the update count when a new realtime bar comes in.
█ OUR SCRIPT
Let's move on to our script. It has three parts:
— Part 1 demonstrates how to generate alerts on timed conditions.
— Part 2 calculates the average of realtime update prices using a varip array.
— Part 3 presents a function to calculate the up/down/neutral volume by looking at price and volume variations between realtime bar updates.
Something we could not do in Pine before varip was to time the duration for which a condition is continuously true in the realtime bar. This was not possible because we could not save the beginning time of the first occurrence of the true condition.
One use case for this is a strategy where the system modeler wants to exit before the end of the realtime bar, but only if the exit condition occurs for a specific amount of time. One can thus design a strategy running on a 1H timeframe but able to exit if the exit condition persists for 15 minutes, for example. REMINDER: Using such logic in strategies will make backtesting their complete logic impossible, and backtest results useless, as historical behavior will not match the strategy's behavior in realtime, just as using `calc_on_every_tick = true` will do. Using `calc_on_every_tick = true` is necessary, by the way, when using varip in a strategy, as you want the strategy to run like a study in realtime, i.e., executing on each price or volume update.
Our script presents an `f_secondsSince(_cond, _resetCond)` function to calculate the time for which a condition is continuously true during, or even across multiple realtime bars. It only works in realtime. The abundant comments in the script hopefully provide enough information to understand the details of what it's doing. If you have questions, feel free to ask in the Comments section.
Features
The script's inputs allow you to:
• Specify the number of seconds the tested conditions must last before an alert is triggered (the default is 20 seconds).
• Determine if you want the duration to reset on new realtime bars.
• Require the direction of alerts (up or down) to alternate, which minimizes the number of alerts the script generates.
The inputs showcase the new `tooltip` parameter, which allows additional information to be displayed for each input by hovering over the "i" icon next to it.
The script only displays useful information on realtime bars. This information includes:
• The MA against which the current price is compared to determine the bull or bear conditions.
• A dash which prints on the chart when the bull or bear condition is true.
• An up or down triangle that prints when an alert is generated. The triangle will only appear on the update where the alert is triggered,
and unless that happens to be on the last execution of the realtime bar, it will not persist on the chart.
• The log of all triggered alerts to the right of the realtime bar.
• A gray square on top of the elapsed realtime bars where one or more alerts were generated. The square's tooltip displays the alert log for that bar.
• A yellow dot corresponding to the average price of all realtime bar updates, which is calculated using a varip array in "Part 2" of the script.
• Various key values in the Data Window for each parts of the script.
Note that the directional volume information calculated in Part 3 of the script is not plotted on the chart—only in the Data Window.
Using the script
You can try running the script on an open market with a 30sec timeframe. Because the default settings reset the duration on new realtime bars and require a 20 second delay, a reasonable amount of alerts will trigger.
Creating an alert on the script
You can create a script alert on the script. Keep in mind that when you create an alert from this script, the duration calculated by the instance of the script running the alert will not necessarily match that of the instance running on your chart, as both started their calculations at different times. Note that we use alert.freq_all in our alert() calls, so that alerts will trigger on all instances where the associated condition is met. If your alert is being paused because it reaches the maximum of 15 triggers in 3 minutes, you can configure the script's inputs so that up/down alerts must alternate. Also keep in mind that alerts run a distinct instance of your script on different servers, so discrepancies between the behavior of scripts running on charts and alerts can occur, especially if they trigger very often.
Challenges
Events detected in realtime using variables declared with varip can be transient and not leave visible traces at the close of the realtime bar, as is the case with our script, which can trigger multiple alerts during the same realtime bar, when the script's inputs allow for this. In such cases, elapsed realtime bars will be of no use in detecting past realtime bar events unless dedicated code is used to save traces of events, as we do with our alert log in this script, which we display as a tooltip on elapsed realtime bars.
█ NOTES
Realtime updates
We have no control over when realtime updates occur. A realtime bar can open, and then no realtime updates can occur until the open of the next realtime bar. The time between updates can vary considerably.
Past values
There is no mechanism to refer to past values of a varip variable across realtime executions in the same bar. Using the history-referencing operator will, as usual, return the variable's committed value on previous bars. If you want to preserve past values of a varip variable, they must be saved in other variables or in an array .
Resetting variables
Because varip variables not only preserve their values across realtime updates, but also across bars, you will typically need to plan conditions that will at some point reset their values to a known state. Testing on barstate.isnew , as we do, is a good way to achieve that.
Repainting
The fact that a script uses varip does not make it necessarily repainting. A script could conceivably use varip to calculate values saved when the realtime bar closes, and then use confirmed values of those calculations from the previous bar to trigger alerts or display plots, avoiding repaint.
timenow resolution
Although the variable is expressed in milliseconds it has an actual resolution of seconds, so it only increments in multiples of 1000 milliseconds.
Warn script users
When using varip to implement logic that cannot be replicated on historical bars, it's really important to explain this to traders in published script descriptions, even if you publish open-source. Remember that most TradingViewers do not know Pine.
New Pine features used in this script
This script uses three new Pine features:
• varip
• The `tooltip` parameter in input() .
• The new += assignment operator. See these also: -= , *= , /= and %= .
Example scripts
These are other scripts by PineCoders that use varip :
• Tick Delta Volume , by RicadoSantos .
• Tick Chart and Volume Info from Lower Time Frames by LonesomeTheBlue .
Thanks
Thanks to the PineCoders who helped improve this publication—especially to bmistiaen .
Look first. Then leap.
`security()` revisited [PineCoders]NOTE
The non-repainting technique in this publication that relies on bar states is now deprecated, as we have identified inconsistencies that undermine its credibility as a universal solution. The outputs that use the technique are still available for reference in this publication. However, we do not endorse its usage. See this publication for more information about the current best practices for requesting HTF data and why they work.
█ OVERVIEW
This script presents a new function to help coders use security() in both repainting and non-repainting modes. We revisit this often misunderstood and misused function, and explain its behavior in different contexts, in the hope of dispelling some of the coder lure surrounding it. The function is incredibly powerful, yet misused, it can become a dangerous WMD and an instrument of deception, for both coders and traders.
We will discuss:
• How to use our new `f_security()` function.
• The behavior of Pine code and security() on the three very different types of bars that make up any chart.
• Why what you see on a chart is a simulation, and should be taken with a grain of salt.
• Why we are presenting a new version of a function handling security() calls.
• Other topics of interest to coders using higher timeframe (HTF) data.
█ WARNING
We have tried to deliver a function that is simple to use and will, in non-repainting mode, produce reliable results for both experienced and novice coders. If you are a novice coder, stick to our recommendations to avoid getting into trouble, and DO NOT change our `f_security()` function when using it. Use `false` as the function's last argument and refrain from using your script at smaller timeframes than the chart's. To call our function to fetch a non-repainting value of close from the 1D timeframe, use:
f_security(_sym, _res, _src, _rep) => security(_sym, _res, _src )
previousDayClose = f_security(syminfo.tickerid, "D", close, false)
If that's all you're interested in, you are done.
If you choose to ignore our recommendation and use the function in repainting mode by changing the `false` in there for `true`, we sincerely hope you read the rest of our ramblings before you do so, to understand the consequences of your choice.
Let's now have a look at what security() is showing you. There is a lot to cover, so buckle up! But before we dig in, one last thing.
What is a chart?
A chart is a graphic representation of events that occur in markets. As any representation, it is not reality, but rather a model of reality. As Scott Page eloquently states in The Model Thinker : "All models are wrong; many are useful". Having in mind that both chart bars and plots on our charts are imperfect and incomplete renderings of what actually occurred in realtime markets puts us coders in a place from where we can better understand the nature of, and the causes underlying the inevitable compromises necessary to build the data series our code uses, and print chart bars.
Traders or coders complaining that charts do not reflect reality act like someone who would complain that the word "dog" is not a real dog. Let's recognize that we are dealing with models here, and try to understand them the best we can. Sure, models can be improved; TradingView is constantly improving the quality of the information displayed on charts, but charts nevertheless remain mere translations. Plots of data fetched through security() being modelized renderings of what occurs at higher timeframes, coders will build more useful and reliable tools for both themselves and traders if they endeavor to perfect their understanding of the abstractions they are working with. We hope this publication helps you in this pursuit.
█ FEATURES
This script's "Inputs" tab has four settings:
• Repaint : Determines whether the functions will use their repainting or non-repainting mode.
Note that the setting will not affect the behavior of the yellow plot, as it always repaints.
• Source : The source fetched by the security() calls.
• Timeframe : The timeframe used for the security() calls. If it is lower than the chart's timeframe, a warning appears.
• Show timeframe reminder : Displays a reminder of the timeframe after the last bar.
█ THE CHART
The chart shows two different pieces of information and we want to discuss other topics in this section, so we will be covering:
A — The type of chart bars we are looking at, indicated by the colored band at the top.
B — The plots resulting of calling security() with the close price in different ways.
C — Points of interest on the chart.
A — Chart bars
The colored band at the top shows the three types of bars that any chart on a live market will print. It is critical for coders to understand the important distinctions between each type of bar:
1 — Gray : Historical bars, which are bars that were already closed when the script was run on them.
2 — Red : Elapsed realtime bars, i.e., realtime bars that have run their course and closed.
The state of script calculations showing on those bars is that of the last time they were made, when the realtime bar closed.
3 — Green : The realtime bar. Only the rightmost bar on the chart can be the realtime bar at any given time, and only when the chart's market is active.
Refer to the Pine User Manual's Execution model page for a more detailed explanation of these types of bars.
B — Plots
The chart shows the result of letting our 5sec chart run for a few minutes with the following settings: "Repaint" = "On" (the default is "Off"), "Source" = `close` and "Timeframe" = 1min. The five lines plotted are the following. They have progressively thinner widths:
1 — Yellow : A normal, repainting security() call.
2 — Silver : Our recommended security() function.
3 — Fuchsia : Our recommended way of achieving the same result as our security() function, for cases when the source used is a function returning a tuple.
4 — White : The method we previously recommended in our MTF Selection Framework , which uses two distinct security() calls.
5 — Black : A lame attempt at fooling traders that MUST be avoided.
All lines except the first one in yellow will vary depending on the "Repaint" setting in the script's inputs. The first plot does not change because, contrary to all other plots, it contains no conditional code to adapt to repainting/no-repainting modes; it is a simple security() call showing its default behavior.
C — Points of interest on the chart
Historical bars do not show actual repainting behavior
To appreciate what a repainting security() call will plot in realtime, one must look at the realtime bar and at elapsed realtime bars, the bars where the top line is green or red on the chart at the top of this page. There you can see how the plots go up and down, following the close value of each successive chart bar making up a single bar of the higher timeframe. You would see the same behavior in "Replay" mode. In the realtime bar, the movement of repainting plots will vary with the source you are fetching: open will not move after a new timeframe opens, low and high will change when a new low or high are found, close will follow the last feed update. If you are fetching a value calculated by a function, it may also change on each update.
Now notice how different the plots are on historical bars. There, the plot shows the close of the previously completed timeframe for the whole duration of the current timeframe, until on its last bar the price updates to the current timeframe's close when it is confirmed (if the timeframe's last bar is missing, the plot will only update on the next timeframe's first bar). That last bar is the only one showing where the plot would end if that timeframe's bars had elapsed in realtime. If one doesn't understand this, one cannot properly visualize how his script will calculate in realtime when using repainting. Additionally, as published scripts typically show charts where the script has only run on historical bars, they are, in fact, misleading traders who will naturally assume the script will behave the same way on realtime bars.
Non-repainting plots are more accurate on historical bars
Now consider this chart, where we are using the same settings as on the chart used to publish this script, except that we have turned "Repainting" off this time:
The yellow line here is our reference, repainting line, so although repainting is turned off, it is still repainting, as expected. Because repainting is now off, however, plots on historical bars show the previous timeframe's close until the first bar of a new timeframe, at which point the plot updates. This correctly reflects the behavior of the script in the realtime bar, where because we are offsetting the series by one, we are always showing the previously calculated—and thus confirmed—higher timeframe value. This means that in realtime, we will only get the previous timeframe's values one bar after the timeframe's last bar has elapsed, at the open of the first bar of a new timeframe. Historical and elapsed realtime bars will not actually show this nuance because they reflect the state of calculations made on their close , but we can see the plot update on that bar nonetheless.
► This more accurate representation on historical bars of what will happen in the realtime bar is one of the two key reasons why using non-repainting data is preferable.
The other is that in realtime, your script will be using more reliable data and behave more consistently.
Misleading plots
Valiant attempts by coders to show non-repainting, higher timeframe data updating earlier than on our chart are futile. If updates occur one bar earlier because coders use the repainting version of the function, then so be it, but they must then also accept that their historical bars are not displaying information that is as accurate. Not informing script users of this is to mislead them. Coders should also be aware that if they choose to use repainting data in realtime, they are sacrificing reliability to speed and may be running a strategy that behaves very differently from the one they backtested, thus invalidating their tests.
When, however, coders make what are supposed to be non-repainting plots plot artificially early on historical bars, as in examples "c4" and "c5" of our script, they would want us to believe they have achieved the miracle of time travel. Our understanding of the current state of science dictates that for now, this is impossible. Using such techniques in scripts is plainly misleading, and public scripts using them will be moderated. We are coding trading tools here—not video games. Elementary ethics prescribe that we should not mislead traders, even if it means not being able to show sexy plots. As the great Feynman said: You should not fool the layman when you're talking as a scientist.
You can readily appreciate the fantasy plot of "c4", the thinnest line in black, by comparing its supposedly non-repainting behavior between historical bars and realtime bars. After updating—by miracle—as early as the wide yellow line that is repainting, it suddenly moves in a more realistic place when the script is running in realtime, in synch with our non-repainting lines. The "c5" version does not plot on the chart, but it displays in the Data Window. It is even worse than "c4" in that it also updates magically early on historical bars, but goes on to evaluate like the repainting yellow line in realtime, except one bar late.
Data Window
The Data Window shows the values of the chart's plots, then the values of both the inside and outside offsets used in our calculations, so you can see them change bar by bar. Notice their differences between historical and elapsed realtime bars, and the realtime bar itself. If you do not know about the Data Window, have a look at this essential tool for Pine coders in the Pine User Manual's page on Debugging . The conditional expressions used to calculate the offsets may seem tortuous but their objective is quite simple. When repainting is on, we use this form, so with no offset on all bars:
security(ticker, i_timeframe, i_source )
// which is equivalent to:
security(ticker, i_timeframe, i_source)
When repainting is off, we use two different and inverted offsets on historical bars and the realtime bar:
// Historical bars:
security(ticker, i_timeframe, i_source )
// Realtime bar (and thus, elapsed realtime bars):
security(ticker, i_timeframe, i_source )
The offsets in the first line show how we prevent repainting on historical bars without the need for the `lookahead` parameter. We use the value of the function call on the chart's previous bar. Since values between the repainting and non-repainting versions only differ on the timeframe's last bar, we can use the previous value so that the update only occurs on the timeframe's first bar, as it will in realtime when not repainting.
In the realtime bar, we use the second call, where the offsets are inverted. This is because if we used the first call in realtime, we would be fetching the value of the repainting function on the previous bar, so the close of the last bar. What we want, instead, is the data from the previous, higher timeframe bar , which has elapsed and is confirmed, and thus will not change throughout realtime bars, except on the first constituent chart bar belonging to a new higher timeframe.
After the offsets, the Data Window shows values for the `barstate.*` variables we use in our calculations.
█ NOTES
Why are we revisiting security() ?
For four reasons:
1 — We were seeing coders misuse our `f_secureSecurity()` function presented in How to avoid repainting when using security() .
Some novice coders were modifying the offset used with the history-referencing operator in the function, making it zero instead of one,
which to our horror, caused look-ahead bias when used with `lookahead = barmerge.lookahead_on`.
We wanted to present a safer function which avoids introducing the dreaded "lookahead" in the scripts of unsuspecting coders.
2 — The popularity of security() in screener-type scripts where coders need to use the full 40 calls allowed per script made us want to propose
a solid method of allowing coders to offer a repainting/no-repainting choice to their script users with only one security() call.
3 — We wanted to explain why some alternatives we see circulating are inadequate and produce misleading behavior.
4 — Our previous publication on security() focused on how to avoid repainting, yet many other considerations worthy of attention are not related to repainting.
Handling tuples
When sending function calls that return tuples with security() , our `f_security()` function will not work because Pine does not allow us to use the history-referencing operator with tuple return values. The solution is to integrate the inside offset to your function's arguments, use it to offset the results the function is returning, and then add the outside offset in a reassignment of the tuple variables, after security() returns its values to the script, as we do in our "c2" example.
Does it repaint?
We're pretty sure Wilder was not asked very often if RSI repainted. Why? Because it wasn't in fashion—and largely unnecessary—to ask that sort of question in the 80's. Many traders back then used daily charts only, and indicator values were calculated at the day's close, so everybody knew what they were getting. Additionally, indicator values were calculated by generally reputable outfits or traders themselves, so data was pretty reliable. Today, almost anybody can write a simple indicator, and the programming languages used to write them are complex enough for some coders lacking the caution, know-how or ethics of the best professional coders, to get in over their heads and produce code that does not work the way they think it does.
As we hope to have clearly demonstrated, traders do have legitimate cause to ask if MTF scripts repaint or not when authors do not specify it in their script's description.
► We recommend that authors always use our `f_security()` with `false` as the last argument to avoid repainting when fetching data dependent on OHLCV information. This is the only way to obtain reliable HTF data. If you want to offer users a choice, make non-repainting mode the default, so that if users choose repainting, it will be their responsibility. Non-repainting security() calls are also the only way for scripts to show historical behavior that matches the script's realtime behavior, so you are not misleading traders. Additionally, non-repainting HTF data is the only way that non-repainting alerts can be configured on MTF scripts, as users of MTF scripts cannot prevent their alerts from repainting by simply configuring them to trigger on the bar's close.
Data feeds
A chart at one timeframe is made up of multiple feeds that mesh seamlessly to form one chart. Historical bars can use one feed, and the realtime bar another, which brokers/exchanges can sometimes update retroactively so that elapsed realtime bars will reappear with very slight modifications when the browser's tab is refreshed. Intraday and daily chart prices also very often originate from different feeds supplied by brokers/exchanges. That is why security() calls at higher timeframes may be using a completely different feed than the chart, and explains why the daily high value, for example, can vary between timeframes. Volume information can also vary considerably between intraday and daily feeds in markets like stocks, because more volume information becomes available at the end of day. It is thus expected behavior—and not a bug—to see data variations between timeframes.
Another point to keep in mind concerning feeds it that when you are using a repainting security() plot in realtime, you will sometimes see discrepancies between its plot and the realtime bars. An artefact revealing these inconsistencies can be seen when security() plots sometimes skip a realtime chart bar during periods of high market activity. This occurs because of races between the chart and the security() feeds, which are being monitored by independent, concurrent processes. A blue arrow on the chart indicates such an occurrence. This is another cause of repainting, where realtime bar-building logic can produce different outcomes on one closing price. It is also another argument supporting our recommendation to use non-repainting data.
Alternatives
There is an alternative to using security() in some conditions. If all you need are OHLC prices of a higher timeframe, you can use a technique like the one Duyck demonstrates in his security free MTF example - JD script. It has the great advantage of displaying actual repainting values on historical bars, which mimic the code's behavior in the realtime bar—or at least on elapsed realtime bars, contrary to a repainting security() plot. It has the disadvantage of using the current chart's TF data feed prices, whereas higher timeframe data feeds may contain different and more reliable prices when they are compiled at the end of the day. In its current state, it also does not allow for a repainting/no-repainting choice.
When `lookahead` is useful
When retrieving non-price data, or in special cases, for experiments, it can be useful to use `lookahead`. One example is our Backtesting on Non-Standard Charts: Caution! script where we are fetching prices of standard chart bars from non-standard charts.
Warning users
Normal use of security() dictates that it only be used at timeframes equal to or higher than the chart's. To prevent users from inadvertently using your script in contexts where it will not produce expected behavior, it is good practice to warn them when their chart is on a higher timeframe than the one in the script's "Timeframe" field. Our `f_tfReminderAndErrorCheck()` function in this script does that. It can also print a reminder of the higher timeframe. It uses one security() call.
Intrabar timeframes
security() is not supported by TradingView when used with timeframes lower than the chart's. While it is still possible to use security() at intrabar timeframes, it then behaves differently. If no care is taken to send a function specifically written to handle the successive intrabars, security() will return the value of the last intrabar in the chart's timeframe, so the last 1H bar in the current 1D bar, if called at "60" from a "D" chart timeframe. If you are an advanced coder, see our FAQ entry on the techniques involved in processing intrabar timeframes. Using intrabar timeframes comes with important limitations, which you must understand and explain to traders if you choose to make scripts using the technique available to others. Special care should also be taken to thoroughly test this type of script. Novice coders should refrain from getting involved in this.
█ TERMINOLOGY
Timeframe
Timeframe , interval and resolution are all being used to name the concept of timeframe. We have, in the past, used "timeframe" and "resolution" more or less interchangeably. Recently, members from the Pine and PineCoders team have decided to settle on "timeframe", so from hereon we will be sticking to that term.
Multi-timeframe (MTF)
Some coders use "multi-timeframe" or "MTF" to name what are in fact "multi-period" calculations, as when they use MAs of progressively longer periods. We consider that a misleading use of "multi-timeframe", which should be reserved for code using calculations actually made from another timeframe's context and using security() , safe for scripts like Duyck's one mentioned earlier, or TradingView's Relative Volume at Time , which use a user-selected timeframe as an anchor to reset calculations. Calculations made at the chart's timeframe by varying the period of MAs or other rolling window calculations should be called "multi-period", and "MTF-anchored" could be used for scripts that reset calculations on timeframe boundaries.
Colophon
Our script was written using the PineCoders Coding Conventions for Pine .
The description was formatted using the techniques explained in the How We Write and Format Script Descriptions PineCoders publication.
Snippets were lifted from our MTF Selection Framework , then massaged to create the `f_tfReminderAndErrorCheck()` function.
█ THANKS
Thanks to apozdnyakov for his help with the innards of security() .
Thanks to bmistiaen for proofreading our description.
Look first. Then leap.
String Manipulation Framework [PineCoders FAQ]█ OVERVIEW
This script provides string manipulation functions to help Pine coders.
█ FUNCTIONS PROVIDED
f_strLeft(_str, _n)
Function returning the leftmost `_n` characters in `_str`.
f_strRight(_str, _n)
Function returning the rightmost `_n` characters in `_str`.
f_strMid(_str, _from, _to)
Function returning the substring of `_str` from character position `_from` to `_to` inclusively.
f_strLeftOf(_str, _of)
Function returning the sub-string of `_str` to the left of the `_of` separating character.
f_strRightOf(_str, _of)
Function returning the sub-string of `_str` to the right of the `_of` separating character.
f_strCharPos(_str, _chr)
Function returning the position of the first occurrence of `_chr` in `_str`, where the first character position is 0. Returns -1 if the character is not found.
f_strReplace(_src, _pos, _str)
Function that replaces a character at position `_pos` in the `_src` string with the `_str` character or string.
f_tickFormat()
Function returning a format string usable with `tostring()` to round a value to the symbol's tick precision.
f_tostringPad(_val, _fmt)
Function returning a string representation of a numeric `_val` using a special `_fmt` string allowing all strings to be of the same width, to help align columns of values.
`f_tostringPad()`
Using the functions should be straightforward, but `f_tostringPad()` requires more explanations. Its purpose is to help coders produce columns of fixed-width string representations of numbers which can be used to produce columns of numbers that vertically align neatly in labels, something that comes in handy when, for example, you need to center columns, yet still produce numbers of various lengths that nonetheless align.
While the formatting string used with this function resembles the one used in tostring() , it has a few additional characteristics:
• The question mark (" ? ") is used to indicate that padding is needed.
• If negative numbers must be handled by the function, the first character of the formatting string must be a minus sign ("-"),
otherwise the unary minus sign of negative numbers will be stripped out.
• You will produce more predictable results by using "0" rather than "#" in the formatting string.
You can experiment with `f_tostringPad()` formatting strings by changing the one used in the script's inputs and see the results on the chart.
These are some valid examples of formatting strings that can be used with `f_tostringPad()`:
"???0": forces strings to be four units wide, in all-positive "int" format.
"-???0": forces strings to be four units wide, plus room for a unary minus sign in the first position, in "int" format.
"???0.0": forces strings to be four units wide to the left of the point, all-positive, with a decimal point and then a mantissa rounded to a single digit.
"-???0.0?": same as above, but adds a unary minus sign for negative values, and adds a space after the single-digit mantissa.
"?????????0.0": forces the left part of the float to occupy the space of 10 digits, with a decimal point and then a mantissa rounded to a single digit.
█ CHART
The information displayed by this indicator uses the values in the script's Inputs, so you can use them to play around.
The chart shows the following information:
• Column 0 : The numeric input values in a centered column, converted to strings using tostring() without a formatting argument.
• Column 1 : Shows the values formatted using `f_tostringPad()` with the formatting string from the inputs.
• Column 2 : Shows the values formatted using `f_tostringPad()` but with only the part of the formatting string left of the decimal point, if it contains one.
• Column 3 : Shows the values formatted using `f_tostringPad()` but with the part of the formatting string left of the decimal point,
to which is added the right part of the `f_tostringPad()` formatting string, to obtain the precision in ticks of the symbol the chart is on.
• Column 4 : Shows the result of using the other string manipulation functions in the script on the source string supplied in the inputs.
It also demonstrates how to split up a label in two distinct parts so that you can vertically align columns when the leftmost part contains strings with varying lengths.
You will see in our code how we construct this column in two steps.
█ LIMITATIONS
The Pine runtime is optimized for number crunching. Too many string manipulations will take a toll on the performance of your scripts, as can readily be seen with the running time of this script. To minimize the impact of using string manipulation functions in your scripts, consider limiting their calculation to the first or last bar of the dataset when possible. This can be achieved by using the var keyword when declaring variables containing the result of your string manipulations, or by enclosing blocks of code in if blocks using barstate.isfirst or barstate.islast .
█ NOTES
To understand the challenges we face when trying to align strings vertically, it is useful to know that:
• As is the case in many other places in the TadingView UI and other docs, the Pine runtime uses the MS Trebuchet font to display label text.
• Trebuchet uses proportionally-spaced letters (a "W" takes more horizontal space than an "I"), but fixed-space digits (a "1" takes the same horizontal space as a "3").
Digits all use a figure space width, and it is this property that allows us to align numbers vertically.
The fact that letters are proportionally spaced is the reason why we can't vertically align columns using a "legend" + ":" `+ value structure when the "legend" part varies in width.
• The unary minus sign is the width of a punctuation space . We use this property to pad the beginning of numbers
when you use a "-" as the first character of the `f_tostringPad()` formatting string.
Our script was written using the PineCoders Coding Conventions for Pine .
The description was formatted using the techniques explained in the How We Write and Format Script Descriptions PineCoders publication.
█ THANKS
Thanks to LonesomeTheBlue for the `f_strReplace()` function.
Look first. Then leap.
Time Offset Calculation Framework - PineCoders FAQ█ OVERVIEW
Calculating time-based offsets is necessary when coders need to draw lines or labels into the future because using `xloc = xloc.bar_time` in `label.new()` or `line.new()` is then mandatory.
This script provides a function to help with those calculations:
f_timeFrom(_from, _qty, _units)
The function calculates a negative (into the past) or positive (into the future) offset from the current bar's starting or closing time, or from the current time of day.
The offset can be expressed in units of chart resolution, or in seconds, minutes, hours, days, months or years.
█ HOW TO USE THE FRAMEWORK
1. You will need to include the supplied `f_resInMinutes()` function in your script in order to use `f_timeFrom()`.
It is used to calculate offsets using chart units when `f_timeFrom(_, _, "chart")` is used.
2. Whether you use `f_timeFrom()` for labels or lines, remember to use `xloc = xloc.bar_time`, as the default is `xloc = xloc.bar_index`.
3. Use `f_timeFrom()` for the `x` argument in `label.new()`, or for `x1` or `x2` in `line.new()`.
It can of course also be used in the relevant `label.set_*()` or `line.set_*()` functions.
Examples
// Label 3 days into the future from current bar's time.
label.new(f_timeFrom("bar", 3, "days"), high, "time + 3 days", xloc.bar_time)
// Label 2 hours into the future from current time
label.new(f_timeFrom("now", 2, "hours"), high, "timenow + 3 hours", xloc.bar_time)
// Label at bar's time plus 4 units of the chart's resolution.
label.new(f_timeFrom("bar", 4, "chart"), high, "time + 3 chart units", xloc.bar_time)
The parameters are:
f_timeFrom(_from, _qty, _units) =>
// _from : starting time from where the offset is calculated: "bar" to start from the bar's starting time, "close" to start from the bar's closing time, "now" to start from the current time.
// _qty : the +/- qty of _units of offset required. A "series float" can be used but it will be cast to a "series int".
// _units : string containing one of the seven allowed time units: "chart" (chart's resolution), "seconds", "minutes", "hours", "days", "months", "years".
█ LIMITATIONS
While this function makes it easier for coders to calculate time offsets using a variety of methods, it does not solve the inherent problematic that offsets do not calculate accurately when bars are missing between the start and end times of the offset. There is currently no way to circumvent this challenge in Pine.
Missing bars will occur on holidays, during no-trade periods (including normal periods where markets are closed) and when there are irregularities in data feeds. Charts at seconds resolutions, for example, will often miss bars when there are no trades to update the feed. On hourly charts of non 24x7 markets, periods when the markets are closed will also cause irregularities, as will holidays on day charts.
Other irregularities can occur because of how the offsets are calculated. A calculation of a one second offset from the bar's time will end one bar further on daily charts, for example. `f_timeFrom()` is no panacea; it simply makes offsets easier to calculate, however imprecise they are.
█ HOW TO USE THIS SCRIPT
The script's Inputs allow you to specify an offset, its units and starting time, and control the frequency of bars where lines are drawn.
Use the Inputs to play around with the parameters; you will quickly notice the irregularities mentioned above and be able to judge the usefulness of time-based offsets on the type of chart you use.
Look first. Then leap.
MTF Oscillator Framework [PineCoders]This framework allows Pine coders to quickly build a complete multi-timeframe oscillator from any calculation producing values around a centerline, whether the values are bounded or not. Insert your calculation in the script and you have a ready-to-publish MTF Oscillator offering a plethora of presentation options and features.
█ HOW TO USE THE FRAMEWORK
1 — Insert your calculation in the `f_signal()` function at the top of the "Helper Functions" section of the script.
2 — Change the script's name in the `study()` declaration statement and the `alertcondition()` text in the last part of the "Plots" section.
3 — Adapt the default value used to initialize the CENTERLINE constant in the script's "Constants" section.
4 — If you want to publish the script, copy/paste the following description in your new publication's description and replace the "OVERVIEW" section with a description of your calculations.
5 — Voilà!
═════════════════════════════════════════════════════════════════════════
█ OVERVIEW
This oscillator calculates a directional value of True Range. When a bar is up, the positive value of True Range is used. A negative value is used when the bar is down. When there is no movement during the bar, a zero value is generated, even if True Range is different than zero. Because the unit of measure of True Range is price, the oscillator is unbounded (it does not have fixed upper/lower bounds).
True Range can be used as a metric for volatility, but by using a signed value, this oscillator will show the directional bias of progressively increasing/decreasing volatility, which can make it more useful than an always positive value of True Range.
The True Range calculation appeared for the first time in J. Welles Wilder's New Concepts in Technical Trading Systems book published in 1978. Wilder's objective was to provide a reliable measure of the effective movement—or range—between two bars, to measure volatility. True Range is also the building block used to calculate ATR (Average True Range), which calculates the average of True Range values over a given period using the `rma` averaging method—the same used in the calculation of another of Wilder's remarkable creations: RSI.
█ CONCEPTS
This oscillator's design stems from a few key concepts.
Relative Levels
Other than the centerline, relative rather than absolute levels are used to identify levels of interest. Accordingly, no fixed levels correspond to overbought/oversold conditions. Relative levels of interest are identified using:
• A Donchian channel (historical highs/lows).
• The oscillator's position relative to higher timeframe values.
• Oscillator levels following points in time where a divergence is identified.
Higher timeframes
Two progressively higher timeframes are used to calculate larger-context values for the oscillator. The rationale underlying the use of timeframes higher than the chart's is that, while they change less frequently than the values calculated at the chart's resolution, they are more meaningful because more work (trader activity) is required to calculate them. Combining the immediacy of values calculated at the chart's resolution to higher timeframe values achieves a compromise between responsiveness and reliability.
Divergences as points of interest rather than directional clues
A very simple interpretation of what constitutes a divergence is used. A divergence is defined as a discrepancy between any bar's direction and the direction of the signal line on that same bar. No attempt is made to attribute a directional bias to divergences when they occur. Instead, the oscillator's level is saved and subsequent movement of the oscillator relative to the saved level is what determines the bullish/bearish state of the oscillator.
Conservative coloring scheme
Several additive coloring conditions allow the bull/bear coloring of the oscillator's main line to be restricted to specific areas meeting all the selected conditions. The concept is built on the premise that most of the time, an oscillator's value should be viewed as mere noise, and that somewhat like price, it only occasionally conveys actionable information.
█ FEATURES
Plots
• Three lines can be plotted. They are named Main line , Line 2 and Line 3 . You decide which calculation to use for each line:
• The oscillator's value at the chart's resolution.
• The oscillator's value at a medium timeframe higher than the chart's resolution.
• The oscillator's value at the highest timeframe.
• An aggregate line calculated using a weighed average of the three previous lines (see the Aggregate Weights section of Inputs to configure the weights).
• The coloring conditions, divergence levels and the Hi/Lo channel always apply to the Main line, whichever calculation you decide to use for it.
• The color of lines 2 and 3 are fixed but can be set in the "Colors" section of Inputs.
• You can change the thickness of each line.
• When the aggregate line is displayed, higher timeframe values are only used in its calculation when they become available in the chart's history,
otherwise the aggregate line would appear much later on the chart. To indicate when each higher timeframe value becomes available,
a small label appears near the centerline.
• Divergences can be shown as small dots on the centerline.
• Divergence levels can be shown. The level and fill are determined by the oscillator's position relative to the last saved divergence level.
• Bull/bear markers can be displayed. They occur whenever a new bull/bear state is determined by the "Main Line Coloring Conditions".
• The Hi/Lo (Donchian) channel can be displayed, and its period defined.
• The background can display the state of any one of 11 different conditions.
• The resolutions used for the higher timeframes can be displayed to the right of the last bar's value.
• Four key values are always displayed in the Data Window (fourth icon down to the right of your chart):
oscillator values for the chart, medium and highest timeframes, and the oscillator's instant value before it is averaged.
Main Line Coloring Conditions
• Nine different conditions can be selected to determine the bull/bear coloring of the main line. All conditions set to "ON" must be met to determine the bull/bear state.
• A volatility state can also be used to filter the conditions.
• When the coloring conditions and the filter do not allow for a bull/bear state to be determined, the neutral color is used.
Signal
• Seven different averages can be used to calculate the average of the oscillator's value.
• The average's period can be set. A period of one will show the instant value of the oscillator,
provided you don't use linear regression or the Hull MA as they do not work with a period of one.
• An external signal can be used as the oscillator's instant value. If an already averaged external value is used, set the period to one in this indicator.
• For the cases where an external signal is used, a centerline value can be set.
Higher Timeframes
• The two higher timeframes are named Medium timeframe and Highest timeframe . They can be determined using one of three methods:
• Auto-steps: the higher timeframes are determined using the chart's resolution. If the chart uses a seconds resolution, for example,
the medium and highest resolutions will be 15 and 60 minutes.
• Multiples: the timeframes are calculated using a multiple of the chart's resolution, which you can set.
• Fixed: the set timeframes do not change with the chart's resolution.
Repainting
• Repainting can be controlled separately for the chart's value and the higher timeframe values.
• The default is a repainting chart value and non-repainting higher timeframe values. The Aggregate line will thus repaint by default,
as it uses the chart's value along with the higher timeframes values.
Aggregate Weights
• The weight of each component of the Aggregate line can be set.
• The default is equal weights for the three components, meaning that the chart's value accounts for one third of the weight in the Aggregate.
High Volatility
• This provides control over the volatility filter used in the Main line's coloring conditions and the background display.
• Volatility is determined to be high when the short-term ATR is greater than the long-term ATR.
Colors
• You can define your own colors for all of the oscillator's plots.
• The default colors will perform well on both white and black chart backgrounds.
Alerts
• An alert can be defined for the script. The alert will trigger whenever a bull/bear marker appears in the indicator's display.
The particular combination of coloring conditions and the display of bull/bear markers when you create the alert will thus determine when the alert triggers.
Once the alerts are created, subsequent changes to the conditions controlling the display of markers will not affect the existing alert(s).
• You can create multiple alerts from this script, each triggering on different conditions.
Backtesting & Trading Engine Signal Line
• An invisible plot named "BTE Signal" is provided. It can be used as an entry signal when connected to the PineCoders Backtesting & Trading Engine as an external input.
It will generate an entry whenever a marker is displayed.
Look first. Then leap.
Computing FIR Filters Using Arrays [WMA Example]Over the years, many FIR filters have been proposed by the Pine community, with the standard way of computing them being `for` loops. The arrival of arrays allows for a new, more efficient way to compute them.
This script provides a template showing how you can compute FIR filters using Pine arrays.
FIR Filters
FIR stands for "Finite Impulse Response", and is associated with types of filters whose impulse response reaches a steady state.
FIR filters are calculated using convolution, or more simply put, using a weighted sum between a set of filter coefficients and past input values over a finite window.
In Pine, FIR filters are generally computed inside a `for` loop executing three processes:
1- Computing the coefficients.
2- Summing all the computed coefficients.
3- Performing the weighted sum between the inputs values and the computed coefficients.
Then we divide the result of our weighted sum by the sum of the coefficients obtained in step 2.
Because the computations inside the `for` loop execute on each bar, execution time can be significant when the calculation of coefficients is complex. This is where arrays are handy, as we can compute the coefficients just once, store them into an array, and use them in a weighted sum without the need to recalculate them over and over. This drastically reduces the computation time required to calculate a FIR filter.
The new `array.sum()` function helps eliminate step 2, thus further decreasing computation time.
How to Use This Template
All you need to do is to put the code that computes your coefficients in the first `for` loop (variable `w`). If the code that computes your coefficients contains more than one line, just make sure your final coefficient is placed in variable `w` (or change the `value` argument in `array.push()`). Another option is to declare a function that computes the coefficients and use it instead of variable `w`.
Look first. Then leap.
Multi-Timeframe Configuration DemoThis is a developer friendly solution to the current PineScript limitation of not being able to easily configure presets for multiple timeframes.
If you're developing multi-timeframe strategies then you've no doubt done battle with built-in `input` function which only allows for a single default value. You've probably come up with all kinds of fancy workarounds, including messy hardcoding, and even gritting your teeth and patiently reentering all the necessary values each time you refresh the chart or change the timeframe. The last one is my personal favourite.
As you can see in the code below we have defined a `usePresets` condition which tells the script to use our preset configuration, otherwise the default `input` values will be used. If `usePresets` is false then we use our presets which are defined in a (fairly) easy to read condition chain with the help of some basic timeframe utility functions.
Obviously this is nothing groundbreaking, but its helped me clean up my scripts a bit, so hopefully it will help you too.