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.
@@ -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.THREE_DAYS.value,
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.THREE_DAYS.value,
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.EIGHT_HOURS.value,
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.THREE_DAYS.value,
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.ONE_DAY.value,
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, timedelta
4
- from typing import Optional, List, Iterator
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=28500, # 7 hours, 55 minutes
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=259200, # 3 days
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=259200, # 3 days
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=259200, # 3 days
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.EIGHT_HOURS.value
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.TWELVE_HOURS.value
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.TWELVE_HOURS.value
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
- # Hours
6
- ONE_HOUR = 3600
7
- TWO_HOURS = 7200
8
- FOUR_HOURS = 14400
9
- SIX_HOURS = 21600
10
- EIGHT_HOURS = 28800
11
- TWELVE_HOURS = 43200
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,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: kuhl-haus-mdp
3
- Version: 0.1.9
3
+ Version: 0.1.10
4
4
  Summary: Market data processing pipeline for stock market scanner
5
5
  Author-Email: Tom Pounders <git@oldschool.engineer>
6
6
  License: The MIT License (MIT)
@@ -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=WSb7T8X4u2ue7Du7sf_fqxjgjEbR6ThllSNT1CncIM0,3866
5
- kuhl_haus/mdp/analyzers/top_stocks.py,sha256=s4xI6_S7K3CxUm3jtMi4BPD17v2T1URTMgKIRK85V_s,9814
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=LT_yddNwB-l6skJgvDWHmUO6GjdBM0EmlMCGHX5kwKY,7209
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=a43ys3S61Y0ADdb03ThgrRd9x7B1EsI6FplCjecdNLY,373
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.9.dist-info/METADATA,sha256=iwhFbwovPdoPkMO2vMr-9KroOXZ5vNGhz4YMPcjYIpk,8887
28
- kuhl_haus_mdp-0.1.9.dist-info/WHEEL,sha256=tsUv_t7BDeJeRHaSrczbGeuK-TtDpGsWi_JfpzD255I,90
29
- kuhl_haus_mdp-0.1.9.dist-info/entry_points.txt,sha256=6OYgBcLyFCUgeqLgnvMyOJxPCWzgy7se4rLPKtNonMs,34
30
- kuhl_haus_mdp-0.1.9.dist-info/licenses/LICENSE.txt,sha256=DRkJftAJcMqoTkQ_Y6-HtKj3nm4pZah_p8XBZiYnw-c,1079
31
- kuhl_haus_mdp-0.1.9.dist-info/RECORD,,
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,,