Skip to main content

AlphaEngine: the research loop, on your machine

AlphaEngine

The research loop, on your machine.
Ask what is worth looking at, whether it holds up, how much to hold,
and whether anything has crossed a line. Your data never leaves.

PyPI Python 3.10+ Apache 2.0 CI Two dependencies: numpy and scipy

pip install alphaengine                 # library and one-shot commands
pip install "alphaengine[tui]"          # the full-screen session
alphaengine demo                        # offline. no account, no data of yours
alphaengine                             # the session
alphaengine process                     # fit a DGP to the demo walk and stress it

If the shell cannot find alphaengine, this always works:

python -m alphaengine demo
python -m alphaengine
┌──────────┬─────────────────────────────────────┬──────────────────┐
│ ● maths  │  Ask in plain English.              │  sharpe          │
│   always │                                     │  mean / std √252 │
│ ○ flows  │  > which names are overbought?      │  ▁▂▃▅▇█▇▅▃       │
│ ○ ask    │                                     │  0    0.0012     │
│          │  chose screen_universe              │  1   -0.0040     │
│ loaded   │                                     │                  │
│  sp500   │                                     │                  │
└──────────┴─────────────────────────────────────┴──────────────────┘

There is one session, and it is this screen. A sentence picks a workflow. run <name> follows that workflow exactly. The math pane opens when a run has a statistic to show.

alphaengine
> login
> load prices.csv
> screen

Prices stay on this machine. A math line's series can travel on its own trace so it can be charted. The figures posted with the step stay summaries.


What it answers

Eight questions, in the order a research week actually asks them. The command IS the question; only two of them need code of yours.

Ask Command Workflow Needs
Can I trust this data? diagnose diagnose_data prices
What is worth a look? screen screen_universe prices
Does this signal carry information? signal evaluate_signal a signal panel + prices
Is this real, once you count the tries? validate validate_study prices + your backtest
Where does it break? stress stress_study a return series
Is it new, or my book again? overlap check_overlap the candidate + the book
How much should I hold? size size_position a return series
Still inside the lines? monitor monitor_sleeve a return series
alphaengine diagnose --data prices.csv     # before anything runs on it
alphaengine screen --universe sp500
alphaengine size --data returns.csv

The refusals are the point. A screen over a universe that mostly could not be measured is refused as a survivorship artifact rather than ranked. A size on a record shorter than its own minimum track length is refused outright, because a small position is still a claim and the caveat does not travel with it into a book. A monitor with no stated tolerances reports unchecked — never a green light. A stop exits 0: "this did not clear the bar" is the system working.

Or say it in plain English and let your own model pick:

alphaengine
❯ which of my names are overbought on RSI?

That second path is EXPLORATORY: the model chooses a workflow and then chooses each step from what the server permits. Two runs of the same question may differ, and the run says so. run <workflow> is SCRIPTED and reproducible. Both are legitimate; presenting one as the other is not.


The three rungs

Each is useful without the one above it. login lights the next one.

Rung What you need What you get
The maths nothing Every statistic, offline, forever. No account.
Workflows a QuantOS ae_live_ key (login) The loop end to end, with the record.
Ask anything your OWN model key (login anthropic) Plain English in. Runs under your account, not ours.

Nothing here stores a model key: it is read from your environment at call time and handed to the provider's own client. There is no field to put one in.

flowchart LR
  A["demo / import<br/>offline maths"] --> B["login<br/>QuantOS key"]
  B --> C["login anthropic<br/>your model"]
  A -.->|"no account"| D["DSR · PBO · ICIR · HRP"]
  B -.->|"ae_live_"| E["screen · validate · runs"]
  C -.->|"BYOK"| F["plain English in"]

Getting your data in

One verb, three shapes. Nothing is ever fetched on your behalf.

load prices.csv              # a local CSV
load sp500                   # registered in the portal, with the closes you stored
load research.momentum       # a module of yours (the only door that can carry a simulator)

From a shell the same doors are flags, for scripts:

alphaengine screen --data prices.csv
alphaengine screen --universe sp500
alphaengine validate --project research.momentum

