bullishpy 0.11.0__py3-none-any.whl → 0.12.0__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.

Potentially problematic release.


This version of bullishpy might be problematic. Click here for more details.

@@ -1,4 +1,7 @@
1
1
  import logging
2
+ import time
3
+ from itertools import batched
4
+ from pathlib import Path
2
5
  from typing import (
3
6
  Annotated,
4
7
  Any,
@@ -40,6 +43,7 @@ from bearish.types import TickerOnlySources # type: ignore
40
43
  from pydantic import BaseModel, BeforeValidator, Field, create_model
41
44
 
42
45
  from bullish.analysis.indicators import Indicators, IndicatorModels
46
+ from joblib import Parallel, delayed # type: ignore
43
47
 
44
48
  if TYPE_CHECKING:
45
49
  from bullish.database.crud import BullishDb
@@ -482,10 +486,27 @@ class Analysis(AnalysisView, BaseEquity, TechnicalAnalysis, FundamentalAnalysis)
482
486
  )
483
487
 
484
488
 
489
+ def compute_analysis(database_path: Path, ticker: Ticker) -> Analysis:
490
+ from bullish.database.crud import BullishDb
491
+
492
+ bullish_db = BullishDb(database_path=database_path)
493
+ return Analysis.from_ticker(bullish_db, ticker)
494
+
495
+
485
496
  def run_analysis(bullish_db: "BullishDb") -> None:
486
497
  price_trackers = set(bullish_db._read_tracker(TrackerQuery(), PriceTracker))
487
498
  finance_trackers = set(bullish_db._read_tracker(TrackerQuery(), FinancialsTracker))
488
499
  tickers = list(price_trackers.intersection(finance_trackers))
489
- for ticker in tickers:
490
- analysis = Analysis.from_ticker(bullish_db, ticker)
491
- bullish_db.write_analysis(analysis)
500
+ parallel = Parallel(n_jobs=-1)
501
+
502
+ for batch_ticker in batched(tickers, 1000):
503
+ start = time.perf_counter()
504
+ many_analysis = parallel(
505
+ delayed(compute_analysis)(bullish_db.database_path, ticker)
506
+ for ticker in batch_ticker
507
+ )
508
+ bullish_db.write_many_analysis(many_analysis)
509
+ elapsed_time = time.perf_counter() - start
510
+ print(
511
+ f"Computed analysis for {len(batch_ticker)} tickers in {elapsed_time:.2f} seconds."
512
+ )
bullish/database/crud.py CHANGED
@@ -67,6 +67,16 @@ class BullishDb(BearishDb, BullishDbBase): # type: ignore
67
67
  session.exec(stmt) # type: ignore
68
68
  session.commit()
69
69
 
70
+ def _write_many_analysis(self, many_analysis: List[Analysis]) -> None:
71
+ with Session(self._engine) as session:
72
+ stmt = (
73
+ insert(AnalysisORM)
74
+ .prefix_with("OR REPLACE")
75
+ .values([a.model_dump() for a in many_analysis])
76
+ )
77
+ session.exec(stmt) # type: ignore
78
+ session.commit()
79
+
70
80
  def _read_analysis(self, ticker: Ticker) -> Optional[Analysis]:
71
81
  with Session(self._engine) as session:
72
82
  query = select(AnalysisORM).where(AnalysisORM.symbol == ticker.symbol)
@@ -19,6 +19,9 @@ class BullishDbBase(BearishDbBase): # type: ignore
19
19
  def write_analysis(self, analysis: "Analysis") -> None:
20
20
  return self._write_analysis(analysis)
21
21
 
22
+ def write_many_analysis(self, many_analysis: List["Analysis"]) -> None:
23
+ return self._write_many_analysis(many_analysis)
24
+
22
25
  def read_analysis(self, ticker: Ticker) -> Optional["Analysis"]:
23
26
  return self._read_analysis(ticker)
24
27
 
@@ -62,6 +65,9 @@ class BullishDbBase(BearishDbBase): # type: ignore
62
65
  @abc.abstractmethod
63
66
  def _write_analysis(self, analysis: "Analysis") -> None: ...
64
67
 
68
+ @abc.abstractmethod
69
+ def _write_many_analysis(self, many_analysis: List["Analysis"]) -> None: ...
70
+
65
71
  @abc.abstractmethod
66
72
  def _read_analysis(self, ticker: Ticker) -> Optional["Analysis"]: ...
67
73
 
@@ -1,15 +1,16 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: bullishpy
3
- Version: 0.11.0
3
+ Version: 0.12.0
4
4
  Summary:
5
5
  Author: aan
6
6
  Author-email: andoludovic.andriamamonjy@gmail.com
7
7
  Requires-Python: >=3.12,<3.13
8
8
  Classifier: Programming Language :: Python :: 3
9
9
  Classifier: Programming Language :: Python :: 3.12
10
- Requires-Dist: bearishpy (>=0.20.0,<0.21.0)
10
+ Requires-Dist: bearishpy (>=0.22.0,<0.23.0)
11
11
  Requires-Dist: click (>=7.0,<=8.1)
12
12
  Requires-Dist: huey (>=2.5.3,<3.0.0)
