liquidator-indicator 0.0.4__tar.gz → 0.0.6__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.
Files changed (23) hide show
  1. {liquidator_indicator-0.0.4 → liquidator_indicator-0.0.6}/PKG-INFO +4 -3
  2. {liquidator_indicator-0.0.4 → liquidator_indicator-0.0.6}/pyproject.toml +7 -3
  3. {liquidator_indicator-0.0.4 → liquidator_indicator-0.0.6}/setup.cfg +4 -3
  4. liquidator_indicator-0.0.6/src/liquidator_indicator/__init__.py +6 -0
  5. liquidator_indicator-0.0.6/src/liquidator_indicator/collectors/__init__.py +11 -0
  6. liquidator_indicator-0.0.6/src/liquidator_indicator/collectors/funding.py +202 -0
  7. liquidator_indicator-0.0.6/src/liquidator_indicator/core.py +447 -0
  8. liquidator_indicator-0.0.6/src/liquidator_indicator/indicators.py +52 -0
  9. liquidator_indicator-0.0.6/src/liquidator_indicator/numba_optimized.py +351 -0
  10. liquidator_indicator-0.0.6/src/liquidator_indicator/parsers.py +119 -0
  11. {liquidator_indicator-0.0.4 → liquidator_indicator-0.0.6/src}/liquidator_indicator.egg-info/PKG-INFO +4 -3
  12. liquidator_indicator-0.0.6/src/liquidator_indicator.egg-info/SOURCES.txt +19 -0
  13. liquidator_indicator-0.0.6/src/liquidator_indicator.egg-info/requires.txt +5 -0
  14. liquidator_indicator-0.0.6/src/liquidator_indicator.egg-info/top_level.txt +1 -0
  15. liquidator_indicator-0.0.4/liquidator_indicator.egg-info/SOURCES.txt +0 -12
  16. liquidator_indicator-0.0.4/liquidator_indicator.egg-info/requires.txt +0 -2
  17. liquidator_indicator-0.0.4/liquidator_indicator.egg-info/top_level.txt +0 -1
  18. {liquidator_indicator-0.0.4 → liquidator_indicator-0.0.6}/LICENSE +0 -0
  19. {liquidator_indicator-0.0.4 → liquidator_indicator-0.0.6}/README.md +0 -0
  20. {liquidator_indicator-0.0.4 → liquidator_indicator-0.0.6/src}/liquidator_indicator.egg-info/dependency_links.txt +0 -0
  21. {liquidator_indicator-0.0.4 → liquidator_indicator-0.0.6}/tests/test_core.py +0 -0
  22. {liquidator_indicator-0.0.4 → liquidator_indicator-0.0.6}/tests/test_indicators_parsers.py +0 -0
  23. {liquidator_indicator-0.0.4 → liquidator_indicator-0.0.6}/tests/test_zones_integration.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: liquidator_indicator
3
- Version: 0.0.4
3
+ Version: 0.0.6
4
4
  Summary: Lightweight liquidation zone indicator with multi-signal detection and visual chart integration
5
5
  Home-page: https://github.com/ViWarshawski/liquidator_indicator
6
6
  Author: ViWarshawski
@@ -18,8 +18,9 @@ Classifier: Topic :: Office/Business :: Financial :: Investment
18
18
  Requires-Python: >=3.9
19
19
  Description-Content-Type: text/markdown
20
20
  License-File: LICENSE
21
- Requires-Dist: pandas==2.3.3
22
- Requires-Dist: numpy==1.26.4
21
+ Requires-Dist: pandas>=1.3.0
22
+ Requires-Dist: numpy>=1.20.0
23
+ Requires-Dist: numba>=0.56.0; python_version >= "3.9"
23
24
  Dynamic: license-file
24
25
 
25
26
  # liquidator_indicator
@@ -1,12 +1,13 @@
1
1
  [project]
2
2
  name = "liquidator_indicator"
3
- version = "0.0.4"
3
+ version = "0.0.6"
4
4
  description = "Lightweight liquidation zone indicator with multi-signal detection and visual chart integration"
5
5
  license = {text = "MIT"}
6
6
  requires-python = ">=3.9"
7
7
  dependencies = [
8
- "pandas==2.3.3",
9
- "numpy==1.26.4"
8
+ "pandas>=1.3.0",
9
+ "numpy>=1.20.0",
10
+ "numba>=0.56.0; python_version>='3.9'"
10
11
  ]
11
12
  readme = "README.md"
12
13
  keywords = ["trading", "liquidation", "zones", "cryptocurrency", "technical-analysis"]