--data reads three shapes, decided by the header and nothing else:

wide     date,AAPL,MSFT,NVDA      one column per name
long     date,symbol,close        one row per name per day
series   date,close               a single series, or one bare column of numbers

A file it cannot place raises and names all three rather than guessing. A loader that guesses eventually guesses wrong on somebody's book, and the failure is not an error: it is a screen that ranked returns as prices and produced a shortlist nobody can tell is wrong.

--project is the only door that can carry a simulator, because a simulator is code. That is why validate_study needs it — and evaluate_signal needs it for the scores it measures — while the rest run on prices alone.

--universe brings the closes you stored with it in the portal. That is your own upload decrypted back to your own account, not us fetching market data, and the distinction is the whole of the data boundary below.

Your machine holds prices and notebooks; only figures cross to the QuantOS record


What's new in 0.9.0

next_open fills wait for a prior close. The first bar of a next-open backtest no longer trades that bar's own signal at that bar's open. Close fills are unchanged, and the published goldens do not move.

The session is the full-screen terminal (pip install "alphaengine[tui]"). Each statistic keeps its formula, inputs, and series. Those series post to /api/harness/runs/{id}/traces. A portal that rejects the trace does not fail the run.

What's new in 0.8.0

Named processes, Grinold, and a frozen chart contract. Existing goldens (deflated Sharpe, PBO, performance, screen) are byte-identical. New figures are a public contract from this release. The study schema is 1.1: optional process and charts fields; 1.0 studies still load.

You have You get Module
A spread or a close OU / GBM / jump / GARCH(1,1) calibration, then Monte Carlo stress under that law core.process
An IC and a cross-section Grinold alpha, breadth, transfer coefficient core.active
A return panel Detoned covariance and a PCA variance-explained table core.covariance
Figures that already travel {kind, key, title} hints a portal maps to a chart charts, figure contract

The terminal boot is the README banner: tracked ALPHAENGINE, the subtitle, a teal-left / amber-right mesh (plateau, valley, knife-edge ridge), and your data never leaves. alphaengine process fits a DGP offline, no account.

from alphaengine.core import ou_calibrate, garch_calibrate, dgp_stress, grinold_alpha

ou = ou_calibrate(spread)            # kappa, theta, half_life; or not mean-reverting
g = garch_calibrate(returns)         # omega, alpha, beta, persistence in (0, 1)
s = dgp_stress(close, dgp="ou")      # n_trials = n_paths, source monte_carlo
a = grinold_alpha(panel, ic=0.05)    # alpha vector stays here; scalars travel

What's new in 0.7.0

The daily modelling morning, and the overnight book, without a third dependency. Existing goldens (deflated Sharpe, PBO, performance, screen) are byte-identical. New figures are a public contract from this release.

You have You get Module
A raw factor panel Cross-sectional rank, z-score, winsorize, neutralize core.panel
A signal and prices ICIR, Newey-West t-stat, Fama-MacBeth λ, quantile book with one-way turnover core.signals, core.cross_section
A return panel EWMA / Ledoit-Wolf / Marchenko-Pastur covariance, HRP, risk parity, vol target core.covariance, core.allocate

The session is slimmer too: login lights a rung, load is the one data verb, and boot paints the parameter surface this tool actually judges rather than a command encyclopedia.

from alphaengine.core import cs_zscore, signal_icir, hrp_weights, fama_macbeth

z = cs_zscore(factor_panel)          # skipped names are counted, not dropped
ic = signal_icir(signal, prices)     # Spearman ICIR; Pearson is opt-in
fm = fama_macbeth(signal, prices)    # λ_mean, t-stat, Newey-West
w = hrp_weights(cov, names=names)    # no matrix inverse; weights sum to one

Command reference

alphaengine commands prints this directory in the terminal, and alphaengine commands run expands any one of them.

Get started

