nlalpha-performance
nlalpha-performance 0.6.0 provides shared performance analytics and annualized statistics from account equity observations for backtest engines.
Capability discovery
The nlalpha.capabilities entry point is performance = nlalpha_performance:PerformancePlugin. Its stable provider ID is performance, classified under performance; the plugin caches one provider instance per discovery record. If empyrical-reloaded is missing from a degraded environment, the installed plugin reports provider performance as unavailable with a reason. The capability catalog omits it from available helpers and diagnose_providers() exposes the installed-but-unavailable state. The package does not start its own MCP server; query it through nlalpha-capability.
Install the community package and its declared dependencies with:
python -m pip install nlalpha-performance
Set annualization to a positive integer observations-per-year assumption. Without it, annual return, annual volatility, and Sharpe are returned as null with an annualization_not_provided diagnostic; the provider does not infer a conventional frequency. The finite annual risk_free_rate must be greater than -1 and defaults to 0 with source engine_default. When annualization is configured, it is converted to a per-observation compound rate as expm1(log1p(rate) / annualization).
Statistics use simple returns of net account equity, sample variance (ddof=1), and explicit observation counts. Missing samples, insufficient observations, zero variance for Sharpe, non-positive equity, and numerical overflow are reported as unavailable with reasons. Annualization counts observations rather than calendar time; irregular spacing is not filled or resampled. Consumers record sampling timestamps and spacing, setting provenance, return basis, and fee treatment in diagnostics.
Drawdown episodes
The shared drawdown summary is metrics.risk.drawdowns with episode_count, recovered_episode_count, unrecovered_episode_count, and deepest, longest, current episode rows (each nullable when absent). metrics.risk.max_drawdown remains the scalar maximum and agrees with deepest.depth, or is zero when observations exist without an episode. reports.drawdowns uses the standard report envelope and columns: episode_id, status, peak_equity, peak_timestamp_ns, peak_observation_index, peak_is_initial, start_timestamp_ns, start_observation_index, trough_equity, trough_timestamp_ns, trough_observation_index, recovery_equity, recovery_timestamp_ns, recovery_observation_index, end_timestamp_ns, end_observation_index, depth, decline_duration_ns, recovery_duration_ns, duration_ns, observed_duration_ns, duration_is_lower_bound, decline_observations, recovery_observations, duration_observations. The Vector and Nautilus schema IDs and sources remain engine-specific.
Episodes use completed-bar-close net equity, with fees already reflected. The initial-capital reference is index 0 but has no economic timestamp; its actual reference timestamp, when known, is informational metadata only. The high-water mark resets on equal or greater equity (latest equal peak); a drawdown starts strictly below it, recovery is the first observation at or above the episode peak, and equal troughs keep the earliest trough. Depth is (peak_equity - trough_equity) / peak_equity, a proportion. deepest chooses greatest depth (ties: earlier episode); longest means longest observed drawdown, ordered by observed elapsed duration, then observation intervals, then earlier episode.
If the peak is initial capital, peak timestamp, decline duration and total duration are null because the economic start is unknown. Observed duration from the first underwater point is only a lower bound (duration_is_lower_bound=true). Recovery duration is measured from trough to recovery only for recovered episodes; unrecovered recovery fields remain null. Elapsed nanoseconds and observation interval counts are separate, exact quantities: the initial reference to the first actual observation counts as an interval, never as a fabricated 1 ns. An episode still open at sample end uses the last observed point as its observational end without assuming recovery. No observations yield unavailable/no_equity_observations; available with zero rows means observations existed and no episode occurred.
The report describes sampled closes, not intrabar peaks/troughs. It does not resample calendars, infer annualization, or synthesize timestamps. Nautilus always records its available observed path, while Vector summary keeps bounded O(1) tracker state and aggregate rows but marks episode history not_recorded/record_mode_summary with the known episode count; Vector full records all episodes. Continue using get_backtest_report for paged drawdown rows (maximum 200 rows per page); the existing 32 MiB artifact cap remains.
Historical 0.3.0 focused verification
Historical Empyrical 0.3.0 tracker verification passed for four hand-calculated episodes, initial-peak lower-bound durations, tie rules, separate deepest/longest/current selection, negative equity, extreme 2^64-1 nanosecond span, invalid input, flat and empty observations, and input nonmutation. This is targeted private verification, not a full suite or benchmark rerun.
Monthly and yearly net returns
metrics.performance.period_returns summarizes observed monthly and yearly buckets; detailed rows are exposed by the existing reports.monthly_returns and reports.yearly_returns tables and retrieved with get_backtest_report. No tool ID or input schema is added. Each report has an engine-specific schema and the shared report envelope. Rows identify the Gregorian period in execution.analysis_timezone and its exact calendar bounds represented as UTC nanoseconds, reference/end equity and timestamps, endpoint net PnL/return, observation indexes/count, sample-boundary flags, cross-period attribution, skipped periods, non-positive-equity observation count, and per-field unavailable reasons.
Buckets use local Gregorian month/year boundaries from raw nanosecond timestamps in execution.analysis_timezone (default UTC); boundaries are represented as UTC nanoseconds. A bucket return is the net-equity change assigned to the period of its ending observation; the initial bucket uses starting capital as reference and has no economic reference timestamp. Later buckets use the preceding real observation as reference. Fees and slippage are already reflected in net equity. Non-positive reference equity makes return unavailable; valid negative/zero end equity is preserved. Missing calendar periods are omitted, never filled with zero or carried equity. Skipped-period and cross-period interval diagnostics disclose when a bucket endpoint return spans a gap. diagnostics.period_returns records the analysis timezone, pinned timezone database version and TZIF hash, and strict local-midnight boundary policy; ambiguous or nonexistent month boundaries fail explicitly.
Summary counts, positive fraction, best/worst/current include valid observed buckets, including partial first and last sample periods; denominators are valid observed buckets, not all elapsed or only complete calendar periods. yearly_returns are observed yearly endpoint changes, not annual_return or CAGR and are not compounded from monthly rows. A summary run retains these bounded aggregates but marks report rows not_recorded; full stores rows. Vector uses O(1) aggregation without per-bar date conversion within a bucket. Nautilus independently derives its period rows from its own raw-nanosecond net-equity path, excluding its artificial baseline from buckets while preserving native execution and reporting. Engine schemas and sources remain distinct.
Each frequency summary reports observed_period_count, valid_period_count, unavailable_period_count, positive/negative/flat counts and fraction, skipped-period and cross-period interval counts, skipped-gap bucket count, and best/worst/current rows. Row fields include period, local calendar start/end represented as UTC nanoseconds, reference and ending equity/timestamp/index, net_pnl, net_return, observation_count, first/last flags, closed_by_next_period, cross_period_interval_count, skipped_periods_before, non_positive_equity_observation_count, and unavailable reasons. yearly and monthly use the same conceptual fields under their own table schema.
Historical Empyrical 0.4.0 verification
Empyrical 0.4.0 shared tracker hand cases passed for independent monthly/yearly endpoints, UTC boundary ±1 ns, leap years/gaps, valid-period denominator, non-positive references, overflow-to-null behavior, stable finish, and exact i128 calendar bounds/JSON conversion for signed-i64 extremes. Offline lock and local package rebuild checks passed. This was focused verification, not the full suite or a benchmark rerun.
PeriodReturnsTracker accepts analysis_timezone (default UTC) and groups the ordered UTC-nanosecond observations by that timezone’s local Gregorian boundaries. Python and Rust share Core’s exact pinned TZIF bytes. Report timestamps and bounds remain UTC ns; diagnostics include timezone database identity/hash, and ambiguous or nonexistent local month boundaries fail explicitly. This changes the analysis calendar only; source interpretation and event execution remain unchanged.
Public dependency verification
An isolated CPython 3.12.13 environment using public empyrical-reloaded 0.5.12, NumPy 2.5.4, and pandas 2.3.3 passed 6 tests and 13 subtests in 1.33 seconds. The parent checked the six metric outputs against independent mathematical expectations. The workspace lock update is still in progress; this focused result does not establish that the official lock or every supported environment has been verified.
License
Community distribution under AGPL-3.0-or-later. This applies to the NLAlpha adapter package; empyrical-reloaded and other third-party dependencies retain their own licenses.
Metadata
Release files for nlalpha-performance 0.6.0
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 |
|---|---|---|---|---|
| nlalpha_performance-0.6.0.tar.gz | 33.5 kB | Without provenance | Details for nlalpha_performance-0.6.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| nlalpha_performance-0.6.0-py3-none-any.whl | Python 3 | none | any | Details for nlalpha_performance-0.6.0-py3-none-any.whl |
Total release size: 66.0 kB
Release files / nlalpha_performance-0.6.0.tar.gz
| Download URL | nlalpha_performance-0.6.0.tar.gz |
|---|---|
| Size | 33.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
517beade4b333a1a26d9c52d5543286b66eff53565dc83cf0195aa7fb24708ed
|
|
BLAKE2b-256 checksum How to use checksums |
22ade41b85c77e71e110442b6f7d8cb1d34fd127d7262bd16e47d16325edca01
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.13
|
Release files / nlalpha_performance-0.6.0-py3-none-any.whl
| Download URL | nlalpha_performance-0.6.0-py3-none-any.whl |
|---|---|
| Size | 32.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ced7945dcc8d5015cad20b4d5b0805aa77a653679b4cf81ee30ee3b0b2476f39
|
|
BLAKE2b-256 checksum How to use checksums |
91ec01498bfbef30d8460375c790939ea662adcc072c318b47f3725c87bd3744
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.13
|
Security for nlalpha-performance 0.6.0
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.