kuhl-haus-mdp 0.1.7__py3-none-any.whl → 0.1.9__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.
@@ -126,6 +126,7 @@ class TopStocksAnalyzer(Analyzer):
126
126
  prev_day_close = cached_data["prev_day_close"]
127
127
  prev_day_volume = cached_data["prev_day_volume"]
128
128
  prev_day_vwap = cached_data["prev_day_vwap"]
129
+ free_float = cached_data["free_float"]
129
130
  else:
130
131
  # Get snapshot for previous day's data
131
132
  retry_count = 0
@@ -140,8 +141,7 @@ class TopStocksAnalyzer(Analyzer):
140
141
  prev_day_volume = snapshot.prev_day.volume
141
142
  prev_day_vwap = snapshot.prev_day.vwap
142
143
  break
143
- except BadResponse as e:
144
- self.logger.error(f"Error getting snapshot for {event.symbol}: {repr(e)}", exc_info=e, stack_info=True)
144
+ except Exception:
145
145
  retry_count += 1
146
146
  if retry_count == max_tries and prev_day_close == 0:
147
147
  self.logger.error(f"Failed to get snapshot for {event.symbol} after {max_tries} tries.")
@@ -155,13 +155,25 @@ class TopStocksAnalyzer(Analyzer):
155
155
  try:
156
156
  avg_volume = await self.cache.get_avg_volume(event.symbol)
157
157
  break
158
- except (BadResponse, ZeroDivisionError) as e:
159
- self.logger.error(f"Error getting average volume for {event.symbol}: {repr(e)}", exc_info=e, stack_info=True)
158
+ except Exception:
160
159
  retry_count += 1
161
160
  if retry_count == max_tries and avg_volume == 0:
162
161
  self.logger.error(f"Failed to get average volume for {event.symbol} after {max_tries} tries.")
163
162
  return
164
163
 
164
+ # Get free float - this uses an experimental API
165
+ retry_count = 0
166
+ max_tries = 2
167
+ free_float = 0
168
+ while retry_count < max_tries:
169
+ try:
170
+ free_float = await self.cache.get_free_float(event.symbol)
171
+ break
172
+ except Exception:
173
+ retry_count += 1
174
+ if retry_count == max_tries and free_float == 0:
175
+ self.logger.error(f"Failed to get free float for {event.symbol} after {max_tries} tries.")
176
+
165
177
  # Calculate relative volume
166
178
  if avg_volume == 0:
167
179
  relative_volume = 0
@@ -196,6 +208,7 @@ class TopStocksAnalyzer(Analyzer):
196
208
  self.cache_item.symbol_data_cache[event.symbol] = {
197
209
  "symbol": event.symbol,
198
210
  "volume": event.volume,
211
+ "free_float": free_float,
199
212
  "accumulated_volume": event.accumulated_volume,
200
213
  "relative_volume": relative_volume,
201
214
  "official_open_price": event.official_open_price,
@@ -57,77 +57,6 @@ class MarketDataCache:
57
57
  ticker=ticker
58
58
  )
59
59
  self.logger.info(f"Snapshot result: {snapshot}")
