bbstrader 0.2.99__py3-none-any.whl → 0.2.991__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 bbstrader might be problematic. Click here for more details.
- bbstrader/__init__.py +19 -0
- bbstrader/btengine/event.py +15 -14
- bbstrader/core/data.py +98 -2
- bbstrader/metatrader/trade.py +1 -1
- bbstrader/models/nlp.py +9 -2
- {bbstrader-0.2.99.dist-info → bbstrader-0.2.991.dist-info}/METADATA +1 -3
- {bbstrader-0.2.99.dist-info → bbstrader-0.2.991.dist-info}/RECORD +11 -10
- {bbstrader-0.2.99.dist-info → bbstrader-0.2.991.dist-info}/WHEEL +1 -1
- {bbstrader-0.2.99.dist-info → bbstrader-0.2.991.dist-info}/entry_points.txt +0 -0
- {bbstrader-0.2.99.dist-info → bbstrader-0.2.991.dist-info}/licenses/LICENSE +0 -0
- {bbstrader-0.2.99.dist-info → bbstrader-0.2.991.dist-info}/top_level.txt +0 -0
bbstrader/__init__.py
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Simplified Investment & Trading Toolkit
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
__author__ = "Bertin Balouki SIMYELI"
|
|
7
|
+
__copyright__ = "2023-2025 Bertin Balouki SIMYELI"
|
|
8
|
+
__email__ = "bertin@bbstrader.com"
|
|
9
|
+
__license__ = "MIT"
|
|
10
|
+
__version__ = "0.2.0"
|
|
11
|
+
|
|
12
|
+
from bbstrader import compat # noqa: F401
|
|
13
|
+
from bbstrader import core # noqa: F401
|
|
14
|
+
from bbstrader import btengine # noqa: F401
|
|
15
|
+
from bbstrader import metatrader # noqa: F401
|
|
16
|
+
from bbstrader import models # noqa: F401
|
|
17
|
+
from bbstrader import trading # noqa: F401
|
|
18
|
+
from bbstrader import tseries # noqa: F401
|
|
19
|
+
from bbstrader.config import config_logger # noqa: F401
|
bbstrader/btengine/event.py
CHANGED
|
@@ -2,7 +2,7 @@ from datetime import datetime
|
|
|
2
2
|
from enum import Enum
|
|
3
3
|
from typing import Literal
|
|
4
4
|
|
|
5
|
-
__all__ = ["Event", "MarketEvent", "SignalEvent", "OrderEvent", "FillEvent"]
|
|
5
|
+
__all__ = ["Event", "Events", "MarketEvent", "SignalEvent", "OrderEvent", "FillEvent"]
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class Event(object):
|
|
@@ -134,20 +134,21 @@ class OrderEvent(Event):
|
|
|
134
134
|
self.price = price
|
|
135
135
|
self.signal = signal
|
|
136
136
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
)
|
|
137
|
+
def print_order(self):
|
|
138
|
+
"""
|
|
139
|
+
Outputs the values within the Order.
|
|
140
|
+
"""
|
|
141
|
+
print(
|
|
142
|
+
"Order: Symbol=%s, Type=%s, Quantity=%s, Direction=%s, Price=%s"
|
|
143
|
+
% (
|
|
144
|
+
self.symbol,
|
|
145
|
+
self.order_type,
|
|
146
|
+
self.quantity,
|
|
147
|
+
self.direction,
|
|
148
|
+
self.price,
|
|
150
149
|
)
|
|
150
|
+
)
|
|
151
|
+
|
|
151
152
|
|
|
152
153
|
|
|
153
154
|
class FillEvent(Event):
|
bbstrader/core/data.py
CHANGED
|
@@ -2,7 +2,7 @@ import json
|
|
|
2
2
|
import re
|
|
3
3
|
import ssl
|
|
4
4
|
from datetime import datetime
|
|
5
|
-
from typing import List
|
|
5
|
+
from typing import List, Literal
|
|
6
6
|
from urllib.request import urlopen
|
|
7
7
|
|
|
8
8
|
import certifi
|
|
@@ -18,7 +18,7 @@ __all__ = ["FmpData", "FmpNews", "FinancialNews"]
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
def _get_search_query(query: str) -> str:
|
|
21
|
-
if " " in query:
|
|
21
|
+
if " " in query or query == "":
|
|
22
22
|
return query
|
|
23
23
|
try:
|
|
24
24
|
name = yf.Ticker(query).info["shortName"]
|
|
@@ -422,6 +422,102 @@ class FinancialNews(object):
|
|
|
422
422
|
def get_fmp_news(self, api=None) -> FmpNews:
|
|
423
423
|
return FmpNews(api=api)
|
|
424
424
|
|
|
425
|
+
def get_coindesk_news(
|
|
426
|
+
self,
|
|
427
|
+
query="",
|
|
428
|
+
lang: Literal["EN", "ES", "TR", "FR", "JP", "PT"] = "EN",
|
|
429
|
+
limit=50,
|
|
430
|
+
list_of_str=False,
|
|
431
|
+
) -> List[str] | List[dict]:
|
|
432
|
+
"""
|
|
433
|
+
Fetches and filters recent news articles from CoinDesk's News API.
|
|
434
|
+
|
|
435
|
+
Args:
|
|
436
|
+
query : str, optional
|
|
437
|
+
A search term to filter articles by title, body, or keywords.
|
|
438
|
+
If empty, all articles are returned without filtering (default is "").
|
|
439
|
+
|
|
440
|
+
lang : Literal["EN", "ES", "TR", "FR", "JP", "PT"], optional
|
|
441
|
+
Language in which to fetch news articles. Supported languages:
|
|
442
|
+
English (EN), Spanish (ES), Turkish (TR), French (FR), Japanese (JP), and Portuguese (PT).
|
|
443
|
+
Default is "EN".
|
|
444
|
+
|
|
445
|
+
limit : int, optional
|
|
446
|
+
Maximum number of articles to retrieve. Default is 50.
|
|
447
|
+
|
|
448
|
+
list_of_str : bool, optional
|
|
449
|
+
If True, returns a list of strings (concatenated article content).
|
|
450
|
+
If False, returns a list of filtered article dictionaries.
|
|
451
|
+
Default is False.
|
|
452
|
+
|
|
453
|
+
Returns:
|
|
454
|
+
List[str] | List[dict]
|
|
455
|
+
- If `query` is empty: returns a list of filtered article dictionaries.
|
|
456
|
+
- If `query` is provided:
|
|
457
|
+
- Returns a list of strings if `list_of_str=True`.
|
|
458
|
+
- Returns a list of filtered article dictionaries otherwise.
|
|
459
|
+
|
|
460
|
+
Each article dictionary contains the following fields:
|
|
461
|
+
- 'published_on': datetime of publication
|
|
462
|
+
- 'title': article headline
|
|
463
|
+
- 'subtitle': secondary headline
|
|
464
|
+
- 'url': direct link to the article
|
|
465
|
+
- 'body': article content
|
|
466
|
+
- 'keywords': associated tags
|
|
467
|
+
- 'sentiment': sentiment label
|
|
468
|
+
- 'status': publication status
|
|
469
|
+
|
|
470
|
+
Notes:
|
|
471
|
+
- Articles marked as sponsored are automatically excluded.
|
|
472
|
+
"""
|
|
473
|
+
maximum = 100
|
|
474
|
+
if limit > maximum:
|
|
475
|
+
raise ValueError(f"Number of total news articles allowed is {maximum}")
|
|
476
|
+
|
|
477
|
+
response = requests.get(
|
|
478
|
+
"https://data-api.coindesk.com/news/v1/article/list",
|
|
479
|
+
params={"lang": lang, "limit": limit},
|
|
480
|
+
headers={"Content-type": "application/json; charset=UTF-8"},
|
|
481
|
+
)
|
|
482
|
+
json_response = response.json()
|
|
483
|
+
articles = json_response["Data"]
|
|
484
|
+
if len(articles) == 0:
|
|
485
|
+
return []
|
|
486
|
+
to_keep = [
|
|
487
|
+
"PUBLISHED_ON",
|
|
488
|
+
"TITLE",
|
|
489
|
+
"SUBTITLE",
|
|
490
|
+
"URL",
|
|
491
|
+
"BODY",
|
|
492
|
+
"KEYWORDS",
|
|
493
|
+
"SENTIMENT",
|
|
494
|
+
"STATUS",
|
|
495
|
+
]
|
|
496
|
+
filtered_articles = []
|
|
497
|
+
for article in articles:
|
|
498
|
+
filtered_articles.append(
|
|
499
|
+
{
|
|
500
|
+
k.lower(): article[k]
|
|
501
|
+
if k in article and k != "PUBLISHED_ON"
|
|
502
|
+
else datetime.fromtimestamp(article[k])
|
|
503
|
+
for k in to_keep
|
|
504
|
+
if article[k] is not None and "sponsored" not in str(article[k])
|
|
505
|
+
}
|
|
506
|
+
)
|
|
507
|
+
if query == "" or len(filtered_articles) == 0:
|
|
508
|
+
return filtered_articles
|
|
509
|
+
to_return = []
|
|
510
|
+
query = _get_search_query(query)
|
|
511
|
+
for article in filtered_articles:
|
|
512
|
+
if not all(k in article for k in ("title", "body", "keywords")):
|
|
513
|
+
continue
|
|
514
|
+
text = article["title"] + " " + article["body"] + " " + article["keywords"]
|
|
515
|
+
if list_of_str and _find_news(query, text=text):
|
|
516
|
+
to_return.append(text)
|
|
517
|
+
if not list_of_str and _find_news(query, text=text):
|
|
518
|
+
to_return.append(article)
|
|
519
|
+
return to_return
|
|
520
|
+
|
|
425
521
|
|
|
426
522
|
class FmpData(Toolkit):
|
|
427
523
|
"""
|
bbstrader/metatrader/trade.py
CHANGED
|
@@ -531,6 +531,7 @@ class Trade(RiskManagement):
|
|
|
531
531
|
mm (bool): Weither to put stop loss and tp or not
|
|
532
532
|
trail (bool): Weither to trail the stop loss or not
|
|
533
533
|
comment (str): The comment for the opening position
|
|
534
|
+
volume (float): The volume (lot) to trade
|
|
534
535
|
sl (float): The stop loss price
|
|
535
536
|
tp (float): The take profit price
|
|
536
537
|
"""
|
|
@@ -621,7 +622,6 @@ class Trade(RiskManagement):
|
|
|
621
622
|
mm (bool): Weither to put stop loss and tp or not
|
|
622
623
|
trail (bool): Weither to trail the stop loss or not
|
|
623
624
|
comment (str): The comment for the closing position
|
|
624
|
-
symbol (str): The symbol to trade
|
|
625
625
|
volume (float): The volume (lot) to trade
|
|
626
626
|
sl (float): The stop loss price
|
|
627
627
|
tp (float): The take profit price
|
bbstrader/models/nlp.py
CHANGED
|
@@ -506,6 +506,7 @@ class SentimentAnalyzer(object):
|
|
|
506
506
|
reddit_posts = news.get_reddit_posts(
|
|
507
507
|
ticker, n_posts=top_news, **{k: kwargs.get(k) for k in rd_params}
|
|
508
508
|
)
|
|
509
|
+
coindesk_news = news.get_coindesk_news(query=ticker, list_of_str=True)
|
|
509
510
|
fmp_source_news = []
|
|
510
511
|
fmp_news = news.get_fmp_news(kwargs.get("fmp_api"))
|
|
511
512
|
for source in ["articles"]: # , "releases", asset_type]:
|
|
@@ -518,7 +519,7 @@ class SentimentAnalyzer(object):
|
|
|
518
519
|
source_news = []
|
|
519
520
|
if any([len(s) > 0 for s in [yahoo_news, google_news]]):
|
|
520
521
|
sources += 1
|
|
521
|
-
for source in [reddit_posts, fmp_source_news]:
|
|
522
|
+
for source in [reddit_posts, fmp_source_news, coindesk_news]:
|
|
522
523
|
if len(source) > 0:
|
|
523
524
|
sources += 1
|
|
524
525
|
# Compute sentiment
|
|
@@ -531,11 +532,17 @@ class SentimentAnalyzer(object):
|
|
|
531
532
|
fmp_sentiment = self.analyze_sentiment(
|
|
532
533
|
fmp_source_news, lexicon=lexicon, textblob=True
|
|
533
534
|
)
|
|
535
|
+
coindesk_sentiment = self.analyze_sentiment(
|
|
536
|
+
coindesk_news, lexicon=lexicon, textblob=True
|
|
537
|
+
)
|
|
534
538
|
|
|
535
539
|
# Weighted average sentiment score
|
|
536
540
|
if sources != 0:
|
|
537
541
|
overall_sentiment = (
|
|
538
|
-
news_sentiment
|
|
542
|
+
news_sentiment
|
|
543
|
+
+ reddit_sentiment
|
|
544
|
+
+ fmp_sentiment
|
|
545
|
+
+ coindesk_sentiment
|
|
539
546
|
) / sources
|
|
540
547
|
else:
|
|
541
548
|
overall_sentiment = 0.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bbstrader
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.991
|
|
4
4
|
Summary: Simplified Investment & Trading Toolkit
|
|
5
5
|
Home-page: https://github.com/bbalouki/bbstrader
|
|
6
6
|
Download-URL: https://pypi.org/project/bbstrader/
|
|
@@ -81,8 +81,6 @@ Dynamic: requires-dist
|
|
|
81
81
|
Dynamic: summary
|
|
82
82
|
|
|
83
83
|
# Simplified Investment & Trading Toolkit
|
|
84
|
-

