Metadata-Version: 2.4
Name: dollarsmore-faro
Version: 0.1.1
Summary: tastytrade order-execution consumer / SDK: drains order intents off Redis Streams and places them
Project-URL: Homepage, https://github.com/dollarsmore/faro
Project-URL: Repository, https://github.com/dollarsmore/faro
Project-URL: Issues, https://github.com/dollarsmore/faro/issues
Author: Robert Krzysztoforski
License-Expression: MIT
License-File: LICENSE
Keywords: broker,orders,redis,tastytrade,trading
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Office/Business :: Financial :: Investment
Requires-Python: >=3.11
Requires-Dist: dollarsmore-wire>=0.2.0
Requires-Dist: redis<6,>=5.3.1
Requires-Dist: requests<3,>=2.34.2
Description-Content-Type: text/markdown

# faro

A tastytrade order-execution consumer (and the seed of a small tastytrade SDK).
`faro` drains order intents off a Redis Stream and places them against
tastytrade, reporting results back on a results stream. It owns a minimal,
in-house tastytrade REST client (not a third-party broker library), so the
credential and money path is auditable end to end.

The wire schema it speaks is [`wire`](../wire) (`dollarsmore-wire`); a producer
emits `OrderIntent`s, `faro` consumes them and emits `ResultEvent`s.

## Install

```bash
pip install dollarsmore-faro
# or
uv add dollarsmore-faro
```

The distribution is `dollarsmore-faro`; the import package is `faro`.

## Run

```bash
python -m faro                 # cert/sandbox by default
python -m faro --prod          # production
python -m faro --account ... --redis-url redis://host:6379/0 --consumer faro-1
```

Credentials and wiring come from the environment (never baked into the image):

| Variable | Purpose |
|----------|---------|
| `TASTYTRADE_CLIENT_SECRET` | OAuth2 client secret |
| `TASTYTRADE_REFRESH_TOKEN` | OAuth2 refresh token |
| `TASTYTRADE_ACCOUNT` | account number (optional if exactly one account) |
| `REDIS_URL` | Redis connection (default `redis://localhost:6379/0`) |

## Layout

Two layers live side by side; the seam is where a future fuller SDK grows:

- **SDK core** — `session.py` (OAuth2 refresh-token session, never logs tokens,
  refuses non-tastyworks hosts), `client.py` (`TastytradeClient` REST),
  `symbols.py` (OCC option symbols), `executor.py` (`BrokerExecutor` port +
  `TastytradeExecutor` adapter — the swappable broker seam).
- **Consumer app** — `stream.py` (Redis Streams transport: intents / results /
  dead-letter), `service.py` (`FaroService` dispatch loop, crash-tolerant with
  PEL recovery), `heartbeat.py` (container healthcheck verdict), `__main__.py`
  (wires it together).

## Develop

```bash
uv sync                        # wire resolves from PyPI (dollarsmore-wire)
uv run pytest -q
uv run ruff check .
```

## Docker

```bash
docker build -t faro .         # installs dollarsmore-wire from PyPI
```

The image ships only `faro` + `wire` + `requests`/`redis` — no strategy code — so
it is safe to publish.
