Versions 1.3.03 – 1.3.05 of the Data Saham Indonesia app added the Stock Screener and Stock Scoring features. This article covers how to write criteria for both.


Boolean Expression
Screener criteria are written as a mathematical formula called a Boolean Expression (BE) — a logical statement the system evaluates to one of two values: true or false.
Examples:
4 == 4 ==> true
4 == 3 + 1 ==> true
4 > 5 ==> false
true and false ==> false
true or false ==> true
4 == 4 and 4 == 3 + 1 ==> true
==is the operator for testing equality of values.
The screener evaluates your Boolean Expression against every stock listed on the Indonesia Stock Exchange, then shows those that return true.
For example:
prev hourly close <= current hourly close
Returns stocks whose close on the previous hourly candle is less than or equal to the close on the current hourly candle.
prev hourly close <= current hourly close AND hourly close >= hourly sma("close", 5)
The same criterion, AND close above the hourly MA5.
Screener criteria are flexible. They can be as simple as:
open < close
or as involved as:
hourly high > prev hourly hhv("high", 100) and
hourly close > hourly open and
index macd_histogram > 0 and
high < bollinger_top
Expression hierarchy
Boolean Expressions and Arithmetic Expressions are both derived from Expression. An Arithmetic Expression is a statement that produces a single value in the set of real numbers. Expression itself is defined as “anything that produces a single value”.
The hierarchy is as follows:
Expression :
- Boolean Expression (BE)
- Boolean Value : true, false
- Bracket Expression : ( BE )
- Boolean Operation : and, or, not
- Arithmetic Comparison : >= , <= , > , < , == , !=
- Boolean Function : code_index("<index code>")
- Arithmetic Expression (E)
- Numeric Expression
- Arithmetic Operation : * , / , + , -
- Bracket Expression : ( E )
- Stock Expression
In this document and in the criteria composer,
Eis shorthand for Arithmetic Expression.
Number notation
Numeric values can be written with a unit suffix, so large numbers stay short and readable:
K = thousand 1,000
M = million 1,000,000
B = billion 1,000,000,000
T = trillion 1,000,000,000,000
Examples:
value > 1B ==> transaction value above 1 billion rupiah
market_cap >= 10T ==> market capitalisation of at least 10 trillion rupiah
volume > 500K ==> volume above 500 thousand
Writing the number in full still works — 1B and 1000000000 are the same value.
Conditional operator
The ? : operator picks one of two values based on a condition:
<condition> ? <value if true> : <value if false>
It is most useful inside a subformula, because it turns a condition into a number that can then be summed or averaged.
sum("close > open ? 1 : 0", 20) ==> how many green candles in 20 bars
sma("volume > 1B ? 1 : 0", 10) ==> proportion of high-volume days
sum("close > prev close ? volume : 0", 5) ==> volume on up days only
To simply count how many times a condition holds, the count function is shorter:
count("close > open", 20) ==> equivalent to the first example above
Stock Expression
The most important part of a screener criterion is the Stock Expression, which is derived from Arithmetic Expression.
Its structure is:
E: stock_expression: [candle_selector] [timeframe] [target] <stock_attr>
E: stock_expression: [candle_selector] [timeframe] [target] <stock_function>
E: stock_expression: <stock_fundamental_attr>
E: stock_expression: <bid_offer_variables>
candle_selector
candle_selector: prev_N, ..., prev_3, prev_2, prev, current
default: current

