flowex 0.1.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.
flowex-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 KhavrTrading
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.
flowex-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,199 @@
1
+ Metadata-Version: 2.4
2
+ Name: flowex
3
+ Version: 0.1.0
4
+ Summary: Real-time multi-exchange crypto market data in Python — WebSocket streaming, order book metrics, and per-symbol actor workers for Binance, Bybit, and Bitget.
5
+ Author: KhavrTrading
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/KhavrTrading/flowex-py
8
+ Project-URL: Repository, https://github.com/KhavrTrading/flowex-py
9
+ Project-URL: Issues, https://github.com/KhavrTrading/flowex-py/issues
10
+ Keywords: crypto,trading,market-data,websocket,binance,bybit,bitget,order-book,depth,real-time,go,cgo
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Intended Audience :: Financial and Insurance Industry
14
+ Classifier: Operating System :: POSIX :: Linux
15
+ Classifier: Operating System :: MacOS
16
+ Classifier: Operating System :: Microsoft :: Windows
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Topic :: Office/Business :: Financial
23
+ Classifier: Topic :: Office/Business :: Financial :: Investment
24
+ Classifier: Topic :: Software Development :: Libraries
25
+ Classifier: Typing :: Typed
26
+ Requires-Python: >=3.10
27
+ Description-Content-Type: text/markdown
28
+ License-File: LICENSE
29
+ Dynamic: license-file
30
+
31
+ # flowex
32
+
33
+ [![CI](https://github.com/KhavrTrading/flowex-py/actions/workflows/build.yml/badge.svg)](https://github.com/KhavrTrading/flowex-py/actions/workflows/build.yml)
34
+ [![PyPI](https://img.shields.io/pypi/v/flowex)](https://pypi.org/project/flowex/)
35
+ [![Python](https://img.shields.io/pypi/pyversions/flowex)](https://pypi.org/project/flowex/)
36
+ [![License](https://img.shields.io/github/license/KhavrTrading/flowex-py)](LICENSE)
37
+
38
+ Real-time multi-exchange crypto market data for Python — powered by Go via cgo shared library. WebSocket streaming, order book metrics, and per-symbol actor workers for Binance, Bybit, and Bitget.
39
+
40
+ No subprocess, no gRPC, no serialization overhead on the hot path. The Go runtime lives inside the Python process. Every symbol gets its own goroutine. `get_snapshot()` hits the atomic store directly.
41
+
42
+ ## Install
43
+
44
+ ```bash
45
+ pip install flowex
46
+ ```
47
+
48
+ ## Quick start
49
+
50
+ ```python
51
+ import time
52
+ from flowex import Manager
53
+
54
+ mgr = Manager("binance")
55
+ mgr.subscribe(["BTCUSDT", "ETHUSDT", "SOLUSDT"])
56
+ time.sleep(2)
57
+
58
+ snap = mgr.get_snapshot("BTCUSDT")
59
+ print(snap.depth.spread_bps)
60
+ print(snap.depth.mid_price)
61
+ print(snap.candles[-1].close)
62
+
63
+ mgr.close()
64
+ ```
65
+
66
+ Or use as a context manager:
67
+
68
+ ```python
69
+ with Manager("binance") as mgr:
70
+ mgr.subscribe(["BTCUSDT"])
71
+ time.sleep(2)
72
+ snap = mgr.get_snapshot("BTCUSDT")
73
+ ```
74
+
75
+ ## Supported exchanges
76
+
77
+ - **Binance** — futures WebSocket (candles, depth, aggTrade)
78
+ - **Bybit** — linear futures WebSocket
79
+ - **Bitget** — USDT futures WebSocket
80
+
81
+ ## API
82
+
83
+ ### `Manager(exchange)`
84
+
85
+ Create a manager for an exchange. Initializes the Go runtime and WebSocket connections.
86
+
87
+ ```python
88
+ mgr = Manager("binance") # or "bybit", "bitget"
89
+ ```
90
+
91
+ ### `mgr.subscribe(symbols)`
92
+
93
+ Subscribe to one or more symbols. Starts candle, depth, and trade streams for each.
94
+
95
+ ```python
96
+ mgr.subscribe("BTCUSDT")
97
+ mgr.subscribe(["BTCUSDT", "ETHUSDT", "SOLUSDT"])
98
+ ```
99
+
100
+ ### `mgr.get_snapshot(symbol) -> Snapshot | None`
101
+
102
+ Get the latest point-in-time snapshot for a symbol.
103
+
104
+ ```python
105
+ snap = mgr.get_snapshot("BTCUSDT")
106
+ snap.timestamp # Unix ms
107
+ snap.depth # DepthMetrics
108
+ snap.candles # list[CandleHLCV]
109
+ snap.trades # list[NormalizedTrade]
110
+ ```
111
+
112
+ ### `mgr.get_all_snapshots() -> dict[str, Snapshot]`
113
+
114
+ Get snapshots for all subscribed symbols in one call.
115
+
116
+ ### `mgr.unsubscribe(symbol)`
117
+
118
+ Remove all streams for a symbol.
119
+
120
+ ### `mgr.close()`
121
+
122
+ Shutdown all managers and WebSocket connections.
123
+
124
+ ## Data models
125
+
126
+ ### `DepthMetrics`
127
+
128
+ Order book metrics computed from raw depth data:
129
+
130
+ | Field | Description |
131
+ |-------|-------------|
132
+ | `mid_price` | (best_bid + best_ask) / 2 |
133
+ | `spread_bps` | Spread in basis points |
134
+ | `bid_liquidity_10` | USD liquidity, top 10 bid levels |
135
+ | `ask_liquidity_10` | USD liquidity, top 10 ask levels |
136
+ | `imbalance_ratio_10` | bid_liq / ask_liq (>1 = bullish) |
137
+ | `slippage_buy_10k` | Estimated slippage % for $10k buy |
138
+
139
+ Plus 70+ more fields: liquidity at 5/10/20/50 levels, volumes, imbalance deltas, largest walls, slippage at 8 USD sizes, velocity, momentum, z-scores, and depth quality metrics.
140
+
141
+ ### `CandleHLCV`
142
+
143
+ ```python
144
+ candle.ts # Unix ms
145
+ candle.open
146
+ candle.high
147
+ candle.low
148
+ candle.close
149
+ candle.volume
150
+ ```
151
+
152
+ ### `NormalizedTrade`
153
+
154
+ ```python
155
+ trade.timestamp # Unix ms
156
+ trade.price
157
+ trade.size
158
+ trade.side # "buy" or "sell"
159
+ trade.symbol
160
+ ```
161
+
162
+ ## Architecture
163
+
164
+ ```
165
+ Python process
166
+ |
167
+ +-- ctypes loads libflowex.so <-- Go runtime starts inside Python
168
+ | |
169
+ | +-- Manager (binance)
170
+ | | +-- Worker: BTCUSDT -> atomic snapshot
171
+ | | +-- Worker: ETHUSDT -> atomic snapshot
172
+ | | +-- Worker: SOLUSDT -> atomic snapshot
173
+ | |
174
+ | +-- Manager (bybit)
175
+ | +-- Worker: BTCUSDT -> atomic snapshot
176
+ |
177
+ +-- mgr.subscribe(["BTCUSDT"]) -> FlowexSubscribeBatch()
178
+ +-- mgr.get_snapshot("BTCUSDT") -> FlowexGetSnapshot() -> atomic.Load -> JSON -> Python
179
+ +-- mgr.get_all_snapshots() -> FlowexGetSnapshots() -> one call, all symbols
180
+ ```
181
+
182
+ ## Build from source
183
+
184
+ Requires Go 1.22+ and Python 3.10+.
185
+
186
+ ```bash
187
+ # macOS (Apple Silicon)
188
+ make build-mac
189
+
190
+ # Linux (amd64)
191
+ make build-linux
192
+
193
+ # All platforms (requires cross-compilers)
194
+ make build-all
195
+ ```
196
+
197
+ ## License
198
+
199
+ MIT
flowex-0.1.0/README.md ADDED
@@ -0,0 +1,169 @@
1
+ # flowex
2
+
3
+ [![CI](https://github.com/KhavrTrading/flowex-py/actions/workflows/build.yml/badge.svg)](https://github.com/KhavrTrading/flowex-py/actions/workflows/build.yml)
4
+ [![PyPI](https://img.shields.io/pypi/v/flowex)](https://pypi.org/project/flowex/)
5
+ [![Python](https://img.shields.io/pypi/pyversions/flowex)](https://pypi.org/project/flowex/)
6
+ [![License](https://img.shields.io/github/license/KhavrTrading/flowex-py)](LICENSE)
7
+
8
+ Real-time multi-exchange crypto market data for Python — powered by Go via cgo shared library. WebSocket streaming, order book metrics, and per-symbol actor workers for Binance, Bybit, and Bitget.
9
+
10
+ No subprocess, no gRPC, no serialization overhead on the hot path. The Go runtime lives inside the Python process. Every symbol gets its own goroutine. `get_snapshot()` hits the atomic store directly.
11
+
12
+ ## Install
13
+
14
+ ```bash
15
+ pip install flowex
16
+ ```
17
+
18
+ ## Quick start
19
+
20
+ ```python
21
+ import time
22
+ from flowex import Manager
23
+
24
+ mgr = Manager("binance")
25
+ mgr.subscribe(["BTCUSDT", "ETHUSDT", "SOLUSDT"])
26
+ time.sleep(2)
27
+
28
+ snap = mgr.get_snapshot("BTCUSDT")
29
+ print(snap.depth.spread_bps)
30
+ print(snap.depth.mid_price)
31
+ print(snap.candles[-1].close)
32
+
33
+ mgr.close()
34
+ ```
35
+
36
+ Or use as a context manager:
37
+
38
+ ```python
39
+ with Manager("binance") as mgr:
40
+ mgr.subscribe(["BTCUSDT"])
41
+ time.sleep(2)
42
+ snap = mgr.get_snapshot("BTCUSDT")
43
+ ```
44
+
45
+ ## Supported exchanges
46
+
47
+ - **Binance** — futures WebSocket (candles, depth, aggTrade)
48
+ - **Bybit** — linear futures WebSocket
49
+ - **Bitget** — USDT futures WebSocket
50
+
51
+ ## API
52
+
53
+ ### `Manager(exchange)`
54
+
55
+ Create a manager for an exchange. Initializes the Go runtime and WebSocket connections.
56
+
57
+ ```python
58
+ mgr = Manager("binance") # or "bybit", "bitget"
59
+ ```
60
+
61
+ ### `mgr.subscribe(symbols)`
62
+
63
+ Subscribe to one or more symbols. Starts candle, depth, and trade streams for each.
64
+
65
+ ```python
66
+ mgr.subscribe("BTCUSDT")
67
+ mgr.subscribe(["BTCUSDT", "ETHUSDT", "SOLUSDT"])
68
+ ```
69
+
70
+ ### `mgr.get_snapshot(symbol) -> Snapshot | None`
71
+
72
+ Get the latest point-in-time snapshot for a symbol.
73
+
74
+ ```python
75
+ snap = mgr.get_snapshot("BTCUSDT")
76
+ snap.timestamp # Unix ms
77
+ snap.depth # DepthMetrics
78
+ snap.candles # list[CandleHLCV]
79
+ snap.trades # list[NormalizedTrade]
80
+ ```
81
+
82
+ ### `mgr.get_all_snapshots() -> dict[str, Snapshot]`
83
+
84
+ Get snapshots for all subscribed symbols in one call.
85
+
86
+ ### `mgr.unsubscribe(symbol)`
87
+
88
+ Remove all streams for a symbol.
89
+
90
+ ### `mgr.close()`
91
+
92
+ Shutdown all managers and WebSocket connections.
93
+
94
+ ## Data models
95
+
96
+ ### `DepthMetrics`
97
+
98
+ Order book metrics computed from raw depth data:
99
+
100
+ | Field | Description |
101
+ |-------|-------------|
102
+ | `mid_price` | (best_bid + best_ask) / 2 |
103
+ | `spread_bps` | Spread in basis points |
104
+ | `bid_liquidity_10` | USD liquidity, top 10 bid levels |
105
+ | `ask_liquidity_10` | USD liquidity, top 10 ask levels |
106
+ | `imbalance_ratio_10` | bid_liq / ask_liq (>1 = bullish) |
107
+ | `slippage_buy_10k` | Estimated slippage % for $10k buy |
108
+
109
+ Plus 70+ more fields: liquidity at 5/10/20/50 levels, volumes, imbalance deltas, largest walls, slippage at 8 USD sizes, velocity, momentum, z-scores, and depth quality metrics.
110
+
111
+ ### `CandleHLCV`
112
+
113
+ ```python
114
+ candle.ts # Unix ms
115
+ candle.open
116
+ candle.high
117
+ candle.low
118
+ candle.close
119
+ candle.volume
120
+ ```
121
+
122
+ ### `NormalizedTrade`
123
+
124
+ ```python
125
+ trade.timestamp # Unix ms
126
+ trade.price
127
+ trade.size
128
+ trade.side # "buy" or "sell"
129
+ trade.symbol
130
+ ```
131
+
132
+ ## Architecture
133
+
134
+ ```
135
+ Python process
136
+ |
137
+ +-- ctypes loads libflowex.so <-- Go runtime starts inside Python
138
+ | |
139
+ | +-- Manager (binance)
140
+ | | +-- Worker: BTCUSDT -> atomic snapshot
141
+ | | +-- Worker: ETHUSDT -> atomic snapshot
142
+ | | +-- Worker: SOLUSDT -> atomic snapshot
143
+ | |
144
+ | +-- Manager (bybit)
145
+ | +-- Worker: BTCUSDT -> atomic snapshot
146
+ |
147
+ +-- mgr.subscribe(["BTCUSDT"]) -> FlowexSubscribeBatch()
148
+ +-- mgr.get_snapshot("BTCUSDT") -> FlowexGetSnapshot() -> atomic.Load -> JSON -> Python
149
+ +-- mgr.get_all_snapshots() -> FlowexGetSnapshots() -> one call, all symbols
150
+ ```
151
+
152
+ ## Build from source
153
+
154
+ Requires Go 1.22+ and Python 3.10+.
155
+
156
+ ```bash
157
+ # macOS (Apple Silicon)
158
+ make build-mac
159
+
160
+ # Linux (amd64)
161
+ make build-linux
162
+
163
+ # All platforms (requires cross-compilers)
164
+ make build-all
165
+ ```
166
+
167
+ ## License
168
+
169
+ MIT
@@ -0,0 +1,86 @@
1
+ from __future__ import annotations
2
+
3
+ import atexit
4
+ import ctypes
5
+ import json
6
+
7
+ from flowex._lib import lib as _lib
8
+ from flowex._models import CandleHLCV, DepthMetrics, NormalizedTrade, Snapshot
9
+
10
+ __all__ = [
11
+ "Manager",
12
+ "Snapshot",
13
+ "CandleHLCV",
14
+ "DepthMetrics",
15
+ "NormalizedTrade",
16
+ ]
17
+
18
+ _shutdown_registered = False
19
+
20
+
21
+ class Manager:
22
+ """Wraps a flowex exchange manager loaded via the shared library.
23
+
24
+ Usage::
25
+
26
+ with Manager("binance") as mgr:
27
+ mgr.subscribe(["BTCUSDT", "ETHUSDT"])
28
+ snap = mgr.get_snapshot("BTCUSDT")
29
+ """
30
+
31
+ def __init__(self, exchange: str) -> None:
32
+ global _shutdown_registered
33
+ self._exchange = exchange.lower()
34
+ self._exchange_b = self._exchange.encode("utf-8")
35
+ rc = _lib.FlowexInit(self._exchange_b)
36
+ if rc != 0:
37
+ raise RuntimeError(f"FlowexInit failed for {exchange!r}")
38
+ if not _shutdown_registered:
39
+ atexit.register(_lib.FlowexShutdown)
40
+ _shutdown_registered = True
41
+
42
+ def subscribe(self, symbols: list[str] | str) -> None:
43
+ if isinstance(symbols, str):
44
+ symbols = [symbols]
45
+ arr = (ctypes.c_char_p * len(symbols))(
46
+ *(s.encode("utf-8") for s in symbols)
47
+ )
48
+ rc = _lib.FlowexSubscribeBatch(self._exchange_b, arr, len(symbols))
49
+ if rc != 0:
50
+ raise RuntimeError("FlowexSubscribeBatch failed")
51
+
52
+ def get_snapshot(self, symbol: str) -> Snapshot | None:
53
+ ptr = _lib.FlowexGetSnapshot(self._exchange_b, symbol.encode("utf-8"))
54
+ if not ptr:
55
+ return None
56
+ try:
57
+ raw = ctypes.string_at(ptr)
58
+ data = json.loads(raw)
59
+ finally:
60
+ _lib.FlowexFree(ptr)
61
+ return Snapshot.from_dict(data)
62
+
63
+ def get_all_snapshots(self) -> dict[str, Snapshot]:
64
+ ptr = _lib.FlowexGetSnapshots(self._exchange_b)
65
+ if not ptr:
66
+ return {}
67
+ try:
68
+ raw = ctypes.string_at(ptr)
69
+ data = json.loads(raw)
70
+ finally:
71
+ _lib.FlowexFree(ptr)
72
+ return {sym: Snapshot.from_dict(snap) for sym, snap in data.items()}
73
+
74
+ def unsubscribe(self, symbol: str) -> None:
75
+ rc = _lib.FlowexUnsubscribe(self._exchange_b, symbol.encode("utf-8"))
76
+ if rc != 0:
77
+ raise RuntimeError(f"FlowexUnsubscribe failed for {symbol!r}")
78
+
79
+ def close(self) -> None:
80
+ _lib.FlowexShutdown()
81
+
82
+ def __enter__(self) -> Manager:
83
+ return self
84
+
85
+ def __exit__(self, *args: object) -> None:
86
+ self.close()
@@ -0,0 +1,67 @@
1
+ import ctypes
2
+ import os
3
+ import platform
4
+
5
+
6
+ def _load():
7
+ system = platform.system()
8
+ machine = platform.machine()
9
+
10
+ pkg_dir = os.path.dirname(os.path.abspath(__file__))
11
+ lib_dir = os.path.join(pkg_dir, "lib")
12
+
13
+ if system == "Linux":
14
+ if machine in ("aarch64", "arm64"):
15
+ name = "libflowex-arm64.so"
16
+ else:
17
+ name = "libflowex.so"
18
+ elif system == "Darwin":
19
+ name = "libflowex.dylib"
20
+ elif system == "Windows":
21
+ name = "libflowex.dll"
22
+ else:
23
+ raise OSError(f"Unsupported platform: {system}")
24
+
25
+ path = os.path.join(lib_dir, name)
26
+ lib = ctypes.CDLL(path)
27
+
28
+ # FlowexInit(exchange *char) -> int
29
+ lib.FlowexInit.argtypes = [ctypes.c_char_p]
30
+ lib.FlowexInit.restype = ctypes.c_int
31
+
32
+ # FlowexSubscribe(exchange *char, symbol *char) -> int
33
+ lib.FlowexSubscribe.argtypes = [ctypes.c_char_p, ctypes.c_char_p]
34
+ lib.FlowexSubscribe.restype = ctypes.c_int
35
+
36
+ # FlowexSubscribeBatch(exchange *char, symbols **char, count int) -> int
37
+ lib.FlowexSubscribeBatch.argtypes = [
38
+ ctypes.c_char_p,
39
+ ctypes.POINTER(ctypes.c_char_p),
40
+ ctypes.c_int,
41
+ ]
42
+ lib.FlowexSubscribeBatch.restype = ctypes.c_int
43
+
44
+ # FlowexGetSnapshot(exchange *char, symbol *char) -> *char (caller must free)
45
+ lib.FlowexGetSnapshot.argtypes = [ctypes.c_char_p, ctypes.c_char_p]
46
+ lib.FlowexGetSnapshot.restype = ctypes.c_void_p
47
+
48
+ # FlowexGetSnapshots(exchange *char) -> *char (caller must free)
49
+ lib.FlowexGetSnapshots.argtypes = [ctypes.c_char_p]
50
+ lib.FlowexGetSnapshots.restype = ctypes.c_void_p
51
+
52
+ # FlowexUnsubscribe(exchange *char, symbol *char) -> int
53
+ lib.FlowexUnsubscribe.argtypes = [ctypes.c_char_p, ctypes.c_char_p]
54
+ lib.FlowexUnsubscribe.restype = ctypes.c_int
55
+
56
+ # FlowexShutdown() -> void
57
+ lib.FlowexShutdown.argtypes = []
58
+ lib.FlowexShutdown.restype = None
59
+
60
+ # FlowexFree(ptr *char) -> void
61
+ lib.FlowexFree.argtypes = [ctypes.c_void_p]
62
+ lib.FlowexFree.restype = None
63
+
64
+ return lib
65
+
66
+
67
+ lib = _load()
@@ -0,0 +1,148 @@
1
+ from __future__ import annotations
2
+
3
+ import dataclasses
4
+ from dataclasses import dataclass, field
5
+
6
+
7
+ @dataclass
8
+ class CandleHLCV:
9
+ ts: int = 0
10
+ open: float = 0.0
11
+ high: float = 0.0
12
+ low: float = 0.0
13
+ close: float = 0.0
14
+ volume: float = 0.0
15
+
16
+
17
+ @dataclass
18
+ class NormalizedTrade:
19
+ timestamp: int = 0
20
+ price: float = 0.0
21
+ size: float = 0.0
22
+ size_usd: float = 0.0
23
+ side: str = ""
24
+ trade_id: str = ""
25
+ symbol: str = ""
26
+ exchange: str = ""
27
+
28
+
29
+ @dataclass
30
+ class DepthMetrics:
31
+ # Basic
32
+ timestamp: int = 0
33
+ symbol: str = ""
34
+ best_bid: float = 0.0
35
+ best_ask: float = 0.0
36
+ spread: float = 0.0
37
+ spread_bps: float = 0.0
38
+ mid_price: float = 0.0
39
+
40
+ # Liquidity (USD) at different depths
41
+ bid_liquidity_5: float = 0.0
42
+ ask_liquidity_5: float = 0.0
43
+ bid_liquidity_10: float = 0.0
44
+ ask_liquidity_10: float = 0.0
45
+ bid_liquidity_20: float = 0.0
46
+ ask_liquidity_20: float = 0.0
47
+ bid_liquidity_50: float = 0.0
48
+ ask_liquidity_50: float = 0.0
49
+
50
+ # Volumes (coin size) at different depths
51
+ bid_volume_5: float = 0.0
52
+ ask_volume_5: float = 0.0
53
+ bid_volume_10: float = 0.0
54
+ ask_volume_10: float = 0.0
55
+ bid_volume_20: float = 0.0
56
+ ask_volume_20: float = 0.0
57
+ bid_volume_50: float = 0.0
58
+ ask_volume_50: float = 0.0
59
+
60
+ # Imbalance ratios
61
+ imbalance_ratio_5: float = 0.0
62
+ imbalance_ratio_10: float = 0.0
63
+ imbalance_ratio_20: float = 0.0
64
+ imbalance_ratio_50: float = 0.0
65
+
66
+ # Imbalance deltas
67
+ imbalance_delta_10: float = 0.0
68
+ imbalance_delta_20: float = 0.0
69
+
70
+ # Largest single orders (walls)
71
+ largest_bid_size: float = 0.0
72
+ largest_bid_price: float = 0.0
73
+ largest_bid_value: float = 0.0
74
+ largest_ask_size: float = 0.0
75
+ largest_ask_price: float = 0.0
76
+ largest_ask_value: float = 0.0
77
+
78
+ # Slippage estimation (%)
79
+ slippage_buy_100: float = 0.0
80
+ slippage_sell_100: float = 0.0
81
+ slippage_buy_1k: float = 0.0
82
+ slippage_sell_1k: float = 0.0
83
+ slippage_buy_5k: float = 0.0
84
+ slippage_sell_5k: float = 0.0
85
+ slippage_buy_10k: float = 0.0
86
+ slippage_sell_10k: float = 0.0
87
+ slippage_buy_50k: float = 0.0
88
+ slippage_sell_50k: float = 0.0
89
+ slippage_buy_100k: float = 0.0
90
+ slippage_sell_100k: float = 0.0
91
+ slippage_buy_500k: float = 0.0
92
+ slippage_sell_500k: float = 0.0
93
+ slippage_buy_1m: float = 0.0
94
+ slippage_sell_1m: float = 0.0
95
+
96
+ # Velocity metrics
97
+ liquidity_velocity_10: float = 0.0
98
+ liquidity_velocity_50: float = 0.0
99
+ imbalance_velocity: float = 0.0
100
+ spread_velocity: float = 0.0
101
+ wall_velocity: float = 0.0
102
+
103
+ # Momentum
104
+ buy_pressure_momentum: float = 0.0
105
+ sell_pressure_momentum: float = 0.0
106
+ wall_building_bid: bool = False
107
+ wall_building_ask: bool = False
108
+
109
+ # Z-scores
110
+ liquidity_zscore_10: float = 0.0
111
+ imbalance_zscore: float = 0.0
112
+ spread_zscore: float = 0.0
113
+
114
+ # Depth quality
115
+ bid_levels_count: int = 0
116
+ ask_levels_count: int = 0
117
+ avg_bid_size_10: float = 0.0
118
+ avg_ask_size_10: float = 0.0
119
+ top_bid_concentration_5: float = 0.0
120
+ top_ask_concentration_5: float = 0.0
121
+ spread_norm_imbalance_delta_10: float = 0.0
122
+ spread_norm_imbalance_delta_20: float = 0.0
123
+ slippage_gradient_buy: float = 0.0
124
+ slippage_gradient_sell: float = 0.0
125
+ slippage_skew_1k: float = 0.0
126
+ slippage_skew_10k: float = 0.0
127
+
128
+ @classmethod
129
+ def from_dict(cls, d: dict) -> DepthMetrics:
130
+ known = {f.name for f in dataclasses.fields(cls)}
131
+ return cls(**{k: v for k, v in d.items() if k in known})
132
+
133
+
134
+ @dataclass
135
+ class Snapshot:
136
+ timestamp: int = 0
137
+ candles: list[CandleHLCV] = field(default_factory=list)
138
+ depth: DepthMetrics | None = None
139
+ trades: list[NormalizedTrade] = field(default_factory=list)
140
+
141
+ @classmethod
142
+ def from_dict(cls, d: dict) -> Snapshot:
143
+ return cls(
144
+ timestamp=d.get("timestamp", 0),
145
+ candles=[CandleHLCV(**c) for c in d.get("candles") or []],
146
+ depth=DepthMetrics.from_dict(d["depth"]) if d.get("depth") else None,
147
+ trades=[NormalizedTrade(**t) for t in d.get("trades") or []],
148
+ )
Binary file
Binary file
Binary file
@@ -0,0 +1,199 @@
1
+ Metadata-Version: 2.4
2
+ Name: flowex
3
+ Version: 0.1.0
4
+ Summary: Real-time multi-exchange crypto market data in Python — WebSocket streaming, order book metrics, and per-symbol actor workers for Binance, Bybit, and Bitget.
5
+ Author: KhavrTrading
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/KhavrTrading/flowex-py
8
+ Project-URL: Repository, https://github.com/KhavrTrading/flowex-py
9
+ Project-URL: Issues, https://github.com/KhavrTrading/flowex-py/issues
10
+ Keywords: crypto,trading,market-data,websocket,binance,bybit,bitget,order-book,depth,real-time,go,cgo
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Intended Audience :: Financial and Insurance Industry
14
+ Classifier: Operating System :: POSIX :: Linux
15
+ Classifier: Operating System :: MacOS
16
+ Classifier: Operating System :: Microsoft :: Windows
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Topic :: Office/Business :: Financial
23
+ Classifier: Topic :: Office/Business :: Financial :: Investment
24
+ Classifier: Topic :: Software Development :: Libraries
25
+ Classifier: Typing :: Typed
26
+ Requires-Python: >=3.10
27
+ Description-Content-Type: text/markdown
28
+ License-File: LICENSE
29
+ Dynamic: license-file
30
+
31
+ # flowex
32
+
33
+ [![CI](https://github.com/KhavrTrading/flowex-py/actions/workflows/build.yml/badge.svg)](https://github.com/KhavrTrading/flowex-py/actions/workflows/build.yml)
34
+ [![PyPI](https://img.shields.io/pypi/v/flowex)](https://pypi.org/project/flowex/)
35
+ [![Python](https://img.shields.io/pypi/pyversions/flowex)](https://pypi.org/project/flowex/)
36
+ [![License](https://img.shields.io/github/license/KhavrTrading/flowex-py)](LICENSE)
37
+
38
+ Real-time multi-exchange crypto market data for Python — powered by Go via cgo shared library. WebSocket streaming, order book metrics, and per-symbol actor workers for Binance, Bybit, and Bitget.
39
+
40
+ No subprocess, no gRPC, no serialization overhead on the hot path. The Go runtime lives inside the Python process. Every symbol gets its own goroutine. `get_snapshot()` hits the atomic store directly.
41
+
42
+ ## Install
43
+
44
+ ```bash
45
+ pip install flowex
46
+ ```
47
+
48
+ ## Quick start
49
+
50
+ ```python
51
+ import time
52
+ from flowex import Manager
53
+
54
+ mgr = Manager("binance")
55
+ mgr.subscribe(["BTCUSDT", "ETHUSDT", "SOLUSDT"])
56
+ time.sleep(2)
57
+
58
+ snap = mgr.get_snapshot("BTCUSDT")
59
+ print(snap.depth.spread_bps)
60
+ print(snap.depth.mid_price)
61
+ print(snap.candles[-1].close)
62
+
63
+ mgr.close()
64
+ ```
65
+
66
+ Or use as a context manager:
67
+
68
+ ```python
69
+ with Manager("binance") as mgr:
70
+ mgr.subscribe(["BTCUSDT"])
71
+ time.sleep(2)
72
+ snap = mgr.get_snapshot("BTCUSDT")
73
+ ```
74
+
75
+ ## Supported exchanges
76
+
77
+ - **Binance** — futures WebSocket (candles, depth, aggTrade)
78
+ - **Bybit** — linear futures WebSocket
79
+ - **Bitget** — USDT futures WebSocket
80
+
81
+ ## API
82
+
83
+ ### `Manager(exchange)`
84
+
85
+ Create a manager for an exchange. Initializes the Go runtime and WebSocket connections.
86
+
87
+ ```python
88
+ mgr = Manager("binance") # or "bybit", "bitget"
89
+ ```
90
+
91
+ ### `mgr.subscribe(symbols)`
92
+
93
+ Subscribe to one or more symbols. Starts candle, depth, and trade streams for each.
94
+
95
+ ```python
96
+ mgr.subscribe("BTCUSDT")
97
+ mgr.subscribe(["BTCUSDT", "ETHUSDT", "SOLUSDT"])
98
+ ```
99
+
100
+ ### `mgr.get_snapshot(symbol) -> Snapshot | None`
101
+
102
+ Get the latest point-in-time snapshot for a symbol.
103
+
104
+ ```python
105
+ snap = mgr.get_snapshot("BTCUSDT")
106
+ snap.timestamp # Unix ms
107
+ snap.depth # DepthMetrics
108
+ snap.candles # list[CandleHLCV]
109
+ snap.trades # list[NormalizedTrade]
110
+ ```
111
+
112
+ ### `mgr.get_all_snapshots() -> dict[str, Snapshot]`
113
+
114
+ Get snapshots for all subscribed symbols in one call.
115
+
116
+ ### `mgr.unsubscribe(symbol)`
117
+
118
+ Remove all streams for a symbol.
119
+
120
+ ### `mgr.close()`
121
+
122
+ Shutdown all managers and WebSocket connections.
123
+
124
+ ## Data models
125
+
126
+ ### `DepthMetrics`
127
+
128
+ Order book metrics computed from raw depth data:
129
+
130
+ | Field | Description |
131
+ |-------|-------------|
132
+ | `mid_price` | (best_bid + best_ask) / 2 |
133
+ | `spread_bps` | Spread in basis points |
134
+ | `bid_liquidity_10` | USD liquidity, top 10 bid levels |
135
+ | `ask_liquidity_10` | USD liquidity, top 10 ask levels |
136
+ | `imbalance_ratio_10` | bid_liq / ask_liq (>1 = bullish) |
137
+ | `slippage_buy_10k` | Estimated slippage % for $10k buy |
138
+
139
+ Plus 70+ more fields: liquidity at 5/10/20/50 levels, volumes, imbalance deltas, largest walls, slippage at 8 USD sizes, velocity, momentum, z-scores, and depth quality metrics.
140
+
141
+ ### `CandleHLCV`
142
+
143
+ ```python
144
+ candle.ts # Unix ms
145
+ candle.open
146
+ candle.high
147
+ candle.low
148
+ candle.close
149
+ candle.volume
150
+ ```
151
+
152
+ ### `NormalizedTrade`
153
+
154
+ ```python
155
+ trade.timestamp # Unix ms
156
+ trade.price
157
+ trade.size
158
+ trade.side # "buy" or "sell"
159
+ trade.symbol
160
+ ```
161
+
162
+ ## Architecture
163
+
164
+ ```
165
+ Python process
166
+ |
167
+ +-- ctypes loads libflowex.so <-- Go runtime starts inside Python
168
+ | |
169
+ | +-- Manager (binance)
170
+ | | +-- Worker: BTCUSDT -> atomic snapshot
171
+ | | +-- Worker: ETHUSDT -> atomic snapshot
172
+ | | +-- Worker: SOLUSDT -> atomic snapshot
173
+ | |
174
+ | +-- Manager (bybit)
175
+ | +-- Worker: BTCUSDT -> atomic snapshot
176
+ |
177
+ +-- mgr.subscribe(["BTCUSDT"]) -> FlowexSubscribeBatch()
178
+ +-- mgr.get_snapshot("BTCUSDT") -> FlowexGetSnapshot() -> atomic.Load -> JSON -> Python
179
+ +-- mgr.get_all_snapshots() -> FlowexGetSnapshots() -> one call, all symbols
180
+ ```
181
+
182
+ ## Build from source
183
+
184
+ Requires Go 1.22+ and Python 3.10+.
185
+
186
+ ```bash
187
+ # macOS (Apple Silicon)
188
+ make build-mac
189
+
190
+ # Linux (amd64)
191
+ make build-linux
192
+
193
+ # All platforms (requires cross-compilers)
194
+ make build-all
195
+ ```
196
+
197
+ ## License
198
+
199
+ MIT
@@ -0,0 +1,14 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ flowex/__init__.py
5
+ flowex/_lib.py
6
+ flowex/_models.py
7
+ flowex.egg-info/PKG-INFO
8
+ flowex.egg-info/SOURCES.txt
9
+ flowex.egg-info/dependency_links.txt
10
+ flowex.egg-info/top_level.txt
11
+ flowex/lib/libflowex-arm64.so
12
+ flowex/lib/libflowex.dll
13
+ flowex/lib/libflowex.dylib
14
+ flowex/lib/libflowex.so
@@ -0,0 +1 @@
1
+ flowex
@@ -0,0 +1,56 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "flowex"
7
+ version = "0.1.0"
8
+ description = "Real-time multi-exchange crypto market data in Python — WebSocket streaming, order book metrics, and per-symbol actor workers for Binance, Bybit, and Bitget."
9
+ requires-python = ">=3.10"
10
+ license = "MIT"
11
+ readme = "README.md"
12
+ authors = [
13
+ { name = "KhavrTrading" },
14
+ ]
15
+ keywords = [
16
+ "crypto",
17
+ "trading",
18
+ "market-data",
19
+ "websocket",
20
+ "binance",
21
+ "bybit",
22
+ "bitget",
23
+ "order-book",
24
+ "depth",
25
+ "real-time",
26
+ "go",
27
+ "cgo",
28
+ ]
29
+ classifiers = [
30
+ "Development Status :: 4 - Beta",
31
+ "Intended Audience :: Developers",
32
+ "Intended Audience :: Financial and Insurance Industry",
33
+ "Operating System :: POSIX :: Linux",
34
+ "Operating System :: MacOS",
35
+ "Operating System :: Microsoft :: Windows",
36
+ "Programming Language :: Python :: 3",
37
+ "Programming Language :: Python :: 3.10",
38
+ "Programming Language :: Python :: 3.11",
39
+ "Programming Language :: Python :: 3.12",
40
+ "Programming Language :: Python :: 3.13",
41
+ "Topic :: Office/Business :: Financial",
42
+ "Topic :: Office/Business :: Financial :: Investment",
43
+ "Topic :: Software Development :: Libraries",
44
+ "Typing :: Typed",
45
+ ]
46
+
47
+ [project.urls]
48
+ Homepage = "https://github.com/KhavrTrading/flowex-py"
49
+ Repository = "https://github.com/KhavrTrading/flowex-py"
50
+ Issues = "https://github.com/KhavrTrading/flowex-py/issues"
51
+
52
+ [tool.setuptools.packages.find]
53
+ include = ["flowex*"]
54
+
55
+ [tool.setuptools.package-data]
56
+ flowex = ["lib/*"]
flowex-0.1.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+