Using Expressions¶
polars only
The mintalib.expressions module provides polars expression factory methods for use with polars select and with_columns.
Expressions factory methods are named in upper case (e.g. SMA, EMA, MACD). The output is named after the method name converted to lower case. Use .alias() to rename.
import polars as pl
from mintalib.samples import sample_prices
from mintalib.expressions import SMA, EMA, ATR, MACD, ROC, TYPPRICE
prices = sample_prices(backend="polars")
prices
| date | open | high | low | close | volume |
|---|---|---|---|---|---|
| date | f64 | f64 | f64 | f64 | i64 |
| 1980-12-12 | 0.098207 | 0.098634 | 0.098207 | 0.098207 | 469033600 |
| 1980-12-15 | 0.09351 | 0.09351 | 0.093083 | 0.093083 | 175884800 |
| 1980-12-16 | 0.086678 | 0.086678 | 0.086251 | 0.086251 | 105728000 |
| 1980-12-17 | 0.088386 | 0.088813 | 0.088386 | 0.088386 | 86441600 |
| 1980-12-18 | 0.090949 | 0.091376 | 0.090949 | 0.090949 | 73449600 |
| … | … | … | … | … | … |
| 2026-07-31 | 304.809998 | 310.690002 | 300.0 | 308.910004 | 132489100 |
| 2026-08-03 | 309.579987 | 311.799988 | 302.559998 | 303.420013 | 75052000 |
| 2026-08-04 | 302.730011 | 310.420013 | 301.320007 | 309.380005 | 68001000 |
| 2026-08-05 | 309.359985 | 311.709991 | 305.670013 | 311.0 | 49178700 |
| 2026-08-06 | 314.339996 | 316.289398 | 313.48999 | 314.26001 | 7165536 |
Series Expressions¶
Series-based expressions accept a src input arguments, that generally defaults to the close column.
prices.select(
SMA(20), # default src is the close column, output named "sma"
SMA(20, src=TYPPRICE()).alias("sma_typ"), # src accepts a column name or an expression
)
| sma | sma_typ |
|---|---|
| f64 | f64 |
| null | null |
| null | null |
| null | null |
| null | null |
| null | null |
| … | … |
| 324.367 | 323.631168 |
| 323.905 | 323.363167 |
| 323.841 | 323.110334 |
| 323.7215 | 322.995668 |
| 323.6235 | 323.047824 |
Prices Expressions¶
Prices-based expressions accept arguments for the column inputs like open, high, low, close. These arguments are optional and default to the same column names all in lower case.
prices.select(
ATR(14).alias("atr-14")
)
| atr-14 |
|---|
| f64 |
| null |
| null |
| null |
| null |
| null |
| … |
| 9.872007 |
| 9.826863 |
| 9.774945 |
| 9.508161 |
| 9.206821 |
Multi-Output Expressions¶
Multi-output expressions return a polars struct expression. You can unpack all fields with .struct.unnest(), or select a field with the .struct accessor.
prices.select(
MACD().struct.unnest()
)
| macd | macdsignal | macdhist |
|---|---|---|
| f64 | f64 | f64 |
| null | null | null |
| null | null | null |
| null | null | null |
| null | null | null |
| null | null | null |
| … | … | … |
| 6.894136 | 8.260785 | -1.366649 |
| 4.536518 | 7.515932 | -2.979414 |
| 3.113124 | 6.63537 | -3.522246 |
| 2.091683 | 5.726633 | -3.63495 |
| 1.527629 | 4.886832 | -3.359203 |
prices.select(MACD().struct[0])
| macd |
|---|
| f64 |
| null |
| null |
| null |
| null |
| null |
| … |
| 6.894136 |
| 4.536518 |
| 3.113124 |
| 2.091683 |
| 1.527629 |
prices.select(MACD().struct["macdsignal"])
| macdsignal |
|---|
| f64 |
| null |
| null |
| null |
| null |
| null |
| … |
| 8.260785 |
| 7.515932 |
| 6.63537 |
| 5.726633 |
| 4.886832 |
Piping Series Expressions¶
Series expressions compose with Expr.pipe: the leading expression is passed as src to the next factory.
# Expression can be piped into other expression factory functions.
# The first expression argument is passed as `src` to the next function.
prices.select(
EMA(20).pipe(ROC, 1)
)
| roc |
|---|
| f64 |
| null |
| null |
| null |
| null |
| null |
| … |
| -0.446016 |
| -0.567401 |
| -0.33936 |
| -0.25983 |
| -0.138335 |
prices.select(
MACD(),
sma=SMA(50),
atr=ATR(14),
trend=EMA(50).pipe(ROC, 1)
).unnest()
| macd | macdsignal | macdhist | sma | atr | trend |
|---|---|---|---|---|---|
| f64 | f64 | f64 | f64 | f64 | f64 |
| null | null | null | null | null | null |
| null | null | null | null | null | null |
| null | null | null | null | null | null |
| null | null | null | null | null | null |
| null | null | null | null | null | null |
| … | … | … | … | … | … |
| 6.894136 | 8.260785 | -1.366649 | 309.4994 | 9.872007 | -0.012648 |
| 4.536518 | 7.515932 | -2.979414 | 309.5228 | 9.826863 | -0.081632 |
| 3.113124 | 6.63537 | -3.522246 | 309.610601 | 9.774945 | -0.003007 |
| 2.091683 | 5.726633 | -3.63495 | 309.6542 | 9.508161 | 0.01763 |
| 1.527629 | 4.886832 | -3.359203 | 309.772801 | 9.206821 | 0.058221 |
Studies over multiple symbols¶
An ExprBundle collects several expressions into a reusable study. Its .over() method applies the same window partition to every expression in the bundle.
from mintalib.expressions import ExprBundle
dataset = pl.concat(
[prices.select(pl.lit(symbol).alias("symbol"), pl.all()) for symbol in ["AAA", "BBB", "CCC"]]
)
study = ExprBundle(MACD().struct.unnest(), sma20=SMA(20), sma50=SMA(50))
dataset.with_columns(study.over("symbol"))
| symbol | date | open | high | low | close | volume | macd | macdsignal | macdhist | sma20 | sma50 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| str | date | f64 | f64 | f64 | f64 | i64 | f64 | f64 | f64 | f64 | f64 |
| "AAA" | 1980-12-12 | 0.098207 | 0.098634 | 0.098207 | 0.098207 | 469033600 | null | null | null | null | null |
| "AAA" | 1980-12-15 | 0.09351 | 0.09351 | 0.093083 | 0.093083 | 175884800 | null | null | null | null | null |
| "AAA" | 1980-12-16 | 0.086678 | 0.086678 | 0.086251 | 0.086251 | 105728000 | null | null | null | null | null |
| "AAA" | 1980-12-17 | 0.088386 | 0.088813 | 0.088386 | 0.088386 | 86441600 | null | null | null | null | null |
| "AAA" | 1980-12-18 | 0.090949 | 0.091376 | 0.090949 | 0.090949 | 73449600 | null | null | null | null | null |
| … | … | … | … | … | … | … | … | … | … | … | … |
| "CCC" | 2026-07-31 | 304.809998 | 310.690002 | 300.0 | 308.910004 | 132489100 | 6.894136 | 8.260785 | -1.366649 | 324.367 | 309.4994 |
| "CCC" | 2026-08-03 | 309.579987 | 311.799988 | 302.559998 | 303.420013 | 75052000 | 4.536518 | 7.515932 | -2.979414 | 323.905 | 309.5228 |
| "CCC" | 2026-08-04 | 302.730011 | 310.420013 | 301.320007 | 309.380005 | 68001000 | 3.113124 | 6.63537 | -3.522246 | 323.841 | 309.610601 |
| "CCC" | 2026-08-05 | 309.359985 | 311.709991 | 305.670013 | 311.0 | 49178700 | 2.091683 | 5.726633 | -3.63495 | 323.7215 | 309.6542 |
| "CCC" | 2026-08-06 | 314.339996 | 316.289398 | 313.48999 | 314.26001 | 7165536 | 1.527629 | 4.886832 | -3.359203 | 323.6235 | 309.772801 |