timeframe
timeframe: yearly, monthly, weekly, daily, hourly, 15min, 5min, 1min
default: daily
target
target: stock, sector, index
default: stock
- stock — the chart of the stock itself. For TLKM and BMRI, target
stockselects the TLKM and BMRI charts. - sector — the chart of the sectoral index. For TLKM and BMRI, target
sectorselects the INFRA and FINANCE index charts. - index — the composite index chart for that stock. For TLKM and BMRI, target
indexselects COMPOSITE (^JKSE).
Writing parameters
Parameters with a default value may be omitted. In a Stock Expression, only stock_attr is required.
current daily stock close == close ==> true
current daily stock close == daily close ==> true
current daily stock close == stock close ==> true
current daily stock close == current daily close ==> true
But when parameters are written, they must follow the order defined above:
stock daily close ==> error
daily current close ==> error
current daily close ==> OK
stock_attr list
open, high, low, close, volume
macd, macd_signal, macd_histogram
rsi, stoch_k, stoch_d, stochrsi, atr, adx, pdx, ndx, cci, uo, roc, william_r, mfi, cmf
up_fractal, down_fractal
alligator_jaw, alligator_teeth, alligator_lips, alligator_ao, alligator_ac
bollinger_top, bollinger_bottom, bollinger_mean, bollinger_bandwidth,
bollinger_percent_b, bollinger_percent_b_avg
value, top_broker, foreign, top_broker_hist, foreign_hist
dto_stochk, dto_stochd, obv, adl, sar
pivot_s1, pivot_s2, pivot_s3, pivot_r1, pivot_r2, pivot_r3
camarilla_h1, camarilla_h2, camarilla_h3, camarilla_h4
camarilla_l1, camarilla_l2, camarilla_l3, camarilla_l4
mid_price, avg_price, tick, freq, change_percent
up_fractal_index, down_fractal_index
frequency_analyzer, mfv, ma_net_buy_sell_signal_count
projected_volume, projected_value
iep, iev, time_progress
open_date, open_time, close_date, close_time
stock_attr definitions
open,high,low,close,volume— the open, high, low, close and volume of the candlestick chartmacd,macd_signal,macd_histogram— values from the MACD(12,26,9) chart;macd_histogram=macd−macd_signalrsi— value from the RSI(14) chartstoch_k,stoch_d— values from the Stochastic(15,3,3) chartstochrsi— value from the StochRSI(9,6) chartatr— value from the ATR(14) chartadx,pdx,ndx— values from the ADX(14) chart;pdxis the DI+ line andndxthe DI− linecci— value from the CCI(14) chartuo— value from the UO(7,14,28) chartroc— value from the ROC(12) chartwilliam_r— value from the WilliamsR(14) chartmfi— value from the MFI(14) chartcmf— value from the CMF(21) chartalligator_jaw,alligator_teeth,alligator_lips,alligator_ao,alligator_ac— values from the Alligator(13,8,5) chartbollinger_top,bollinger_bottom,bollinger_mean,bollinger_bandwidth,bollinger_percent_b,bollinger_percent_b_avg— values from the Bollinger(20,2) chartvalue— total transaction value of the stocktop_broker— cumulative top broker transactions (current top_broker=prev top_broker+current top_broker_hist)foreign— cumulative foreign transactions (current foreign=prev foreign+current foreign_hist)top_broker_hist— value from the top broker transaction histogram, in sharesforeign_hist— value from the foreign transaction histogram, in sharesadl— Accumulation/Distribution Line, a running total of money flow volume: the position of the close within the daily range, multiplied by volume. It rises when closes sit near the high and falls when they sit near the lowdto_stochk,dto_stochd— values from the DTOStoch(8,5,3) chartsar— value from the SAR(0.02,0.2) chartmid_price—mid_price= (high+low) / 2tick— the exchange price fraction (price < 200 : 1 ; 200–500 : 2 ; 500–2000 : 5 ; 2000–5000 : 10 ; > 5000 : 25)vwap—vwap= (high+low+close) / 3avg_price— the average transaction price on that bar;avg_price=value/volumefreq— the number of transactions on that barchange_percent— price change against the previous close, as a percentagecamarilla_h1…camarilla_h4,camarilla_l1…camarilla_l4— Camarilla pivot levelsup_fractal_index,down_fractal_index— bars elapsed since the last upper or lower fractal formedfrequency_analyzer—volume/freq³, a measure of average transaction size. High values indicate trading dominated by large ordersmfv— money flow volume, the position of the close within the daily range multiplied by volumema_net_buy_sell_signal_count— buy signals minus sell signals across 12 moving averages (SMA and EMA at periods 5, 10, 20, 50, 100, 200). Ranges from −12 to +12projected_volume,projected_value— estimated volume and transaction value through to the session close, based on the pace of trading so fariep,iev— indicative equilibrium price and volume during the pre-opening sessiontime_progress— the proportion of the trading session elapsed, 0 to 1open_date,close_date,open_time,close_time— the opening and closing date and time of the bar
A note on
adl,top_brokerandforeign. All three are cumulative, counted from the oldest bar available, so their values are relative: they cannot be compared between stocks, nor stored and compared again on a different day. What carries meaning is the direction — against the previous bar, or against an average of the value itself.
adl > prev adl ==> accumulation increased today
adl > sma("adl", 20) ==> accumulation above its own average
prev adl < prev sma("adl", 20) and adl > sma("adl", 20)

