kuhl-haus-mdp 0.1.5__py3-none-any.whl → 0.1.6__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.
@@ -1,14 +1,15 @@
1
1
  from typing import Optional, List
2
2
  from kuhl_haus.mdp.models.market_data_analyzer_result import MarketDataAnalyzerResult
3
+ from kuhl_haus.mdp.components.market_data_cache import MarketDataCache
3
4
 
4
5
 
5
6
  class Analyzer:
6
- cache_key: str
7
+ cache: MarketDataCache
7
8
 
8
- def __init__(self, cache_key: str, **kwargs):
9
- self.cache_key = cache_key
9
+ def __init__(self, cache: MarketDataCache, **kwargs):
10
+ self.cache = cache
10
11
 
11
- async def rehydrate(self, data: dict):
12
+ async def rehydrate(self):
12
13
  pass
13
14
 
14
15
  async def analyze_data(self, data: dict) -> Optional[List[MarketDataAnalyzerResult]]:
@@ -26,21 +26,15 @@ from kuhl_haus.mdp.models.top_stocks_cache_item import TopStocksCacheItem
26
26
  class TopStocksAnalyzer(Analyzer):
27
27
 
28
28
  def __init__(self, cache: MarketDataCache, **kwargs):
29
- if "cache_key" not in kwargs:
30
- kwargs["cache_key"] = MarketDataCacheKeys.TOP_STOCKS_SCANNER.value
31
- super().__init__(**kwargs)
29
+ super().__init__(cache=cache, **kwargs)
32
30
  self.cache = cache
31
+ self.cache_key = MarketDataCacheKeys.TOP_STOCKS_SCANNER.value
33
32
  self.logger = logging.getLogger(__name__)
34
33
  self.cache_item = TopStocksCacheItem()
35
34
  self.last_update_time = 0
36
35
  self.pre_market_reset = False
37
36
 
38
- async def rehydrate(self, data: dict):
39
- if not data:
40
- self.cache_item = TopStocksCacheItem()
41
- self.logger.info("No data to rehydrate TopStocksCacheItem.")
42
- return
43
-
37
+ async def rehydrate(self):
44
38
  # Get current time in UTC, then convert to Eastern Time
45
39
  utc_now = datetime.now(timezone.utc)
46
40
  et_now = utc_now.astimezone(ZoneInfo("America/New_York"))
@@ -52,6 +46,11 @@ class TopStocksAnalyzer(Analyzer):
52
46
  self.cache_item = TopStocksCacheItem()
53
47
  self.logger.info(f"Outside market hours ({et_now.strftime('%H:%M:%S %Z')}), clearing cache.")
54
48
  return
49
+ data = await self.cache.get_cache(self.cache_key)
50
+ if not data:
51
+ self.cache_item = TopStocksCacheItem()
52
+ self.logger.info("No data to rehydrate TopStocksCacheItem.")
53
+ return
55
54
  self.cache_item = TopStocksCacheItem(**data)
56
55
  self.logger.info("Rehydrated TopStocksCacheItem")
57
56
 
@@ -1,13 +1,16 @@
1
1
  import asyncio
2
2
  import json
3
3
  import logging
4
- from typing import Union, Optional, List
4
+ from typing import Any, Union, Optional, List
5
5
 
6
6
  import redis.asyncio as aioredis
7
7
  from redis.exceptions import ConnectionError
8
8
 
9
+ from massive.rest import RESTClient
10
+
9
11
  from kuhl_haus.mdp.analyzers.analyzer import Analyzer
10
12
  from kuhl_haus.mdp.models.market_data_analyzer_result import MarketDataAnalyzerResult
13
+ from kuhl_haus.mdp.components.market_data_cache import MarketDataCache
11
14
 
12
15
 
13
16
  class MarketDataScanner:
@@ -18,11 +21,14 @@ class MarketDataScanner:
18
21
  error: int
19
22
  restarts: int
20
23
 
21
- def __init__(self, redis_url: str, analyzer: Analyzer, subscriptions: List[str]):
24
+ def __init__(self, redis_url: str, massive_api_key: str, subscriptions: List[str], analyzer_class: Any):
22
25
  self.redis_url = redis_url
23
- self.analyzer = analyzer
26
+ self.massive_api_key = massive_api_key
24
27
  self.logger = logging.getLogger(__name__)
25
28
 
29
+ self.analyzer: Analyzer = None
30
+ self.analyzer_class = analyzer_class
31
+
26
32
  # Connection objects
27
33
  self.redis_client = None # : aioredis.Redis = None
28
34
  self.pubsub_client: Optional[aioredis.client.PubSub] = None
@@ -30,6 +36,7 @@ class MarketDataScanner:
30
36
  # State
31
37
  self.mdc_connected = False
32
38
  self.running = False
39
+ self.mdc: Optional[MarketDataCache] = None
33
40
 
34
41
  self.subscriptions: List[str] = subscriptions
35
42
  self._pubsub_task: Union[asyncio.Task, None] = None
@@ -48,9 +55,9 @@ class MarketDataScanner:
48
55
  await self.connect()
49
56
  self.pubsub_client = self.redis_client.pubsub()
50
57
 
51
- scanner_cache = await self.get_cache(self.analyzer.cache_key)
58
+ self.analyzer = self.analyzer_class(cache=self.mdc)
52
59
  self.logger.info(f"mds rehydrating from cache")
53
- await self.analyzer.rehydrate(scanner_cache)
60
+ await self.analyzer.rehydrate()
54
61
  self.logger.info("mds rehydration complete")
