Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: Docs

on:
push:
branches: [main]
paths:
- "docs/**"
- "mkdocs.yml"
- ".github/workflows/docs.yml"
workflow_dispatch:

# Allow only one concurrent deployment, and let in-progress runs finish.
concurrency:
group: pages
cancel-in-progress: false

permissions:
contents: read
pages: write
id-token: write

jobs:
build:
name: Build site
runs-on: ubuntu-latest
steps:
- name: Check out repo
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Install MkDocs
run: |
python -m pip install -U pip
python -m pip install \
"mkdocs-material>=9.5" \
"pymdown-extensions>=10"

- name: Build (strict)
run: mkdocs build --strict

- name: Upload Pages artifact
uses: actions/upload-pages-artifact@v3
with:
path: site

deploy:
name: Deploy to GitHub Pages
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy
id: deployment
uses: actions/deploy-pages@v4
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,6 @@ tools/NNS/src/*.o

# Stray R plotting artifact from headless regeneration
Rplots.pdf

# MkDocs build output
/site/
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

[![PyPI package](https://img.shields.io/badge/package-ovvo--nns-blue)](https://pypi.org/project/ovvo-nns/)
[![Python](https://img.shields.io/badge/python-3.11%2B-blue)](https://www.python.org/)
[![Docs](https://img.shields.io/badge/docs-ovvo--financial.github.io-blue)](https://ovvo-financial.github.io/NNS-python/)
[![License](https://img.shields.io/badge/license-GPL--3.0--only-blue)](LICENSE)

`ovvo-nns` brings Nonlinear Nonparametric Statistics to Python as the `nns` import package. It is a parity-focused port of the R `NNS` 13.0+ package, designed for real-world data that violate symmetry, linearity, or distributional assumptions.
Expand Down Expand Up @@ -178,6 +179,9 @@ uv run python examples/run_all_vignettes.py

## Documentation

The full documentation site is hosted at
**<https://ovvo-financial.github.io/NNS-python/>**.

- [API reference manual](docs/api_reference.md)
- [API status and known gaps](docs/api_status.md)
- [Behavior conventions and intentional divergences](docs/conventions.md)
Expand Down
Binary file added docs/assets/nns_hex_sticker.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
119 changes: 119 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
<img src="assets/nns_hex_sticker.png" width="150" alt="NNS hex sticker" style="border: none; outline: none; margin: 0; padding: 0; display: block;">

[![PyPI package](https://img.shields.io/pypi/v/ovvo-nns?label=ovvo-nns&color=2780e3)](https://pypi.org/project/ovvo-nns/)
[![Python](https://img.shields.io/badge/python-3.11%2B-2780e3)](https://www.python.org/)
[![License](https://img.shields.io/badge/license-GPL--3.0--only-2780e3)](https://github.com/OVVO-Financial/NNS-python/blob/main/LICENSE)

# NNS Python

`ovvo-nns` brings **Nonlinear Nonparametric Statistics** to Python as the `nns`
import package. It is a parity-focused port of the R `NNS` 13.0+ package,
designed for real-world data that violate symmetry, linearity, or distributional
assumptions.

NNS is built around partial moments — the lower and upper components of variance —
and uses them across nonlinear dependence, correlation, causation, regression,
classification, forecasting, stochastic dominance, stochastic superiority, Monte
Carlo simulation, and numerical differentiation workflows.

!!! note "Origin"
NNS was created by Fred Viole as the companion R package to Viole, F. and
Nawrocki, D. (2013), *Nonlinear Nonparametric Statistics: Using Partial
Moments*. **Book (2nd Edition):** <https://ovvo-financial.github.io/NNS/book/>.
For a direct quantitative finance implementation of NNS, see
[OVVO Labs](https://www.ovvolabs.com).

## Package at a glance

| Item | Value |
|---|---|
| Distribution package | `ovvo-nns` |
| Import package | `nns` |
| Python | `>=3.11` |
| Required runtime dependencies | NumPy, SciPy |
| R required at runtime | No |
| Native acceleration | Private, optional `nns._nnscore` kernels where available |
| Public API status | Stable, parity-focused |
| License | GPL-3.0-only |

The public package is Python-native and does not call R at runtime. Some core
kernels can use the private `_nnscore` extension when it is present, while public
functions keep Python implementations and explicit fallback behavior.

## Get started

<div class="grid cards" markdown>

- :material-download: **[Install](install.md)**

`pip install ovvo-nns`, then `import nns`.

- :material-rocket-launch: **[Quick start](quick_start.md)**

Partial moments, dependence, regression, and forecasting in a few lines.

- :material-book-open-variant: **[API reference](api_reference.md)**

Function-by-function index with R `NNS` name crosswalks.

- :material-check-decagram: **[API status](api_status.md)**

Implemented, partial, guarded, and known-gap paths.

</div>

## Main API areas

| Area | Representative functions |
|---|---|
| Partial moments | `lpm`, `upm`, `lpm_ratio`, `upm_ratio`, `pm_matrix` |
| Classical moment helpers | `mean_pm`, `var_pm`, `skew_pm`, `kurt_pm`, `nns_moments` |
| Dependence, correlation, copula | `nns_dep`, `nns_cor`, `nns_copula` |
| Causation | `nns_causation`, `causal_matrix` |
| Regression and classification | `nns_reg`, `nns_m_reg`, `nns_stack`, `nns_boost` |
| Forecasting | `nns_seas`, `nns_arma`, `nns_arma_optim`, `nns_var` |
| Distribution tools | `nns_cdf`, `nns_anova`, `nns_norm` |
| Stochastic dominance | `fsd`, `ssd`, `tsd`, `nns_sd_cluster`, `sd_efficient_set` |
| Stochastic superiority and simulation | `nns_ss`, `nns_mc`, `nns_meboot` |
| Differentiation | `nns_diff`, `dy_dx`, `dy_d` |
| Categorical helpers | `encode_factor_codes`, `factor_2_dummy`, `factor_2_dummy_fr`, `prepare_factor_predictors` |

See [API status](api_status.md) for implemented, partial, guarded, and known-gap
paths.

## Design boundaries

NNS Python prioritizes stable public behavior from installed R NNS 13.0+, not
private helper parity. The package returns NumPy arrays and plain dictionaries
rather than R `data.table` objects, uses explicit Python errors for several
unsafe R coercions, and generally ignores plotting side effects.

See [behavior conventions](conventions.md) for detailed compatibility notes and
[parity with R NNS](parity.md) for the parity target and automation.

## Links

- [View on PyPI](https://pypi.org/project/ovvo-nns/)
- [Browse source code](https://github.com/OVVO-Financial/NNS-python)
- [Report a bug](https://github.com/OVVO-Financial/NNS-python/issues)

## License

[GPL-3.0-only](https://www.gnu.org/licenses/gpl-3.0.en.html)

## Citation

NNS is the companion to Viole, F. and Nawrocki, D. (2013),
*Nonlinear Nonparametric Statistics: Using Partial Moments* (ISBN: 1490523995).
2nd edition: <https://ovvo-financial.github.io/NNS/book/>.

## Developers

- **Fred Viole** — author and maintainer
- **Roberto Spadim** — contributor
- **Rasheed Khoshnaw** — contributor

## Attribution

Upstream R package and reference implementation:
[OVVO-Financial/NNS](https://github.com/OVVO-Financial/NNS).
55 changes: 55 additions & 0 deletions docs/install.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Install

## From PyPI

```bash
pip install ovvo-nns
```

The distribution package is **`ovvo-nns`**; the import package is **`nns`**:

```python
import nns

print(nns.__version__)
```

Installing `ovvo-nns` includes the Matplotlib plotting API (`nns.plotting`).
Matplotlib is a regular dependency and is imported lazily, so `import nns` stays
light. See the [plot parity policy](plot_parity_policy.md) for details.

## Requirements

| Requirement | Value |
|---|---|
| Python | `>=3.11` (CPython 3.11, 3.12, 3.13, 3.14) |
| Runtime dependencies | NumPy, SciPy, Matplotlib |
| R at runtime | Not required |

R is used only for parity tests and local cache regeneration, never at normal
runtime.

## Wheels vs. source builds

Published wheels should be preferred when available. They ship the optional
private native extension (`nns._nnscore`) prebuilt for supported platforms.

Source builds compile the optional native extension with
[`scikit-build-core`](https://scikit-build-core.readthedocs.io/) and
[`nanobind`](https://nanobind.readthedocs.io/), which require a C++17 toolchain.
Public APIs keep Python implementations and explicit fallback behavior, so the
native extension remains a private, benchmark-backed implementation detail rather
than a public API.

## Development install

```bash
uv sync --group dev
uv run pytest
uv run ruff check .
uv run mypy
```

The default parity suite is cache-backed and does not require `Rscript`.
`Rscript` and the R `NNS` package are needed only when regenerating parity caches
or running live R comparison scripts.
75 changes: 75 additions & 0 deletions docs/quick_start.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Quick start

These snippets mirror the runnable
[example vignettes](https://github.com/OVVO-Financial/NNS-python/tree/main/examples/vignettes),
which are exercised in CI so they stay in sync with the package.

## Partial moments

```python
import numpy as np
from nns import lpm, upm

x = np.array([-2.0, -1.0, 0.5, 3.0], dtype=np.float64)

lower = lpm(degree=2, target=0.0, x=x)
upper = upm(degree=2, target=0.0, x=x)

print("lower partial moment:", lower)
print("upper partial moment:", upper)
```

## Nonlinear dependence

```python
import numpy as np
from nns import nns_cor, nns_dep

grid = np.linspace(-2.0, 2.0, 80, dtype=np.float64)
y = grid**2

print("NNS dependence:", nns_dep(grid, y))
print("NNS correlation:", nns_cor(grid, y))
```

## Nonlinear regression

Fit a nonlinear regression and estimate new points:

```python
import numpy as np
from nns import nns_reg

x = np.linspace(-3.0, 3.0, 80, dtype=np.float64)
y = np.sin(x) + 0.2 * x
points = np.array([-1.5, 0.0, 1.5], dtype=np.float64)

fit = nns_reg(x, y, point_est=points, confidence_interval=None)

print("R2:", fit["R2"])
print(np.column_stack((points, fit["Point.est"])))
```

## Forecasting

Forecast a univariate series:

```python
import numpy as np
from nns import nns_arma, nns_seas

t = np.arange(1, 60, dtype=np.float64)
series = 10.0 + np.sin(t / 3.0) + 0.05 * t

seasonality = nns_seas(series, modulo=[3, 4, 6], mod_only=True)
forecast = nns_arma(series, h=3, seasonal_factor=4, method="lin")

print("best seasonal period:", seasonality["best.period"])
print("forecast:", forecast)
```

## Next steps

- Browse the full [API reference](api_reference.md).
- Check the [API status](api_status.md) for partial, guarded, and known-gap paths.
- Read the [behavior conventions](conventions.md) for intentional divergences from R.
31 changes: 31 additions & 0 deletions docs/release_notes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Release notes

The authoritative, per-version release history is published to:

- **PyPI release history:** <https://pypi.org/project/ovvo-nns/#history>
- **GitHub Releases:** <https://github.com/OVVO-Financial/NNS-python/releases>

The currently published version is shown by the badge on the
[home page](index.md) and by:

```python
import nns

print(nns.__version__)
```

## Versioning

`ovvo-nns` uses standard semantic-style version numbers (`MAJOR.MINOR.PATCH`).
The public API is **stable and parity-focused**: documented public behavior is
not expected to break across minor releases. Known partial, guarded, and
known-gap paths are tracked on the [API status](api_status.md) page, and
intentional divergences from R `NNS` are recorded in the
[conventions](conventions.md).

Version numbers are kept consistent across `pyproject.toml`, the package
`__version__`, and the README. This is enforced in CI by
`scripts/check_version_consistency.py`.

For how releases are built, signed, and published, see the
[release process](releasing.md).
Loading
Loading