Command Does Where
demo run the built-in example offline, with no account and no data shell + session
process [ou | gbm | jump | garch] fit a named process to a series and stress it, offline shell + session
runs [--limit N] your own week: what ran, what it decided, what it filed shell + session
gaps what your record says is UNANSWERED, and what closes each one shell + session
tonight [--budget N] what would run unattended tonight, without running any of it shell + session
workflows what the server offers, what each needs, and which reproduce shell + session
login [quantos | anthropic | openai | gemini | groq | azure | openrouter | gateway] sign in, or login anthropic for a model key shell + session
key [quantos | anthropic | openai | gemini | groq | azure | openrouter | gateway] same as login: enter a credential, or see which rungs are lit session
commands [verb] this directory, or one command in full shell + session
models which model providers this machine can actually use shell + session
model [<provider[:name]>] pin the model for this session, or show the pin session
trace [run_id] local model/run events for a run, hashed prompts only shell + session

Do the work

Command Does Where
diagnose can I trust this data? shell + session
screen what is worth a look? shell + session
signal does this signal carry information? shell + session
validate is this real? shell + session
stress where does it break? shell + session
overlap is it new, or my book again? shell + session
size how much? shell + session
monitor still inside the lines? shell + session
run <workflow> run one workflow exactly as written shell + session
<anything else> ask in plain English; your model picks a workflow and drives it session
status the current run, and what is loaded session

Bring your data

Command Does Where
book [<name> | status] show or load sleeves on the multi-strategy book session
load <file | module | universe> a CSV, a project module, or a portal universe session
thesis [<name> | clear] choose a portal thesis for the next run session
universe <name> same as load: a universe registered in the portal session
data <file> same as load: a local CSV or parquet session
project <module> same as load: a module with data and backtest_fn session

Session

Command Does Where
logout remove stored credentials from this machine shell + session
version print the version shell
help the short list: demo, login, load, then a question session
quit leave the session session

Data flags

Flag What it takes
--data FILE a local CSV. Wide (date,AAPL,MSFT), long (date,symbol,close), or one series.
--universe NAME a universe you registered in the portal, with the closes you stored.
--project MODULE a Python module. The only door that can carry a simulator.

Flags

Flag Does
--url URL workflow server (default $QUANTOS_API_URL or the public API)
--key KEY portal-issued ae_live_ key (default $QUANTOS_API_KEY)
--project MODULE a module exposing data and backtest_fn
--data FILE a local CSV: wide, long, or a single series
--universe NAME a universe registered in the portal, with its stored closes
--thesis NAME a thesis on this account; the run is attached to it
--symbol TICKER one name out of a loaded universe; its closes become the return series
--label TEXT what to call the artifact this run produces
--input K=V a workflow input; repeatable
--quiet only the result, no step narration
--stream print the answer once the citation guard has passed
--limit N how many rows to show (default 25)
--budget N how many runs a night is worth (default 3)

Examples

alphaengine diagnose --universe <name>
alphaengine screen --universe <name>
alphaengine signal
alphaengine validate
alphaengine stress
alphaengine overlap
alphaengine size
alphaengine monitor
alphaengine demo
alphaengine process
alphaengine process ou
alphaengine runs
alphaengine runs --limit 50
alphaengine gaps
alphaengine tonight
alphaengine tonight --budget 5
alphaengine workflows
alphaengine login
alphaengine commands
alphaengine run screen_universe --universe sp500
alphaengine run size_position --data returns.csv
alphaengine run validate_study --project research.momentum
alphaengine models
alphaengine trace
alphaengine run screen_universe --thesis momentum
alphaengine logout
alphaengine version

The library, without the CLI

The commands above are a wrapper. Everything they compute is importable, runs offline, and needs no account:

from alphaengine import sweep

r = sweep(backtest_fn, {"fast": [5, 10, 20], "slow": [50, 100, 200]}, data=prices)

r.surface()  # is the result a broad plateau or a single lucky configuration?
r.verdict()  # deflated for the 9 trials that were actually run
r.save()  # study.json, on your disk

The trial count is derived from the grid that ran, never asserted. Omit it and it is recorded as not_recorded rather than defaulting to a flattering 1, and an unrecorded denominator cannot reach an edge verdict at all.

Writing your own backtest_fn

Two rules, both easy to get wrong the first time, and the reason the example above exists to copy:

