kuhl-haus-mdp 0.1.9__py3-none-any.whl → 0.1.10__py3-none-any.whl
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.
- kuhl_haus/mdp/analyzers/massive_data_analyzer.py +8 -8
- kuhl_haus/mdp/analyzers/top_stocks.py +13 -15
- kuhl_haus/mdp/components/market_data_cache.py +5 -3
- kuhl_haus/mdp/models/constants.py +24 -0
- kuhl_haus/mdp/models/market_data_cache_ttl.py +25 -15
- {kuhl_haus_mdp-0.1.9.dist-info → kuhl_haus_mdp-0.1.10.dist-info}/METADATA +1 -1
- {kuhl_haus_mdp-0.1.9.dist-info → kuhl_haus_mdp-0.1.10.dist-info}/RECORD +10 -9
- {kuhl_haus_mdp-0.1.9.dist-info → kuhl_haus_mdp-0.1.10.dist-info}/WHEEL +0 -0
- {kuhl_haus_mdp-0.1.9.dist-info → kuhl_haus_mdp-0.1.10.dist-info}/entry_points.txt +0 -0
- {kuhl_haus_mdp-0.1.9.dist-info → kuhl_haus_mdp-0.1.10.dist-info}/licenses/LICENSE.txt +0 -0
|
@@ -50,7 +50,7 @@ class MassiveDataAnalyzer:
|
|
|
50
50
|
return [MarketDataAnalyzerResult(
|
|
51
51
|
data=data,
|
|
52
52
|
cache_key=f"{MarketDataCacheKeys.HALTS.value}:{symbol}",
|
|
53
|
-
cache_ttl=MarketDataCacheTTL.
|
|
53
|
+
cache_ttl=MarketDataCacheTTL.HALTS.value,
|
|
54
54
|
publish_key=f"{MarketDataCacheKeys.HALTS.value}:{symbol}",
|
|
55
55
|
)]
|
|
56
56
|
|
|
@@ -58,8 +58,8 @@ class MassiveDataAnalyzer:
|
|
|
58
58
|
def handle_equity_agg_event(data: dict, symbol: str) -> Optional[List[MarketDataAnalyzerResult]]:
|
|
59
59
|
return [MarketDataAnalyzerResult(
|
|
60
60
|
data=data,
|
|
61
|
-
cache_key=f"{MarketDataCacheKeys.AGGREGATE.value}:{symbol}",
|
|
62
|
-
cache_ttl=MarketDataCacheTTL.
|
|
61
|
+
# cache_key=f"{MarketDataCacheKeys.AGGREGATE.value}:{symbol}",
|
|
62
|
+
# cache_ttl=MarketDataCacheTTL.AGGREGATE.value,
|
|
63
63
|
publish_key=f"{MarketDataCacheKeys.AGGREGATE.value}:{symbol}",
|
|
64
64
|
)]
|
|
65
65
|
|
|
@@ -67,8 +67,8 @@ class MassiveDataAnalyzer:
|
|
|
67
67
|
def handle_equity_trade_event(data: dict, symbol: str) -> Optional[List[MarketDataAnalyzerResult]]:
|
|
68
68
|
return [MarketDataAnalyzerResult(
|
|
69
69
|
data=data,
|
|
70
|
-
cache_key=f"{MarketDataCacheKeys.TRADES.value}:{symbol}",
|
|
71
|
-
cache_ttl=MarketDataCacheTTL.
|
|
70
|
+
# cache_key=f"{MarketDataCacheKeys.TRADES.value}:{symbol}",
|
|
71
|
+
# cache_ttl=MarketDataCacheTTL.TRADES.value,
|
|
72
72
|
publish_key=f"{MarketDataCacheKeys.TRADES.value}:{symbol}",
|
|
73
73
|
)]
|
|
74
74
|
|
|
@@ -76,8 +76,8 @@ class MassiveDataAnalyzer:
|
|
|
76
76
|
def handle_equity_quote_event(data: dict, symbol: str) -> Optional[List[MarketDataAnalyzerResult]]:
|
|
77
77
|
return [MarketDataAnalyzerResult(
|
|
78
78
|
data=data,
|
|
79
|
-
cache_key=f"{MarketDataCacheKeys.QUOTES.value}:{symbol}",
|
|
80
|
-
cache_ttl=MarketDataCacheTTL.
|
|
79
|
+
# cache_key=f"{MarketDataCacheKeys.QUOTES.value}:{symbol}",
|
|
80
|
+
# cache_ttl=MarketDataCacheTTL.QUOTES.value,
|
|
81
81
|
publish_key=f"{MarketDataCacheKeys.QUOTES.value}:{symbol}",
|
|
82
82
|
)]
|
|
83
83
|
|
|
@@ -88,6 +88,6 @@ class MassiveDataAnalyzer:
|
|
|
88
88
|
return [MarketDataAnalyzerResult(
|
|
89
89
|
data=data,
|
|
90
90
|
cache_key=cache_key,
|
|
91
|
-
cache_ttl=MarketDataCacheTTL.
|
|
91
|
+
cache_ttl=MarketDataCacheTTL.UNKNOWN.value,
|
|
92
92
|
publish_key=f"{MarketDataCacheKeys.UNKNOWN.value}",
|
|
93
93
|
)]
|
|
@@ -1,15 +1,9 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import time
|
|
3
|
-
from datetime import datetime, timezone
|
|
4
|
-
from typing import Optional, List
|
|
3
|
+
from datetime import datetime, timezone
|
|
4
|
+
from typing import Optional, List
|
|
5
5
|
from zoneinfo import ZoneInfo
|
|
6
6
|
|
|
7
|
-
from massive.exceptions import BadResponse
|
|
8
|
-
from massive.rest import RESTClient
|
|
9
|
-
from massive.rest.models import (
|
|
10
|
-
TickerSnapshot,
|
|
11
|
-
Agg,
|
|
12
|
-
)
|
|
13
7
|
from massive.websocket.models import (
|
|
14
8
|
EquityAgg,
|
|
15
9
|
EventType
|
|
@@ -19,6 +13,7 @@ from kuhl_haus.mdp.analyzers.analyzer import Analyzer
|
|
|
19
13
|
from kuhl_haus.mdp.components.market_data_cache import MarketDataCache
|
|
20
14
|
from kuhl_haus.mdp.models.market_data_analyzer_result import MarketDataAnalyzerResult
|
|
21
15
|
from kuhl_haus.mdp.models.market_data_cache_keys import MarketDataCacheKeys
|
|
16
|
+
from kuhl_haus.mdp.models.market_data_cache_ttl import MarketDataCacheTTL
|
|
22
17
|
from kuhl_haus.mdp.models.market_data_pubsub_keys import MarketDataPubSubKeys
|
|
23
18
|
from kuhl_haus.mdp.models.top_stocks_cache_item import TopStocksCacheItem
|
|
24
19
|
|
|
@@ -94,24 +89,24 @@ class TopStocksAnalyzer(Analyzer):
|
|
|
94
89
|
MarketDataAnalyzerResult(
|
|
95
90
|
data=self.cache_item.to_dict(),
|
|
96
91
|
cache_key=self.cache_key,
|
|
97
|
-
cache_ttl=
|
|
92
|
+
cache_ttl=MarketDataCacheTTL.TOP_STOCKS_SCANNER.value,
|
|
98
93
|
),
|
|
99
94
|
MarketDataAnalyzerResult(
|
|
100
95
|
data=self.cache_item.top_volume(100),
|
|
101
96
|
cache_key=MarketDataPubSubKeys.TOP_VOLUME_SCANNER.value,
|
|
102
|
-
cache_ttl=
|
|
97
|
+
cache_ttl=MarketDataCacheTTL.TOP_VOLUME_SCANNER.value,
|
|
103
98
|
publish_key=MarketDataPubSubKeys.TOP_VOLUME_SCANNER.value,
|
|
104
99
|
),
|
|
105
100
|
MarketDataAnalyzerResult(
|
|
106
101
|
data=self.cache_item.top_gainers(500),
|
|
107
102
|
cache_key=MarketDataPubSubKeys.TOP_GAINERS_SCANNER.value,
|
|
108
|
-
cache_ttl=
|
|
103
|
+
cache_ttl=MarketDataCacheTTL.TOP_GAINERS_SCANNER.value,
|
|
109
104
|
publish_key=MarketDataPubSubKeys.TOP_GAINERS_SCANNER.value,
|
|
110
105
|
),
|
|
111
106
|
MarketDataAnalyzerResult(
|
|
112
107
|
data=self.cache_item.top_gappers(500),
|
|
113
108
|
cache_key=MarketDataPubSubKeys.TOP_GAPPERS_SCANNER.value,
|
|
114
|
-
cache_ttl=
|
|
109
|
+
cache_ttl=MarketDataCacheTTL.TOP_GAPPERS_SCANNER.value,
|
|
115
110
|
publish_key=MarketDataPubSubKeys.TOP_GAPPERS_SCANNER.value,
|
|
116
111
|
)
|
|
117
112
|
]
|
|
@@ -141,7 +136,8 @@ class TopStocksAnalyzer(Analyzer):
|
|
|
141
136
|
prev_day_volume = snapshot.prev_day.volume
|
|
142
137
|
prev_day_vwap = snapshot.prev_day.vwap
|
|
143
138
|
break
|
|
144
|
-
except Exception:
|
|
139
|
+
except Exception as e:
|
|
140
|
+
self.logger.error(f"Failed to get snapshot for {event.symbol}: {e}")
|
|
145
141
|
retry_count += 1
|
|
146
142
|
if retry_count == max_tries and prev_day_close == 0:
|
|
147
143
|
self.logger.error(f"Failed to get snapshot for {event.symbol} after {max_tries} tries.")
|
|
@@ -155,7 +151,8 @@ class TopStocksAnalyzer(Analyzer):
|
|
|
155
151
|
try:
|
|
156
152
|
avg_volume = await self.cache.get_avg_volume(event.symbol)
|
|
157
153
|
break
|
|
158
|
-
except Exception:
|
|
154
|
+
except Exception as e:
|
|
155
|
+
self.logger.error(f"Failed to get average volume for {event.symbol}: {e}")
|
|
159
156
|
retry_count += 1
|
|
160
157
|
if retry_count == max_tries and avg_volume == 0:
|
|
161
158
|
self.logger.error(f"Failed to get average volume for {event.symbol} after {max_tries} tries.")
|
|
@@ -169,7 +166,8 @@ class TopStocksAnalyzer(Analyzer):
|
|
|
169
166
|
try:
|
|
170
167
|
free_float = await self.cache.get_free_float(event.symbol)
|
|
171
168
|
break
|
|
172
|
-
except Exception:
|
|
169
|
+
except Exception as e:
|
|
170
|
+
self.logger.error(f"Failed to get free float for {event.symbol}: {e}")
|
|
173
171
|
retry_count += 1
|
|
174
172
|
if retry_count == max_tries and free_float == 0:
|
|
175
173
|
self.logger.error(f"Failed to get free float for {event.symbol} after {max_tries} tries.")
|
|
@@ -61,7 +61,7 @@ class MarketDataCache:
|
|
|
61
61
|
await self.cache_data(
|
|
62
62
|
data=data,
|
|
63
63
|
cache_key=cache_key,
|
|
64
|
-
cache_ttl=MarketDataCacheTTL.
|
|
64
|
+
cache_ttl=MarketDataCacheTTL.TICKER_SNAPSHOTS.value
|
|
65
65
|
)
|
|
66
66
|
return snapshot
|
|
67
67
|
|
|
@@ -109,13 +109,15 @@ class MarketDataCache:
|
|
|
109
109
|
periods_calculated += 1
|
|
110
110
|
else:
|
|
111
111
|
break
|
|
112
|
+
if periods_calculated == 0:
|
|
113
|
+
raise Exception(f"No volume data returned for {ticker}")
|
|
112
114
|
avg_volume = total_volume / periods_calculated
|
|
113
115
|
|
|
114
116
|
self.logger.info(f"average volume {ticker}: {avg_volume}")
|
|
115
117
|
await self.cache_data(
|
|
116
118
|
data=avg_volume,
|
|
117
119
|
cache_key=cache_key,
|
|
118
|
-
cache_ttl=MarketDataCacheTTL.
|
|
120
|
+
cache_ttl=MarketDataCacheTTL.TICKER_AVG_VOLUME.value
|
|
119
121
|
)
|
|
120
122
|
return avg_volume
|
|
121
123
|
|
|
@@ -162,7 +164,7 @@ class MarketDataCache:
|
|
|
162
164
|
await self.cache_data(
|
|
163
165
|
data=free_float,
|
|
164
166
|
cache_key=cache_key,
|
|
165
|
-
cache_ttl=MarketDataCacheTTL.
|
|
167
|
+
cache_ttl=MarketDataCacheTTL.TICKER_FREE_FLOAT.value
|
|
166
168
|
)
|
|
167
169
|
return free_float
|
|
168
170
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Minutes in seconds
|
|
2
|
+
ONE_MINUTE = 60
|
|
3
|
+
FIVE_MINUTES = 300
|
|
4
|
+
TEN_MINUTES = 600
|
|
5
|
+
FIFTEEN_MINUTES = 900
|
|
6
|
+
TWENTY_MINUTES = 1200
|
|
7
|
+
THIRTY_MINUTES = 1800
|
|
8
|
+
|
|
9
|
+
# Hours in seconds
|
|
10
|
+
ONE_HOUR = 3600
|
|
11
|
+
TWO_HOURS = 7200
|
|
12
|
+
FOUR_HOURS = 14400
|
|
13
|
+
SIX_HOURS = 21600
|
|
14
|
+
EIGHT_HOURS = 28800
|
|
15
|
+
TWELVE_HOURS = 43200
|
|
16
|
+
|
|
17
|
+
# Days in seconds
|
|
18
|
+
ONE_DAY = 86400
|
|
19
|
+
TWO_DAYS = 172800
|
|
20
|
+
THREE_DAYS = 259200
|
|
21
|
+
FOUR_DAYS = 345600
|
|
22
|
+
FIVE_DAYS = 432000
|
|
23
|
+
SIX_DAYS = 518400
|
|
24
|
+
SEVEN_DAYS = 604800
|
|
@@ -1,20 +1,30 @@
|
|
|
1
1
|
from enum import Enum
|
|
2
|
+
from kuhl_haus.mdp.models.constants import (
|
|
3
|
+
EIGHT_HOURS,
|
|
4
|
+
FIVE_MINUTES,
|
|
5
|
+
ONE_DAY,
|
|
6
|
+
ONE_HOUR,
|
|
7
|
+
THREE_DAYS,
|
|
8
|
+
TWELVE_HOURS,
|
|
9
|
+
)
|
|
2
10
|
|
|
3
11
|
|
|
4
12
|
class MarketDataCacheTTL(Enum):
|
|
5
|
-
#
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
13
|
+
# Raw market data caches
|
|
14
|
+
AGGREGATE = FIVE_MINUTES
|
|
15
|
+
HALTS = ONE_DAY
|
|
16
|
+
QUOTES = ONE_HOUR
|
|
17
|
+
TRADES = ONE_HOUR
|
|
18
|
+
UNKNOWN = ONE_DAY
|
|
19
|
+
|
|
20
|
+
# Ticker caches
|
|
21
|
+
TICKER_AVG_VOLUME = TWELVE_HOURS
|
|
22
|
+
TICKER_FREE_FLOAT = TWELVE_HOURS
|
|
23
|
+
TICKER_SNAPSHOTS = EIGHT_HOURS
|
|
24
|
+
|
|
25
|
+
# Scanner caches
|
|
26
|
+
TOP_STOCKS_SCANNER = EIGHT_HOURS
|
|
27
|
+
TOP_VOLUME_SCANNER = THREE_DAYS
|
|
28
|
+
TOP_GAINERS_SCANNER = THREE_DAYS
|
|
29
|
+
TOP_GAPPERS_SCANNER = THREE_DAYS
|
|
12
30
|
|
|
13
|
-
# Days
|
|
14
|
-
ONE_DAY = 86400
|
|
15
|
-
TWO_DAYS = 172800
|
|
16
|
-
THREE_DAYS = 259200
|
|
17
|
-
FOUR_DAYS = 345600
|
|
18
|
-
FIVE_DAYS = 432000
|
|
19
|
-
SIX_DAYS = 518400
|
|
20
|
-
SEVEN_DAYS = 604800
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
kuhl_haus/mdp/__init__.py,sha256=5dEpAdB3kypH8tCRECoXwbly1WV9kFU5kh8ldGSa0VI,349
|
|
2
2
|
kuhl_haus/mdp/analyzers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
3
|
kuhl_haus/mdp/analyzers/analyzer.py,sha256=rIU1lcHwP2IBai0QLt0y-4ySg_ibWsutNU8JUgSxa1U,471
|
|
4
|
-
kuhl_haus/mdp/analyzers/massive_data_analyzer.py,sha256=
|
|
5
|
-
kuhl_haus/mdp/analyzers/top_stocks.py,sha256=
|
|
4
|
+
kuhl_haus/mdp/analyzers/massive_data_analyzer.py,sha256=i3XFnornuGGhe6nbk6QqIupND0MYTxwKPjvyFw_UBDU,3863
|
|
5
|
+
kuhl_haus/mdp/analyzers/top_stocks.py,sha256=ZZy7legxmLYad-p_a7N6hqj2mN7bn-ZdPEt9xgk4mrQ,10111
|
|
6
6
|
kuhl_haus/mdp/components/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
-
kuhl_haus/mdp/components/market_data_cache.py,sha256=
|
|
7
|
+
kuhl_haus/mdp/components/market_data_cache.py,sha256=jhBdR8rJEvby7eXTTvXn_PceMSf_gS71oEZV1bK7HdM,7337
|
|
8
8
|
kuhl_haus/mdp/components/market_data_scanner.py,sha256=45MgprFlq03MvmIRYXENsrc7UlTcBE_hIsPyOvNs1zc,9745
|
|
9
9
|
kuhl_haus/mdp/components/widget_data_service.py,sha256=ikygD9NRpidcXBEqft5Q11rHy_eUOwKGyOLEezo-Dd4,7439
|
|
10
10
|
kuhl_haus/mdp/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -17,15 +17,16 @@ kuhl_haus/mdp/integ/massive_data_processor.py,sha256=H1WlbGtuSF45n7qLTLleuNlG-Ol
|
|
|
17
17
|
kuhl_haus/mdp/integ/massive_data_queues.py,sha256=zC_uV2vwZCMyVerDQ18RAQwIMMF75iK4qUSqwuWqgwc,5050
|
|
18
18
|
kuhl_haus/mdp/integ/web_socket_message_serde.py,sha256=XdaoaByc7IhtzbPDXBtXKOTjyDzfPSDuZVCoHSIaTl4,5468
|
|
19
19
|
kuhl_haus/mdp/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
20
|
+
kuhl_haus/mdp/models/constants.py,sha256=t55gVHl3IVDSA5Y-mu7zdA8FXAuw4TbOEkI2r2U__1Y,420
|
|
20
21
|
kuhl_haus/mdp/models/market_data_analyzer_result.py,sha256=iICb5GVCtuqARNbR1JNCAfbxMijM3uppDNdL8_FB3eI,422
|
|
21
22
|
kuhl_haus/mdp/models/market_data_cache_keys.py,sha256=_CSPtwvZo5W6cuj9vb7lRTu6MMuRGASe_VigAaOQXwE,1067
|
|
22
|
-
kuhl_haus/mdp/models/market_data_cache_ttl.py,sha256=
|
|
23
|
+
kuhl_haus/mdp/models/market_data_cache_ttl.py,sha256=v7tnc7-qaxSIWvpInlxqDDTByHLY2uilCPhnP7UaNR0,643
|
|
23
24
|
kuhl_haus/mdp/models/market_data_pubsub_keys.py,sha256=PEIPXK9jBehJB7G4pqoSuQZcfMZgOQq8Yho1itqv-1A,1306
|
|
24
25
|
kuhl_haus/mdp/models/market_data_scanner_names.py,sha256=BYn1C0rYgGF1Sq583BkHADKUu-28ytNZQ-XgptuCH-Y,260
|
|
25
26
|
kuhl_haus/mdp/models/massive_data_queue.py,sha256=MfYBcjVc4Fi61DWIvvhhWLUOiLmRpE9egtW-2KH6FTE,188
|
|
26
27
|
kuhl_haus/mdp/models/top_stocks_cache_item.py,sha256=Zn9LociBatP2a1OUfjXDFlWM7tCudO-CR4oj6jYfEEM,7916
|
|
27
|
-
kuhl_haus_mdp-0.1.
|
|
28
|
-
kuhl_haus_mdp-0.1.
|
|
29
|
-
kuhl_haus_mdp-0.1.
|
|
30
|
-
kuhl_haus_mdp-0.1.
|
|
31
|
-
kuhl_haus_mdp-0.1.
|
|
28
|
+
kuhl_haus_mdp-0.1.10.dist-info/METADATA,sha256=Sku0puFIexyTNpzIO8EoUfV8GXQrfw-T6gAREUrqKYs,8888
|
|
29
|
+
kuhl_haus_mdp-0.1.10.dist-info/WHEEL,sha256=tsUv_t7BDeJeRHaSrczbGeuK-TtDpGsWi_JfpzD255I,90
|
|
30
|
+
kuhl_haus_mdp-0.1.10.dist-info/entry_points.txt,sha256=6OYgBcLyFCUgeqLgnvMyOJxPCWzgy7se4rLPKtNonMs,34
|
|
31
|
+
kuhl_haus_mdp-0.1.10.dist-info/licenses/LICENSE.txt,sha256=DRkJftAJcMqoTkQ_Y6-HtKj3nm4pZah_p8XBZiYnw-c,1079
|
|
32
|
+
kuhl_haus_mdp-0.1.10.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|