Standard financial calculations
finance-calcs provides financial calculations as composable Polars
expressions. It is designed for lazy execution, namespace-style ergonomics, and
direct interoperability with the rest of the finance-* stack.
The public API follows a few rules:
- every expression metric accepts and returns
pl.Expr - metrics are exposed once, with optional
window=andperiod=controls rather than separate rolling, monthly, and annual variants - functions are also available through the
.fcalcsnamespace on bothpl.Exprandpl.Series - examples use synthetic but realistic fixtures from
finance-datagen
| Topic | Functions |
|---|---|
| Returns and periods | period_bucket, simple_returns, log_returns, cum_returns, cum_returns_final, returns, aggregate_returns, annualized_return, annualized_volatility |
| Risk and drawdown | volatility, sharpe, sortino, calmar, downside_deviation, downside_risk, drawdown_series, underwater_series, max_drawdown, value_at_risk, conditional_value_at_risk, parametric_var |
| Technical indicators | Moving averages, Bollinger/Donchian channels, momentum oscillators, range volatility, and volume indicators |
| Alpha and quantiles | Forward returns, conditional/horizon IC, IC decay, IC summaries, quantile assignment, signal normalization, quantile returns, turnover, and long/short spreads |
| Factor and benchmark metrics | Alpha, beta, up/down capture, batting average, tracking error, and information ratio |
| Distribution and tail risk | Higher moments, Sharpe significance helpers, tail ratio, ulcer index, omega ratio, GPD VaR, and GPD CVaR |
| Portfolio and post-trade | Exposure, concentration, active share, transaction costs/volume/attribution, slippage, turnover, round trips, MAE/MFE, and trade-quality metrics |
See the Examples page for workflows with generated data and the API page for a complete grouped reference for every public function.
Generate a deterministic daily equity path with finance-datagen, then compute
return and risk metrics as Polars expressions.
import polars as pl
from finance_datagen import generate_prices
import finance_calcs as fc
prices = generate_prices(symbol="ACME", seed=7)
out = prices.with_columns(
pl.col("price").fcalcs.simple_returns().alias("ret"),
).select(
fc.returns(pl.col("ret")).alias("total_return"),
pl.col("ret").fcalcs.annualized_return().alias("ann_return"),
pl.col("ret").fcalcs.volatility().alias("ann_vol"),
pl.col("ret").fcalcs.sharpe().alias("sharpe"),
pl.col("ret").fcalcs.max_drawdown().alias("max_drawdown"),
)Use finance-datagen.ohlc_from_close when calculations need OHLCV bars:
from finance_datagen import ohlc_from_close
bars = ohlc_from_close(prices["price"], symbol="ACME", seed=7)
features = bars.with_columns(
pl.col("close").fcalcs.sma(20).alias("sma_20"),
pl.col("close").fcalcs.rsi(14).alias("rsi_14"),
fc.atr(pl.col("high"), pl.col("low"), pl.col("close")).alias("atr_14"),
fc.obv(pl.col("close"), pl.col("volume")).alias("obv"),
)Use period= for calendar-style slices and keep window= for rolling row-count
windows. A period can be a finance_enums.Frequency, any alias accepted by
finance_enums.to_frequency(), any Polars dt.truncate() duration string, or a
precomputed bucket expression.
import polars as pl
from finance_enums import Frequency
monthly = prices.with_columns(
pl.col("price").fcalcs.simple_returns().alias("ret"),
).with_columns(
fc.period_bucket(pl.col("timestamp"), Frequency.Month).alias("month"),
pl.col("ret").fcalcs.returns(period="month", date=pl.col("timestamp")).alias("month_return"),
pl.col("ret").fcalcs.sharpe(period="1q", date=pl.col("timestamp")).alias("quarter_sharpe"),
)For fiscal periods, strategy regimes, or exchange-calendar grids built upstream, pass the bucket expression directly:
bucketed = prices.with_columns(
pl.col("price").fcalcs.simple_returns().alias("ret"),
pl.col("timestamp").dt.year().alias("fiscal_year"),
).with_columns(
fc.returns(pl.col("ret"), period=pl.col("fiscal_year")).alias("fiscal_return"),
)finance-calcs is intended to pair with:
finance-datagenfor synthetic fixtures and test inputsfinance-datesfor calendar-aware date handling upstreamfinance-enumsfor shared enum-backed trading semantics upstream
That keeps calculations focused on typed expressions instead of schema cleanup, string parsing, or calendar repair.