Return a bare 1-D return series. Not a dict, not a stats object — the per-period returns themselves. sweep does np.asarray(list(raw)), so a dict of results iterates its keys and fails on the first string.

Return the same length for every combination. PBO splits the trial matrix into time blocks and compares configurations within each block, which only means anything if they line up in time. Ragged output is refused rather than truncated, because silently trimming produces a confident number over series that do not correspond. In practice: pick a warm-up long enough for the slowest window in your grid and start every configuration there.

WARMUP = 200  # covers the slowest `slow` in the grid


def backtest_fn(*, data, fast, slow):
    close = data["close"]
    return [
        (close[i + 1] - close[i]) / close[i] * (1 if sma(close, fast, i) > sma(close, slow, i) else 0)
        for i in range(WARMUP, len(close) - 1)
    ]

data is whatever you want it to be — a DataFrame, a dict of series, an array. The package never inspects it and it never leaves your machine.

What it does

Runs your parameter grid. sweep() calls your backtest function once per combination. It does not backtest anything itself, so the engine you already trust stays the engine you trust.

Counts the trials for you. The statistics that correct a Sharpe ratio for multiple testing need to know how many variants were tested. That number is almost never recorded, because nobody counts what they discarded. Running the grid makes it len(grid), so it never has to be asked for or asserted.

Refuses to flatter an unrecorded count. Since 0.2.0, omitting n_trials means not_recorded — not 1. The trial count comes back null, n_trials_source travels beside it, and a verdict of edge is unreachable without a recorded denominator. A deflated Sharpe is a ratio; deflating by a denominator nobody wrote down does not produce a weaker claim, it produces a claim about nothing.

Shows you the neighbourhood. The output is whether your result sits on a broad plateau or a knife edge, and where the robust region is centred. A single spike surrounded by failures is a result fitted to its own parameters.

Produces a portable study. A JSON artifact holding what was tried, what came back, and a content hash of the data it ran on. Readable in a text editor, diffable, and versioned so it still parses in two years.

What is in it

Module Contents
alphaengine.core deflated Sharpe, PSR, PBO via CSCV, CPCV, minimum track record length, performance and risk
alphaengine.core.panel cross-sectional rank, z-score, winsorize, neutralize
alphaengine.core.signals IC, ICIR, quantile returns, decay
alphaengine.core.cross_section Fama-MacBeth, quantile book with turnover
alphaengine.core.covariance EWMA, Ledoit-Wolf, Marchenko-Pastur denoise, detone, variance explained
alphaengine.core.allocate HRP, risk parity, vol target (EWMA or GARCH)
alphaengine.core.process OU, GBM, jumps, GARCH(1,1), DGP stress
alphaengine.core.active Grinold alpha, breadth, transfer coefficient
alphaengine.charts frozen {kind, key, title} hints; see figure contract
alphaengine.sweep the grid runner and the sensitivity surface
alphaengine.study the study artifact and its schema
alphaengine.client the workflow client and the step executor
alphaengine.cli the alphaengine terminal entry point

Two runtime dependencies, numpy and scipy, both already present in a typical research environment. import alphaengine makes no network call and needs no account. Factor decomposition and cointegration testing need statsmodels and are available as pip install 'alphaengine[factors]'.

Getting a study to somebody else

save() writes to your disk and needs no account. When the work has to reach the PM who will act on it, report() sends the study — and only the study.

import os
from alphaengine import Study, sweep

os.environ["QUANTOS_API_KEY"] = "ae_live_..."  # created in the portal

r = sweep(backtest_fn, grid, data=prices)
r.save()  # yours, on your disk, always

Study.from_sweep(r, label="momentum, 9 configs").report()

What crosses is an explicit allowlist: the trial count and how it was obtained, a content hash of the data, the verdict, the shape of the neighbourhood, the performance figures. Your returns, your prices and your parameter grid stay on the machine, and a guard keyed on length rather than field name refuses to send anything series-shaped whatever it is called.

Reporting is the only part of this package that touches a network, so it is the only part that is not imported until you call it. import alphaengine still makes no network call.

Where this sits in QuantOS

