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
4 changes: 3 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@ jobs:
python-version: ${{ matrix.python-version }}
cache: pip
- run: python -m pip install --upgrade pip
- run: python -m pip install -e '.[dev,ccxt]'
- run: python -m pip install -e '.[dev,ccxt,release]'
- run: ruff check .
- run: mypy src
- run: pytest
- if: matrix.python-version == '3.13'
run: python -m build
- if: matrix.python-version == '3.13'
run: python -m twine check --strict dist/*

docker:
runs-on: ubuntu-latest
Expand Down
48 changes: 48 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Documentation

on:
push:
branches: [main]
pull_request:
workflow_dispatch:

permissions:
contents: read

concurrency:
group: pages-${{ github.ref }}
cancel-in-progress: true

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v6
with:
python-version: "3.13"
cache: pip
- run: python -m pip install --upgrade pip
- run: python -m pip install -e '.[docs]'
- run: mkdocs build --strict
- if: github.event_name != 'pull_request'
uses: actions/configure-pages@v5
- if: github.event_name != 'pull_request'
uses: actions/upload-pages-artifact@v4
with:
path: site

deploy:
if: github.event_name != 'pull_request'
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
permissions:
pages: write
id-token: write
steps:
- name: Deploy GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
57 changes: 57 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: Release

on:
release:
types: [published]

permissions:
contents: read

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
ref: ${{ github.event.release.tag_name }}
persist-credentials: false
- uses: actions/setup-python@v6
with:
python-version: "3.13"
cache: pip
- run: python -m pip install --upgrade pip
- run: python -m pip install '.[release]'
- name: Verify release tag
run: python scripts/verify_release.py "${{ github.event.release.tag_name }}"
- name: Build wheel and source distribution
run: python -m build
- name: Check distribution metadata
run: python -m twine check --strict dist/*
- name: Install wheel in a clean environment
run: |
python -m venv /tmp/pineforge-wheel
/tmp/pineforge-wheel/bin/python -m pip install dist/*.whl
/tmp/pineforge-wheel/bin/python -c "import pineforge_data; assert 'Bar' in pineforge_data.__all__"
- name: Upload validated distributions
uses: actions/upload-artifact@v5
with:
name: python-package-distributions
path: dist/
if-no-files-found: error

publish:
needs: build
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/project/pineforge-data/
permissions:
id-token: write
steps:
- name: Download validated distributions
uses: actions/download-artifact@v6
with:
name: python-package-distributions
path: dist/
- name: Publish to PyPI with Trusted Publishing
uses: pypa/gh-action-pypi-publish@release/v1
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ __pycache__/
.venv/
build/
dist/
site/
7 changes: 7 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,16 @@ became available; using today's revised value in an old backtest is lookahead.
## Checks

```bash
python -m pip install -e '.[dev,ccxt,database,server,docs,release]'
ruff check .
mypy src
pytest
mkdocs build --strict
python -m build
python -m twine check dist/*
PINEFORGE_DOCKER_TEST=1 pytest tests/test_docker_integration.py
```

Maintainers should follow the version, tag, artifact, and Trusted Publishing
steps in the [release guide](docs/releasing.md). Contributors cannot publish a
package from a pull request.
35 changes: 19 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,19 @@ the engine receives only normalized bars and ordered trades.

## Documentation

- [Documentation home](docs/index.md) — architecture, guarantees, and guide map.
- [Getting started](docs/getting-started.md) — installation, first provider
- [Documentation home](https://pineforge-4pass.github.io/pineforge-data/) — architecture, guarantees, and guide map.
- [Getting started](https://pineforge-4pass.github.io/pineforge-data/getting-started/) — installation, first provider
request, and local or remote backtest.
- [Normalized data model](docs/data-model.md) — instruments, contracts, bars,
- [Python API reference](https://pineforge-4pass.github.io/pineforge-data/api/) — generated signatures, types, and docstrings.
- [Normalized data model](https://pineforge-4pass.github.io/pineforge-data/data-model/) — instruments, contracts, bars,
live trades, macro vintages, and validation rules.
- [Provider catalog](docs/providers.md) — shared lifecycle and second-level API
- [Provider catalog](https://pineforge-4pass.github.io/pineforge-data/providers/) — shared lifecycle and second-level API
guides for CCXT, CSV, SQLite, and SQLAlchemy.
- [Backtesting](docs/backtesting.md) — CLI options, configuration files, runtime
- [Backtesting](https://pineforge-4pass.github.io/pineforge-data/backtesting/) — CLI options, configuration files, runtime
channels, report schema, and reproducibility.
- [FastAPI server](docs/server.md) — concurrency, authentication, timeouts,
- [FastAPI server](https://pineforge-4pass.github.io/pineforge-data/server/) — concurrency, authentication, timeouts,
compile cache, and deployment.
- [Provider contract](docs/provider-contract.md) — implementing and testing a
- [Provider contract](https://pineforge-4pass.github.io/pineforge-data/provider-contract/) — implementing and testing a
community exchange or broker adapter.

## Why Python first
Expand Down Expand Up @@ -129,9 +130,11 @@ schema = await provider.inspect_schema()
SQL identifiers are validated against reflected metadata; filter values are
bound parameters. For complex transformations, expose a database view rather
than putting raw SQL in harness configuration. See the complete
[provider catalog](docs/providers.md), with dedicated API guides for
[CSV](docs/providers/csv.md), [SQLite](docs/providers/sqlite.md), and
[SQLAlchemy](docs/providers/sqlalchemy.md).
[provider catalog](https://pineforge-4pass.github.io/pineforge-data/providers/),
with dedicated API guides for
[CSV](https://pineforge-4pass.github.io/pineforge-data/providers/csv/),
[SQLite](https://pineforge-4pass.github.io/pineforge-data/providers/sqlite/), and
[SQLAlchemy](https://pineforge-4pass.github.io/pineforge-data/providers/sqlalchemy/).

## Direct backtest harness

Expand Down Expand Up @@ -238,8 +241,8 @@ The server always transpiles Pine deterministically and hashes the generated
C++. Its cache stores the compiled `.so` under a key containing that C++ hash
plus the release, engine, architecture, and compile flags. Concurrent misses
for the same key compile once; subsequent requests skip compilation. Cache
hit/key/hash are included in response provenance. See
[docs/server.md](docs/server.md) for endpoints, limits, deployment, and cache
hit/key/hash are included in response provenance. See the
[server guide](https://pineforge-4pass.github.io/pineforge-data/server/) for endpoints, limits, deployment, and cache
settings.

## Contributing
Expand All @@ -253,10 +256,10 @@ through `pineforge-release`.

| Contribution | Primary location | Start here |
|---|---|---|
| Exchange or broker adapter | `src/pineforge_data/providers/` | [Provider contract](docs/provider-contract.md) |
| Exchange or broker adapter | `src/pineforge_data/providers/` | [Provider contract](https://pineforge-4pass.github.io/pineforge-data/provider-contract/) |
| Market, contract, bar, or request model | `src/pineforge_data/models.py`, `src/pineforge_data/requests.py`, `src/pineforge_data/providers/base.py` | Existing public models and protocols |
| Backtest harness or HTTP client | `src/pineforge_data/cli/backtest.py`, `src/pineforge_data/server_client.py` | Harness unit tests |
| FastAPI concurrency or compile cache | `src/pineforge_data/server.py`, `src/pineforge_data/compile_cache.py` | [Server guide](docs/server.md) |
| FastAPI concurrency or compile cache | `src/pineforge_data/server.py`, `src/pineforge_data/compile_cache.py` | [Server guide](https://pineforge-4pass.github.io/pineforge-data/server/) |
| Release-container integration | `src/pineforge_data/release_contract.py`, `src/pineforge_data/docker_runtime.py` | Pinned release contract and Docker tests |
| Documentation or examples | `README.md`, `docs/` | A focused documentation PR |

Expand Down Expand Up @@ -303,8 +306,8 @@ end-to-end backtest work.
PINEFORGE_DOCKER_TEST=1 .venv/bin/pytest tests/test_docker_integration.py
```

Read the [documentation home](docs/index.md) and
[CONTRIBUTING.md](CONTRIBUTING.md) for provider requirements,
Read the [documentation home](https://pineforge-4pass.github.io/pineforge-data/)
and [CONTRIBUTING.md](https://github.com/pineforge-4pass/pineforge-data/blob/main/CONTRIBUTING.md) for provider requirements,
determinism rules, external provider entry points, and the complete checklist.
For broad changes to public models or the report contract, open an issue first
so providers and runtime consumers can agree on the shape before implementation.
31 changes: 31 additions & 0 deletions docs/api/backtesting.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Backtesting

## Runtime options and reports

::: pineforge_data.backtest.BacktestOptions

::: pineforge_data.backtest.MagnifierDistribution

::: pineforge_data.backtest.BacktestReport

::: pineforge_data.backtest.PineForgeBacktestRunner

::: pineforge_data.backtest.EngineBacktestError

## Published release container

::: pineforge_data.docker_runtime.DockerBacktestRuntime

::: pineforge_data.docker_runtime.DockerPrerequisiteError

::: pineforge_data.docker_runtime.DockerExecutionError

::: pineforge_data.release_contract.DEFAULT_RELEASE_IMAGE

::: pineforge_data.release_contract.ReleaseContractError

## Remote FastAPI client

::: pineforge_data.server_client.FastApiBacktestClient

::: pineforge_data.server_client.BacktestServerError
43 changes: 43 additions & 0 deletions docs/api/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Python API reference

The reference is generated from the package's type annotations, signatures,
and docstrings. Import stable user-facing objects from `pineforge_data` unless
a guide explicitly documents a submodule path.

```python
from pineforge_data import Bar, BarRequest, CcxtProvider, Instrument
```

## Reference map

| Area | Use it for |
|---|---|
| [Models](models.md) | instruments, contracts, OHLCV bars, trades, and macro vintages |
| [Requests](requests.md) | market discovery, historical ranges, live handoffs, and macro queries |
| [Providers](providers.md) | provider protocols, registry extensions, CCXT, CSV, and databases |
| [Backtesting](backtesting.md) | raw-Pine release execution, compiled strategies, reports, and remote clients |
| [Streaming and C ABI](streaming.md) | packing normalized data into native arrays and feeding live trades |
| [Server components](server.md) | embedding the FastAPI service and managing its compile cache |

## Compatibility policy

Names exported by `pineforge_data.__all__` are the intended public Python API.
Modules, functions, and classes whose names begin with an underscore are
internal. The package is currently alpha, so incompatible public API changes
may occur before 1.0, but releases document and version those changes rather
than silently changing an installed version.

Provider implementations use structural protocols. A community package does
not need to inherit from a PineForge base class when it satisfies the required
typed methods. See the [provider contract](../provider-contract.md) for a
complete extension example.

## Optional dependencies

| Extra | Adds |
|---|---|
| `pineforge-data[ccxt]` | CCXT exchange provider |
| `pineforge-data[database]` | SQLAlchemy-compatible databases |
| `pineforge-data[server]` | FastAPI and Uvicorn server runtime |
| `pineforge-data[docs]` | local documentation build toolchain |
| `pineforge-data[release]` | distribution build and metadata checks |
6 changes: 6 additions & 0 deletions docs/api/models.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Models

Normalized records keep vendor data out of the engine boundary while retaining
the source and instrument identity needed for reproducibility.

::: pineforge_data.models
55 changes: 55 additions & 0 deletions docs/api/providers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Providers

## Structural provider protocols

::: pineforge_data.providers.base

## Registry and third-party entry points

::: pineforge_data.providers.registry.ProviderFactory

::: pineforge_data.providers.registry.ProviderRegistry

::: pineforge_data.providers.registry.ProviderRegistryError

::: pineforge_data.providers.registry.ProviderNotFoundError

::: pineforge_data.providers.registry.create_provider

## Runtime tabular mapping

::: pineforge_data.providers.tabular.TimestampUnit

::: pineforge_data.providers.tabular.SourceColumn

::: pineforge_data.providers.tabular.BarColumnMapping

::: pineforge_data.providers.tabular.TabularSchema

::: pineforge_data.providers.tabular.TabularBarProvider

::: pineforge_data.providers.tabular.SchemaMappingError

::: pineforge_data.providers.tabular.TabularDataError

## Built-in providers

::: pineforge_data.providers.ccxt.CcxtProvider

::: pineforge_data.providers.local.CsvBarProvider

::: pineforge_data.providers.local.SqliteBarProvider

::: pineforge_data.providers.sqlalchemy.SqlAlchemyBarProvider

## Provider errors

::: pineforge_data.providers.ccxt.CcxtError

::: pineforge_data.providers.ccxt.CcxtDependencyError

::: pineforge_data.providers.ccxt.CcxtCapabilityError

::: pineforge_data.providers.ccxt.CcxtDataError

::: pineforge_data.providers.sqlalchemy.SqlAlchemyDependencyError
6 changes: 6 additions & 0 deletions docs/api/requests.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Requests

Request objects describe provider-neutral filters and time ranges. Provider-
specific query parameters remain inside each adapter.

::: pineforge_data.requests
17 changes: 17 additions & 0 deletions docs/api/server.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Server components

Most users run the packaged `pineforge-backtest-server` command or submit work
through `FastApiBacktestClient`. These objects support applications that embed
the service or manage its compiled-strategy cache directly.

::: pineforge_data.server.create_app

::: pineforge_data.server.BacktestService

::: pineforge_data.server.BacktestServiceError

::: pineforge_data.compile_cache.CompileCache

The running service also publishes an interactive OpenAPI schema at `/docs`.
See the [server guide](../server.md) for HTTP behavior, concurrency, security,
and deployment configuration.
Loading