top_broker_hist = [5 top net buyer] - [5 top net seller]
stock_function list
A stock_function is a function of a stock_attr.
sma(n), sma(subformula,n)
ema(n), ema(subformula,n)
aema(n), aema(subformula,n)
med(n), med(subformula,n)
highest(subformula,n), hhv(subformula,n)
lowest(subformula,n), llv(subformula,n)
ranking(subformula,n)
ranking_per_sector(subformula,n)
roc(n)
macd(fast_period,slow_period)
macd_signal(fast_period,slow_period,signal_period)
macd_histogram(fast_period,slow_period,signal_period)
sum(subformula,n)
vwap(n)
vwma(n)
cci(n)
atr(n)
adx(n)
pdx(n)
ndx(n)
stoch_k(lookback_period,k_period)
stoch_d(lookback_period,k_period,d_period)
bollinger_top(period, multiplier)
bollinger_bottom(period, multiplier)
bollinger_mean(period, multiplier)
bollinger_bandwidth(period, multiplier)
bollinger_percent_b(period, multiplier)
bollinger_percent_b_avg(period, multiplier)
rsi(n)
stochrsi(period,dtostoch_period,dtostoch_k_period,dtostoch_d_period)
dto_stochk(period,dtostoch_period,dtostoch_k_period,dtostoch_d_period)
dto_stochd(period,dtostoch_period,dtostoch_k_period,dtostoch_d_period)
mfi(n)
cmf(n)
chaikin_osc(fast_period, slow_period)
aroon_up(period)
aroon_down(period)
aroon_osc(period)
dema(period)
tema(period)
trix(period)
mass_index(ema_period, sum_period)
tsi(long_period, short_period)
donchian_up(period)
donchian_down(period)
donchian_mid(period)
ppo(fast_period, slow_period)
ppo_signal(fast_period, slow_period, signal_period)
ppo_histogram(fast_period, slow_period, signal_period)
pvo(fast_period, slow_period)
ao(fast_period, slow_period)
abs(x)
pow(x, y)
ceil(x), ceil(x, decimals)
floor(x), floor(x, decimals)
round(x), round(x, decimals)
trunc(x, decimals)
min(a, b, ...), max(a, b, ...), avg(a, b, ...)
count(subformula, n)
hhvbars(subformula, n)
llvbars(subformula, n)
trade_book(price)
freq(price)
tick_up(price), tick_down(price)
stock_function definitions
sma("<stock_attr>", N) — simple moving average of a stock_attr over N bars.
sma("close", 5) ==> daily MA5 of close
hourly sma("volume", 20) ==> hourly MA20 of volume
ema("<stock_attr>", N) — exponential moving average of a stock_attr over N bars.
ema("close", 5) ==> daily EMA5 of close
hourly ema("volume", 20) ==> hourly EMA20 of volume
aema("<stock_attr>", N) — an exponential moving average that stays more accurate on limited history. Written exactly like ema.
aema("close", 5) ==> daily EMA5 of close
aema("volume * close", 20) ==> EMA20 of transaction value
Use aema when your criterion uses a long period or works on sharply fluctuating values — volume, price differences, ratios. For short periods on price, the two give practically identical results.
If you already have screeners or alerts running on
ema, there is no need to change them.emaremains available and its behaviour is unchanged.
highest("<stock_attr>", N) / hhv("<stock_attr>", N) — the highest value of a stock_attr over N bars.
daily hhv("high", 5) ==> 5 day highest high daily
hourly hhv("close", 5) ==> 5 hour highest close hourly
lowest("<stock_attr>", N) / llv("<stock_attr>", N) — the lowest value of a stock_attr over N bars.
daily llv("low", 5) ==> 5 day lowest low daily
hourly llv("close", 5) ==> 5 hour lowest close hourly
ranking("<stock_attr>", N) — the rank of a stock_attr across all stocks, where rank 1 is the highest value. To order from lowest to highest instead, multiply the stock_attr by −1.
ranking("value") <= 10 ==> the top 10 stocks by transaction value
ranking("roc") <= 10 ==> the 10 stocks with the highest ROC
ranking("roc * -1") <= 10 ==> the 10 stocks with the lowest ROC
roc(period) — value from the Rate of Change (ROC) chart.
roc(12) ==> value of roc(12)
macd(fast_period, slow_period), macd_signal(...), macd_histogram(...) — values from the macd, macd_signal and macd_histogram charts.
macd(12, 26) ==> value of macd(12, 26)
macd_signal(12, 26, 9) ==> value of macd signal(12, 26, 9)
macd_histogram(12, 26, 9) ==> value of macd histogram(12, 26, 9)
sum("<stock_attr>", N) — the sum of a stock_attr over N bars.
sum("foreign", 5) ==> total foreign accumulation over the last 5 days
vwap(N) — value from the Volume-Weighted Average Price indicator.
vwap(N) = sum("volume * (high + low + close) / 3", N) / sum("volume", N)
vwap(5) ==> vwap over the last 5 days
vwma(N) — Volume Weighted Moving Average, a close-price average weighted by volume. Unlike vwap, the weighting is applied to the close.
vwma(20) ==> 20-period VWMA
close > vwma(20) ==> price above VWMA20
atr(period), adx(period), cci(period)
atr(14) ==> value of the atr(14) line
adx(14) ==> value of the adx(14) line
pdx(14) ==> value of the DI+ line in adx(14)
ndx(14) ==> value of the DI- line in adx(14)
cci(20) ==> value of cci(20)
stoch_k(lookback_period, k_period) / stoch_d(lookback_period, k_period, d_period) — values from the Stochastic Oscillator chart.
stoch_k(15, 3) ==> Stochastic %K(15, 3)
stoch_d(15, 3, 3) ==> Stochastic %D(15, 3, 3)
bollinger_*(period, multiplier) — values from the Bollinger Bands chart.
bollinger_top(20, 2) ==> Bollinger Band top line(20, 2)
bollinger_bottom(20, 2) ==> Bollinger Band bottom line(20, 2)
rsi(n) — value from the Relative Strength Index chart.
rsi(14) ==> value of the rsi(14) line
stochrsi(...), dto_stochk(...), dto_stochd(...) — values from the StochRSI chart.
stochrsi(14, 8, 5, 3) ==> value of the stochrsi(14, 8, 5, 3) line
dto_stochk(14, 8, 5, 3) ==> the %K line of stochrsi(14, 8, 5, 3)
dto_stochd(14, 8, 5, 3) ==> the %D line of stochrsi(14, 8, 5, 3)
chaikin_osc(fast_period, slow_period) — the Chaikin Oscillator: the difference between two EMAs of the Accumulation/Distribution Line. It measures accumulation and distribution pressure by taking the position of the close within the daily range, multiplied by volume.
Positive values indicate accumulation pressure, negative values distribution. Zero-line crossings are commonly used as a signal.
chaikin_osc(3, 10) ==> Chaikin Oscillator with standard periods
chaikin_osc(5, 20) ==> a slower variant
Example: switching from distribution to accumulation.
prev chaikin_osc(3, 10) < 0 and chaikin_osc(3, 10) > 0
aroon_up(period) and aroon_down(period) — measure how recently the highest or lowest price was reached within the last N periods, not how high the price is.
Values range from 0 to 100:
- 100 means the high (or low) occurred on the current bar.
- 0 means it occurred on the oldest bar in the window.
aroon_up(25) ==> 100 if today is the highest price of the last 25 days
aroon_down(25) ==> 100 if today is the lowest price of the last 25 days
aroon_osc(period) — the difference between the two, aroon_up minus aroon_down. It ranges from −100 to +100; positive values indicate an upward bias.
aroon_osc(25) ==> equivalent to aroon_up(25) - aroon_down(25)
The usual periods are 25 (Chande’s default) and 14.
dema(period) and tema(period) — Double and Triple Exponential Moving Average of the close. Both track price faster than a plain EMA of the same period, making them more responsive to changes in direction.
dema(20) ==> 20-period DEMA
close > tema(50) ==> price above TEMA50
prev close <= prev dema(20) and close > dema(20)
trix(period) — the percentage rate of change of a triple-smoothed price. It oscillates around zero: positive indicates upward momentum, negative downward.
trix(15) ==> 15-period TRIX
prev trix(15) < 0 and trix(15) > 0 ==> momentum turning up
mass_index(ema_period, sum_period) — detects expansion in the price range (the high-to-low distance), which often precedes a reversal. Standard parameters are mass_index(9, 25).
The common pattern is the reversal bulge: the value rises above 27, then falls back below 26.5.
mass_index(9, 25) > 27
prev mass_index(9, 25) > 27 and mass_index(9, 25) < 26.5
tsi(long_period, short_period) — True Strength Index, measuring the strength and direction of momentum on a scale of −100 to +100. Standard parameters are tsi(25, 13).
tsi(25, 13) > 0 ==> net positive momentum
prev tsi(25, 13) < 0 and tsi(25, 13) > 0
donchian_up(period), donchian_down(period) and donchian_mid(period) — the upper band, lower band and midline of the Donchian Channel: the highest and lowest values over the last N bars.
donchian_up(20) ==> highest high of the last 20 bars
donchian_down(20) ==> lowest low of the last 20 bars
donchian_mid(20) ==> the midpoint of the two
The current bar is included, as with
hhvandllv. This meansclose > donchian_up(20)can never be true — to find a breakout, compare against the previous bar usingprev.
close > prev donchian_up(20) ==> upside breakout
close < prev donchian_down(20) ==> downside breakdown
ppo(fast_period, slow_period) — Percentage Price Oscillator, MACD expressed as a percentage. Because the unit is a percentage, values are comparable across stocks trading at very different price levels.
ppo(12, 26) ==> PPO with standard periods
ppo(12, 26) > 0 ==> short-term trend above long-term
prev ppo(12, 26) < 0 and ppo(12, 26) > 0
ppo_signal(fast_period, slow_period, signal_period) and ppo_histogram(fast_period, slow_period, signal_period) — the signal line and histogram for PPO, matching macd_signal and macd_histogram.
The signal line is a moving average of the PPO value itself; the histogram is the difference between the two (ppo minus ppo_signal).
ppo_signal(12, 26, 9) ==> signal line with standard periods
ppo_histogram(12, 26, 9) ==> PPO relative to its signal line
PPO crossing its signal line — equivalent to the histogram turning from negative to positive:
prev ppo_histogram(12, 26, 9) < 0 and ppo_histogram(12, 26, 9) > 0
Momentum strengthening while the trend is still below zero:
ppo(12, 26) < 0 and ppo_histogram(12, 26, 9) > 0
pvo(fast_period, slow_period) — Percentage Volume Oscillator, the same formula applied to volume. Useful for spotting surges or a drying-up of trading activity.
pvo(12, 26) > 0 ==> short-term volume above the long-term average
ao(fast_period, slow_period) — Awesome Oscillator, the difference between two simple moving averages of the median price. Standard parameters are ao(5, 34).
ao(5, 34) ==> Awesome Oscillator value
prev ao(5, 34) < 0 and ao(5, 34) > 0 ==> zero-line crossing
alligator_aois also available as astock_attr, but its value follows the Alligator(13,8,5) chart settings. Useao(5, 34)if you want the standard periods.
Maths functions
These work on plain numbers rather than price series, so they can be used anywhere in a formula.
abs(x) ==> absolute value
pow(x, y) ==> x to the power of y
ceil(x), ceil(x, d) ==> round up, optionally to d decimal places
floor(x), floor(x, d) ==> round down
round(x), round(x, d) ==> round to nearest
trunc(x, d) ==> truncate decimals without rounding
min(a, b, ...) ==> the smallest of several arguments
max(a, b, ...) ==> the largest
avg(a, b, ...) ==> the average of several arguments
Examples:
abs(close - open) / open * 100 > 3 ==> intrabar move above 3%, up or down
max(high, prev high) > bollinger_top
med(n) and med(subformula, n) — the median (not the mean) over the last N bars. More resistant to a single extreme bar than sma.
med("volume", 20) ==> 20-day median volume
volume > med("volume", 20) * 3
count(subformula, n) — counts how many times a condition holds over the last N bars.
count("close > open", 20) >= 14 ==> at least 14 green candles out of 20
count("volume > sma(\"volume\", 20)", 10) >= 5
hhvbars(subformula, n) and llvbars(subformula, n) — how many bars have passed since the highest or lowest value occurred within the last N bars. A value of 0 means it occurred on the current bar.
hhvbars("high", 50) == 0 ==> today is the 50-day high
llvbars("low", 20) <= 3 ==> the 20-day low occurred within the last 3 bars
Trade book functions
These read the trade book — the breakdown of transactions at each price level within a bar.
trade_book(price) — the transaction volume executed at that price.
freq(price) — the transaction frequency at that price.
trade_book(close) > trade_book(open)
tick_up(price) and tick_down(price) — the price one tick above or below the given price, following the exchange’s price fraction rules.
close == tick_up(prev close) ==> up exactly one tick from yesterday's close
Accurate period limits
Every calculation reads only a bounded slice of recent bars. The longer the period you ask for, the more of that history it consumes — and past a certain point the result is no longer reliable.
The table below gives the maximum period that still produces an accurate result. Beyond it the function returns an empty value and the stock will not appear in your screening results.
| Function | Safe period | Notes |
|---|---|---|
sma, hhv, llv, sum, ranking | up to 500 | No practical limit |
aroon_up, aroon_down, aroon_osc | up to 500 | No practical limit |
donchian_up, donchian_down, donchian_mid | up to 500 | No practical limit |
vwma, vwap, ao | up to 500 | No practical limit |
ema | 120 | Up to 250 when used on price (close, open, high, low) |
aema | 140 | Up to 200 on price; more accurate than ema for volume and ratios |
dema, tema | 160 | |
trix | 75 | Considerably stricter than the other functions |
ppo, pvo | slow_period up to 140 | Up to 200 for ppo; the standard (12, 26) is well inside |
ppo_signal, ppo_histogram | slow + signal up to 128 | The standard (12, 26, 9) is well inside |
chaikin_osc | slow_period up to 60 | The standard (3, 10) is well inside |
mass_index | ema_period up to 100 | The standard (9, 25) is well inside |
tsi | long + short up to 120 | The standard (25, 13) is well inside |
These are conservative figures that hold for any kind of input. Where your criterion works on closing prices, ema and aema stay accurate to the longer periods noted in the last column.
For everyday use, the periods people actually reach for — 5, 9, 14, 20, 26, 50, even 100 — sit far inside the limit for every function.
Boolean functions
Unlike a stock_function, which produces a number, the following produce a true or false value directly — so they can be used as a criterion without a comparison operator.
code_index("<index code>") — tests whether the stock being evaluated is a member of that index. Returns true if it is, false otherwise.
code_index("ISSI") ==> true for members of the ISSI index
Because the result is already a Boolean Expression, the function is written as-is and combined with and or or:
code_index("ISSI") and rsi < 30
code_index("ISSI") and code_index("LQ45")
code_index("LQ45") and close > sma("close", 20)
Writing it with a comparison operator — code_index("ISSI") > 0, for instance — is not valid, because there is no numeric value to compare.
stock_fundamental_attr
debt_equity, ebitda, ebitda_anl, eps, eps_anl
ev_ebitda, ev_ebitda_anl, market_cap, netprofit, netprofit_anl
pbv, pbv_anl, per, per_anl, revenue, revenue_anl
roa, roa_anl, roe, roe_anl
The _anl suffix means the annualized value; without it, the value comes from the most recent financial report.
debt_equity— Debt to Equity Ratioebitda/ebitda_anl— Earnings Before Interest, Taxes, Depreciation and Amortizationeps/eps_anl— Earning Per Shareev_ebitda/ev_ebitda_anl— Enterprise Multiplemarket_cap— Market Capitalizationnetprofit/netprofit_anl— Net Profitpbv/pbv_anl— Price-to-Book Ratioper/per_anl— Price-Earnings Ratiorevenue/revenue_anl— Revenueroa/roa_anl— Return on Assetsroe/roe_anl— Return on Equity
bid_offer_variables
top1_bid_volume, top1_bid_count, top1_offer_volume, top1_offer_count
top3_bid_volume, top3_bid_count, top3_offer_volume, top3_offer_count
top5_bid_volume, top5_bid_count, top5_offer_volume, top5_offer_count
top10_bid_volume, top10_bid_count, top10_offer_volume, top10_offer_count
all_bid_volume, all_bid_count, all_offer_volume, all_offer_count