60
- # data = {
61
- # "day": {
62
- # "open": snapshot.day.open,
63
- # "high": snapshot.day.high,
64
- # "low": snapshot.day.low,
65
- # "close": snapshot.day.close,
66
- # "volume": snapshot.day.volume,
67
- # "vwap": snapshot.day.vwap,
68
- # "timestamp": snapshot.day.timestamp,
69
- # "transactions": snapshot.day.transactions,
70
- # "otc": snapshot.day.otc,
71
- # },
72
- # "last_quote": {
73
- # "ticker": snapshot.last_quote.ticker,
74
- # "trf_timestamp": snapshot.last_quote.trf_timestamp,
75
- # "sequence_number": snapshot.last_quote.sequence_number,
76
- # "sip_timestamp": snapshot.last_quote.sip_timestamp,
77
- # "participant_timestamp": snapshot.last_quote.participant_timestamp,
78
- # "ask_price": snapshot.last_quote.ask_price,
79
- # "ask_size": snapshot.last_quote.ask_size,
80
- # "ask_exchange": snapshot.last_quote.ask_exchange,
81
- # "conditions": snapshot.last_quote.conditions,
82
- # "indicators": snapshot.last_quote.indicators,
83
- # "bid_price": snapshot.last_quote.bid_price,
84
- # "bid_size": snapshot.last_quote.bid_size,
85
- # "bid_exchange": snapshot.last_quote.bid_exchange,
86
- # "tape": snapshot.last_quote.tape,
87
- # },
88
- # "last_trade": {
89
- # "ticker": snapshot.last_trade.ticker,
90
- # "trf_timestamp": snapshot.last_trade.trf_timestamp,
91
- # "sequence_number": snapshot.last_trade.sequence_number,
92
- # "sip_timestamp": snapshot.last_trade.sip_timestamp,
93
- # "participant_timestamp": snapshot.last_trade.participant_timestamp,
94
- # "conditions": snapshot.last_trade.conditions,
95
- # "correction": snapshot.last_trade.correction,
96
- # "id": snapshot.last_trade.id,
97
- # "price": snapshot.last_trade.price,
98
- # "trf_id": snapshot.last_trade.trf_id,
99
- # "size": snapshot.last_trade.size,
100
- # "exchange": snapshot.last_trade.exchange,
101
- # "tape": snapshot.last_trade.tape,
102
- # },
103
- # "min": {
104
- # "accumulated_volume": snapshot.min.accumulated_volume,
105
- # "open": snapshot.min.open,
106
- # "high": snapshot.min.high,
107
- # "low": snapshot.min.low,
108
- # "close": snapshot.min.close,
109
- # "volume": snapshot.min.volume,
110
- # "vwap": snapshot.min.vwap,
111
- # "otc": snapshot.min.otc,
112
- # "timestamp": snapshot.min.timestamp,
113
- # "transactions": snapshot.min.transactions,
114
- # },
115
- # "prev_day": {
116
- # "open": snapshot.prev_day.open,
117
- # "high": snapshot.prev_day.high,
118
- # "low": snapshot.prev_day.low,
119
- # "close": snapshot.prev_day.close,
120
- # "volume": snapshot.prev_day.volume,
121
- # "vwap": snapshot.prev_day.vwap,
122
- # "timestamp": snapshot.prev_day.timestamp,
123
- # "transactions": snapshot.prev_day.transactions,
124
- # "otc": snapshot.prev_day.otc,
125
- # },
126
- # "ticker": snapshot.ticker,
127
- # "todaysChange": snapshot.todays_change,
128
- # "todaysChangePerc": snapshot.todays_change_percent,
129
- # "updated": snapshot.updated,
130
- # }
131
60
  data = ticker_snapshot_to_dict(snapshot)