13
+ Requires-Dist: joblib (>=1.5.1,<2.0.0)
13
14
  Requires-Dist: pandas-ta (>=0.3.14b0,<0.4.0)
14
15
  Requires-Dist: plotly (>=6.1.2,<7.0.0)
15
16
  Requires-Dist: streamlit (>=1.45.1,<2.0.0)
@@ -1,6 +1,6 @@
1
1
  bullish/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  bullish/analysis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- bullish/analysis/analysis.py,sha256=9ugJp2fGuA6xFUlGIJVIHWZ8d8E6TdbQHWjg5zWPIwY,18445
3
+ bullish/analysis/analysis.py,sha256=v5MFGhQUpMwGAVE0dg2293ldRSgQmqy5CiF8MQFTibM,19165
4
4
  bullish/analysis/filter.py,sha256=S8TuxoTAUY0U8ARPjNHE0tSSE_ToWkfZazAgnfgswk4,18136
5
5
  bullish/analysis/functions.py,sha256=KKz_0C7maQmcGu2tGwZvioxzmh-JcB-YNpPQGjyyheA,13825
6
6
  bullish/analysis/indicators.py,sha256=hZgzTq-80XPP6x7dXGhxd-Zzgra-6D-g3pVxUBYOW44,20167
@@ -23,7 +23,7 @@ bullish/database/alembic/versions/73564b60fe24_.py,sha256=MTlDRDNHj3E9gK7IMeAzv2
23
23
  bullish/database/alembic/versions/d663166c531d_.py,sha256=U92l6QXqPniAYrPeu2Bt77ReDbXveLj4aGXtgd806JY,1915
24
24
  bullish/database/alembic/versions/ee5baabb35f8_.py,sha256=nBMEY-_C8AsSXVPyaDdUkwrFFo2gxShzJhmrjejDwtc,1632
25
25
  bullish/database/alembic/versions/fc191121f522_.py,sha256=0sstF6TpAJ09-Mt-Vek9SdSWksvi4C58a5D92rBtuY8,1894
26
- bullish/database/crud.py,sha256=6-Fb1AjGZqsrmwwl2Qay_leqQ9_-RAIjZ8D0efe8nKA,7022
26
+ bullish/database/crud.py,sha256=0AMrs07MMeDq5AVft_pf43KWPFOusMNzUmxuXwMX6K4,7400
27
27
  bullish/database/schemas.py,sha256=bU-DW49NqpBp--1VN486LUdDmLeScrI8TF69afzjoTc,1507
28
28
  bullish/database/scripts/create_revision.py,sha256=rggIf-3koPqJNth8FIg89EOfnIM7a9QrvL8X7UJsP0g,628
29
29
  bullish/database/scripts/stamp.py,sha256=PWgVUEBumjNUMjTnGw46qmU3p221LeN-KspnW_gFuu4,839
@@ -33,14 +33,14 @@ bullish/exceptions.py,sha256=4z_i-dD-CDz1bkGmZH9DOf1L_awlCPCgdUDPF7dhWAI,106
33
33
  bullish/figures/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
34
  bullish/figures/figures.py,sha256=SWTTiEoVyWMZeIIxg0ERi23v7s4tySB5BLKyPu12jC4,4193
35
35
  bullish/interface/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
- bullish/interface/interface.py,sha256=-3V4M1J2VVn0ugwbaCKzMuBYRHH7eFmz9gij0hUTNUw,3013
36
+ bullish/interface/interface.py,sha256=6HXSK-N-vOuOGVserizknP4CeUGbUhB8P642oZmgpk0,3252
37
37
  bullish/jobs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
38
  bullish/jobs/app.py,sha256=5MJ5KXUo7JSNAvOPgkpIMasD11VTrjQvGzM7vmCY65E,77
39
39
  bullish/jobs/models.py,sha256=ndrGTMP08S57yGLGEG9TQt8Uw2slc4HvbG-TZtEEuN0,744
40
40
  bullish/jobs/tasks.py,sha256=V_b0c8_GQC0-KIxaHDlLFhtkclQJOsck0gXaW6OlC_w,3055
41
41
  bullish/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
42
42
  bullish/utils/checks.py,sha256=Va10_xDVVnxYkOD2hafvyQ-TFV8FQpOkr4huJ7XgpDM,2188
43
- bullishpy-0.11.0.dist-info/METADATA,sha256=2eQfm9prQaZjTnRzLUDvRd0jjE8EapQ1RMhJtQ0CXjQ,745
44
- bullishpy-0.11.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
45
- bullishpy-0.11.0.dist-info/entry_points.txt,sha256=eaPpmL6vmSBFo0FBtwibCXGqAW4LFJ83whJzT1VjD-0,43
46
- bullishpy-0.11.0.dist-info/RECORD,,
43
+ bullishpy-0.12.0.dist-info/METADATA,sha256=hmEQ5ZWQ8ROXE5_Vm0l3npGSM6BfuBQD1-glStH16us,784
44
+ bullishpy-0.12.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
45
+ bullishpy-0.12.0.dist-info/entry_points.txt,sha256=eaPpmL6vmSBFo0FBtwibCXGqAW4LFJ83whJzT1VjD-0,43
46
+ bullishpy-0.12.0.dist-info/RECORD,,