The functions we present here all fetch data from other sources than the chart the script is running on. That data can be:
These are the signatures of the functions in the request
namespace:
request.security(symbol, timeframe, expression, gaps, lookahead, ignore_invalid_symbol, currency) → series int/float/bool/color
request.security_lower_tf(symbol, timeframe, expression, ignore_invalid_symbol, currency) → <array with values of the same type as `expression`>
request.financial(symbol, financial_id, period, gaps, ignore_invalid_symbol, currency) → series float
request.dividends(ticker, field, gaps, lookahead, ignore_invalid_symbol, currency) → series float
request.earnings(ticker, field, gaps, lookahead, ignore_invalid_symbol, currency) → series float
request.splits(ticker, field, gaps, lookahead, ignore_invalid_symbol, currency) → series float
request.quandl(ticker, gaps, index, ignore_invalid_symbol, currency) → series float
Note
Functions in the request.*()
family have many different applications, and their use can be rather involved.
Accordingly, this page is quite lengthy.
Many of the functions in the request
namespace share common properties and parameters.
Before exploring each function in detail, let’s go over their common characteristics.
While the request.*()
functions return “series” results, which means they can be different on every bar,
their parameters require arguments of either “const”, “input” or “simple” form
because they must be known when the script begins execution on bar zero.
This also entails that, except for the expression
parameter in
request.security()
which allows a “series” argument, the arguments of request.*()
function calls cannot vary during the execution of a script, e.g.:
symbol
parameter in a request.security()
call must be a “simple string”. This means is can be determined through the script’s inputs, but it cannot then change on the script’s last bar, for example.
The same goes for its timeframe
parameter.expression
, i.e.,
gaps
, lookahead
, ignore_invalid_symbol
and currency
, require a “const” argument,
which means it must be known at compile time and cannot be determined through inputs.request.*()
functions cannot be used in local blocks of either conditional structures or loops, nor in library functions.
They can be used in user-defined functions.Think of request.*()
function calls as requiring all arguments needed for the function to execute on bar zero and
not varying during the script’s execution on all bars.
You can make multiple calls in one script and choose which result you will use based on “series” criteria that may vary bar to bar,
but all the necessary calls whose results you will be selecting from will need to have been previously made by the script,
available for choosing among them.
Because of the fact that one cannot turn request.*()
function calls on or off during the script’s execution,
the only way to improve the performance of scripts using such functions is to minimize the number of different calls defined in the script.
While a maximum of 40 calls can be made in any given script, programmers should strive to minimize the quantity of calls,
as they have a sizable impact on script performance.
A maximum of 40 calls to request.*()
functions is allowed per script.
See the page on limitations for more information.
All the request.*()
functions include the gaps
parameter in their signature.
Gaps are na values
(see the section on `na` if you are not familiar with it).
A script running on a 60min chart has access to prices such as close
on each bar of the chart. When retrieving data from other contexts, however, new values for that data may not be coming in for each new bar on the chart.
When fetching daily data on our 60min chart, for example, new data will not be coming in on every chart bar.
A choice must thus be made as to how the data from the outside context will be merged on chart bars.
That behavior is what the gaps
parameter controls.
When functions do not return a value on each of the chart bars the calling script is running on, one must determine if the function should return na values in those cases (barmerge.gaps_on), or the latest non-na value returned by the function (barmerge.gaps_off).
In cases where no gaps are allowed, the last non-na value will repeat on chart bars until a new value comes in. This shows the diffence between using gaps or not:
//@version=5
indicator("gaps", "", true)
noGaps = request.security(syminfo.tickerid, "1", close)
withGaps = request.security(syminfo.tickerid, "1", close, gaps = barmerge.gaps_on)
plot(noGaps, "noGaps", color.blue, 3, plot.style_linebr)
plot(withGaps, "withGaps", color.fuchsia, 12, plot.style_linebr)
bgcolor(barstate.isrealtime ? #00000020 : na)
Note that:
noGaps
shows no gaps. We initialize noGaps
using a request.security()
call that does not specify a value for the gaps
parameter, so the default
barmerge.gaps_off is used.withGaps
shows gaps.All the request.*()
functions include the ignore_invalid_symbol
parameter in their signature.
The parameter’s values can be true
or false
(the default).
It controls the behavior of functions when they are used with arguments that cannot produce valid results, e.g.:
period
requested is not available.When the default ignore_invalid_symbol = false
is used, a runtime error will be generated and the script will stop when no result can be returned.
When ignore_invalid_symbol = true
is used, rather than throwing a runtime error, the function will return na.
This script demonstrates how to use ignore_invalid_symbol = true
to handle invalid results when requesting
the shares outstanding for stocks. It will only display information on instruments where valid data can be obtained:
//@version=5
indicator("", "", true)
printTable(txt) => var table t = table.new(position.middle_right, 1, 1), table.cell(t, 0, 0, txt, bgcolor = color.yellow, text_size = size.huge)
TSO = request.financial(syminfo.tickerid, "TOTAL_SHARES_OUTSTANDING", "FQ", ignore_invalid_symbol = true)
MarketCap = TSO * close
if not na(MarketCap) and barstate.islast
txt = "Market cap\n" + str.tostring(MarketCap, format.volume) + " " + syminfo.currency
printTable(txt)
Note that:
ignore_invalid_symbol = true
in our
request.financial() call.
This will produce na results when the function cannot return a valid value.TSO
value to calculate the stock’s MarketCap
.not na(MarketCap)
condition prevents us from displaying anything when TSO
— and thus MarketCap
— is na.barstate.islast
condition ensures we only make a call to printTable(txt)
on the chart’s last bar.
It would be inefficient to call it on each bar.txt
variable.
"Market cap\n"
is our legend, with a newline character.
str.tostring(MarketCap, format.volume)
converts the MarketCap
“float” value to a string, formatting it like volume, by abbreviating large values.
Adding syminfo.currency
provides script users with the instrument’s quote currency.
In our example, Tencent is traded on HKEX, Hong Kong’s stock exchange, so the currency is HKD, the Hong Kong dollar.printTable()
function declared just after our script’s
indicator() declaration statement handles the table code.All the request.*()
functions also include the currency
parameter in their signature.
It allows conversion of the value returned by the function to another currency.
The currency being converted from is the symbol’s quote currency, i.e., syminfo.currency,
which is determined by the exchange it trades on.
The currency being converted to is the value used for the currency
parameter,
which can be any currency in the ISO 4217 format,
or one of the currency built-ins in the currency.XXX
format, such as currency.JPY.
The conversion rates used are based on the FX_IDC pairs’ daily rates of the previous day, relative to the bar where the calculation occurs.
When no instrument exists to determine a particular pair’s conversion rate, a spread is used. For example, to convert ZAR to USD,
the ZARUSD*USDHKD
spread would be used, as there is no instrument providing a ZARUSD
rate.
Note
Not all values returned by request.*()
functions may be in currency, so it does not always make sense to convert them into another currency.
When requesting financial information with request.financial()
or request.quandl()
for example, many of the values are ratios, or expressed in other units than currency, such as PIOTROSKI_F_SCORE
or NUMBER_OF_EMPLOYEES
.
It is the programmer’s responsibility to determine when currency conversion is applicable.
The lookahead
parameter controls whether future data is returned by the
request.security(),
request.dividends(),
request.earnings() and
request.splits() functions.
In order to avoid future leak, or lookahead bias, which produces unrealistic results, it should generally be avoided — or treated with extreme caution.
lookahead
is only useful in special circumstances, when it doesn’t compromise the integrity of your script’s logic, e.g.:
close[1]
), to produce non-repainting
request.security() calls.The parameter only affects the script’s behavior on historical bars, as there are no future bars to look forward to in realtime, where the future is unknown — as it should.
Note
Using lookahead = barmerge.lookahead_on
when fetching price information, or calculations depending on prices, causes future leak,
which means your script is using future information it should not have access to.
Except in rare cases, this is a very bad idea. Using request.*()
functions this way is misleading, and not allowed in script publications.
It is considered a serious violation of Script publishing rules,
so it is your responsability, if you publish scripts, to ensure you do not mislead users of your script by using future information on historical bars.
While your plots on historical bars will look great because your script will magically acquire prescience (which will not reproduce in realtime, by the way),
you will be misleading users of your scripts — and yourself.
The default value for lookahead
is barmerge.lookahead_off.
To enable it, use barmerge.lookahead_on.
This example shows why using lookahead = barmerge.lookahead_on
to fetch price information can be so dangerous.
We retrieve the 1min high from a 5sec chart
and show the difference in results between using
barmerge.lookahead_on (bad, in red) and
barmerge.lookahead_off (good, in gray):
//@version=5
indicator("lookahead", "", true)
lookaheadOn = request.security(syminfo.tickerid, '1', high, lookahead = barmerge.lookahead_on)
lookaheadOff = request.security(syminfo.tickerid, '1', high, lookahead = barmerge.lookahead_off)
plot(lookaheadOn, "lookaheadOn", color.new(color.red, 60), 6)
plot(lookaheadOff, "lookaheadOff", color.gray, 2)
bgcolor(barstate.isrealtime ? #00000020 : na)
Note that:
Note
In Pine Script™ v1 and v2, security()
did not include a lookahead
parameter, but it behaved as it does in later versions of Pine Script™
with lookahead = barmerge.lookahead_on
, which means it was systematically using future data.
Scripts written with Pine Script™ v1 or v2 and using security()
should therefore be treated with caution, unless they offset the series fetched, e.g., using close[1]
.
The request.security() function is used to request data from other contexts than the chart’s. Those different contexts may be:
ticker.*()
functions
(see this page’s Other contexts, with `ticker.new()` section)The function’s signature is:
request.security(symbol, timeframe, expression, gaps, lookahead, ignore_resolve_errors, currency) → series int/float/bool/color/string
request.security(symbol, timeframe, expression, gaps, lookahead, ignore_resolve_errors, currency) → series int[]/float[]/bool[]/color[]/string[]
symbol
This is the ticker identifier of the symbol whose information is to be fetched. It must be of “simple string” type and can be defined in multiple ways:
- With a literal string containing either a simple ticker like
"IBM"
or"EURUSD"
, or an exchange:symbol pair like"NYSE:IBM"
or"OANDA:EURUSD"
. When an exchange is not provided, a default exchange will be used when it is possible. You will obtain more reliable results by specifying the exchange.- Using the syminfo.ticker or syminfo.tickerid built-in variables, which respectively return only the ticker or the exchange:ticker information of the chart’s symbol. It is recommended to use syminfo.tickerid to avoid ambiguity. See the Symbol information section for more information. Note that an empty string can also be supplied as a value, in which case the chart’s symbol is used.
- Spreads can also be used, e.g.,
"AAPL/BTCUSD"
or"ETH/BTC"
. Note that spreads will not replay in “Replay mode”.- A ticker identifier created using ticker.new(), which provides access to data from non-standard charts, extended hours or other contexts (see the Other contexts, with `ticker.new()` section of this page).
timeframe
expression
This script uses request.security() to fetch the high and low values of a user-defined symbol and timeframe:
//@version=5
indicator("Symbol/TF")
symbolInput = input.symbol("", "Symbol & timeframe", inline = "1")
tfInput = input.timeframe("", "", inline = "1")
[hi, lo] = request.security(symbolInput, tfInput, [high, low])
plot(hi, "hi", color.lime, 3)
plot(lo, "lo", color.fuchsia, 3)
plotchar(ta.change(time(tfInput)), "ta.change(time(tfInput))", "•", location.top, size = size.tiny)
plotchar(barstate.isrealtime, "barstate.isrealtime", "•", location.bottom, color.red, size = size.tiny)
Note that:
inline = "1"
in both input.*()
calls.The request.security() function makes it possible for scripts to request data from other timeframes than the one the chart is running on, which can be done while also accessing another symbol, or not. When another timeframe is accessed, it can be:
The behavior of request.security() when accessing higher and lower timeframes is very different. We assume in our discussions that higher timeframes are accessed, but we also discuss the special cases when lower timeframes are accessed in a dedicated section.
Scripts not written specifically to use lower timeframe data, when they are published for a broader audience, should ideally include protection against running them on chart timeframes where request.security() would be accessing lower timeframes than the chart’s, as it will not produce reliable results in those cases. See the Comparing timeframes section for a code example providing error-checking to avoid just that.
Different data feeds supplied by exchanges/brokers can be used to display information about an instrument on charts:
Not all of these types of feed may exist for every instrument. “ICEEUR:BRN1!” for example, only has EOD data.
For some instruments where both intraday and EOD historical feeds exist, volume data will not be the same because some trades (block trades, OTC trades, etc.) may only be reported at the end of the day. That volume will thus appear in the EOD feed, but not in the intraday feed. Differences in volume data are almost inexistent in the crypto sector, but commonplace in stocks.
Slight prices discrepancies may also occur between both feeds, such that the high for one day’s bar on the EOD feed may not match any of the high values of intraday bars for that day.
Another distinction between intraday and EOD feeds is that EOD feeds do not contain data from extended hours.
These differences may account for variations in the values fetched by request.security() when it is accessing data from varying timeframes, thus shifting between intraday and EOD feeds. The differences may also cause discrepancies between data received in realtime vs the way it is reported on historical data. There are no steadfast rules about the variations. To understand their details, one must consult the exchange/broker information on the feeds available for each of their markets. As a rule, TradingView does not generate data; it relies on its data providers for the information displayed on charts.
The data fetched using request.security()
is specified with the expression
parameter. It can be of types “int”, “float”, “bool”, “color”, or an “array”. Strings are thus not allowed.
The expression supplied to request.security() can be:
One relatively new feature on Pine Script™ is the inclusion of arrays which we will go over in depth in a separate article. In short, arrays are a fairly complicated topic so not a recommended area to cover for a new Pine Script™ programmer. They are special data structures that are one-dimensional and can be used to hold a collection of multiple values.
//@version=5
indicator("New 60 Minute Highs")
var highs = array.new_float(0)
if ta.rising(high, 1)
array.push(highs, high)
src = request.security('AAPL', '60', highs)
float[] srcArray = array.copy(src)
plot(array.size(srcArray) > 0 ? array.pop(srcArray) : na)
Note that we are initializing an array at the first index by using the var keyword and adding new 2 bar highs to this array as they appear. We use this array structure in a security function so we can easily use a custom timeframe like 60 minutes in our example. This allows us to use this same array format to use in a security call in combination with any timeframe.
The request.security() function is extremely versatile and can easily be used in combination with one of TradingView’s many built-in indicators. A common use case would be to plot different timeframes of a built-in indicator on the same chart.
Consider for example you are on a 5 minute chart and want to plot the 20 period SMA for the 1 day timeframe you might try the following:
src = request.security('AAPL', '1D', close)
sma = ta.sma(src, 20)
This would actually give you incorrect output because when you are on a lower timeframe, the security function would probably return 20 copies of the same daily bar since the current timeframe most likely falls on the same day. What you would want to do instead is pass in the built-in indicator directly into the security call and allow TradingView to calculate it properly on their end by doing the following instead:
sma = request.security('AAPL', '1D', ta.sma(close, 20))
Here is an example showing how you can easily plot a built-in indicator such as RSI for both the 5 minute and 30 minute timeframes on the same chart:
//@version=5
indicator("Relative Strength Index MTF", "RSI")
sym = input.symbol('AAPL')
rsi1 = request.security(sym, '5', ta.rsi(close, 14))
rsi2 = request.security(sym, '30', ta.rsi(close, 14))
plot(rsi1, color=color.red)
plot(rsi2, color=color.blue)
One can declare the following variable:
spread = high - low
and calculate it at 1 minute, 15 minutes and 60 minutes:
spread_1 = request.security(syminfo.tickerid, '1', spread)
spread_15 = request.security(syminfo.tickerid, '15', spread)
spread_60 = request.security(syminfo.tickerid, '60', spread)
The request.security() function
returns a series which is then adapted to the time scale of
the current chart’s symbol. This result can be either shown directly on
the chart (i.e., with plot
), or used in further calculations.
The “Advance Decline Ratio” script illustrates a more
involved use of request.security():
//@version=5
indicator("Advance Decline Ratio", "ADR")
ratio(t1, t2, source) =>
s1 = request.security(t1, timeframe.period, source)
s2 = request.security(t2, timeframe.period, source)
s1 / s2
plot(ratio("USI:ADVN.NY", "USI:DECL.NY", close))
The script requests two additional securities. The results of the requests are then used in an arithmetic formula. As a result, we have a stock market indicator used by investors to measure the number of individual stocks participating in an upward or downward trend.
A more advanced way of using the request.security() function
would be to pass in a user defined function into the expression
parameter. This would allow you to create a custom function and then
use this function to plot the results for different timeframes or for different symbols on the same chart. Keep in mind that the same limitations
for security functions apply when using function calls, so for example you wouldn’t be able to use a custom function that returns a string.
//@version=5
indicator("`request.security()` User Defined Function Example")
f_udf(_src, _length, _lbLength) =>
uCount = 0, dCount = 0
for i = 0 to _length - 1 by 1
uCount += (nz(_src[i]) > nz(src[i + _lbLength]) ? 1 : 0)
dCount += (nz(_src[i]) < nz(src[i + _lbLength]) ? 1 : 0)
[uCount, dCount]
[upCount, dnCount] = f_udf(close, 9, 4)
sym = input.symbol('AAPL')
// We are using a blank string for the timeframe so it defaults to the current timeframe
plot(request.security(sym, ' ', upCount)
plot(request.security(sym, ' ', dnCount)
Note that: this is a bit more complicated example that plots the sum amount of bars that were higher than X bars ago and vice versa. We are using a user defined function to create a tuple with our output which is the sum of up bars and the sum of down bars. We pass in a variable from the tuple and Pine Script™ handles the heavy lifting for us.
Tuples are a special data structure that is immutable (meaning it can’t be changed once it is created). They can be used to combine different variables into a single variable that you can reference much easier and using fewer lines of code. This is very handy for use cases where you would like to declare a variable once and then reference it multiple times such as the following:
//@version=5
indicator("`request.security()` Tuple Example")
[h5, l5] = request.security('AAPL', '5', [high, low])
plot(math.avg(h5, high))
plot(math.avg(l5, low))
plot(math.avg(h5, l5))
Note that: we are creating a tuple variable using a request security function and we set the expression
parameter to a tuple containing
the 5 minute timeframe high
and low
. We are then plotting the average of the current timeframe and the aforementioned 5 minute timeframe
as well as the midpoint of our tuple values.
The behavior of request.security() on historical and realtime bars is not the same. On historical bars, new values come in at the close of the last chart bar in the higher timeframe bar. Values then do not move until another timeframe completes, which accounts for the staircase effect of higher timeframe values. In realtime, however, request.security() will return the current value of the incomplete higher timeframe bar, which causes it to vary during a realtime bar, and accross all bars until the close of the last realtime bar marking the end of the higher timeframe bar, at which point its value is final.
These fluctuating values of request.security() values in realtime can sometimes be just what is needed by a script’s logic — if it using volume information, for example, and needs the current volume transacted at the current point in time of the incomplete higher timeframe bar. Fluctuating values are also called repainting values.
In other circumstances, for example when a script is using higher timeframe information to provide a broader context to the script executing on a lower timeframe, one will often need confirmed and stable — as opposed to fluctuating — higher timeframe values. These are called non-repainting values because they are fixed values from a the previously completed higher timeframe bar only.
In general, barmerge.lookahead_on
should only be used when the series is offset, as when you want to avoid repainting:
//@version=5
//...
a = request.security(syminfo.tickerid, 'D', close[1], lookahead = barmerge.lookahead_on)
If you use barmerge.lookahead_off
, a non-repainting value can still be achieved, but it’s more complex:
//@version=5
//...
indexHighTF = barstate.isrealtime ? 1 : 0
indexCurrTF = barstate.isrealtime ? 0 : 1
a0 = request.security(syminfo.tickerid, 'D', close[indexHighTF], lookahead = barmerge.lookahead_off)
a = a0[indexCurrTF]
When an indicator is based on historical data (i.e.,
barstate.isrealtime
is false
), we take the current close of
the daily timeframe and shift the result of request.security()
function call one bar to the right in the current timeframe. When an indicator is calculated on
realtime data, we take the close of the previous day without shifting the
request.security() data.
The request.security() function was designed to request data of a timeframe higher than the current chart timeframe. On a 60 minutes chart, this would mean requesting 240, D, W, or any higher timeframe.
However if you are on a 60 minutes chart and want to use the data from the 1 minute bars, you would need
to specifically use the new request.security_lower_tf()
function. If you were to use the request.security()
function in our example you would actually only get the final minute bar for the last hour since barmerge.lookahead_off
is the default.
If you were to use barmerge.lookahead_on
then you would get the first minute bar instead.
This is why we added the request.security_lower_tf() function so you will now receive an array containing all of the minute bars in the last hour as per our example. The returned array will contain all of the available intrabars sorted by the timestamp in ascending order. However if you were to request a lower timeframe that is equal or higher than the current timeframe, you would get a runtime error. You can now do further calculations on this array as per our example below.
//@version=5
indicator("`request.security_lower_tf()` Example")
float travel = math.abs(high - low)
float[] ltfTravelArray = request.security_lower_tf(syminfo.tickerid, "1", travel)
float volatility = nz(array.sum(ltfTravelArray) / travel)
plot(volatility)
This function returns economic data for a given country or region (i.e. US or EU). Economic data includes information such as the state of a country’s economy (GDP, inflation rate, etc.) or of a particular industry (steel production, ICU beds, etc.).
The signature of request.economic() is:
request.economic(country_code, field, gaps, ignore_invalid_symbol) → series float
We have covered the last two parameters in the Common characteristics section of this page. The first two parameters require a “simple string” argument. They are:
country_code
field
This example plots the current US GDP values
//@version=5
indicator("Economic Data Example")
e = request.economic("US", "GDP")
plot(e)
Note that:
- You will receive an error if the requested metric is not available for the country or region you have selected.
- You can also view this data on a chart like you would with a symbol so for this example you would replace
the exchange name with Economic and the symbol name with a single string combining the
country_code
withfield
. For this example you would use “/”Economic.USGDP”/” in the symbol search box.
An easy method to determine the financial strength of a stock is using earnings data so we offer three options to receive the latest earnings data for a given stock: request.dividends(), request.earnings() and request.splits(). Much of the underlying data of a stock can be interpreted using these metrics but also keep in mind that not all stocks will have these stats available. Small cap stocks for example are not known for giving out dividends.
It is important to remember that data for these functions is only available as the data comes in. This differs from the financial data originating from the request.financial() function in that the underlying financial data becomes available according to the current fiscal period for the underlying financial instrument.
Below we have included an example that creates a handy table containing the latest earnings data for each stock using these three metrics.
//@version=5
indicator("Dividends, Splits, and Earnings Example")
dividends = request.dividends(syminfo.tickerid)
splitsNum = request.splits(syminfo.tickerid, splits.numerator)
splitsDenom = request.splits(syminfo.tickerid, splits.denominator)
earnings = request.earnings(syminfo.tickerid)
plot(earnings, color=color.blue)
plot(dividends, color=color.red)
if barstate.islast
string tableText = "Current Stats \n\n Dividends: " + str.tostring(dividends) + "\n Splits: " + str.tostring(splitsNum) +
"/" + str.tostring(splitsDenom) + " \n Earnings: " + str.tostring(earnings)
var table t = table.new(position.middle_right, 1, 3), table.cell(t, 0, 0, tableText, bgcolor = color.lime)
Note that:
TradingView has partnered with many fintech companies to provide our users with vast amounts of information on everything from crypto to stocks and much much more. One of our partners is Quandl and we have an example below that shows you how easy it is use this request function. Quandl has hundreds of thousands of available feeds and was recently purchased by Nasdaq so the url may be changed to reflect that. Below we have an example showing you a small glimpse of the vast amount of data available.
//@version=5
indicator("Quandl Example")
// We are displaying FRED (Federal Reserve Economic Data) from Quandl showing the Federal Funds Rate as well as the current unemployment rate.
f1 = request.quandl("FRED/FEDFUNDS", barmerge.gaps_off, 0)
f2 = request.quandl("FRED/UNRATE", barmerge.gaps_off, 0)
// Here we are displaying Bitcoin data showing the miner's revenue rate as well as the difficulty of completing the calculations.
b1 = request.quandl("BCHAIN/MIREV", barmerge.gaps_off, 0)
b2 = request.quandl("BCHAIN/DIFF", barmerge.gaps_off, 0)
// The following 2 examples shows how to properly use the index parameter.
// We are displaying Quandl data for University of Michigan Consumer Surveys with index 0 is a percentage of consumers
who believe it is a good time to buy a house, and index 2 is a percentage of consumers who believe it is a bad time to buy a house.
m1 = request.quandl("UMICH/SOC35", barmerge.gaps_off, 0)
m2 = request.quandl("UMICH/SOC35", barmerge.gaps_off, 2)
plot(na)
Note that:
- The `barmerge.gaps_off` is used to remove any `na` values so we don't have any gaps in the plotted data.
- For the `ticker` parameter, you need to specifically use the Quandl symbol matching the data that you want to import.
- For the `index` parameter, you need to make sure to match the index information given on `Quandl <https://data.nasdaq.com/search?filters=%5B%22Quandl%22%5D>`__
- For a full list of available Quandl data feeds, you can go `here <https://data.nasdaq.com/search?filters=%5B%22Quandl%22%5D>`__.
This function returns a financial metric from FactSet for a given fiscal period. More than 200 financial metrics are available, although not for every symbol or fiscal period. Note that financial data is also available on TradingView through the chart’s “Fundamental metrics for stocks” button in the top menu.
It is important to remember that data for this function is only available according to the current fiscal period for the underlying financial instrument. This differs from the request.dividends(), request.earnings(), and request.splits() functions in that the underlying financial data becomes available immediately.
The signature of request.financial() is:
request.financial(symbol, financial_id, period, gaps, ignore_invalid_symbol, currency) → series float
We have covered the last three parameters in the Common characteristics section of this page. The first three parameters all require a “simple string” argument. They are:
symbol
financial_id
period
"FQ"
(quarterly), "FY"
(yearly) and "TTM"
(trailing twelve months).
Not all frequencies are available for all metrics. Possible values for each metric are listed in the second column of the Financial IDs section below.
Note that each frequency is fixed and independent of the exact date where the data is made available within each period.
If for dividends or earnings you require the data when it is made available, use
request.dividends() or
request.earnings() instead.This plots the quarterly value of accounts payable for Apple:
//@version=5
indicator("")
f = request.financial("NASDAQ:AAPL", "ACCOUNTS_PAYABLE", "FQ")
plot(f)
Note that:
Some common financial metrics cannot be fetched with request.financial() because they require combining metrics with an instrument’s current chart price. Such is the case for:
Here, we calculates all five values:
//@version=5
indicator("")
// ————— Market capitalization
marketCap() =>
totalSharesOutstanding = request.financial(syminfo.tickerid, "TOTAL_SHARES_OUTSTANDING", "FQ")
marketCap = totalSharesOutstanding * close
// ————— Earnings yield
earningsYield() =>
earningsPerShare = request.financial(syminfo.tickerid, "EARNINGS_PER_SHARE", "TTM")
earningsYield = (earningsPerShare / close) * 100
// ————— Price Book Ratio
priceBookRatio() =>
bookValuePerShare = request.financial(syminfo.tickerid, "BOOK_VALUE_PER_SHARE", "FQ")
priceBookRatio = close / bookValuePerShare
// ————— Price Earnings Ratio
priceEarningsRatio() =>
earningsPerShare = request.financial(syminfo.tickerid, "EARNINGS_PER_SHARE", "TTM")
priceEarningsRatio = close / earningsPerShare
// ————— Price Sales Ratio
priseSalesRatio() =>
totalSharesOutstanding = request.financial(syminfo.tickerid, "TOTAL_SHARES_OUTSTANDING", "FQ")
mktCap = totalSharesOutstanding * close
totalRevenue = request.financial(syminfo.tickerid, "TOTAL_REVENUE", "TTM")
priseSalesRatio = mktCap / totalRevenue
plot(earningsYield(), "Earnings yield", color.aqua, 2)
plot(priceBookRatio(), "Price Book Ratio", color.orange, 2)
plot(priceEarningsRatio(), "Price Earnings Ratio", color.purple, 2)
plot(priseSalesRatio(), "Price Sales Ratio", color.teal, 2)
// ————— Display market cap using a label because its values are too large compared to the others.
// New function using gaps.
marketCapWithGaps() =>
totalSharesOutstanding = request.financial(syminfo.tickerid, "TOTAL_SHARES_OUTSTANDING", "FQ", gaps = barmerge.gaps_on)
mktCapGaps = totalSharesOutstanding * close
// Convert value to a string, abbreviating large values as is done for volume. Add currency.
mktCapGapsTxt = str.tostring(marketCapWithGaps(), format.volume) + " " + syminfo.currency
// Label's y position is the highest value among the last 50 of the four plotted values.
labelY = ta.highest(math.max(earningsYield(), priceBookRatio(), priceEarningsRatio(), priseSalesRatio()), 50)
// When the function returns a value instead of `na`, display a label.
if not na(marketCapWithGaps())
label.new(bar_index, labelY, mktCapGapsTxt, color = color.new(color.blue, 85), size = size.large)
Note that:
All financial metrics available with request.financial() is listed below. The table columns contain the following information:
period
column lists the arguments that can be used for the namesake parameter in
request.financial().
Only one period can be used per function call. Not all periods are available for all metrics.financial_id
column lists the string to be used for the financial_id
parameter.Metrics are divided in four categories:
Financial | period |
financial_id |
|
After tax other income/expense | FQ, FY | AFTER_TAX_OTHER_INCOME | |
Average basic shares outstanding | FQ, FY | BASIC_SHARES_OUTSTANDING | |
Other COGS | FQ, FY | COST_OF_GOODS_EXCL_DEP_AMORT | |
Cost of goods | FQ, FY | COST_OF_GOODS | |
Deprecation and amortization | FQ, FY | DEP_AMORT_EXP_INCOME_S | |
Diluted net income available to common stockholders | FQ, FY | DILUTED_NET_INCOME | |
Diluted shares outstanding | FQ, FY | DILUTED_SHARES_OUTSTANDING | |
Dilution adjustment | FQ, FY | DILUTION_ADJUSTMENT | |
Discontinued operations | FQ, FY | DISCONTINUED_OPERATIONS | |
Basic EPS | FQ, FY, TTM | EARNINGS_PER_SHARE_BASIC | |
Diluted EPS | FQ, FY | EARNINGS_PER_SHARE_DILUTED | |
EBIT | FQ, FY | EBIT | |
EBITDA | FQ, FY, TTM | EBITDA | |
Equity in earnings | FQ, FY | EQUITY_IN_EARNINGS | |
Gross profit | FQ, FY | GROSS_PROFIT | |
Taxes | FQ, FY | INCOME_TAX | |
Interest capitalized | FQ, FY | INTEREST_CAPITALIZED | |
Interest expense on debt | FQ, FY | INTEREST_EXPENSE_ON_DEBT | |
Non-controlling/minority interest | FQ, FY | MINORITY_INTEREST_EXP | |
Net income before discontinued operations | FQ, FY | NET_INCOME_BEF_DISC_OPE | |
Net income | FQ, FY | NET_INCOME | |
Non-operating income, excl. interest expenses | FQ, FY | NON_OPER_INCOME | |
Interest expense, net of interest capitalized | FQ, FY | NON_OPER_INTEREST_EXP | |
Non-operating interest income | FQ, FY | NON_OPER_INTEREST_INCOME | |
Operating income | FQ, FY | OPER_INCOME | |
Operating expenses (excl. COGS) | FQ, FY | OPERATING_EXPENSES | |
Miscellaneous non-operating expense | FQ, FY | OTHER_INCOME | |
Other operating expenses, total | FQ, FY | OTHER_OPER_EXPENSE_TOTAL | |
Preferred dividends | FQ, FY | PREFERRED_DIVIDENDS | |
Pretax equity in earnings | FQ, FY | PRETAX_EQUITY_IN_EARNINGS | |
Pretax income | FQ, FY | PRETAX_INCOME | |
Research & development | FQ, FY | RESEARCH_AND_DEV | |
Selling/general/admin expenses, other | FQ, FY | SELL_GEN_ADMIN_EXP_OTHER | |
Selling/general/admin expenses, total | FQ, FY | SELL_GEN_ADMIN_EXP_TOTAL | |
Non-operating income, total | FQ, FY | TOTAL_NON_OPER_INCOME | |
Total operating expenses | FQ, FY | TOTAL_OPER_EXPENSE | |
Total revenue | FQ, FY | TOTAL_REVENUE | |
Unusual income/expense | FQ, FY | UNUSUAL_EXPENSE_INC |
Financial | period |
financial_id |
Accounts payable | FQ, FY | ACCOUNTS_PAYABLE |
Accounts receivable - trade, net | FQ, FY | ACCOUNTS_RECEIVABLES_NET |
Accrued payroll | FQ, FY | ACCRUED_PAYROLL |
Accumulated depreciation, total | FQ, FY | ACCUM_DEPREC_TOTAL |
Additional paid-in capital/Capital surplus | FQ, FY | ADDITIONAL_PAID_IN_CAPITAL |
Tangible book value per share | FQ, FY | BOOK_TANGIBLE_PER_SHARE |
Book value per share | FQ, FY | BOOK_VALUE_PER_SHARE |
Capitalized lease obligations | FQ, FY | CAPITAL_LEASE_OBLIGATIONS |
Capital and operating lease obligations | FQ, FY | CAPITAL_OPERATING_LEASE_OBLIGATIONS |
Cash & equivalents | FQ, FY | CASH_N_EQUIVALENTS |
Cash and short term investments | FQ, FY | CASH_N_SHORT_TERM_INVEST |
Common equity, total | FQ, FY | COMMON_EQUITY_TOTAL |
Common stock par/Carrying value | FQ, FY | COMMON_STOCK_PAR |
Current portion of LT debt and capital leases | FQ, FY | CURRENT_PORT_DEBT_CAPITAL_LEASES |
Deferred income, current | FQ, FY | DEFERRED_INCOME_CURRENT |
Deferred income, non-current | FQ, FY | DEFERRED_INCOME_NON_CURRENT |
Deferred tax assets | FQ, FY | DEFERRED_TAX_ASSESTS |
Deferred tax liabilities | FQ, FY | DEFERRED_TAX_LIABILITIES |
Dividends payable | FY | DIVIDENDS_PAYABLE |
Goodwill, net | FQ, FY | GOODWILL |
Income tax payable | FQ, FY | INCOME_TAX_PAYABLE |
Net intangible assets | FQ, FY | INTANGIBLES_NET |
Inventories - finished goods | FQ, FY | INVENTORY_FINISHED_GOODS |
Inventories - progress payments & other | FQ, FY | INVENTORY_PROGRESS_PAYMENTS |
Inventories - raw materials | FQ, FY | INVENTORY_RAW_MATERIALS |
Inventories - work in progress | FQ, FY | INVENTORY_WORK_IN_PROGRESS |
Investments in unconsolidated subsidiaries | FQ, FY | INVESTMENTS_IN_UNCONCSOLIDATE |
Long term debt excl. lease liabilities | FQ, FY | LONG_TERM_DEBT_EXCL_CAPITAL_LEASE |
Long term debt | FQ, FY | LONG_TERM_DEBT |
Long term investments | FQ, FY | LONG_TERM_INVESTMENTS |
Note receivable - long term | FQ, FY | LONG_TERM_NOTE_RECEIVABLE |
Other long term assets, total | FQ, FY | LONG_TERM_OTHER_ASSETS_TOTAL |
Minority interest | FQ, FY | MINORITY_INTEREST |
Notes payable | FY | NOTES_PAYABLE_SHORT_TERM_DEBT |
Operating lease liabilities | FQ, FY | OPERATING_LEASE_LIABILITIES |
Other common equity | FQ, FY | OTHER_COMMON_EQUITY |
Other current assets, total | FQ, FY | OTHER_CURRENT_ASSETS_TOTAL |
Other current liabilities | FQ, FY | OTHER_CURRENT_LIABILITIES |
Other intangibles, net | FQ, FY | OTHER_INTANGIBLES_NET |
Other investments | FQ, FY | OTHER_INVESTMENTS |
Other liabilities, total | FQ, FY | OTHER_LIABILITIES_TOTAL |
Other receivables | FQ, FY | OTHER_RECEIVABLES |
Other short term debt | FY | OTHER_SHORT_TERM_DEBT |
Paid in capital | FQ, FY | PAID_IN_CAPITAL |
Gross property/plant/equipment | FQ, FY | PPE_TOTAL_GROSS |
Net property/plant/equipment | FQ, FY | PPE_TOTAL_NET |
Preferred stock, carrying value | FQ, FY | PREFERRED_STOCK_CARRYING_VALUE |
Prepaid expenses | FQ, FY | PREPAID_EXPENSES |
Provision for risks & charge | FQ, FY | PROVISION_F_RISKS |
Retained earnings | FQ, FY | RETAINED_EARNINGS |
Short term debt excl. current portion of LT debt | FQ, FY | SHORT_TERM_DEBT_EXCL_CURRENT_PORT |
Short term debt | FQ, FY | SHORT_TERM_DEBT |
Short term investments | FQ, FY | SHORT_TERM_INVEST |
Shareholders’ equity | FQ, FY | SHRHLDRS_EQUITY |
Total assets | FQ, FY | TOTAL_ASSETS |
Total current assets | FQ, FY | TOTAL_CURRENT_ASSETS |
Total current liabilities | FQ, FY | TOTAL_CURRENT_LIABILITIES |
Total debt | FQ, FY | TOTAL_DEBT |
Total equity | FQ, FY | TOTAL_EQUITY |
Total inventory | FQ, FY | TOTAL_INVENTORY |
Total liabilities | FQ, FY | TOTAL_LIABILITIES |
Total liabilities & shareholders’ equities | FQ, FY | TOTAL_LIABILITIES_SHRHLDRS_EQUITY |
Total non-current assets | FQ, FY | TOTAL_NON_CURRENT_ASSETS |
Total non-current liabilities | FQ, FY | TOTAL_NON_CURRENT_LIABILITIES |
Total receivables, net | FQ, FY | TOTAL_RECEIVABLES_NET |
Treasury stock - common | FQ, FY | TREASURY_STOCK_COMMON |
Financial | period |
financial_id |
Amortization | FQ, FY | AMORTIZATION |
Capital expenditures - fixed assets | FQ, FY | CAPITAL_EXPENDITURES_FIXED_ASSETS |
Capital expenditures | FQ, FY | CAPITAL_EXPENDITURES |
Capital expenditures - other assets | FQ, FY | CAPITAL_EXPENDITURES_OTHER_ASSETS |
Cash from financing activities | FQ, FY | CASH_F_FINANCING_ACTIVITIES |
Cash from investing activities | FQ, FY | CASH_F_INVESTING_ACTIVITIES |
Cash from operating activities | FQ, FY | CASH_F_OPERATING_ACTIVITIES |
Deferred taxes (cash flow) | FQ, FY | CASH_FLOW_DEFERRED_TAXES |
Depreciation & amortization (cash flow) | FQ, FY | CASH_FLOW_DEPRECATION_N_AMORTIZATION |
Change in accounts payable | FQ, FY | CHANGE_IN_ACCOUNTS_PAYABLE |
Change in accounts receivable | FQ, FY | CHANGE_IN_ACCOUNTS_RECEIVABLE |
Change in accrued expenses | FQ, FY | CHANGE_IN_ACCRUED_EXPENSES |
Change in inventories | FQ, FY | CHANGE_IN_INVENTORIES |
Change in other assets/liabilities | FQ, FY | CHANGE_IN_OTHER_ASSETS |
Change in taxes payable | FQ, FY | CHANGE_IN_TAXES_PAYABLE |
Changes in working capital | FQ, FY | CHANGES_IN_WORKING_CAPITAL |
Common dividends paid | FQ, FY | COMMON_DIVIDENDS_CASH_FLOW |
Depreciation/depletion | FQ, FY | DEPRECIATION_DEPLETION |
Free cash flow | FQ, FY | FREE_CASH_FLOW |
Funds from operations | FQ, FY | FUNDS_F_OPERATIONS |
Issuance/retirement of debt, net | FQ, FY | ISSUANCE_OF_DEBT_NET |
Issuance/retirement of long term debt | FQ, FY | ISSUANCE_OF_LONG_TERM_DEBT |
Issuance/retirement of other debt | FQ, FY | ISSUANCE_OF_OTHER_DEBT |
Issuance/retirement of short term debt | FQ, FY | ISSUANCE_OF_SHORT_TERM_DEBT |
Issuance/retirement of stock, net | FQ, FY | ISSUANCE_OF_STOCK_NET |
Net income (cash flow) | FQ, FY | NET_INCOME_STARTING_LINE |
Non-cash items | FQ, FY | NON_CASH_ITEMS |
Other financing cash flow items, total | FQ, FY | OTHER_FINANCING_CASH_FLOW_ITEMS_TOTAL |
Financing activities - other sources | FQ, FY | OTHER_FINANCING_CASH_FLOW_SOURCES |
Financing activities - other uses | FQ, FY | OTHER_FINANCING_CASH_FLOW_USES |
Other investing cash flow items, total | FQ, FY | OTHER_INVESTING_CASH_FLOW_ITEMS_TOTAL |
Investing activities - other sources | FQ, FY | OTHER_INVESTING_CASH_FLOW_SOURCES |
Investing activities - other uses | FQ, FY | OTHER_INVESTING_CASH_FLOW_USES |
Preferred dividends paid | FQ, FY | PREFERRED_DIVIDENDS_CASH_FLOW |
Purchase/acquisition of business | FQ, FY | PURCHASE_OF_BUSINESS |
Purchase of investments | FQ, FY | PURCHASE_OF_INVESTMENTS |
Repurchase of common & preferred stock | FQ, FY | PURCHASE_OF_STOCK |
Purchase/sale of business, net | FQ, FY | PURCHASE_SALE_BUSINESS |
Purchase/sale of investments, net | FQ, FY | PURCHASE_SALE_INVESTMENTS |
Reduction of long term debt | FQ, FY | REDUCTION_OF_LONG_TERM_DEBT |
Sale of common & preferred stock | FQ, FY | SALE_OF_STOCK |
Sale of fixed assets & businesses | FQ, FY | SALES_OF_BUSINESS |
Sale/maturity of investments | FQ, FY | SALES_OF_INVESTMENTS |
Supplying of long term debt | FQ, FY | SUPPLYING_OF_LONG_TERM_DEBT |
Total cash dividends paid | FQ, FY | TOTAL_CASH_DIVIDENDS_PAID |
Financial | period |
financial_id |
Accruals | FQ, FY | ACCRUALS_RATIO |
Altman Z-score | FQ, FY | ALTMAN_Z_SCORE |
Asset turnover | FQ, FY | ASSET_TURNOVER |
Beneish M-score | FQ, FY | BENEISH_M_SCORE |
Buyback yield % | FQ, FY | BUYBACK_YIELD |
Cash conversion cycle | FQ, FY | CASH_CONVERSION_CYCLE |
Cash to debt ratio | FQ, FY | CASH_TO_DEBT |
COGS to revenue ratio | FQ, FY | COGS_TO_REVENUE |
Current ratio | FQ, FY | CURRENT_RATIO |
Days sales outstanding | FQ, FY | DAY_SALES_OUT |
Days inventory | FQ, FY | DAYS_INVENT |
Days payable | FQ, FY | DAYS_PAY |
Debt to assets ratio | FQ, FY | DEBT_TO_ASSET |
Debt to EBITDA ratio | FQ, FY | DEBT_TO_EBITDA |
Debt to equity ratio | FQ, FY | DEBT_TO_EQUITY |
Debt to revenue ratio | FQ, FY | DEBT_TO_REVENUE |
Dividend payout ratio % | FQ, FY | DIVIDEND_PAYOUT_RATIO |
Dividend yield % | FQ, FY | DIVIDENDS_YIELD |
Dividends per share - common stock primary issue | FQ, FY | DPS_COMMON_STOCK_PRIM_ISSUE |
EPS estimates | FQ, FY | EARNINGS_ESTIMATE |
EPS basic one year growth | FQ, FY | EARNINGS_PER_SHARE_BASIC_ONE_YEAR_GROWTH |
EPS diluted one year growth | FQ, FY | EARNINGS_PER_SHARE_DILUTED_ONE_YEAR_GROWTH |
EBITDA margin % | FQ, FY | EBITDA_MARGIN |
Effective interest rate on debt % | FQ, FY | EFFECTIVE_INTEREST_RATE_ON_DEBT |
Enterprise value to EBITDA ratio | FQ, FY | ENTERPRISE_VALUE_EBITDA |
Enterprise value | FQ, FY | ENTERPRISE_VALUE |
Equity to assets ratio | FQ, FY | EQUITY_TO_ASSET |
Enterprise value to EBIT ratio | FQ, FY | EV_EBIT |
Enterprise value to revenue ratio | FQ, FY | EV_REVENUE |
Float shares outstanding | FY | FLOAT_SHARES_OUTSTANDING |
Free cash flow margin % | FQ, FY | FREE_CASH_FLOW_MARGIN |
Fulmer H factor | FQ, FY | FULMER_H_FACTOR |
Goodwill to assets ratio | FQ, FY | GOODWILL_TO_ASSET |
Graham’s number | FQ, FY | GRAHAM_NUMBERS |
Gross margin % | FQ, FY | GROSS_MARGIN |
Gross profit to assets ratio | FQ, FY | GROSS_PROFIT_TO_ASSET |
Interest coverage | FQ, FY | INTERST_COVER |
Inventory to revenue ratio | FQ, FY | INVENT_TO_REVENUE |
Inventory turnover | FQ, FY | INVENT_TURNOVER |
KZ index | FY | KZ_INDEX |
Long term debt to total assets ratio | FQ, FY | LONG_TERM_DEBT_TO_ASSETS |
Net current asset value per share | FQ, FY | NCAVPS_RATIO |
Net income per employee | FY | NET_INCOME_PER_EMPLOYEE |
Net margin % | FQ, FY | NET_MARGIN |
Number of employees | FY | NUMBER_OF_EMPLOYEES |
Operating earnings yield % | FQ, FY | OPERATING_EARNINGS_YIELD |
Operating margin % | FQ, FY | OPERATING_MARGIN |
PEG ratio | FQ, FY | PEG_RATIO |
Piotroski F-score | FQ, FY | PIOTROSKI_F_SCORE |
Price earnings ratio forward | FQ, FY | PRICE_EARNINGS_FORWARD |
Price sales ratio forward | FQ, FY | PRICE_SALES_FORWARD |
Price to free cash flow ratio | FQ, FY | PRICE_TO_FREE_CASH_FLOW |
Price to tangible book ratio | FQ, FY | PRICE_TO_TANGIBLE_BOOK |
Quality ratio | FQ, FY | QUALITY_RATIO |
Quick ratio | FQ, FY | QUICK_RATIO |
Research & development to revenue ratio | FQ, FY | RESEARCH_AND_DEVELOP_TO_REVENUE |
Return on assets % | FQ, FY | RETURN_ON_ASSETS |
Return on equity adjusted to book value % | FQ, FY | RETURN_ON_EQUITY_ADJUST_TO_BOOK |
Return on equity % | FQ, FY | RETURN_ON_EQUITY |
Return on invested capital % | FQ, FY | RETURN_ON_INVESTED_CAPITAL |
Return on tangible assets % | FQ, FY | RETURN_ON_TANG_ASSETS |
Return on tangible equity % | FQ, FY | RETURN_ON_TANG_EQUITY |
Revenue one year growth | FQ, FY | REVENUE_ONE_YEAR_GROWTH |
Revenue per employee | FY | REVENUE_PER_EMPLOYEE |
Revenue estimates | FQ, FY | SALES_ESTIMATES |
Shares buyback ratio % | FQ, FY | SHARE_BUYBACK_RATIO |
Sloan ratio % | FQ, FY | SLOAN_RATIO |
Springate score | FQ, FY | SPRINGATE_SCORE |
Sustainable growth rate | FQ, FY | SUSTAINABLE_GROWTH_RATE |
Tangible common equity ratio | FQ, FY | TANGIBLE_COMMON_EQUITY_RATIO |
Tobin’s Q (approximate) | FQ, FY | TOBIN_Q_RATIO |
Total common shares outstanding | FQ, FY | TOTAL_SHARES_OUTSTANDING |
Zmijewski score | FQ, FY | ZMIJEWSKI_SCORE |
Footnotes
[1] | Actually the highest supported minute timeframe is “1440” (which is the number of minutes in 24 hours). |
[2] | Requesting data of "1h" or "1H" timeframe would result in an error. Use "60" instead. |
[3] | These are the only second-based timeframes available. To use a second-based timeframe, the timeframe of the chart should be equal to or less than the requested timeframe. |