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
65 changes: 65 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
name: ci
on:
push:
branches: ["main"]
pull_request:

jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.10", "3.12"]

steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy

- name: Install Python deps
shell: bash
run: |
py="${{ matrix.python-version }}"
if [[ "$py" == "3.10" || "$py" == "3.11" || "$py" == "3.12" ]]; then
spec="==1.26.*"
else
spec="==1.24.*"
fi
python -m pip install --upgrade pip
python -m pip install "numpy${spec}" pytest pytest-cov maturin

- name: Install cargo-tarpaulin
run: cargo install cargo-tarpaulin --locked

- name: Rust fmt
run: cargo fmt --check

- name: Rust clippy
run: cargo clippy -- -D warnings

- name: Rust tests
run: cargo test

- name: Rust coverage
run: cargo tarpaulin --out Xml

- name: Build Python extension
run: maturin develop --release

- name: Python tests
run: pytest --cov=ddstats --cov-report=xml

- name: Upload coverage artifacts
uses: actions/upload-artifact@v4
with:
name: coverage-${{ matrix.python-version }}
path: |
cobertura.xml
coverage.xml
27 changes: 24 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Fast drawdown & CED metrics in Rust with NumPy bindings.

## Overview

`ddstats` provides high-performance financial metrics, including drawdown and Expected Drawdown (CED), implemented in Rust and exposed to Python via NumPy bindings. This allows for fast computations directly from Python, leveraging Rust's speed and safety.
`ddstats` provides high-performance financial metrics, including drawdown and Conditional Expected Drawdown (CED), implemented in Rust and exposed to Python via NumPy bindings. This allows for fast computations directly from Python, leveraging Rust's speed and safety.

## Features

Expand Down Expand Up @@ -49,12 +49,28 @@ Computes the maximum drawdown of a time series.

- **x**: 1D NumPy array of floats.

### `ddstats.ced(x: np.ndarray, level: float) -> float`
### `ddstats.ced(x: np.ndarray, t: int, alpha: float) -> float`

Computes the Conditional Expected Drawdown at a given confidence level.

- **x**: 1D NumPy array of floats.
- **level**: Confidence level (e.g., 0.95).
- **t**: Rolling drawdown distribution window size.
- **alpha**: Confidence level (between 0 and 1).

## Behavior and edge cases

- Any `NaN` in inputs yields `NaN` in the corresponding output.
- Empty inputs return `NaN`.
- Rolling windows honor `min_window` warm-up and `step` stride.

## Testing

```sh
python -m pip install maturin pytest
maturin develop
pytest
cargo test
```

## Building

Expand All @@ -67,3 +83,8 @@ maturin build
## License

MIT License. See [LICENSE](LICENSE).

## Acknowledgements

Inspired by the work of Lisa R. Goldberg and Ola Mahmoud, Drawdown: From Practice to Theory and Back Again.
arXiv:1404.7493
2 changes: 2 additions & 0 deletions ddstats.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ from typing import Literal
from numpy.typing import NDArray
import numpy as np

__version__: str

def max_drawdown(returns: NDArray[np.float64], /) -> float:
"""
Compute the maximum drawdown (MDD).
Expand Down
6 changes: 6 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ dependencies = [
"numpy>=2.0; python_version>='3.13'",
]

[project.optional-dependencies]
test = [
"pytest>=7",
"pytest-cov>=4",
]

[tool.maturin]
features = ["pyo3/extension-module"]
include = ["ddstats.pyi", "py.typed"]
Loading
Loading