bullishpy 0.48.0__py3-none-any.whl → 0.50.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.
- bullish/analysis/analysis.py +4 -2
- bullish/analysis/predefined_filters.py +7 -0
- bullish/app/app.py +5 -3
- bullish/jobs/models.py +3 -1
- bullish/jobs/tasks.py +28 -1
- bullish/utils/checks.py +2 -17
- {bullishpy-0.48.0.dist-info → bullishpy-0.50.0.dist-info}/METADATA +1 -1
- {bullishpy-0.48.0.dist-info → bullishpy-0.50.0.dist-info}/RECORD +10 -10
- {bullishpy-0.48.0.dist-info → bullishpy-0.50.0.dist-info}/WHEEL +0 -0
- {bullishpy-0.48.0.dist-info → bullishpy-0.50.0.dist-info}/entry_points.txt +0 -0
bullish/analysis/analysis.py
CHANGED
|
@@ -530,8 +530,10 @@ class SubjectAnalysis(BaseModel):
|
|
|
530
530
|
|
|
531
531
|
def compute_upside(self, last_price: float) -> None:
|
|
532
532
|
if self.high_price_target is not None:
|
|
533
|
-
self.upside = (
|
|
534
|
-
last_price
|
|
533
|
+
self.upside = (
|
|
534
|
+
(float(self.high_price_target) - float(last_price))
|
|
535
|
+
* 100
|
|
536
|
+
/ float(last_price)
|
|
535
537
|
)
|
|
536
538
|
|
|
537
539
|
def to_news(self) -> Optional[str]:
|
|
@@ -164,6 +164,13 @@ SMALL_CAP = NamedFilterQuery(
|
|
|
164
164
|
market_capitalization=[5e7, 5e8],
|
|
165
165
|
properties=["positive_debt_to_equity"],
|
|
166
166
|
average_volume_30=[50000, 5e9],
|
|
167
|
+
volume_above_average=DATE_THRESHOLD,
|
|
168
|
+
sma_50_above_sma_200=[
|
|
169
|
+
datetime.date.today() - datetime.timedelta(days=5000),
|
|
170
|
+
datetime.date.today(),
|
|
171
|
+
],
|
|
172
|
+
weekly_growth=[1, 100],
|
|
173
|
+
monthly_growth=[8, 100],
|
|
167
174
|
order_by_desc="market_capitalization",
|
|
168
175
|
).variants()
|
|
169
176
|
|
bullish/app/app.py
CHANGED
|
@@ -27,14 +27,13 @@ from bullish.analysis.filter import (
|
|
|
27
27
|
GeneralFilter,
|
|
28
28
|
TechnicalAnalysisFilters,
|
|
29
29
|
)
|
|
30
|
-
from bullish.jobs.tasks import update, news, analysis
|
|
30
|
+
from bullish.jobs.tasks import update, news, analysis, initialize
|
|
31
31
|
from pydantic import BaseModel
|
|
32
32
|
|
|
33
33
|
from bullish.utils.checks import (
|
|
34
34
|
compatible_bearish_database,
|
|
35
35
|
compatible_bullish_database,
|
|
36
36
|
empty_analysis_table,
|
|
37
|
-
DataBaseSingleTon,
|
|
38
37
|
)
|
|
39
38
|
|
|
40
39
|
CACHE_SHELVE = "user_cache"
|
|
@@ -421,7 +420,10 @@ def main() -> None:
|
|
|
421
420
|
if st.session_state.database_path is None:
|
|
422
421
|
dialog_pick_database()
|
|
423
422
|
bearish_db_ = bearish_db(st.session_state.database_path)
|
|
424
|
-
|
|
423
|
+
initialize(
|
|
424
|
+
database_path=st.session_state.database_path,
|
|
425
|
+
job_type="Initialize",
|
|
426
|
+
)
|
|
425
427
|
charts_tab, jobs_tab = st.tabs(["Charts", "Jobs"])
|
|
426
428
|
if "data" not in st.session_state:
|
|
427
429
|
st.session_state.data = load_analysis_data(bearish_db_)
|
bullish/jobs/models.py
CHANGED
|
@@ -4,7 +4,9 @@ from typing import Literal, get_args
|
|
|
4
4
|
import pandas as pd
|
|
5
5
|
from pydantic import BaseModel, Field
|
|
6
6
|
|
|
7
|
-
JobType = Literal[
|
|
7
|
+
JobType = Literal[
|
|
8
|
+
"Update data", "Update analysis", "Fetching news", "backtest signals", "Initialize"
|
|
9
|
+
]
|
|
8
10
|
JobStatus = Literal["Completed", "Failed", "Running", "Started"]
|
|
9
11
|
StatusIcon = ["✅ Completed", "❌ Failed", "🔄 Running", "🚀 Started"]
|
|
10
12
|
|
bullish/jobs/tasks.py
CHANGED
|
@@ -18,11 +18,26 @@ from ..analysis.industry_views import compute_industry_view
|
|
|
18
18
|
from ..analysis.predefined_filters import predefined_filters, load_custom_filters
|
|
19
19
|
from ..database.crud import BullishDb
|
|
20
20
|
from bullish.analysis.filter import FilterUpdate
|
|
21
|
-
from ..utils.checks import DataBaseSingleTon
|
|
22
21
|
|
|
23
22
|
logger = logging.getLogger(__name__)
|
|
24
23
|
|
|
25
24
|
|
|
25
|
+
class DataBaseSingleTon:
|
|
26
|
+
_instance = None
|
|
27
|
+
|
|
28
|
+
def __new__(cls, *args: Any, **kwargs: Any) -> Any:
|
|
29
|
+
if cls._instance is None:
|
|
30
|
+
cls._instance = super().__new__(cls)
|
|
31
|
+
return cls._instance
|
|
32
|
+
|
|
33
|
+
def __init__(self, path: Optional[Path] = None) -> None:
|
|
34
|
+
if not hasattr(self, "path"): # Only set once
|
|
35
|
+
self.path = path
|
|
36
|
+
|
|
37
|
+
def valid(self) -> bool:
|
|
38
|
+
return hasattr(self, "path") and self.path is not None
|
|
39
|
+
|
|
40
|
+
|
|
26
41
|
def job_tracker(func: Callable[..., Any]) -> Callable[..., Any]:
|
|
27
42
|
@functools.wraps(func)
|
|
28
43
|
def wrapper(
|
|
@@ -75,6 +90,18 @@ def _base_update(
|
|
|
75
90
|
compute_industry_view(bullish_db)
|
|
76
91
|
|
|
77
92
|
|
|
93
|
+
@huey.task(context=True) # type: ignore
|
|
94
|
+
@job_tracker
|
|
95
|
+
def initialize(
|
|
96
|
+
database_path: Path,
|
|
97
|
+
job_type: JobType,
|
|
98
|
+
task: Optional[Task] = None,
|
|
99
|
+
) -> None:
|
|
100
|
+
database = DataBaseSingleTon(path=database_path)
|
|
101
|
+
if not database.valid():
|
|
102
|
+
raise ValueError("Database path is not valid.")
|
|
103
|
+
|
|
104
|
+
|
|
78
105
|
@huey.task(context=True) # type: ignore
|
|
79
106
|
@job_tracker
|
|
80
107
|
def update(
|
bullish/utils/checks.py
CHANGED
|
@@ -2,9 +2,10 @@ import sqlite3
|
|
|
2
2
|
from contextlib import contextmanager
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
from sqlite3 import Connection
|
|
5
|
-
from typing import
|
|
5
|
+
from typing import Generator, List
|
|
6
6
|
|
|
7
7
|
from bearish.database.schemas import * # type: ignore # noqa: F403
|
|
8
|
+
|
|
8
9
|
from bullish.database.schemas import * # noqa: F403
|
|
9
10
|
|
|
10
11
|
|
|
@@ -64,19 +65,3 @@ def compatible_bearish_database(database_path: Path) -> bool:
|
|
|
64
65
|
|
|
65
66
|
def compatible_bullish_database(database_path: Path) -> bool:
|
|
66
67
|
return _compatible_table(database_path, "bullish.database.schemas")
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
class DataBaseSingleTon:
|
|
70
|
-
_instance = None
|
|
71
|
-
|
|
72
|
-
def __new__(cls, *args: Any, **kwargs: Any) -> Any:
|
|
73
|
-
if cls._instance is None:
|
|
74
|
-
cls._instance = super().__new__(cls)
|
|
75
|
-
return cls._instance
|
|
76
|
-
|
|
77
|
-
def __init__(self, path: Optional[Path] = None) -> None:
|
|
78
|
-
if not hasattr(self, "path"): # Only set once
|
|
79
|
-
self.path = path
|
|
80
|
-
|
|
81
|
-
def valid(self) -> bool:
|
|
82
|
-
return hasattr(self, "path")
|
|
@@ -1,15 +1,15 @@
|
|
|
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=
|
|
3
|
+
bullish/analysis/analysis.py,sha256=Bcupt-qROPddj1hGTNAY8vhu0pnFqNvXoDtUNhRXErY,24217
|
|
4
4
|
bullish/analysis/backtest.py,sha256=x91ek5kOzJHvYq0TmJh1Q8wBDDduIaieE0zDaoZFXew,14325
|
|
5
5
|
bullish/analysis/constants.py,sha256=X3oCyYNA6B-jsZSYJLeGQ94S453Z7jIVNPmv3lMPp8Q,9922
|
|
6
6
|
bullish/analysis/filter.py,sha256=LKmsO3ei7Eo_SJsEVbZqETyIdOpW55xVheO6_GNoA0s,9286
|
|
7
7
|
bullish/analysis/functions.py,sha256=CuMgOjpQeg4KsDMUBdHRlxL1dRlos16KRyLhQe8PYUQ,14819
|
|
8
8
|
bullish/analysis/indicators.py,sha256=XsMHc4-hEZwxFpI3JI-s4C2hcg0eCQLWcAQ8P46dtL8,26812
|
|
9
9
|
bullish/analysis/industry_views.py,sha256=-B4CCAYz2arGQtWTXLLMpox0loO_MGdVQd2ycCRMOQQ,6799
|
|
10
|
-
bullish/analysis/predefined_filters.py,sha256=
|
|
10
|
+
bullish/analysis/predefined_filters.py,sha256=96SFmkATBvq2TmIBRJCMi92-J8I4V1jW_6xJIzM6ueI,8815
|
|
11
11
|
bullish/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
|
-
bullish/app/app.py,sha256
|
|
12
|
+
bullish/app/app.py,sha256=-LXZC9w5DR4m6sXvsc5JXNQU85yi6-4vScFKcIUeFH4,16876
|
|
13
13
|
bullish/cli.py,sha256=yYqiEQAvOIQ-pTn77RPuE449gwaEGBeQwNHHAJ5yQDM,2739
|
|
14
14
|
bullish/database/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
15
|
bullish/database/alembic/README,sha256=heMzebYwlGhnE8_4CWJ4LS74WoEZjBy-S-mIJRxAEKI,39
|
|
@@ -51,11 +51,11 @@ bullish/interface/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU
|
|
|
51
51
|
bullish/interface/interface.py,sha256=R2qVEMyBl9mBlPUO40zXp4vhfLKH7pgl_u2BmAVlD4w,5250
|
|
52
52
|
bullish/jobs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
53
53
|
bullish/jobs/app.py,sha256=5MJ5KXUo7JSNAvOPgkpIMasD11VTrjQvGzM7vmCY65E,77
|
|
54
|
-
bullish/jobs/models.py,sha256=
|
|
55
|
-
bullish/jobs/tasks.py,sha256=
|
|
54
|
+
bullish/jobs/models.py,sha256=rBXxtGFBpgZprrxq5_X2Df-bh8BLYEfw-VLMRucrqa8,784
|
|
55
|
+
bullish/jobs/tasks.py,sha256=vmglWAADUUkhc_2ArzgAGdjtWotkYymvK6LQt08vGo4,6096
|
|
56
56
|
bullish/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
57
|
-
bullish/utils/checks.py,sha256=
|
|
58
|
-
bullishpy-0.
|
|
59
|
-
bullishpy-0.
|
|
60
|
-
bullishpy-0.
|
|
61
|
-
bullishpy-0.
|
|
57
|
+
bullish/utils/checks.py,sha256=g-5QXNWNe1_BwHKrc2PtvPiLraL0tqGgxnzG7u-Wkgo,2189
|
|
58
|
+
bullishpy-0.50.0.dist-info/METADATA,sha256=ndTkDX8uYRTwBLq68DTvI7bnjsaaxm0q2mR8sN6MiD0,830
|
|
59
|
+
bullishpy-0.50.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
60
|
+
bullishpy-0.50.0.dist-info/entry_points.txt,sha256=eaPpmL6vmSBFo0FBtwibCXGqAW4LFJ83whJzT1VjD-0,43
|
|
61
|
+
bullishpy-0.50.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|