Metadata-Version: 2.4
Name: soritrading-watch-together
Version: 0.1.1
Summary: Client for the SoriTrading agent's local API: WATCH TOGETHER signals and exchange rate-limit coordination
Author: Value Connect Global Inc.
License: MIT
Project-URL: Homepage, https://github.com/valueconnectinc/soritrading-watch-together
Project-URL: Source, https://github.com/valueconnectinc/soritrading-watch-together/tree/main/python
Project-URL: Issues, https://github.com/valueconnectinc/soritrading-watch-together/issues
Keywords: soritrading,trading,websocket,sse,rate-limit
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Framework :: AsyncIO
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# soritrading-watch-together (Python)

```sh
pip install soritrading-watch-together
```

asyncio, standard library only. Python 3.8+. The import name is `watch_together`.

```python
import asyncio
from watch_together import connect

async def main():
    api = await connect(
        rest={"url": "http://127.0.0.1:27719", "token": open("local-api.token").read().strip()},
        ws={"url": "ws://127.0.0.1:27720/v1", "token": open("ws-api.token").read().strip()},
        name="my-bot",
        uses=[{"ex": "binance", "sameKey": True, "sameHost": True}],
    )
    print("transport:", api.transport)          # 'ws' or 'rest' - what is actually in use

    api.on("signal", lambda s: print("signal", s["seq"], s["signal"]["sym"]))
    api.guard.on("binance", lambda e: print("binance is now", e["level"], e["why"]))

    while True:
        await api.guard.clear("binance")          # waits while 'hard' (bounded by the lease)
        ...                                       # your own background calls
        await api.report_usage("binance", 5)      # optional: shown to the agent as `external`
        await asyncio.sleep(1)

asyncio.run(main())
```

- `guard.level(ex)` is `free`, `soft`, `hard` or `unknown`. `unknown` means the agent has no control plane (older agent) or no state has been received yet — it is never reported as `free`. `api.tracker.unsupported` tells the two apart.
- `guard.clear()` never blocks on `unknown`.
- Errors are `ApiError` with a machine-readable `code` (and `reason` for `not-contributing`). Read codes, not message text.

Tests: `python3 -m unittest discover -s tests` runs the shared vectors in `../conformance`.