132
61
  await self.cache_data(
133
62
  data=data,
@@ -1,5 +1,6 @@
1
1
  import logging
2
2
  import os
3
+ from typing import Dict, Any
3
4
 
4
5
  from massive.rest.models import TickerSnapshot
5
6
 
@@ -38,7 +39,7 @@ def get_massive_api_key():
38
39
  return api_key
39
40
 
40
41
 
41
- def ticker_snapshot_to_dict(snapshot: TickerSnapshot) -> dict:
42
+ def ticker_snapshot_to_dict(snapshot: TickerSnapshot) -> Dict[str, Any]:
42
43
  """
43
44
  Convert a TickerSnapshot instance into a JSON-serializable dictionary.
44
45
 
@@ -15,10 +15,10 @@ class MarketDataCacheKeys(Enum):
15
15
  UNKNOWN = 'unknown'
16
16
 
17
17
  # MARKET DATA CACHE
18
- DAILY_AGGREGATES = 'aggregate:daily'
19
- TICKER_SNAPSHOTS = 'snapshots'
20
- TICKER_AVG_VOLUME = 'avg_volume'
21
- TICKER_FREE_FLOAT = 'free_float'
18
+ DAILY_AGGREGATES = 'mdc:aggregate:daily'
19
+ TICKER_SNAPSHOTS = 'mdc:snapshots'
20
+ TICKER_AVG_VOLUME = 'mdc:avg_volume'
21
+ TICKER_FREE_FLOAT = 'mdc:free_float'
22
22
 
23
23
  # MARKET DATA PROCESSOR CACHE
24
24
  TOP_TRADES_SCANNER = f'cache:{MarketDataScannerNames.TOP_TRADES.value}'
@@ -45,6 +45,7 @@ class TopStocksCacheItem:
45
45
  ret.append({
46
46
  "symbol": ticker,
47
47
  "volume": self.symbol_data_cache[ticker]["volume"],
48
+ "free_float": self.symbol_data_cache[ticker]["free_float"],
48
49
  "accumulated_volume": self.symbol_data_cache[ticker]["accumulated_volume"],
49
50
  "relative_volume": self.symbol_data_cache[ticker]["relative_volume"],
50
51
  "official_open_price": self.symbol_data_cache[ticker]["official_open_price"],
@@ -81,6 +82,7 @@ class TopStocksCacheItem:
81
82
  ret.append({
82
83
  "symbol": ticker,
83
84
  "volume": self.symbol_data_cache[ticker]["volume"],
85
+ "free_float": self.symbol_data_cache[ticker]["free_float"],
84
86
  "accumulated_volume": self.symbol_data_cache[ticker]["accumulated_volume"],
85
87
  "relative_volume": self.symbol_data_cache[ticker]["relative_volume"],
86
88
  "official_open_price": self.symbol_data_cache[ticker]["official_open_price"],
@@ -117,6 +119,7 @@ class TopStocksCacheItem:
117
119
  ret.append({
118
120
  "symbol": ticker,
119
121
  "volume": self.symbol_data_cache[ticker]["volume"],
122
+ "free_float": self.symbol_data_cache[ticker]["free_float"],
120
123
  "accumulated_volume": self.symbol_data_cache[ticker]["accumulated_volume"],
121
124
  "relative_volume": self.symbol_data_cache[ticker]["relative_volume"],
122
125
  "official_open_price": self.symbol_data_cache[ticker]["official_open_price"],
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: kuhl-haus-mdp
3
- Version: 0.1.7
3
+ Version: 0.1.9
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)
@@ -28,7 +28,7 @@ License: The MIT License (MIT)
28
28
  Classifier: Development Status :: 4 - Beta
29
29
  Classifier: Programming Language :: Python
30
30
  Project-URL: Homepage, https://github.com/kuhl-haus/kuhl-haus-mdp
31
- Project-URL: Documentation, https://github.com/kuhl-haus/kuhl-haus-mdp/wiki
31
+ Project-URL: Documentation, https://kuhl-haus-mdp.readthedocs.io
32
32
  Project-URL: Source, https://github.com/kuhl-haus/kuhl-haus-mdp.git
33
33
  Project-URL: Changelog, https://github.com/kuhl-haus/kuhl-haus-mdp/commits
34
34
  Project-URL: Tracker, https://github.com/kuhl-haus/kuhl-haus-mdp/issues
@@ -2,15 +2,15 @@ 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
4
  kuhl_haus/mdp/analyzers/massive_data_analyzer.py,sha256=WSb7T8X4u2ue7Du7sf_fqxjgjEbR6ThllSNT1CncIM0,3866
5
- kuhl_haus/mdp/analyzers/top_stocks.py,sha256=GvNSa7yWZZ7WUgpaV2t1nVOxWA2R2qpISy16x2RGaQ8,9463
5
+ kuhl_haus/mdp/analyzers/top_stocks.py,sha256=s4xI6_S7K3CxUm3jtMi4BPD17v2T1URTMgKIRK85V_s,9814
6
6
  kuhl_haus/mdp/components/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- kuhl_haus/mdp/components/market_data_cache.py,sha256=qc19TN05efgdpqobcF9rlNL8D8ZFDVYfKN-flTaZLks,11086
7
+ kuhl_haus/mdp/components/market_data_cache.py,sha256=LT_yddNwB-l6skJgvDWHmUO6GjdBM0EmlMCGHX5kwKY,7209
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
11
11
  kuhl_haus/mdp/helpers/process_manager.py,sha256=Is3Jx8nlBWvywQ1acdsdaSJTAG0olKskpPvrRB4VMDE,9024
12
12
  kuhl_haus/mdp/helpers/queue_name_resolver.py,sha256=l_zfRLxrjR9uwRCV2VDO4vPWLK_lj5KVG2p4Lh8xWiw,770
13
- kuhl_haus/mdp/helpers/utils.py,sha256=i6ILSa884jp7ijBsP_wBT3yHsUa91xSQEFkDhzqe1aQ,5164
13
+ kuhl_haus/mdp/helpers/utils.py,sha256=2jECmezuDBABcB1Fhe1_GPnlEAFnld2bZ1vSdaCZApg,5203
14
14
  kuhl_haus/mdp/integ/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
15
  kuhl_haus/mdp/integ/massive_data_listener.py,sha256=fPEYc6zZzHzFFjbP3zFInajKtEGInj8UQKKo3nKQEwQ,5098
16
16
  kuhl_haus/mdp/integ/massive_data_processor.py,sha256=H1WlbGtuSF45n7qLTLleuNlG-OlIXz4llJ7q3XRSS-s,8605
@@ -18,14 +18,14 @@ kuhl_haus/mdp/integ/massive_data_queues.py,sha256=zC_uV2vwZCMyVerDQ18RAQwIMMF75i
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
20
  kuhl_haus/mdp/models/market_data_analyzer_result.py,sha256=iICb5GVCtuqARNbR1JNCAfbxMijM3uppDNdL8_FB3eI,422
21
- kuhl_haus/mdp/models/market_data_cache_keys.py,sha256=04nFRdNZtvEeKFnpjZ6CNSu-4MiUgifPXPHGAZhZRsE,1051
21
+ kuhl_haus/mdp/models/market_data_cache_keys.py,sha256=_CSPtwvZo5W6cuj9vb7lRTu6MMuRGASe_VigAaOQXwE,1067
22
22
  kuhl_haus/mdp/models/market_data_cache_ttl.py,sha256=a43ys3S61Y0ADdb03ThgrRd9x7B1EsI6FplCjecdNLY,373
23
23
  kuhl_haus/mdp/models/market_data_pubsub_keys.py,sha256=PEIPXK9jBehJB7G4pqoSuQZcfMZgOQq8Yho1itqv-1A,1306
24
24
  kuhl_haus/mdp/models/market_data_scanner_names.py,sha256=BYn1C0rYgGF1Sq583BkHADKUu-28ytNZQ-XgptuCH-Y,260
25
25
  kuhl_haus/mdp/models/massive_data_queue.py,sha256=MfYBcjVc4Fi61DWIvvhhWLUOiLmRpE9egtW-2KH6FTE,188
26
- kuhl_haus/mdp/models/top_stocks_cache_item.py,sha256=4vwwPTMkRRf1ct6iFInJnLSbBadM-tRk-zhqdD_ITE0,7676
27
- kuhl_haus_mdp-0.1.7.dist-info/METADATA,sha256=YbJ2dQ8MBJrdtgCtDtfuWYEtX7FZDCF-gilSTjxDTmw,8898
28
- kuhl_haus_mdp-0.1.7.dist-info/WHEEL,sha256=tsUv_t7BDeJeRHaSrczbGeuK-TtDpGsWi_JfpzD255I,90
29
- kuhl_haus_mdp-0.1.7.dist-info/entry_points.txt,sha256=6OYgBcLyFCUgeqLgnvMyOJxPCWzgy7se4rLPKtNonMs,34
30
- kuhl_haus_mdp-0.1.7.dist-info/licenses/LICENSE.txt,sha256=DRkJftAJcMqoTkQ_Y6-HtKj3nm4pZah_p8XBZiYnw-c,1079
31
- kuhl_haus_mdp-0.1.7.dist-info/RECORD,,
26
+ 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,,