# headless-oracle (Python SDK)

Prevent your trading bot from executing orders against closed, halted, or holiday-closed markets. Handles ~1,300 schedule edge cases per year across 7 global exchanges.

Built on [Headless Oracle V5](https://headlessoracle.com) — every status assertion is Ed25519-signed and expires in 60 seconds, so stale receipts never reach your execution layer.

## Installation

```bash
pip install headless-oracle
```

With LangChain integration:
```bash
pip install "headless-oracle[langchain]"
```

With CrewAI integration:
```bash
pip install "headless-oracle[crewai]"
```

## Quick start

```python
from headless_oracle import OracleClient, verify

client = OracleClient(api_key="ok_live_...")

# Fetch a signed receipt and verify it
receipt = client.get_status("XNYS")
result = verify(receipt)

if not result.valid:
    raise RuntimeError(f"Receipt invalid: {result.reason}")

# Fail-closed: treat anything that isn't OPEN as CLOSED
if receipt["status"] != "OPEN":
    print("Market is not open — halting all execution")
else:
    print("Market is OPEN — proceed with trading logic")
```

## Verification without a network call

For high-throughput use cases, pass the public key directly to skip the key registry fetch:

```python
PUBLIC_KEY = "03dc27993a2c90856cdeb45e228ac065f18f69f0933c917b2336c1e75712f178"

result = verify(receipt, public_key=PUBLIC_KEY)
```

## Batch queries

```python
receipts = client.get_batch(["XNYS", "XNAS", "XLON"])
for r in receipts["receipts"]:
    print(r["mic"], r["status"])
```

## Verifying receipt fields

| Field | Description |
|-------|-------------|
| `receipt_id` | UUID, unique per receipt |
| `issued_at` | ISO 8601 UTC timestamp |
| `expires_at` | Act before this time (60s TTL) |
| `issuer` | `"headlessoracle.com"` — resolve `{issuer}/v5/keys` to find the public key |
| `mic` | Exchange MIC code (e.g. `XNYS`) |
| `status` | `OPEN`, `CLOSED`, `HALTED`, or `UNKNOWN` |
| `source` | `SCHEDULE`, `OVERRIDE`, or `SYSTEM` |
| `receipt_mode` | `demo` or `live` |
| `schema_version` | `v5.0` |
| `public_key_id` | Key identifier (matches `/v5/keys` registry) |
| `signature` | 128-char hex Ed25519 signature of canonical payload |

**Always treat `UNKNOWN` as `CLOSED`.** It means the oracle encountered an internal error and failed safely.

## Integrations

- [LangChain tool](integrations/langchain_tool.py)
- [CrewAI tool](integrations/crewai_tool.py)

## Supported exchanges

| MIC | Exchange | Timezone |
|-----|----------|----------|
| XNYS | New York Stock Exchange | America/New_York |
| XNAS | NASDAQ | America/New_York |
| XLON | London Stock Exchange | Europe/London |
| XJPX | Japan Exchange Group | Asia/Tokyo |
| XPAR | Euronext Paris | Europe/Paris |
| XHKG | Hong Kong Exchanges | Asia/Hong_Kong |
| XSES | Singapore Exchange | Asia/Singapore |

## License

MIT
