StonQL Reference
Securities Temporal ObservatioN Query Language
What is StonQL?
StonQL (pronounced "Stonk-QL") is a domain-specific language for filtering stocks based on price, volume, and technical indicators.
A basic scan:
close > 50;
This returns all stocks with a closing price above $50.
A more practical example:
close > sma(close, 50);
This returns stocks trading above their 50-day simple moving average.
Statements
A statement is a single condition that must be true for a stock to appear in your results. Every statement ends with a semicolon.
volume > 1M;
This statement filters for stocks with volume greater than 1 million shares.
Comments
Add notes to your scans using comments. Comments are ignored when the scan runs.
// Single-line comment
volume > 1M; // Comment at end of line
/* Multi-line comment
spanning multiple lines */
close > open;
Combining Statements
When you write multiple statements, a stock must satisfy all of them to appear in results. Think of it as "AND" logic.
close > 10; // Price above $10
close < 50; // Price below $50
volume > 500K; // Volume above 500,000
This scan returns only stocks where all three conditions are true: price between $10-$50 with decent volume.
Need "OR" logic? Use the or operator within a single statement:
rsi(close, 14) < 30 or rsi(close, 14) > 70;
This finds stocks that are either oversold (RSI below 30) or overbought (RSI above 70).
Fields
Fields are the data points you use in your scans. They represent price, volume, and other stock information.
close
Closing price for the period
close > 100;
open
Opening price for the period
close > open;
high
Highest price during the period
high > high[1];
low
Lowest price during the period
low > high[1];
volume
Number of shares traded during the period
volume > 1M;
typical_price (alias: hlc3)
(high + low + close) / 3
close > typical_price;
ohlc4
(open + high + low + close) / 4
sma(ohlc4, 20);
first_trade_date
The date the stock first started trading
months_since(first_trade_date) < 6;
Variables
Use variables to name your calculations. This makes complex scans easier to read and lets you reuse values.
avg_vol = sma(volume, 20);
volume > avg_vol * 2; // Volume is 2x the 20-day average
myVar and myvar are different variables.
Variables are especially helpful when you need the same calculation multiple times:
ma50 = sma(close, 50);
ma200 = sma(close, 200);
close > ma50; // Price above 50-day MA
ma50 > ma200; // 50-day MA above 200-day MA (bullish alignment)
Number Formats
StonQL supports several number formats for convenience:
| Format | Example | Equals |
|---|---|---|
K (thousands) |
500K |
500,000 |
M (millions) |
1.5M |
1,500,000 |
B (billions) |
2B |
2,000,000,000 |
Operators
Comparison Operators
| Operator | Description | Example |
|---|---|---|
> |
Greater than | close > 50; // stocks above $50 |
>= |
Greater than or equal to | rsi(close, 14) >= 70; // RSI at or above overbought level |
< |
Less than | close < sma(close, 200); // price below 200-day MA |
<= |
Less than or equal to | rsi(close, 14) <= 30; // RSI at or below oversold level |
== |
Equal to (exact match) | volume == 0; // no trading activity |
!= |
Not equal to | close != open; // price moved during the period |
~= |
Approximately equal (0.1% tolerance) | close ~= high; // closed near the high |
Logical Operators
| Operator | Description | Example |
|---|---|---|
and |
Both conditions must be true | close > 10 and volume > 1M; // above $10 with high volume |
or |
Either condition can be true | rsi(close, 14) < 30 or rsi(close, 14) > 70; // oversold or overbought |
not |
Inverts a condition | not close < 10; // equivalent to close >= 10 |
Arithmetic Operators
| Operator | Description | Example |
|---|---|---|
+ |
Addition | typical = (high + low + close) / 3; // typical price |
- |
Subtraction | range = high - low; // trading range for the period |
* |
Multiplication | volume > sma(volume, 20) * 2; // 2x average volume |
/ |
Division | change = (close - open) / open; // price change ratio |
\ |
Floor division (rounds down to integer) | whole_dollars = close \ 1; // drops decimal portion |
% |
Modulo (remainder) | cents = (close * 100) % 100; // cents portion of price |
Historical Reference
Access values from previous periods. The number in brackets indicates how many periods back.
| Operator | Description | Example |
|---|---|---|
[n] |
Value from n periods ago | close > close[1]; // today's close above yesterday's |
Multi-Timeframe Analysis
Use mtf() blocks to combine conditions across multiple timeframes in a single scan. Filter stocks that meet criteria on daily, weekly, and monthly charts simultaneously.
1D, 2D, 3D, 4D, 5D, 1W, 2W, 3W, 4W, 1M, 2M, 3M, 4M, 6M, 12M
Filter Mode
When a mtf() block contains boolean conditions, stocks must pass all conditions in that timeframe to appear in results.
// Daily scan with weekly and monthly filters
close > sma(close, 20); // Daily: above 20-day MA
mtf("1W") {
close > open; // Weekly: green candle
rsi(close, 14) > 50; // Weekly: bullish momentum
}
mtf("1M") {
close > sma(close, 3); // Monthly: uptrend
}
Stocks must pass daily conditions AND weekly conditions AND monthly conditions.
Value Extraction Mode
Assign a mtf() block to a variable to extract values from another timeframe for use in comparisons.
// Extract previous week's high for breakout detection
prev_weekly_high = mtf("1W") { high[1]; };
// Daily breakout above last week's high
close > prev_weekly_high;
volume > sma(volume, 20) * 1.5;
The [1] gets the previous week's value, avoiding same-bar comparisons.
Scope Isolation
mtf() blocks are completely isolated. Variables defined outside cannot be used inside, and vice versa.
// CORRECT: Self-contained mtf() block
mtf("1W") {
avg = sma(close, 20); // 'avg' only exists inside this block
close > avg;
}
// CORRECT: Value extraction creates outer variable
weekly_rsi = mtf("1W") { rsi(close, 14); };
rsi(close, 14) > weekly_rsi; // Compare daily RSI to weekly RSI
// WRONG: Cannot reference outer variables in mtf() blocks
threshold = 50;
mtf("1W") { rsi(close, 14) > threshold; }; // ERROR!
// VALID: Check if today made the monthly high (equality)
monthly_high = mtf("1M") { high; };
high == monthly_high; // Valid: detecting monthly high bar
// WRONG: Inequality comparison to containing period
monthly_high = mtf("1M") { high; };
high > monthly_high; // NEVER true - daily high can't exceed monthly high it's part of!
// CORRECT: Use [1] for inequality comparisons
prev_monthly_high = mtf("1M") { high[1]; };
close > prev_monthly_high; // Meaningful: breaking above last month's high
The rule: Equality checks (==, ~=) against current period values are valid for detecting extremes. Inequality checks (>, <) are faulty because the daily value is part of the aggregate. Use [1] for inequality comparisons.
Combining Indicators Across Timeframes
// Multi-timeframe momentum alignment
prev_weekly_rsi = mtf("1W") { rsi(close, 14)[1]; };
prev_monthly_rsi = mtf("1M") { rsi(close, 14)[1]; };
// Daily RSI stronger than both higher timeframes
rsi(close, 14) > prev_weekly_rsi;
rsi(close, 14) > prev_monthly_rsi;
rsi(close, 14) > 50; // And above neutral
Functions
Click on any function to view detailed documentation with parameters, formulas, and examples.
Quick Index (A-Z)
abs() ·
all_time_high() ·
all_time_low() ·
and() ·
approx() ·
aroon_down() ·
aroon_osc() ·
aroon_up() ·
atr() ·
bb_lower() ·
bb_upper() ·
bb_width() ·
cci() ·
change() ·
count() ·
cross() ·
crossover() ·
crossunder() ·
days_since() ·
dev() ·
ema() ·
eq() ·
falling() ·
gt() ·
gte() ·
highest() ·
highest_bars_ago() ·
hma() ·
kc_lower() ·
kc_middle() ·
kc_upper() ·
kcw() ·
lowest() ·
lowest_bars_ago() ·
lt() ·
lte() ·
macd_histogram() ·
macd_line() ·
macd_signal() ·
max() ·
mean() ·
median() ·
mfi() ·
min() ·
mom() ·
months_since() ·
ne() ·
obv() ·
or() ·
pct_change() ·
percentrank() ·
pivothigh() ·
pivotlow() ·
pow() ·
range() ·
rising() ·
roc() ·
rsi() ·
sma() ·
sqrt() ·
stdev() ·
stoch_d() ·
stoch_k() ·
streak() ·
swma() ·
true_range() ·
variance() ·
vwma() ·
weeks_since() ·
wilderma() ·
williams_r() ·
wma() ·
years_since()
Functions by Category
Comparison
| Function | Description |
|---|---|
and(left, right)
|
Logical AND |
approx(value, target, tolerance)
|
Approximate equality with absolute tolerance |
cross(source1, source2)
|
Cross detection (either crossover or crossunder) |
crossover(source1, source2)
|
Crossover detection (source1 crosses above source2) |
crossunder(source1, source2)
|
Crossunder detection (source1 crosses below source2) |
eq(left, right)
|
Equality comparison (==) |
gt(left, right)
|
Greater than comparison (>) |
gte(left, right)
|
Greater than or equal comparison (>=) |
lt(left, right)
|
Less than comparison (<) |
lte(left, right)
|
Less than or equal comparison (<=) |
ne(left, right)
|
Not equal comparison (!=) |
or(left, right)
|
Logical OR |
Date Functions
| Function | Description |
|---|---|
days_since(date)
|
Calendar days since given date |
months_since(date)
|
Months since given date (truncated) |
weeks_since(date)
|
Weeks since given date (truncated) |
years_since(date)
|
Years since given date (truncated) |
Math
Momentum
| Function | Description |
|---|---|
cci(period)
|
Commodity Channel Index |
change(source, length)
|
Change (Difference from historical value) |
mfi(period)
|
Money Flow Index (Volume-weighted momentum oscillator) |
mom(source, length)
|
Change (Difference from historical value) |
pct_change(current, base)
|
Percent Change between two values |
roc(source, periods)
|
Rate of Change |
rsi(source, periods, matype="wilder")
|
Relative Strength Index |
stoch_d(k_period, d_period, matype="sma")
|
Stochastic %D (Slow Stochastic - MA of %K) |
stoch_k(period)
|
Stochastic %K (Fast Stochastic) |
williams_r(period)
|
Williams %R momentum oscillator |
Moving Averages
| Function | Description |
|---|---|
ema(source, periods)
|
Exponential Moving Average |
hma(source, period)
|
Hull Moving Average |
sma(source, periods)
|
Simple Moving Average |
swma(source)
|
Symmetrically Weighted Moving Average (fixed 4-period) |
vwma(source, periods)
|
Volume Weighted Moving Average |
wilderma(source, periods)
|
Wilder Moving Average (EMA with α = 1/N) |
wma(source, periods)
|
Weighted Moving Average |
Price
| Function | Description |
|---|---|
all_time_high(source)
|
All-Time High (Maximum value from inception) |
all_time_low(source)
|
All-Time Low (Minimum value from inception) |
Range
| Function | Description |
|---|---|
highest(source, period)
|
Highest value of field over period |
highest_bars_ago(source, period)
|
Bars ago when highest value occurred |
lowest(source, period)
|
Lowest value over period |
lowest_bars_ago(source, period)
|
Bars ago when lowest value occurred |
pivothigh(source, leftbars, rightbars)
|
Detects pivot high (local peak) points in a data series |
pivotlow(source, leftbars, rightbars)
|
Detects pivot low (local trough) points in a data series |
range(max_source, min_source, period)
|
Difference between max_field and min_field over period |
Statistics
| Function | Description |
|---|---|
count(condition, period)
|
Count total occurrences of condition in lookback window |
mean(source, period)
|
Statistical Mean (same as SMA) |
median(source, period)
|
Statistical Median |
percentrank(source, length)
|
Percent Rank |
streak(condition, period)
|
Count consecutive bars where condition is true |
Trend
| Function | Description |
|---|---|
aroon_down(period)
|
Aroon Down - measures time since lowest low |
aroon_osc(period)
|
Aroon Oscillator - difference between Aroon Up and Aroon Down |
aroon_up(period)
|
Aroon Up - measures time since highest high |
falling(source, length)
|
Falling trend detection (consecutively decreasing values) |
macd_histogram(source, fast_period, slow_period, signal_period, fast_matype="ema", slow_matype="ema", matype="ema")
|
MACD Histogram (MACD line - Signal line) |
macd_line(source, fast_period, slow_period, signal_period, fast_matype="ema", slow_matype="ema")
|
MACD Line (fast EMA - slow EMA) |
macd_signal(source, fast_period, slow_period, signal_period, fast_matype="ema", slow_matype="ema", matype="ema")
|
MACD Signal Line (EMA of MACD line) |
rising(source, length)
|
Rising trend detection (consecutively increasing values) |
Volatility
Volume
| Function | Description |
|---|---|
obv(source)
|
On-Balance Volume (Cumulative volume indicator) |
Ready to put this knowledge to use?
Try these functions in the scanner to build powerful stock scans
Open Scanner