@@ -21,6 +22,9 @@ classifiers = [
21
22
  "Topic :: Office/Business :: Financial :: Investment",
22
23
  ]
23
24
 
25
+ [tool.setuptools.packages.find]
26
+ where = ["src"]
27
+
24
28
  [build-system]
25
29
  requires = ["setuptools>=61.0","wheel"]
26
30
  build-backend = "setuptools.build_meta"
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = liquidator_indicator
3
- version = 0.0.4
3
+ version = 0.0.6
4
4
  author = ViWarshawski
5
5
  author_email = nexus2.0.2026@gmail.com
6
6
  description = Lightweight liquidation zone indicator with multi-signal detection and visual chart integration
@@ -23,8 +23,9 @@ classifiers =
23
23
  packages = find:
24
24
  python_requires = >=3.9
25
25
  install_requires =
26
- pandas==2.3.3
27
- numpy==1.26.4
26
+ pandas>=1.3.0
27
+ numpy>=1.20.0
28
+ numba>=0.56.0; python_version>='3.9'
28
29
 
29
30
  [egg_info]
30
31
  tag_build =
@@ -0,0 +1,6 @@
1
+ """Liquidator indicator package - lightweight core API."""
2
+ from .core import Liquidator
3
+ from .indicators import compute_vwap, compute_atr
4
+
5
+ __all__ = ["Liquidator", "compute_vwap", "compute_atr"]
6
+ __version__ = "0.0.2"
@@ -0,0 +1,11 @@
1
+ """
2
+ Data stream collectors for liquidator_indicator package.
3
+
4
+ These are OPTIONAL utilities that help users collect public data feeds.
5
+ Users can either:
6
+ 1. Use these collectors to automate data gathering
7
+ 2. Implement their own collectors
8
+ 3. Feed data from existing sources (files, APIs, etc.)
9
+
10
+ The indicator package itself is data-source agnostic.
11
+ """
@@ -0,0 +1,202 @@
1
+ """
2
+ FundingRateCollector - Collect live funding rates and open interest from Hyperliquid WebSocket.
3
+
4
+ Based on src/data/funding_ws_connection.py pattern but simplified for package distribution.
5
+
6
+ Usage:
7
+ from liquidator_indicator.collectors.funding import FundingRateCollector
8
+
9
+ collector = FundingRateCollector(symbols=['BTC', 'ETH'])
10
+ collector.start()
11
+
12
+ # Get latest data
13
+ data = collector.get_latest()
14
+ print(data)
15
+ # {'BTC': {'funding_rate': 0.0001, 'open_interest': 12345.67, 'timestamp': '2026-02-02T...'}}
16
+
17
+ # Feed to indicator
18
+ liq.ingest_funding_rates(data)
19
+
20
+ collector.stop()
21
+ """
22
+ import json
23
+ import time
24
+ import threading
25
+ from datetime import datetime, timezone
26
+ from typing import List, Dict, Optional, Callable
27
+ import logging
28
+
29
+ try:
30
+ import websocket
31
+ except ImportError:
32
+ raise ImportError("websocket-client required: pip install websocket-client")
33
+
34
+ logger = logging.getLogger("liquidator_indicator.funding_collector")
35
+
36
+
37
+ class FundingRateCollector:
38
+ """Collect live funding rates and open interest from Hyperliquid WebSocket."""
39
+
40
+ def __init__(
41
+ self,
42
+ symbols: List[str],
43
+ ws_url: str = "wss://api.hyperliquid.xyz/ws",
44
+ callback: Optional[Callable] = None
45
+ ):
46
+ """
47
+ Args:
48
+ symbols: List of coin symbols to track (e.g. ['BTC', 'ETH'])
49
+ ws_url: WebSocket endpoint URL
50
+ callback: Optional function called on each update: callback(symbol, data)
51
+ """
52
+ self.symbols = [s.upper() for s in symbols]
53
+ self.ws_url = ws_url
54
+ self.callback = callback
55
+
56
+ self._data = {} # {symbol: {funding_rate, open_interest, timestamp}}
57
+ self._ws = None
58
+ self._thread = None
59
+ self._running = False
60
+ self._lock = threading.Lock()
61
+
62
+ def start(self):
63
+ """Start WebSocket connection in background thread."""
64
+ if self._running:
65
+ logger.warning("Collector already running")
66
+ return
67
+
68
+ self._running = True
69
+ self._thread = threading.Thread(target=self._run_ws, daemon=True)
70
+ self._thread.start()
71
+ logger.info(f"FundingRateCollector started for {self.symbols}")
72
+
73
+ def stop(self):
74
+ """Stop WebSocket connection."""
75
+ self._running = False
76
+ if self._ws:
77
+ try:
78
+ self._ws.close()
79
+ except Exception:
80
+ pass
81
+ if self._thread:
82
+ self._thread.join(timeout=2)
83
+ logger.info("FundingRateCollector stopped")
84
+
85
+ def get_latest(self) -> Dict[str, Dict]:
86
+ """Get latest funding data for all symbols.
87
+
88
+ Returns:
89
+ {symbol: {funding_rate, open_interest, timestamp}}
90
+ """
91
+ with self._lock:
92
+ return self._data.copy()
93
+
94
+ def get_symbol(self, symbol: str) -> Optional[Dict]:
95
+ """Get latest data for specific symbol."""
96
+ with self._lock:
97
+ return self._data.get(symbol.upper())
98
+
99
+ def _run_ws(self):
100
+ """WebSocket main loop (runs in background thread)."""
101
+ while self._running:
102
+ try:
103
+ self._ws = websocket.WebSocketApp(
104
+ self.ws_url,
105
+ on_message=self._on_message,
106
+ on_error=self._on_error,
107
+ on_close=self._on_close,
108
+ on_open=self._on_open
109
+ )
110
+ self._ws.run_forever()
111
+ except Exception as e:
112
+ logger.error(f"WebSocket error: {e}")
113
+
114
+ if self._running:
115
+ logger.info("Reconnecting in 5s...")
116
+ time.sleep(5)
117
+
118
+ def _on_open(self, ws):
119
+ """Subscribe to activeAssetCtx channel for funding rates."""
120
+ logger.info("WebSocket connected")
121
+ for symbol in self.symbols:
122
+ sub_msg = json.dumps({
123
+ "method": "subscribe",
124
+ "subscription": {
125
+ "type": "activeAssetCtx",
126
+ "coin": symbol
127
+ }
128
+ })
129
+ ws.send(sub_msg)
130
+ logger.info(f"Subscribed to {symbol} funding/OI")
131
+
132
+ def _on_message(self, ws, message):
133
+ """Process funding rate updates."""
134
+ try:
135
+ if message == '{"channel":"pong"}':
136
+ return
137
+
138
+ data = json.loads(message)
139
+ channel = data.get('channel', '')
140
+
141
+ if channel == 'activeAssetCtx':
142
+ asset_data = data.get('data', {})
143
+ coin = asset_data.get('coin', '')
144
+ ctx = asset_data.get('ctx', {})
145
+
146
+ if coin and ctx and coin in self.symbols:
147
+ funding_rate = float(ctx.get('funding', 0))
148
+ open_interest = float(ctx.get('openInterest', 0))
149
+ timestamp = datetime.now(timezone.utc).isoformat()
150
+
151
+ update = {
152
+ 'funding_rate': funding_rate,
153
+ 'open_interest': open_interest,
154
+ 'timestamp': timestamp
155
+ }
156
+
157
+ with self._lock:
158
+ self._data[coin] = update
159
+
160
+ logger.debug(f"{coin}: funding={funding_rate:.6f}, oi={open_interest:.2f}")
161
+
162
+ # Call user callback if provided
163
+ if self.callback:
164
+ try:
165
+ self.callback(coin, update)
166
+ except Exception as e:
167
+ logger.error(f"Callback error: {e}")
168
+
169
+ except Exception as e:
170
+ logger.error(f"Message parse error: {e}")
171
+
172
+ def _on_error(self, ws, error):
173
+ logger.error(f"WebSocket error: {error}")
174
+
175
+ def _on_close(self, ws, close_status_code, close_msg):
176
+ logger.info(f"WebSocket closed: {close_status_code} {close_msg}")
177
+
178
+
179
+ # Example usage
180
+ if __name__ == '__main__':
181
+ logging.basicConfig(level=logging.INFO)
182
+
183
+ def on_update(symbol, data):
184
+ print(f"UPDATE: {symbol} @ {data['timestamp']}")
185
+ print(f" Funding: {data['funding_rate']:.6f}")
186
+ print(f" OI: {data['open_interest']:.2f}")
187
+
188
+ collector = FundingRateCollector(
189
+ symbols=['BTC', 'ETH', 'SOL'],
190
+ callback=on_update
191
+ )
192
+
193
+ collector.start()
194
+
195
+ try:
196
+ while True:
197
+ time.sleep(10)
198
+ latest = collector.get_latest()
199
+ print(f"\nLatest data: {len(latest)} symbols")
200
+ except KeyboardInterrupt:
201
+ print("\nStopping...")
202
+ collector.stop()