|
|
85
|
-
|
|
86
84
|
[](https://bbstrader.readthedocs.io/en/latest/?badge=latest)
|
|
87
85
|
[](https://pypi.org/project/bbstrader/)
|
|
88
86
|
[](https://pypi.python.org/pypi/bbstrader)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
bbstrader/__ini__.py,sha256=v6zyJHj5FMRL-_P7AwnTGbCF-riMqhqlTvDgfulj7go,621
|
|
2
|
+
bbstrader/__init__.py,sha256=5q_NaxJHcGYUVhC8cMWO3ZDJhjta7MrphQTYqganepY,581
|
|
2
3
|
bbstrader/__main__.py,sha256=sDdjoiaHSPrVqdjU_zOLajX3rD_3Ha6dHwIivYc_vp4,1525
|
|
3
4
|
bbstrader/compat.py,sha256=djbHMvTvy0HYm1zyZ6Ttp_LMwP2PqTSVw1r7pqbz7So,487
|
|
4
5
|
bbstrader/config.py,sha256=c2nCUw-bYWf5kkyFls5Nqld8HdMczexSilTni7rYUBw,3973
|
|
@@ -6,14 +7,14 @@ bbstrader/tseries.py,sha256=H4D_A966HdN8YjBfuCcF8QBQdhjOrTcidR98wP2KN_I,68339
|
|
|
6
7
|
bbstrader/btengine/__init__.py,sha256=y1btjaEfhWsH8vuE7mBRpP9Tu-Azt9REhuVYsPCAfBU,2955
|
|
7
8
|
bbstrader/btengine/backtest.py,sha256=UiOmtqYSh72KZz0DCXz8iKrqTCOkx9Er3XjqK6H9Do8,14765
|
|
8
9
|
bbstrader/btengine/data.py,sha256=Tuc6M8itbGpPjsfRpZBB8v0FJpPt7-hUkP6I5meP0Sg,26927
|
|
9
|
-
bbstrader/btengine/event.py,sha256=
|
|
10
|
+
bbstrader/btengine/event.py,sha256=Ydl1avAXp9WAWOBXDAckcb9g1UkcnCO0rRzcJZwIq20,8714
|
|
10
11
|
bbstrader/btengine/execution.py,sha256=tN7QIx0PHiQmJcn3MdSQiwwAYCDxFDn3C4i5tlM5xoY,10605
|
|
11
12
|
bbstrader/btengine/performance.py,sha256=1ecWrTzHBQbk4ORvbTEKxwCzlL1brcXOEUwgbnjAwx4,12470
|
|
12
13
|
bbstrader/btengine/portfolio.py,sha256=z98M65HQeCyma8gMZkAxspxBA9jtIhzxMyJUHPPj34c,16128
|
|
13
14
|
bbstrader/btengine/scripts.py,sha256=8o66dq4Ex4DsH4s8xvJqUOFjLzZJSnbBvvNBzohtzoE,4837
|
|
14
15
|
bbstrader/btengine/strategy.py,sha256=FrYoB8ogHODTfRDZf2gW-CGdTxdVoIYwxko1cYgwcgg,31631
|
|
15
16
|
bbstrader/core/__init__.py,sha256=GIFzFSStPfE0XM2j7mDeZZQeMTh_AwPsDOQXwMVJLgw,97
|
|
16
|
-
bbstrader/core/data.py,sha256=
|
|
17
|
+
bbstrader/core/data.py,sha256=hStrx-QTYFjpJdZOJVtV2xmIyywj6T9_Rn3hhNYtFwU,22581
|
|
17
18
|
bbstrader/core/utils.py,sha256=WjuabzBjhY65ku2KL-f7CMalE2x-wrX-6mCA_qhhFPE,2728
|
|
18
19
|
bbstrader/ibkr/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
19
20
|
bbstrader/ibkr/utils.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -24,12 +25,12 @@ bbstrader/metatrader/copier.py,sha256=pCZkRfkUWxufnmiO0cc1Kz6UF59HTUUGs-c60LYNUb
|
|
|
24
25
|
bbstrader/metatrader/rates.py,sha256=0bKyjGnafZ19DwC0-IxXUBJzOdAo-cNmhabwhKLxcos,20585
|
|
25
26
|
bbstrader/metatrader/risk.py,sha256=pwG4q1_uPGgPlokDGVNtd04O6p28yIbgT-evvHuo-Qc,27029
|
|
26
27
|
bbstrader/metatrader/scripts.py,sha256=Yjp7Un-wDTInptHS_rPFpXNKWbVM871VEkaHxsO2MPQ,2115
|
|
27
|
-
bbstrader/metatrader/trade.py,sha256=
|
|
28
|
+
bbstrader/metatrader/trade.py,sha256=uDlYCHqXk4AB0Nx8CHQfYUj4OODhm7W39es0r6Yuc8Q,79922
|
|
28
29
|
bbstrader/metatrader/utils.py,sha256=szORxKJW9OG-H6nof_ovOhToSx_n8EtVwe0mkLt3eFg,17424
|
|
29
30
|
bbstrader/models/__init__.py,sha256=s2mJrtKePXQaw_PvcrtPCD2mPCdVXP4Myzg0MlLVipo,547
|
|
30
31
|
bbstrader/models/factors.py,sha256=-ODeD2GK4nmxFQAIh5MF3SFM9ofppi2pW6Q728LzLv8,12701
|
|
31
32
|
bbstrader/models/ml.py,sha256=tCr7YyODl0CDoOUpYqJ1q12ls86Sc-_Fu3b2Y0Z7TJ8,47551
|
|
32
|
-
bbstrader/models/nlp.py,sha256=
|
|
33
|
+
bbstrader/models/nlp.py,sha256=eN4VnexOt1intfX1T-GkaReqBoWPjoqRSWjXIa67ib8,28385
|
|
33
34
|
bbstrader/models/optimization.py,sha256=vnks6uxFZdqXgxaZJNxq8z0IH45KZ8yaXo38JhIVKGc,6399
|
|
34
35
|
bbstrader/models/portfolio.py,sha256=r-47Zrn2r7iKCHm5YVtwkbBJXAZGM3QYy-rXCWY9-Bg,8079
|
|
35
36
|
bbstrader/models/risk.py,sha256=JQOXPshMOru6Eb0AMU6oKCNzg6mlGfL6_tN90lWcVBE,14878
|
|
@@ -38,9 +39,9 @@ bbstrader/trading/execution.py,sha256=ukOiv1O-a_SdKp35QlU_3_Wt_7CTgh4pLPN9s7qPEd
|
|
|
38
39
|
bbstrader/trading/scripts.py,sha256=Tf5q33WqqygjpIv43_8nA82VZ3GM0qgb4Ggo3fHJ_wg,5744
|
|
39
40
|
bbstrader/trading/strategies.py,sha256=rRNPZM1Z9twzO5UWd5qI3FgkZmOhF3Dd2h7XRn7EoDs,37011
|
|
40
41
|
bbstrader/trading/utils.py,sha256=57dKF9dcRu04oU2VRqydRrzW39dCW2wlDWhVt-sZdRw,1857
|
|
41
|
-
bbstrader-0.2.
|
|
42
|
-
bbstrader-0.2.
|
|
43
|
-
bbstrader-0.2.
|
|
44
|
-
bbstrader-0.2.
|
|
45
|
-
bbstrader-0.2.
|
|
46
|
-
bbstrader-0.2.
|
|
42
|
+
bbstrader-0.2.991.dist-info/licenses/LICENSE,sha256=ZwC_RqqGmOPBUiMDKqLyJZ5HBeHq53LpL7TMRzrJY8c,1094
|
|
43
|
+
bbstrader-0.2.991.dist-info/METADATA,sha256=p3lY0rHksdL6iOhw5Qunyyn_vWPQc8b5CQKrP3mErnM,11411
|
|
44
|
+
bbstrader-0.2.991.dist-info/WHEEL,sha256=GHB6lJx2juba1wDgXDNlMTyM13ckjBMKf-OnwgKOCtA,91
|
|
45
|
+
bbstrader-0.2.991.dist-info/entry_points.txt,sha256=0yDCbhbgHswOzJnY5wRSM_FjjyMHGvY7lJpSSVh0xtI,54
|
|
46
|
+
bbstrader-0.2.991.dist-info/top_level.txt,sha256=Wwj322jZmxGZ6gD_TdaPiPLjED5ReObm5omerwlmZIg,10
|
|
47
|
+
bbstrader-0.2.991.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|