Metadata-Version: 2.4
Name: sharpearena
Version: 0.29.0
Classifier: Programming Language :: Rust
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Office/Business :: Financial :: Investment
Classifier: Topic :: Scientific/Engineering
Requires-Dist: numpy>=1.21
Requires-Dist: gymnasium>=1.0
Requires-Dist: mcp ; extra == 'mcp'
Requires-Dist: minari[create,hdf5] ; extra == 'minari'
Requires-Dist: pillow ; extra == 'minari'
Requires-Dist: pettingzoo ; extra == 'pettingzoo'
Requires-Dist: verifiers ; extra == 'verifiers'
Provides-Extra: mcp
Provides-Extra: minari
Provides-Extra: pettingzoo
Provides-Extra: verifiers
Summary: SharpeArena: a deterministic point-in-time evaluation sandbox and Gymnasium environment for trading agents.
Keywords: trading,agent,environment,backtest,reinforcement-learning,gymnasium
Author: General Liquidity, Inc.
License: MIT OR Apache-2.0
Requires-Python: >=3.9
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM

# SharpeArena for Python

The Python distribution combines SharpeArena's deterministic point-in-time
evaluation sandbox with a Gymnasium-compatible environment and optional adapters
for multi-agent, RLVR, offline-RL, MCP, and local-model workflows.

> Point-in-time observations prevent future-bar access through the environment API.
> They do not isolate Python code from the host. Run trusted local code here, or use
> SharpeBench's digest-pinned container path for an untrusted entrant.

## Install

```bash
pip install sharpearena
```

The base install includes NumPy, Gymnasium, the Python package, and the compiled pyo3
extension. Optional integrations are explicit:

```bash
pip install "sharpearena[pettingzoo]"
pip install "sharpearena[verifiers]"
pip install "sharpearena[minari]"
pip install "sharpearena[mcp]"
```

## Step a Gymnasium environment

```python
from sharpearena import SharpeArenaEnv

env = SharpeArenaEnv(n_symbols=4, n_days=120, seed=7)
observation, info = env.reset(seed=7)

terminated = truncated = False
while not (terminated or truncated):
    action = env.action_space.sample()
    observation, reward, terminated, truncated, info = env.step(action)
```

Actions are signed target-weight vectors in the environment's symbol order. The
default range is `[-1, 1]`; pass `allow_short=False` to make it `[0, 1]`, or set
`max_weight` to change the per-symbol bound.

Importing `sharpearena` registers the following Gymnasium IDs:

```text
SharpeArena/Calm-v1          SharpeArena/Calm-Eval-v1
SharpeArena/Hard-v1          SharpeArena/Hard-Eval-v1
SharpeArena/Extreme-v1       SharpeArena/Extreme-Eval-v1
```

The `-Eval-v1` environments draw from the disjoint evaluation seed band. The `-v1`
suffix freezes the environment semantics; a rule change requires a new versioned ID.

## Native boundary

`sharpearena.sharpearena_py.TradingEnv` is the low-level binding. Its boundary is
JSON: `reset()` returns an observation string, and `step(decision_json)` returns
`(observation_json, reward, done, info_json)`. The Python Gymnasium wrapper converts
between that wire format and NumPy spaces.

The wheel ships `py.typed` and a stub for the compiled extension. Typed boundary
exceptions distinguish invalid input, invalid JSON, invalid salt, unavailable data,
and engine failures.

## Scoring and typed unavailability

`score_run(returns, n_trials, periods_per_year)` returns the pinned SharpeBench
`CompositeScore` as JSON. When the kernel cannot score a series (a non-finite
observation, fewer than two observations) the composite carries a typed error
beside a no-skill floor rather than an estimate: `deflation_error` (the deflated
Sharpe, its bar and its interval are the floor), `bootstrap_error` (the bootstrap
p-value is the conservative `1.0` sentinel) and `selection_error` (the selection
diagnostic is absent). Reading `deflated_sharpe` past such a key publishes the
floor as a score.

`sharpearena.kernel_score` is the one place a consumer reads the ranked numbers:

- `kernel_deflated_sharpe(composite)` and `kernel_psr(composite)` return the
  finite value or raise `KernelScoreUnavailable(reason, errors)` naming every
  typed error key present. Selection, ranking inputs and the paper producers use
  these and stop.
- `kernel_score_or_unavailable(composite, key="deflated_sharpe")` returns the
  float or the reason string `unavailable_scoring_kernel_error: <key>: <message>`
  for rows that must be recorded (eval-seed snapshots, generalization and regime
  rows, the PettingZoo leaderboard, trace `meta`, the local-field journal).
  `kernel_score_difference` makes a gap unavailable when either side is;
  `is_kernel_score_unavailable` tests a recorded cell.

Every `score_run` consumer in this package goes through these helpers; none
substitutes a default. The multi-agent ranking places an unscorable agent after
every scored one with the reason in its cell.

## Other surfaces

| Task | Surface |
|---|---|
| Batched Gymnasium rollout | `SharpeArenaVectorEnv` or `gymnasium.make_vec(...)` |
| Multi-agent environment | `MultiAgentSharpeArenaEnv` with the `pettingzoo` extra |
| RLVR / Prime RL | `load_environment()` with the `verifiers` extra |
| Offline RL export | `to_minari`, `to_minari_train_test` with the `minari` extra |
| External tool server | MCP server with the `mcp` extra |
| Evidence field | `sharpearena-local-field` and the model transport shims; raw schema 2 records source-labelled per-request duration and token/retry accounting |
| Benchmark compilation | `sharpearena-compile-bench`; bridge schema 2 adds a validated, rank-neutral p50/p95 operational profile beside score submissions |
| Strategy search | `sharpearena-strategy-search` |

See the repository's [Gymnasium guide](../../docs/gymnasium.md),
[training guide](../../docs/training.md), and
[agent contract](../../docs/agent-contract.md) for the full workflows.

## Build from source

```bash
python -m maturin develop --manifest-path crates/sharpearena-py/Cargo.toml
```

## License

MIT OR Apache-2.0

