polyws 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,55 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main, develop]
6
+ tags: ["v*"]
7
+ pull_request:
8
+ branches: [main]
9
+
10
+ jobs:
11
+ test:
12
+ runs-on: ubuntu-latest
13
+ strategy:
14
+ matrix:
15
+ python-version: ["3.11", "3.12", "3.13"]
16
+
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+
20
+ - name: Set up Python ${{ matrix.python-version }}
21
+ uses: actions/setup-python@v5
22
+ with:
23
+ python-version: ${{ matrix.python-version }}
24
+
25
+ - name: Install dependencies
26
+ run: pip install -e ".[dev]"
27
+
28
+ - name: Run tests
29
+ run: pytest -v
30
+
31
+ publish:
32
+ needs: test
33
+ runs-on: ubuntu-latest
34
+ if: startsWith(github.ref, 'refs/tags/v')
35
+
36
+ permissions:
37
+ id-token: write
38
+ contents: read
39
+
40
+ steps:
41
+ - uses: actions/checkout@v4
42
+
43
+ - name: Set up Python
44
+ uses: actions/setup-python@v5
45
+ with:
46
+ python-version: "3.12"
47
+
48
+ - name: Install build tools
49
+ run: pip install build
50
+
51
+ - name: Build package
52
+ run: python -m build
53
+
54
+ - name: Publish to PyPI
55
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,11 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ dist/
5
+ build/
6
+ .eggs/
7
+ *.egg
8
+ .venv/
9
+ venv/
10
+ .pytest_cache/
11
+ .mypy_cache/
polyws-0.2.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 David
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
polyws-0.2.0/PKG-INFO ADDED
@@ -0,0 +1,294 @@
1
+ Metadata-Version: 2.4
2
+ Name: polyws
3
+ Version: 0.2.0
4
+ Summary: Real-time Polymarket CLOB WebSocket streaming for Python
5
+ License-Expression: MIT
6
+ License-File: LICENSE
7
+ Requires-Python: >=3.11
8
+ Requires-Dist: orjson>=3.10
9
+ Requires-Dist: websockets>=13.0
10
+ Provides-Extra: dev
11
+ Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
12
+ Requires-Dist: pytest>=8.0; extra == 'dev'
13
+ Description-Content-Type: text/markdown
14
+
15
+ # polyws
16
+
17
+ Real-time Polymarket data streaming for Python. Built for trading bots, data pipelines, and AI agents.
18
+
19
+ ```bash
20
+ pip install polyws
21
+ ```
22
+
23
+ ```bash
24
+ polyws stream --markets 10
25
+ ```
26
+
27
+ ```python
28
+ from polyws import WSSubscriptionManager, WebSocketHandlers
29
+
30
+ stream = WSSubscriptionManager(WebSocketHandlers(
31
+ on_polymarket_price_update=lambda events: [
32
+ print(f"{e.asset_id[:16]}… {float(e.price)*100:.1f}%") for e in events
33
+ ]
34
+ ))
35
+ await stream.add_subscriptions(["<asset-id>"])
36
+ ```
37
+
38
+ ---
39
+
40
+ ## Why polyws?
41
+
42
+ Polymarket has two APIs, no official Python streaming library, and a multi-step lookup just to get real-time prices. polyws solves all of that.
43
+
44
+ ### The problem
45
+
46
+ To stream live Polymarket data in Python today, you need to:
47
+
48
+ 1. Query the **Gamma API** to discover markets and extract `clobTokenIds`
49
+ 2. Connect to the **CLOB WebSocket** with a handshake protocol
50
+ 3. Manage subscriptions, reconnections, and ping/pong keepalive
51
+ 4. Maintain an order book cache to compute display prices
52
+ 5. Implement Polymarket's [price calculation logic](https://docs.polymarket.com/polymarket-learn/trading/how-are-prices-calculated#future-price) (midpoint when spread ≤ $0.10, last trade price otherwise)
53
+
54
+ That's ~500 lines of async boilerplate before you write a single line of business logic.
55
+
56
+ ### What polyws gives you
57
+
58
+ ```python
59
+ stream = WSSubscriptionManager(handlers)
60
+ await stream.add_subscriptions(asset_ids)
61
+ # Done. Events flow to your handlers.
62
+ ```
63
+
64
+ - Automatic WebSocket connection, reconnection, and keepalive
65
+ - Subscription batching with event-driven flush (no polling)
66
+ - Order book cache with sorted bid/ask levels
67
+ - Derived display prices matching the Polymarket UI
68
+ - CLI for discovery and streaming without writing code
69
+ - JSON Lines output for piping into other tools and agents
70
+
71
+ ### How it compares
72
+
73
+ | | polyws | [poly-websockets](https://github.com/nevuamarkets/poly-websockets) (TS) | [py-clob-client](https://github.com/Polymarket/py-clob-client) (official) | [polymarket-cli](https://github.com/polymarket/polymarket-cli) (Rust) |
74
+ |--|--------|-------------------|----------------|-----------------|
75
+ | Language | Python | TypeScript | Python | Rust |
76
+ | Real-time streaming | WebSocket | WebSocket | REST only | REST only |
77
+ | Auto-reconnect | Event-driven | Polling (5s interval) | N/A | N/A |
78
+ | Subscription flush | Instant (`asyncio.Event`) | Polling (100ms interval) | N/A | N/A |
79
+ | Display price logic | Built-in | Built-in | Manual | Manual |
80
+ | Order book cache | `bisect.insort` | Full re-sort | None | None |
81
+ | CLI | `polyws markets/stream` | None | None | Full trading CLI |
82
+ | Agent-friendly output | JSON Lines (auto-detect) | None | None | `--output json` |
83
+ | Trading / orders | No | No | Yes | Yes |
84
+ | Runtime deps | 2 | 5 | 8+ | N/A (binary) |
85
+ | Install | `pip install` | `npm install` | `pip install` | `brew install` |
86
+
87
+ **polyws is not a trading client.** It does one thing — real-time data streaming — and does it well. Use it alongside `py-clob-client` for a complete Python trading stack.
88
+
89
+ ---
90
+
91
+ ## CLI
92
+
93
+ ### Browse markets
94
+
95
+ ```bash
96
+ # Top 20 markets by volume
97
+ polyws markets
98
+
99
+ # Search
100
+ polyws markets --search "bitcoin" --limit 5
101
+
102
+ # Sort options: volume (default), liquidity, newest
103
+ polyws markets --sort liquidity --limit 10
104
+ ```
105
+
106
+ ### Stream real-time data
107
+
108
+ ```bash
109
+ # Stream top 10 markets
110
+ polyws stream --markets 10
111
+
112
+ # Stream specific assets
113
+ polyws stream --asset-id 4655345557056451798919...
114
+
115
+ # Search and stream
116
+ polyws stream --search "election"
117
+ ```
118
+
119
+ ### Output format
120
+
121
+ polyws auto-detects the output context:
122
+
123
+ - **Terminal (TTY):** Human-readable, formatted, colored
124
+ - **Piped / redirected:** JSON Lines — one JSON object per line
125
+
126
+ ```bash
127
+ # Human output
128
+ polyws markets --limit 3
129
+
130
+ # 99.7% $58.7M Will there be no change in Fed rates... [10255981...]
131
+ # 0.2% $53.5M Will the Fed decrease rates by 25... [62938043...]
132
+ # 0.1% $48.3M Will the Fed decrease rates by 50+... [46553455...]
133
+
134
+ # Machine output (piped)
135
+ polyws markets --limit 1 | jq .
136
+ # {"asset_id": "102559...", "question": "Will there be...", "volume": 58739675, "price": "0.9965"}
137
+ ```
138
+
139
+ This makes polyws natively usable by AI agents — pipe the output, parse the JSON, act on it.
140
+
141
+ ---
142
+
143
+ ## Library API
144
+
145
+ ### WSSubscriptionManager
146
+
147
+ ```python
148
+ from polyws import WSSubscriptionManager, WebSocketHandlers
149
+
150
+ handlers = WebSocketHandlers(
151
+ on_book=my_book_handler,
152
+ on_price_change=my_change_handler,
153
+ on_last_trade_price=my_trade_handler,
154
+ on_tick_size_change=my_tick_handler,
155
+ on_polymarket_price_update=my_price_handler, # Derived display price
156
+ on_error=my_error_handler,
157
+ on_ws_open=my_open_handler,
158
+ on_ws_close=my_close_handler,
159
+ )
160
+
161
+ manager = WSSubscriptionManager(handlers, reconnect_interval_s=5.0)
162
+ ```
163
+
164
+ All handlers are `async`, optional, and receive a list of typed events.
165
+
166
+ | Method | Description |
167
+ |--------|-------------|
168
+ | `await add_subscriptions(ids)` | Subscribe to assets. Connects automatically. |
169
+ | `await remove_subscriptions(ids)` | Unsubscribe from assets. |
170
+ | `get_asset_ids()` | List all monitored assets. |
171
+ | `get_statistics()` | Connection stats (`open_websockets`, `asset_ids`, `pending_subscribe`, `pending_unsubscribe`). |
172
+ | `await clear_state()` | Full teardown. Manager is reusable after. |
173
+
174
+ ### Market Discovery
175
+
176
+ ```python
177
+ from polyws import fetch_markets, extract_asset_ids
178
+
179
+ markets = fetch_markets(limit=10, sort="volume", search="crypto")
180
+ assets = extract_asset_ids(markets) # {asset_id: question, ...}
181
+ ```
182
+
183
+ ### Event Types
184
+
185
+ | Event | When | Key Fields |
186
+ |-------|------|------------|
187
+ | `BookEvent` | Full order book snapshot on subscribe | `bids`, `asks`, `asset_id` |
188
+ | `PriceChangeEvent` | Order book level added/removed/updated | `price_changes[].side`, `price`, `size` |
189
+ | `LastTradePriceEvent` | A trade executes | `price`, `side`, `size` |
190
+ | `TickSizeChangeEvent` | Tick size changes | `old_tick_size`, `new_tick_size` |
191
+ | `PolymarketPriceUpdateEvent` | Derived display price changes | `price`, `midpoint`, `spread`, `triggering_event` |
192
+
193
+ ### How display prices work
194
+
195
+ Polymarket doesn't show raw bid/ask prices. It shows a **derived price**:
196
+
197
+ - If bid-ask spread ≤ $0.10 → display the **midpoint**
198
+ - If bid-ask spread > $0.10 → display the **last trade price**
199
+
200
+ `on_polymarket_price_update` fires whenever this derived price changes. This matches what you see on polymarket.com.
201
+
202
+ ---
203
+
204
+ ## For AI Agents
205
+
206
+ polyws is designed as a tool for AI agents that need real-time market intelligence.
207
+
208
+ **As a CLI tool:**
209
+ ```bash
210
+ # Agent discovers markets about a topic
211
+ polyws markets --search "AI" --limit 5 | jq -r '.question'
212
+
213
+ # Agent monitors prices and acts on thresholds
214
+ polyws stream --search "bitcoin" | while read line; do
215
+ price=$(echo "$line" | jq -r 'select(.event=="price_update") | .price')
216
+ # ... agent logic ...
217
+ done
218
+ ```
219
+
220
+ **As a Python library:**
221
+ ```python
222
+ # Agent builds a real-time market monitor
223
+ from polyws import WSSubscriptionManager, WebSocketHandlers, fetch_markets, extract_asset_ids
224
+
225
+ markets = fetch_markets(search="election", limit=20)
226
+ assets = extract_asset_ids(markets)
227
+
228
+ async def on_update(events):
229
+ for e in events:
230
+ if float(e.price) > 0.9:
231
+ await alert(f"High confidence: {assets[e.asset_id]} at {e.price}")
232
+
233
+ mgr = WSSubscriptionManager(WebSocketHandlers(on_polymarket_price_update=on_update))
234
+ await mgr.add_subscriptions(list(assets.keys()))
235
+ ```
236
+
237
+ **Why agents prefer polyws over alternatives:**
238
+ - JSON Lines output — no parsing HTML or tables
239
+ - Zero config — no API keys needed for read-only streaming
240
+ - Predictable schema — every event is typed and documented
241
+ - Instant — WebSocket, not polling REST endpoints
242
+ - Composable — pipe into `jq`, `grep`, other tools, or import as a library
243
+
244
+ ---
245
+
246
+ ## Architecture
247
+
248
+ ```
249
+ polyws/
250
+ ├── src/polyws/
251
+ │ ├── types.py # Typed dataclasses for all events
252
+ │ ├── order_book.py # Sorted order book cache (bisect.insort)
253
+ │ ├── manager.py # WebSocket lifecycle, reconnect, flush
254
+ │ ├── gamma.py # Gamma API market discovery
255
+ │ ├── cli.py # CLI entry point (argparse)
256
+ │ └── logger.py # stdlib logging
257
+ ├── tests/ # 53 unit + integration tests
258
+ └── examples/ # Ready-to-run scripts
259
+ ```
260
+
261
+ **Runtime dependencies:** `websockets`, `orjson`. That's it.
262
+
263
+ **Python:** >= 3.11
264
+
265
+ ---
266
+
267
+ ## Development
268
+
269
+ ```bash
270
+ git clone https://github.com/<org>/polyws.git
271
+ cd polyws
272
+ python -m venv .venv && source .venv/bin/activate
273
+ pip install -e ".[dev]"
274
+
275
+ # Run tests
276
+ pytest
277
+
278
+ # Run live integration test (requires network)
279
+ pytest -m live
280
+ ```
281
+
282
+ ---
283
+
284
+ ## Inspired by
285
+
286
+ [poly-websockets](https://github.com/nevuamarkets/poly-websockets) by Nevua Markets — the TypeScript library that pioneered this approach. polyws is a Python rewrite with performance improvements (event-driven flush, bisect-based order book) and a CLI layer for agents and humans.
287
+
288
+ ## License
289
+
290
+ MIT
291
+
292
+ ## Disclaimer
293
+
294
+ This software is provided "as is", without warranty of any kind. The authors are not responsible for any financial losses, trading decisions, or system failures. Polymarket data is provided by Polymarket's public APIs. Use at your own risk.
polyws-0.2.0/README.md ADDED
@@ -0,0 +1,280 @@
1
+ # polyws
2
+
3
+ Real-time Polymarket data streaming for Python. Built for trading bots, data pipelines, and AI agents.
4
+
5
+ ```bash
6
+ pip install polyws
7
+ ```
8
+
9
+ ```bash
10
+ polyws stream --markets 10
11
+ ```
12
+
13
+ ```python
14
+ from polyws import WSSubscriptionManager, WebSocketHandlers
15
+
16
+ stream = WSSubscriptionManager(WebSocketHandlers(
17
+ on_polymarket_price_update=lambda events: [
18
+ print(f"{e.asset_id[:16]}… {float(e.price)*100:.1f}%") for e in events
19
+ ]
20
+ ))
21
+ await stream.add_subscriptions(["<asset-id>"])
22
+ ```
23
+
24
+ ---
25
+
26
+ ## Why polyws?
27
+
28
+ Polymarket has two APIs, no official Python streaming library, and a multi-step lookup just to get real-time prices. polyws solves all of that.
29
+
30
+ ### The problem
31
+
32
+ To stream live Polymarket data in Python today, you need to:
33
+
34
+ 1. Query the **Gamma API** to discover markets and extract `clobTokenIds`
35
+ 2. Connect to the **CLOB WebSocket** with a handshake protocol
36
+ 3. Manage subscriptions, reconnections, and ping/pong keepalive
37
+ 4. Maintain an order book cache to compute display prices
38
+ 5. Implement Polymarket's [price calculation logic](https://docs.polymarket.com/polymarket-learn/trading/how-are-prices-calculated#future-price) (midpoint when spread ≤ $0.10, last trade price otherwise)
39
+
40
+ That's ~500 lines of async boilerplate before you write a single line of business logic.
41
+
42
+ ### What polyws gives you
43
+
44
+ ```python
45
+ stream = WSSubscriptionManager(handlers)
46
+ await stream.add_subscriptions(asset_ids)
47
+ # Done. Events flow to your handlers.
48
+ ```
49
+
50
+ - Automatic WebSocket connection, reconnection, and keepalive
51
+ - Subscription batching with event-driven flush (no polling)
52
+ - Order book cache with sorted bid/ask levels
53
+ - Derived display prices matching the Polymarket UI
54
+ - CLI for discovery and streaming without writing code
55
+ - JSON Lines output for piping into other tools and agents
56
+
57
+ ### How it compares
58
+
59
+ | | polyws | [poly-websockets](https://github.com/nevuamarkets/poly-websockets) (TS) | [py-clob-client](https://github.com/Polymarket/py-clob-client) (official) | [polymarket-cli](https://github.com/polymarket/polymarket-cli) (Rust) |
60
+ |--|--------|-------------------|----------------|-----------------|
61
+ | Language | Python | TypeScript | Python | Rust |
62
+ | Real-time streaming | WebSocket | WebSocket | REST only | REST only |
63
+ | Auto-reconnect | Event-driven | Polling (5s interval) | N/A | N/A |
64
+ | Subscription flush | Instant (`asyncio.Event`) | Polling (100ms interval) | N/A | N/A |
65
+ | Display price logic | Built-in | Built-in | Manual | Manual |
66
+ | Order book cache | `bisect.insort` | Full re-sort | None | None |
67
+ | CLI | `polyws markets/stream` | None | None | Full trading CLI |
68
+ | Agent-friendly output | JSON Lines (auto-detect) | None | None | `--output json` |
69
+ | Trading / orders | No | No | Yes | Yes |
70
+ | Runtime deps | 2 | 5 | 8+ | N/A (binary) |
71
+ | Install | `pip install` | `npm install` | `pip install` | `brew install` |
72
+
73
+ **polyws is not a trading client.** It does one thing — real-time data streaming — and does it well. Use it alongside `py-clob-client` for a complete Python trading stack.
74
+
75
+ ---
76
+
77
+ ## CLI
78
+
79
+ ### Browse markets
80
+
81
+ ```bash
82
+ # Top 20 markets by volume
83
+ polyws markets
84
+
85
+ # Search
86
+ polyws markets --search "bitcoin" --limit 5
87
+
88
+ # Sort options: volume (default), liquidity, newest
89
+ polyws markets --sort liquidity --limit 10
90
+ ```
91
+
92
+ ### Stream real-time data
93
+
94
+ ```bash
95
+ # Stream top 10 markets
96
+ polyws stream --markets 10
97
+
98
+ # Stream specific assets
99
+ polyws stream --asset-id 4655345557056451798919...
100
+
101
+ # Search and stream
102
+ polyws stream --search "election"
103
+ ```
104
+
105
+ ### Output format
106
+
107
+ polyws auto-detects the output context:
108
+
109
+ - **Terminal (TTY):** Human-readable, formatted, colored
110
+ - **Piped / redirected:** JSON Lines — one JSON object per line
111
+
112
+ ```bash
113
+ # Human output
114
+ polyws markets --limit 3
115
+
116
+ # 99.7% $58.7M Will there be no change in Fed rates... [10255981...]
117
+ # 0.2% $53.5M Will the Fed decrease rates by 25... [62938043...]
118
+ # 0.1% $48.3M Will the Fed decrease rates by 50+... [46553455...]
119
+
120
+ # Machine output (piped)
121
+ polyws markets --limit 1 | jq .
122
+ # {"asset_id": "102559...", "question": "Will there be...", "volume": 58739675, "price": "0.9965"}
123
+ ```
124
+
125
+ This makes polyws natively usable by AI agents — pipe the output, parse the JSON, act on it.
126
+
127
+ ---
128
+
129
+ ## Library API
130
+
131
+ ### WSSubscriptionManager
132
+
133
+ ```python
134
+ from polyws import WSSubscriptionManager, WebSocketHandlers
135
+
136
+ handlers = WebSocketHandlers(
137
+ on_book=my_book_handler,
138
+ on_price_change=my_change_handler,
139
+ on_last_trade_price=my_trade_handler,
140
+ on_tick_size_change=my_tick_handler,
141
+ on_polymarket_price_update=my_price_handler, # Derived display price
142
+ on_error=my_error_handler,
143
+ on_ws_open=my_open_handler,
144
+ on_ws_close=my_close_handler,
145
+ )
146
+
147
+ manager = WSSubscriptionManager(handlers, reconnect_interval_s=5.0)
148
+ ```
149
+
150
+ All handlers are `async`, optional, and receive a list of typed events.
151
+
152
+ | Method | Description |
153
+ |--------|-------------|
154
+ | `await add_subscriptions(ids)` | Subscribe to assets. Connects automatically. |
155
+ | `await remove_subscriptions(ids)` | Unsubscribe from assets. |
156
+ | `get_asset_ids()` | List all monitored assets. |
157
+ | `get_statistics()` | Connection stats (`open_websockets`, `asset_ids`, `pending_subscribe`, `pending_unsubscribe`). |
158
+ | `await clear_state()` | Full teardown. Manager is reusable after. |
159
+
160
+ ### Market Discovery
161
+
162
+ ```python
163
+ from polyws import fetch_markets, extract_asset_ids
164
+
165
+ markets = fetch_markets(limit=10, sort="volume", search="crypto")
166
+ assets = extract_asset_ids(markets) # {asset_id: question, ...}
167
+ ```
168
+
169
+ ### Event Types
170
+
171
+ | Event | When | Key Fields |
172
+ |-------|------|------------|
173
+ | `BookEvent` | Full order book snapshot on subscribe | `bids`, `asks`, `asset_id` |
174
+ | `PriceChangeEvent` | Order book level added/removed/updated | `price_changes[].side`, `price`, `size` |
175
+ | `LastTradePriceEvent` | A trade executes | `price`, `side`, `size` |
176
+ | `TickSizeChangeEvent` | Tick size changes | `old_tick_size`, `new_tick_size` |
177
+ | `PolymarketPriceUpdateEvent` | Derived display price changes | `price`, `midpoint`, `spread`, `triggering_event` |
178
+
179
+ ### How display prices work
180
+
181
+ Polymarket doesn't show raw bid/ask prices. It shows a **derived price**:
182
+
183
+ - If bid-ask spread ≤ $0.10 → display the **midpoint**
184
+ - If bid-ask spread > $0.10 → display the **last trade price**
185
+
186
+ `on_polymarket_price_update` fires whenever this derived price changes. This matches what you see on polymarket.com.
187
+
188
+ ---
189
+
190
+ ## For AI Agents
191
+
192
+ polyws is designed as a tool for AI agents that need real-time market intelligence.
193
+
194
+ **As a CLI tool:**
195
+ ```bash
196
+ # Agent discovers markets about a topic
197
+ polyws markets --search "AI" --limit 5 | jq -r '.question'
198
+
199
+ # Agent monitors prices and acts on thresholds
200
+ polyws stream --search "bitcoin" | while read line; do
201
+ price=$(echo "$line" | jq -r 'select(.event=="price_update") | .price')
202
+ # ... agent logic ...
203
+ done
204
+ ```
205
+
206
+ **As a Python library:**
207
+ ```python
208
+ # Agent builds a real-time market monitor
209
+ from polyws import WSSubscriptionManager, WebSocketHandlers, fetch_markets, extract_asset_ids
210
+
211
+ markets = fetch_markets(search="election", limit=20)
212
+ assets = extract_asset_ids(markets)
213
+
214
+ async def on_update(events):
215
+ for e in events:
216
+ if float(e.price) > 0.9:
217
+ await alert(f"High confidence: {assets[e.asset_id]} at {e.price}")
218
+
219
+ mgr = WSSubscriptionManager(WebSocketHandlers(on_polymarket_price_update=on_update))
220
+ await mgr.add_subscriptions(list(assets.keys()))
221
+ ```
222
+
223
+ **Why agents prefer polyws over alternatives:**
224
+ - JSON Lines output — no parsing HTML or tables
225
+ - Zero config — no API keys needed for read-only streaming
226
+ - Predictable schema — every event is typed and documented
227
+ - Instant — WebSocket, not polling REST endpoints
228
+ - Composable — pipe into `jq`, `grep`, other tools, or import as a library
229
+
230
+ ---
231
+
232
+ ## Architecture
233
+
234
+ ```
235
+ polyws/
236
+ ├── src/polyws/
237
+ │ ├── types.py # Typed dataclasses for all events
238
+ │ ├── order_book.py # Sorted order book cache (bisect.insort)
239
+ │ ├── manager.py # WebSocket lifecycle, reconnect, flush
240
+ │ ├── gamma.py # Gamma API market discovery
241
+ │ ├── cli.py # CLI entry point (argparse)
242
+ │ └── logger.py # stdlib logging
243
+ ├── tests/ # 53 unit + integration tests
244
+ └── examples/ # Ready-to-run scripts
245
+ ```
246
+
247
+ **Runtime dependencies:** `websockets`, `orjson`. That's it.
248
+
249
+ **Python:** >= 3.11
250
+
251
+ ---
252
+
253
+ ## Development
254
+
255
+ ```bash
256
+ git clone https://github.com/<org>/polyws.git
257
+ cd polyws
258
+ python -m venv .venv && source .venv/bin/activate
259
+ pip install -e ".[dev]"
260
+
261
+ # Run tests
262
+ pytest
263
+
264
+ # Run live integration test (requires network)
265
+ pytest -m live
266
+ ```
267
+
268
+ ---
269
+
270
+ ## Inspired by
271
+
272
+ [poly-websockets](https://github.com/nevuamarkets/poly-websockets) by Nevua Markets — the TypeScript library that pioneered this approach. polyws is a Python rewrite with performance improvements (event-driven flush, bisect-based order book) and a CLI layer for agents and humans.
273
+
274
+ ## License
275
+
276
+ MIT
277
+
278
+ ## Disclaimer
279
+
280
+ This software is provided "as is", without warranty of any kind. The authors are not responsible for any financial losses, trading decisions, or system failures. Polymarket data is provided by Polymarket's public APIs. Use at your own risk.