This release is a pre-release and may not be stable for production use.
Finalytics is a portfolio analytics engine written in Rust, with this typed Python package over it. It compares portfolio optimisation methods on returns they have not seen, and keeps the books of a real portfolio to report its performance, risk and attribution.
pip install "finalytics[pandas]" # with pandas, as the examples below use
pip install finalytics # with NumPy only
Without pandas, the datasets come as price tables, which Assets takes as well:
fl.Assets(fl.datasets.asset_class_table(), risk_free_asset="T-Bills").
Until 1.0.0 is released, pip install finalytics gives 0.9; install a 1.0
pre-release with pip install --pre finalytics. The
migration guide explains what
replaces each part of 0.9.
Sample reports, built by the programs below from the bundled datasets: comparison · backtest · optimisation · portfolio · rebalance
Portfolio optimisation
Compare optimisation methods on the same assets. Each method is refitted every quarter on the five years before, and judged on the quarter that follows.
import finalytics as fl
assets = fl.Assets(fl.datasets.asset_class_prices(), risk_free_asset="T-Bills")
result = assets.compare(
methods=[
"equal_weight",
"minimum_variance",
"maximum_sharpe",
"maximum_diversification",
"risk_parity",
"hierarchical_risk_parity",
],
max_weight=0.40,
rebalance="quarterly",
validation=fl.WalkForward(years=5),
trading_cost_bps=10,
)
result.show()
Every result has the same shape: result.report is the report, which
print(result) prints as text and result.show() opens as a page (inline in a
Jupyter notebook), and result.results holds every return and trade behind it.
To test one allocation, give a method or your own weights. Here, the maximum Sharpe ratio fitted to the years before November 2016, held from then on against a 60/40 benchmark:
result = assets.backtest(
method="maximum_sharpe",
max_weight=0.40,
benchmark={"US Equity": 0.60, "Bonds": 0.40},
rebalance="quarterly",
validation=fl.Holdout(start="2016-11-01"),
)
result.show()
To see the weights a method chooses today, where their risk comes from and where they sit on the efficient frontier:
result = assets.optimise(
method="maximum_sharpe", max_weight=0.40, frontier=True
)
result.show()
Portfolio analytics
Load a portfolio from its transactions and prices, and report on it: holdings, performance, risk, attribution and scenarios.
import finalytics as fl
portfolio = fl.Portfolio.from_csv(
transactions="transactions.csv",
prices="prices.csv",
fx="fx.csv",
instruments="instruments.csv",
accounts="accounts.csv",
)
report = portfolio.report(benchmark="BENCH", group_by=["asset_class", "region"])
report.show()
The files are the portfolio dataset: a household's brokerage and retirement
accounts, holding five funds in dollars and euros for three years.
fl.datasets.file("portfolio/prices.csv") and the like return each of them, and
fl.datasets.portfolio() loads the same portfolio without them. BENCH is a
column of prices.csv, the benchmark's levels; asset_class and region are
columns of instruments.csv that classify each holding. The sample report adds
the attribution and scenarios of fl.datasets.report_options(). A portfolio's
report is its own result: every figure in it is the portfolio's, so report()
returns the report, with no results beside it.
The start of the dataset's files
id,kind,currency,name,class.asset_class,class.region
VTI,fund,USD,Vanguard Total Stock Market ETF,Equity,North America
EXSA,fund,EUR,iShares STOXX Europe 600 UCITS ETF (DE),Equity,Europe
date,VTI,EXSA,BND,GLD,VNQ,BENCH
2023-11-01,208.86,43.21,68.99,183.51,73.37,100.0000
2023-11-02,213.01,43.92,69.39,184.12,75.78,101.4345
id,name,lot_method,taxable,class.owner,class.wrapper
brokerage,Brokerage account,fifo,true,Alex,Taxable
ira,Retirement account,fifo,false,Alex,Tax-deferred
The data guide describes every file, column by column.
To move the same funds to their least risky mix, 5% to 40% each, optimise the holdings and rebalance the accounts together, with fees and tax rates:
target = portfolio.assets().optimise(
method="minimum_variance", bounds=(0.05, 0.40)
)
result = portfolio.rebalance(
target, whole_units=True, fee_bps=5, minimum_fee=1, tax=(0.37, 0.20)
)
result.show()
Sales in the brokerage account take the lots that cost the least tax; the
retirement account is not taxable (taxable is false in accounts.csv), so its
sales pay none. portfolio.with_rebalance(result) makes the trades.
What is included
Optimisation
- Equal weight, minimum variance, mean–variance and robust mean–variance, maximum Sharpe, target return or volatility, maximum diversification, minimum CVaR, risk parity, hierarchical risk parity
- Limits on each asset and on groups, turnover, tracking error and factor exposure
- Black–Litterman and resampled estimates; Ledoit–Wolf, OAS and EWMA covariance
- Validation in sample, on a holdout, or walk-forward; calendar or drift rebalancing; trading costs
Analytics
- Books from transactions: lots, corporate actions, several accounts and currencies
- Time- and money-weighted returns, contribution, Brinson–Fachler and currency attribution
- Volatility, drawdowns, value at risk, risk decomposition, factor models and scenarios
- Rebalancing trades with fees and tax-aware lot selection, across accounts
Every report prints as text, 80 columns wide, and shows as one self-contained HTML page, in light and dark. Every model is tested against an independent implementation; the methods pages define each one.
Beneath the front doors, fl.risk, fl.opt and fl.performance give each
method on its own, and results are frozen dataclasses with documented fields
(see finalytics.types). Wheels are published for Linux, macOS and Windows.
Documentation
Data guide · Methods · Performance · Migrating from 0.9 · Source and issues
Contributing and licence
Contributions are welcome: see CONTRIBUTING.md. Finalytics is licensed under MIT or Apache-2.0, at your option. It provides analysis tools only and is not investment advice.
Metadata
Release files for finalytics 1.0.0rc2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| finalytics-1.0.0rc2.tar.gz | 2.0 MB | Without provenance | Details for finalytics-1.0.0rc2.tar.gz |
Built distributions (wheels)
Total release size: 38.8 MB
Release files / finalytics-1.0.0rc2.tar.gz
| Download URL | finalytics-1.0.0rc2.tar.gz |
|---|---|
| Size | 2.0 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6a29ef26c1d73c707ad628c599250469189347754fc97a4a25486315920d767f
|
|
BLAKE2b-256 checksum How to use checksums |
80c3d1ba8ad7ab5e43c511228889d0293783f440fc8960b669cde38b04ee39ae
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / finalytics-1.0.0rc2-cp310-abi3-win_amd64.whl
| Download URL | finalytics-1.0.0rc2-cp310-abi3-win_amd64.whl |
|---|---|
| Size | 5.4 MB |
| Tags | CPython 3.10 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
36cfdf12e4f4bc829626a3db1e2c51c14591fbdb501daa9f1e9dd564527f0bdb
|
|
BLAKE2b-256 checksum How to use checksums |
8ebacec54675641914fec9bb401d0963057f3d3974cf3c270079bfec724cdd77
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / finalytics-1.0.0rc2-cp310-abi3-musllinux_1_2_x86_64.whl
| Download URL | finalytics-1.0.0rc2-cp310-abi3-musllinux_1_2_x86_64.whl |
|---|---|
| Size | 5.6 MB |
| Tags | CPython 3.10 Linux musl 1.2+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
840579f463823d76e4bddd513b76f5b7c25244d0905eafa4af90f75fb864cb4c
|
|
BLAKE2b-256 checksum How to use checksums |
8456b5e6cffe79a4ef6d0077d53a4d1b568c0ef98acf07acf8ff2b23ade56844
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / finalytics-1.0.0rc2-cp310-abi3-musllinux_1_2_aarch64.whl
| Download URL | finalytics-1.0.0rc2-cp310-abi3-musllinux_1_2_aarch64.whl |
|---|---|
| Size | 5.2 MB |
| Tags | CPython 3.10 Linux musl 1.2+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
0cb539c4df4369b4b48a22461d914fb28e414320541d23a236fe667bd6b8f22b
|
|
BLAKE2b-256 checksum How to use checksums |
65f4bc6c45c9875126382979a09e34cf555396f1c17d5e377367c337ed447a1b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / finalytics-1.0.0rc2-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
| Download URL | finalytics-1.0.0rc2-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl |
|---|---|
| Size | 5.4 MB |
| Tags | CPython 3.10 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
4ca72859b90317491e0eac369b270d84150a1c03c23b116f745639eb753f1f66
|
|
BLAKE2b-256 checksum How to use checksums |
3fa32f93145f0a3a8fc52541cc940267f6bfc57d88969b4b170a955047b53c27
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / finalytics-1.0.0rc2-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
| Download URL | finalytics-1.0.0rc2-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl |
|---|---|
| Size | 5.0 MB |
| Tags | CPython 3.10 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
1a96f2b25c2704de19fb66a5af9291a634f2c0222cb6a43fd872cdd70bc08d9a
|
|
BLAKE2b-256 checksum How to use checksums |
f1ddac6c4e57113d8c777f9bdb4e8268abd0e88c7b1e2012bbbfdd60ffebbe7d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / finalytics-1.0.0rc2-cp310-abi3-macosx_11_0_arm64.whl
| Download URL | finalytics-1.0.0rc2-cp310-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 4.9 MB |
| Tags | CPython 3.10 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
d44882f1ebc69b47f82cefe2f18b61f9729decf701e677e0600760c1903c52e4
|
|
BLAKE2b-256 checksum How to use checksums |
e82b550425d1e6f0b01f7b914a0ba637d0d1783f38a16f21654e22c9d4e6ac72
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / finalytics-1.0.0rc2-cp310-abi3-macosx_10_12_x86_64.whl
| Download URL | finalytics-1.0.0rc2-cp310-abi3-macosx_10_12_x86_64.whl |
|---|---|
| Size | 5.2 MB |
| Tags | CPython 3.10 abi3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
f83e498fdfb4f9f22507776b19c76958c070d7a9bc452d15ed1b72ccd9bfaf65
|
|
BLAKE2b-256 checksum How to use checksums |
6da85789bb3a3e615e2f812d325b32c3e6b19953ecec55f94b686c16af202739
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Security for finalytics 1.0.0rc2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.