AlphaEngine is the open research layer of the QuantOS platform. It is the piece that runs on your machine, against your data, and it is complete on its own: everything above works offline and forever, at no cost.

The QuantOS platform builds on it. Studies produced here can be persisted to a firm's record, referenced when an idea becomes a position, and assembled into the reports that go to an investment committee or an allocator. The library computes; the platform remembers and reports. The two halves are separated so that the part touching your data has no reason to phone home.

The methods

Everything in core comes from the published literature. Nothing here is a proprietary formula, which is deliberate: a referee whose reasoning you cannot inspect is not a referee.

Deflated Sharpe Ratio, Probabilistic Sharpe Ratio, minimum track record length Bailey, D. H., and López de Prado, M. (2012). "The Sharpe Ratio Efficient Frontier." Journal of Risk 15(2), 3 to 44. Bailey, D. H., and López de Prado, M. (2014). "The Deflated Sharpe Ratio: Correcting for Selection Bias, Backtest Overfitting, and Non-Normality." Journal of Portfolio Management 40(5), 94 to 107.

Probability of Backtest Overfitting via CSCV Bailey, D. H., Borwein, J., López de Prado, M., and Zhu, Q. J. (2017). "The Probability of Backtest Overfitting." Journal of Computational Finance 20(4), 39 to 69.

Combinatorial purged cross-validation López de Prado, M. (2018). Advances in Financial Machine Learning. Wiley, chapters 7 and 12.

Hierarchical Risk Parity López de Prado, M. (2016). "Building Diversified Portfolios that Outperform Out of Sample." Journal of Portfolio Management 42(4), 59 to 69.

Covariance shrinkage and spectral denoising Ledoit, O., and Wolf, M. (2004). "A Well-Conditioned Estimator for Large-Dimensional Covariance Matrices." Journal of Multivariate Analysis 88(2), 365 to 411. Laloux, L., Cizeau, P., Bouchaud, J.-P., and Potters, M. (1999). "Noise Dressing of Financial Correlation Matrices." Physical Review Letters 83(7), 1467 to 1470.

Multiple testing in asset pricing Harvey, C. R., Liu, Y., and Zhu, H. (2016). "... and the Cross-Section of Expected Returns." Review of Financial Studies 29(1), 5 to 68. Harvey, C. R., and Liu, Y. (2015). "Backtesting." Journal of Portfolio Management 42(1), 13 to 28.

Fama-MacBeth Fama, E. F., and MacBeth, J. D. (1973). "Risk, Return, and Equilibrium: Empirical Tests." Journal of Political Economy 81(3), 607 to 636.

Ornstein-Uhlenbeck / Vasicek Vasicek, O. (1977). "An Equilibrium Characterization of the Term Structure." Journal of Financial Economics 5(2), 177 to 188.

GARCH(1,1) Bollerslev, T. (1986). "Generalized Autoregressive Conditional Heteroskedasticity." Journal of Econometrics 31(3), 307 to 327.

Jump-diffusion Merton, R. C. (1976). "Option Pricing When Underlying Stock Returns Are Discontinuous." Journal of Financial Economics 3(1-2), 125 to 144.

The fundamental law of active management Grinold, R. C., and Kahn, R. N. (2000). Active Portfolio Management. 2nd ed. McGraw-Hill.

Downside deviation Sortino, F. A., and Price, L. N. (1994). "Performance Measurement in a Downside Risk Framework." Journal of Investing 3(3), 59 to 64.

Factor regression standard errors (in the factors extra) Newey, W. K., and West, K. D. (1987). "A Simple, Positive Semi-Definite, Heteroskedasticity and Autocorrelation Consistent Covariance Matrix." Econometrica 55(3), 703 to 708.

Unit root testing for cointegration (in the factors extra) Dickey, D. A., and Fuller, W. A. (1979). "Distribution of the Estimators for Autoregressive Time Series with a Unit Root." Journal of the American Statistical Association 74(366), 427 to 431.

Reproducibility