top1_bid_volume— total volume on the bid at the best price, in sharestop1_bid_count— number of orders on the bid at the best pricetop1_offer_volume— total volume on the offer at the best price, in sharestop1_offer_count— number of offer orders at the best pricetop3_*,top5_*,top10_*— the same pattern across the 3, 5 and 10 best pricesall_bid_volume— total volume on the bid across all prices, in sharesall_bid_count— number of orders on the bid across all pricesall_offer_volume— total volume on the offer across all prices, in sharesall_offer_count— number of offer orders across all prices
Function forms are also available:
bid_volume(n) : volume on the bid at the nth best price, where n: 1,2,3,...
bid_count(n) : number of orders on the bid at the nth best price
offer_volume(n) : volume on the offer at the nth best price
offer_count(n) : number of orders on the offer at the nth best price
sum_bid_volume(n) : total volume on the bid across the n best prices
sum_bid_count(n) : number of orders on the bid across the n best prices
sum_offer_volume(n) : total volume on the offer across the n best prices
sum_offer_count(n) : number of orders on the offer across the n best prices
Other variables
To check the value of a variable or test a formula, use the Formula Evaluator menu.
best_bid_price— the highest (best) bid price for the stockbest_offer_price— the lowest (best) offer price for the stockblot— transaction volume executed at the bid price (ha-ki), in lotsslot— transaction volume executed at the offer price (ha-ka), in lotsbvol— transaction volume executed at the bid price, in sharessvol— transaction volume executed at the offer price, in sharesbfreq— transaction frequency at the bid pricesfreq— transaction frequency at the offer priceall_buy_volume/all_sell_volume— the same asbvol/svolall_buy_freq/all_sell_freq— the same asbfreq/sfreqbroker_buyer_count— the number of brokers buyingbroker_seller_count— the number of brokers sellingnet_broker_buyer_count— the number of brokers with a net buynet_broker_seller_count— the number of brokers with a net sell
Broker transaction variables
Available in the pattern top{1,3,5,10}_net_broker_{buyer,seller}_{volume,value,avg_price}:
top1_net_broker_buyer_volume : net buy volume of the single largest broker, in shares
top1_net_broker_buyer_value : net buy transaction value of the single largest broker
top1_net_broker_buyer_avg_price : average net buy price of the single largest broker
The same pattern applies to top3_, top5_, top10_ and to the seller side, giving the full list:
top1_net_broker_buyer_volume top1_net_broker_buyer_value top1_net_broker_buyer_avg_price
top3_net_broker_buyer_volume top3_net_broker_buyer_value top3_net_broker_buyer_avg_price
top5_net_broker_buyer_volume top5_net_broker_buyer_value top5_net_broker_buyer_avg_price
top10_net_broker_buyer_volume top10_net_broker_buyer_value top10_net_broker_buyer_avg_price
top1_net_broker_seller_volume top1_net_broker_seller_value top1_net_broker_seller_avg_price
top3_net_broker_seller_volume top3_net_broker_seller_value top3_net_broker_seller_avg_price
top5_net_broker_seller_volume top5_net_broker_seller_value top5_net_broker_seller_avg_price
top10_net_broker_seller_volume top10_net_broker_seller_value top10_net_broker_seller_avg_price
Versions without the word net are available in the same pattern, covering _volume, _value and _avg_price:
top1_broker_buyer_volume top1_broker_buyer_value top1_broker_buyer_avg_price
top3_broker_buyer_volume top3_broker_buyer_value top3_broker_buyer_avg_price
top5_broker_buyer_volume top5_broker_buyer_value top5_broker_buyer_avg_price
top10_broker_buyer_volume top10_broker_buyer_value top10_broker_buyer_avg_price
top1_broker_seller_volume top1_broker_seller_value top1_broker_seller_avg_price
top3_broker_seller_volume top3_broker_seller_value top3_broker_seller_avg_price
top5_broker_seller_volume top5_broker_seller_value top5_broker_seller_avg_price
top10_broker_seller_volume top10_broker_seller_value top10_broker_seller_avg_price
Building your own formulas
Beyond the built-in functions, you can assemble calculations yourself. The key: sma, ema, aema, sum, hhv, llv and ranking accept a subformula that is a full expression, not merely a stock_attr name. Look at the definition of vwap above — it contains sum("volume * (high + low + close) / 3", N), a complete expression inside quotes.
This section shows how that works, using several widely known indicators.
Every indicator in this section is now available as its own function. For everyday use, call the function directly — it is shorter, faster, and less prone to typos. The long forms are kept here as worked examples, so you can apply the same pattern to indicators that do not yet have one.
Donchian Channel
The upper and lower Donchian bands are the highest and lowest values over the last N bars:
hhv("high", 20) ==> upper band
llv("low", 20) ==> lower band
(hhv("high", 20) + llv("low", 20)) / 2 ==> midline
Available directly as donchian_up(20), donchian_down(20) and donchian_mid(20).
VWMA — Volume Weighted Moving Average
A close-price average weighted by volume. The pattern matches the definition of vwap:
sum("volume * close", 20) / sum("volume", 20)
Available directly as vwma(20).
PPO and PVO
MACD expressed as a percentage, and the same measure applied to volume:
(ema("close", 12) - ema("close", 26)) / ema("close", 26) * 100
(ema("volume", 12) - ema("volume", 26)) / ema("volume", 26) * 100
Available directly as ppo(12, 26) and pvo(12, 26).
Awesome Oscillator
The difference between two simple moving averages of the median price. Since mid_price is already (high + low) / 2, this becomes:
sma("mid_price", 5) - sma("mid_price", 34)
Available directly as ao(5, 34).
Crossover and breakout signals
The signals people reach for — golden cross, death cross, breakout — are fundamentally a comparison between the previous bar and the current one. Writing them yourself lets you choose your own periods, and keeps the criterion readable.
The pattern is always the same: the condition did not hold on prev, and holds now.
Golden cross and death cross, MA 5–20
prev sma("close", 5) < prev sma("close", 20) and sma("close", 5) > sma("close", 20)
prev sma("close", 5) > prev sma("close", 20) and sma("close", 5) < sma("close", 20)
Replace 5 and 20 with whatever periods suit your strategy, or swap sma for ema or aema.
MACD crossing the zero line
prev macd(12, 26) < 0 and macd(12, 26) > 0 ==> golden cross
prev macd(12, 26) > 0 and macd(12, 26) < 0 ==> death cross
MACD crossing its signal line — equivalent to the histogram changing sign
prev macd_histogram(12, 26, 9) < 0 and macd_histogram(12, 26, 9) > 0
prev macd_histogram(12, 26, 9) > 0 and macd_histogram(12, 26, 9) < 0
Stochastic %K crossing %D
prev stoch_k(15, 3) < prev stoch_d(15, 3, 3) and stoch_k(15, 3) > stoch_d(15, 3, 3)
prev stoch_k(15, 3) > prev stoch_d(15, 3, 3) and stoch_k(15, 3) < stoch_d(15, 3, 3)
Fractal breakout
high > up_fractal and prev close <= up_fractal ==> breaking the upper fractal
low < down_fractal and prev close >= down_fractal ==> breaking the lower fractal
Confirming across many moving averages at once
The ma_net_buy_sell_signal_count variable nets buy against sell signals across 12 moving averages, ranging from −12 to +12.
ma_net_buy_sell_signal_count >= 6 ==> most moving averages strengthening
ma_net_buy_sell_signal_count <= -6 ==> most weakening
Patterns with no function
Some calculations have no function name but are still easy to write with the same pattern.
Distance from a moving average — useful for screening out stocks that have run too far from their average.
(close - sma("close", 20)) / sma("close", 20) * 100 > 5
Volume spike
volume > sma("volume", 20) * 2
The average of an expression — anything you can write as a single-bar expression, you can average.
sma("(high - low)", 14) ==> average daily range
sma("(close - open) / open * 100", 5) ==> average intrabar change
sum("top_broker_hist * close", 5) ==> 5-day broker accumulation value
Ratios across timeframes
volume / weekly volume ==> daily volume as a share of weekly
close / weekly sma("close", 4) ==> price against the 4-week average
Screener formula examples
Higher high higher low
prev high < high and prev low < low
Inside bar
prev high > high and prev low < low
Golden cross MA 5-20 (the MA 5 line crossing above MA 20)
prev sma(5) < prev sma(20) and sma(5) > sma(20)
MACD rising
prev macd < macd and macd > 0
Three white soldiers
prev_2 close > prev_2 open
and prev close > prev open
and close > open
The 10 highest accumulation stocks by top-5-net-broker-accumulation value
ranking("top_broker_hist * daily_price_avg") <= 10
Stochastic %K crossing %D from below
prev stoch_k < prev stoch_d and stoch_k > stoch_d
Stocks that have just set a 25-day high
aroon_up(25) == 100
A strong uptrend by Aroon — the high is recent, the low is old
aroon_up(25) > 70 and aroon_down(25) < 30
Aroon Oscillator crossing up — a turn from down to up
prev aroon_osc(25) < 0 and aroon_osc(25) > 0
A new trend forming, not yet overbought
aroon_up(14) > 70 and aroon_down(14) < 30 and rsi < 70
Accumulation by Chaikin Oscillator, with above-average volume
chaikin_osc(3, 10) > 0
and prev chaikin_osc(3, 10) < 0
and volume > sma("volume", 20)
Accumulation divergence — price sets a new high while accumulation falls away
close == hhv("close", 20) and adl < prev_5 adl
Double confirmation — Chaikin positive alongside top 5 broker accumulation
chaikin_osc(3, 10) > 0 and top_broker_hist > 0
Restricting results to members of a particular index
code_index("ISSI") and close > sma("close", 20)
Liquid stocks with large transaction value — 5-day average above 1 billion
sma("value", 5) > 1B
A combination: price above the weekly SMA26, MACD histogram rising below the centre line, and Stochastic %K below 19 crossing %D from below.
close > weekly sma("close", 26)
and macd_histogram < 0
and prev_2 macd_histogram < prev macd_histogram
and prev macd_histogram < macd_histogram
and stoch_k < 19
and prev stoch_k < prev stoch_d
and stoch_k > stoch_d