# PyO3 Bindings Layer

**Parent**: [/CLAUDE.md](/CLAUDE.md)

PyO3/maturin extension module (`opendeviationbar._core`) bridging Rust crates to Python. Refactored from a monolithic 2999-line file into domain-specific submodules (Issue #94).

---

## Files

| File                         | Purpose                                                                                                                                                                                      | Feature Gate     |
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- |
| `lib.rs`                     | Module entry point: tracing init, rayon pool init, `#[pymodule] fn _core` registration of all classes/functions                                                                              | --               |
| `core_bindings.rs`           | `PyOpenDeviationBarProcessor`, `PyPositionVerification`, `get_feature_manifest_raw()` -- core bar construction                                                                               | --               |
| `arrow_bindings.rs`          | `bars_to_arrow()`, `trades_to_arrow()`, `process_trades_arrow()` -- zero-copy Arrow RecordBatch export                                                                                       | `arrow-export`   |
| `binance_bindings.rs`        | `fetch_binance_aggtrades()`, `fetch_aggtrades_rest()`, `PyBinanceTradeStream`, `PyAdaptiveRateLimiter` -- Binance data fetching (Vision + REST + WS) with per-process singleton rate limiter | `data-providers` |
| `exness_bindings.rs`         | `PyExnessInstrument`, `PyExnessOpenDeviationBarBuilder`, `PyValidationStrictness` -- Exness forex tick data                                                                                  | `data-providers` |
| `streaming_bindings.rs`      | `PyLiveBarEngine`, `PyBinanceLiveStream`, `PyStreamingConfig`, `PyStreamingMetrics`, `PyStreamingOpenDeviationBarProcessor` -- real-time streaming classes                                   | `streaming`      |
| `stream_manager_bindings.rs` | `PyStreamManager`, `PyFormingBarWatcher` -- managed streaming with rate limiting, trade-ID continuity, forming bar watch (Issue #161, #214)                                                  | `streaming`      |
| `odb_engine_bindings.rs`     | `PyOdbEngine` -- unified hot-path/cold-path engine with trait-based source/sink composition (Issue #178)                                                                                     | `streaming`      |
| `gap_bindings.rs`            | `PyGapEventWatcher`, `PyGapFillResult` -- gap detection events and fill results, separate pyclass for borrow safety (Issue #257)                                                             | `streaming`      |
| `helpers.rs`                 | `dict_to_agg_trade()`, `opendeviationbar_to_dict()`, `f64_to_fixed_point()` -- Python dict <-> Rust struct conversions with interned string keys                                             | --               |
| `thread_pool_init.rs`        | `initialize_rayon_pool()` -- one-time rayon global thread pool setup at module load, configurable via `OPENDEVIATIONBAR_RAYON_THREADS`                                                       | --               |

---

## Module Registration

`lib.rs` defines the `#[pymodule] fn _core` entry point. On import, it:

1. Initializes `tracing_subscriber` to stderr (for systemd journal visibility)
2. Calls `thread_pool_init::initialize_rayon_pool()` (eliminates lazy init overhead)
3. Registers classes and functions, gated by Cargo features:
   - **Always**: `PyOpenDeviationBarProcessor`, `PyPositionVerification`, `get_feature_manifest_raw()`
   - **`arrow-export`**: `bars_to_arrow()`, `trades_to_arrow()`
   - **`data-providers`**: Binance + Exness classes and functions
   - **`streaming`**: `PyLiveBarEngine`, `PyStreamManager`, `PyOdbEngine`, `PyGapEventWatcher`, etc.

All submodules use `use super::*` to access shared imports from `lib.rs`.

## Binding Naming Convention

Each `*_bindings.rs` file maps to a domain from the Rust crate workspace:

| Binding File                                                                      | Rust Crate(s)                                                    |
| --------------------------------------------------------------------------------- | ---------------------------------------------------------------- |
| `core_bindings.rs`                                                                | `opendeviationbar-core` (processor, checkpoint, bar)             |
| `arrow_bindings.rs`                                                               | `opendeviationbar-core` (Arrow export functions)                 |
| `binance_bindings.rs`                                                             | `opendeviationbar-providers` (Binance module)                    |
| `exness_bindings.rs`                                                              | `opendeviationbar-providers` (Exness module)                     |
| `streaming_bindings.rs` + `stream_manager_bindings.rs` + `odb_engine_bindings.rs` | `opendeviationbar-streaming` + `opendeviationbar-providers` (WS) |
| `gap_bindings.rs`                                                                 | `opendeviationbar-streaming` (gap events)                        |

Separate pyclass files (e.g., `stream_manager_bindings.rs`, `gap_bindings.rs`) exist for PyO3 borrow safety -- fields within the same `#[pyclass]` share one runtime borrow lock, so independently-accessed objects need separate structs.

## Build

```bash
maturin develop          # Debug build, installs into current venv
maturin develop --release  # Optimized build
```

After any Rust change in `src/` or `crates/`, rebuild with `maturin develop` before testing from Python.

---

## Related

- [/CLAUDE.md](/CLAUDE.md) -- Hub: project overview, architecture, principles
- [/crates/CLAUDE.md](/crates/CLAUDE.md) -- Rust crate workspace: core algorithm, microstructure formulas, streaming engine
- [/python/opendeviationbar/CLAUDE.md](/python/opendeviationbar/CLAUDE.md) -- Python API layer consuming these bindings