55
62
 
56
63
  for subscription in self.subscriptions:
@@ -73,6 +80,10 @@ class MarketDataScanner:
73
80
  pass
74
81
  self._pubsub_task = None
75
82
 
83
+ if self.mdc:
84
+ await self.mdc.close()
85
+ self.mdc = None
86
+
76
87
  if self.pubsub_client:
77
88
  for subscription in self.subscriptions:
78
89
  if subscription.endswith("*"):
@@ -104,6 +115,11 @@ class MarketDataScanner:
104
115
 
105
116
  # Test Redis connection
106
117
  await self.redis_client.ping()
118
+ self.mdc = MarketDataCache(
119
+ rest_client=RESTClient(api_key=self.massive_api_key),
120
+ redis_client=self.redis_client,
121
+ massive_api_key=self.massive_api_key
122
+ )
107
123
  self.mdc_connected = True
108
124
  self.logger.debug(f"Connected to Redis: {self.redis_url}")
109
125
  except Exception as e:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: kuhl-haus-mdp
3
- Version: 0.1.5
3
+ Version: 0.1.6
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)
@@ -68,7 +68,7 @@ Description-Content-Type: text/markdown
68
68
  [![codecov](https://codecov.io/gh/kuhl-haus/kuhl-haus-mdp/branch/mainline/graph/badge.svg)](https://codecov.io/gh/kuhl-haus/kuhl-haus-mdp)
69
69
  [![GitHub issues](https://img.shields.io/github/issues/kuhl-haus/kuhl-haus-mdp)](https://github.com/kuhl-haus/kuhl-haus-mdp/issues)
70
70
  [![GitHub pull requests](https://img.shields.io/github/issues-pr/kuhl-haus/kuhl-haus-mdp)](https://github.com/kuhl-haus/kuhl-haus-mdp/pulls)
71
-
71
+ [![Documentation](https://readthedocs.org/projects/kuhl-haus-mdp/badge/?version=latest)](https://kuhl-haus-mdp.readthedocs.io/en/latest/)
72
72
 
73
73
  # kuhl-haus-mdp
74
74
 
@@ -1,11 +1,11 @@
1
1
  kuhl_haus/mdp/__init__.py,sha256=5dEpAdB3kypH8tCRECoXwbly1WV9kFU5kh8ldGSa0VI,349
2
2
  kuhl_haus/mdp/analyzers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- kuhl_haus/mdp/analyzers/analyzer.py,sha256=eluYM2Iib5kgbpNZUSk2qEUL-j83ZTb3zmEmRazrmiM,404
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=aE8Z4PHkfudM02xLAgqgCMeIGqsioq18SQLs81Z8qvM,9452
5
+ kuhl_haus/mdp/analyzers/top_stocks.py,sha256=GvNSa7yWZZ7WUgpaV2t1nVOxWA2R2qpISy16x2RGaQ8,9463
6
6
  kuhl_haus/mdp/components/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  kuhl_haus/mdp/components/market_data_cache.py,sha256=EmRDlh_GTKyYDvAbbAPQrE8n91JKNFKH8myAM4UTPLM,5835
8
- kuhl_haus/mdp/components/market_data_scanner.py,sha256=vA0HPqVIvuZb93wzJhtER6fcH6bf85AgXCbu7yVFOFE,9152
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
@@ -24,8 +24,8 @@ kuhl_haus/mdp/models/market_data_pubsub_keys.py,sha256=PEIPXK9jBehJB7G4pqoSuQZcf
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
26
  kuhl_haus/mdp/models/top_stocks_cache_item.py,sha256=4vwwPTMkRRf1ct6iFInJnLSbBadM-tRk-zhqdD_ITE0,7676
27
- kuhl_haus_mdp-0.1.5.dist-info/METADATA,sha256=h3NksGfUJk-bpw4YWVtjcCrd8HxrxmDD4PxPn-MTg3k,8761
28
- kuhl_haus_mdp-0.1.5.dist-info/WHEEL,sha256=tsUv_t7BDeJeRHaSrczbGeuK-TtDpGsWi_JfpzD255I,90
29
- kuhl_haus_mdp-0.1.5.dist-info/entry_points.txt,sha256=6OYgBcLyFCUgeqLgnvMyOJxPCWzgy7se4rLPKtNonMs,34
30
- kuhl_haus_mdp-0.1.5.dist-info/licenses/LICENSE.txt,sha256=DRkJftAJcMqoTkQ_Y6-HtKj3nm4pZah_p8XBZiYnw-c,1079
31
- kuhl_haus_mdp-0.1.5.dist-info/RECORD,,
27
+ kuhl_haus_mdp-0.1.6.dist-info/METADATA,sha256=ecQ-j_82U-8JfxrpBMpJovbruVY2VSitRS-BgzG_cb8,8898
28
+ kuhl_haus_mdp-0.1.6.dist-info/WHEEL,sha256=tsUv_t7BDeJeRHaSrczbGeuK-TtDpGsWi_JfpzD255I,90
29
+ kuhl_haus_mdp-0.1.6.dist-info/entry_points.txt,sha256=6OYgBcLyFCUgeqLgnvMyOJxPCWzgy7se4rLPKtNonMs,34
30
+ kuhl_haus_mdp-0.1.6.dist-info/licenses/LICENSE.txt,sha256=DRkJftAJcMqoTkQ_Y6-HtKj3nm4pZah_p8XBZiYnw-c,1079
31
+ kuhl_haus_mdp-0.1.6.dist-info/RECORD,,