The values these functions return are treated as a public contract. A study written today has to reproduce in two years, so a change to a computed value is a breaking change requiring a version bump even when the signature is unchanged. While the leading digit is 0 the minor position carries that rule — 0.1 → 0.2 is what a changed figure costs — so every 0.2.x release produces identical numbers. CI fails if a pinned value moves.

Installing: "command not found"

The console script lives in your venv's Scripts/ (Windows) or bin/ (POSIX), which joins your PATH only while that venv is activated. A fresh install followed by alphaengine therefore says command not found, which reads as a broken install and is not one.

.\.venv\Scripts\Activate.ps1     # Windows PowerShell
source .venv/bin/activate        # macOS / Linux
alphaengine

Or skip activation entirely — python -m alphaengine always works, because the interpreter that can import the package can always run it:

.venv/Scripts/python.exe -m alphaengine      # Windows, unactivated
.venv/bin/python -m alphaengine              # POSIX, unactivated

This is the price of in-process data access, and it is the one cost we will not engineer around: a launcher that worked from anywhere would have to run in its own environment, which is exactly the isolation that makes compute.* unable to see your DataFrames.

The run narrates itself, because a loop you cannot watch is a loop you cannot trust. The server names an op, this machine executes it and hands back figures:

validate_study · <your workflow server>
  server →  compute.sweep
  local  ·  done
  server →  compute.deflated_sharpe
  local  ·  done
  server →  Stop: the surface is a ridge, not a plateau

--project names an ordinary module of yours exposing data and, if the workflow sweeps, backtest_fn. Authenticate with a key from the portal:

export QUANTOS_API_KEY=ae_live_...     # QUANTOS_API_URL for self-hosted or VPC

A stop exits 0. "This did not clear the bar" is the system working, not a broken build — a non-zero exit there would make every CI pipeline treat an honest refusal as a failure, which is exactly the pressure that gets honesty controls switched off. Only a run that could not execute a step exits non-zero.

Install this into the venv you do research in — not with pipx or uv tool install. The compute steps execute in-process against your own DataFrames, so tool isolation, which is normally the right way to install a CLI, is the one thing that cannot work here. You cannot have isolation and in-process data access, and your data not moving is the point.

No LLM dependency and no key field. AgentDriver takes a callable, so you bring your own model by passing a function. There is nowhere in this tool to put a model key, ours or yours, and that is how "runs under your own account" is satisfied structurally rather than promised.

Development

python -m venv .venv && .venv/bin/pip install -e '.[dev,factors]'

CI runs five gates. Run all of them before pushing — ruff check and ruff format are different tools with different opinions, and passing one says nothing about the other:

python -m ruff check src tests
python -m ruff format --check src tests
python -m mypy src
python -m pytest
python -m pytest tests -m golden -q      # the frozen figures

Licence

Apache-2.0. See LICENSE.

Metadata

Release files for alphaengine 0.9.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for alphaengine 0.9.3
File Size Uploaded Provenance
alphaengine-0.9.3.tar.gz 3.2 MB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for alphaengine 0.9.3
File Interpreter ABI Platform
alphaengine-0.9.3-py3-none-any.whl Python 3 none any Details

Total release size: 3.5 MB

Release files / alphaengine-0.9.3.tar.gz

Download URL alphaengine-0.9.3.tar.gz
Size 3.2 MB
Tags Source
SHA-256 checksum
How to use checksums
f544cf181c822cdc7d81899d693473441aea85ca37c0a13fb18597e53302fd61
BLAKE2b-256 checksum
How to use checksums
cc735c29677fc9fb6d139a1df526a548adaf19f62a4df8e77126af9868d62d2d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.

Transparency log

Release files / alphaengine-0.9.3-py3-none-any.whl

Download URL alphaengine-0.9.3-py3-none-any.whl
Size 256.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8ec311b7a6cbbd720b2165b7265c6e90d33d5e8578812c17663f0d15099d32a2
BLAKE2b-256 checksum
How to use checksums
993f39ca41df95312fa18e8c5a97b0a9a6d2c000724f002b44956ad5c26e5781
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.

Transparency log

Security for alphaengine 0.9.3

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.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for alphaengine-0.9.3.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.

Transparency log

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.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page