finbrain-python 0.2.2__tar.gz → 0.2.3__tar.gz
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.
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/CHANGELOG.md +11 -3
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/PKG-INFO +5 -7
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/README.md +4 -6
- finbrain_python-0.2.3/src/finbrain/aio/endpoints/reddit_mentions.py +48 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/aio/endpoints/screener.py +14 -0
- finbrain_python-0.2.3/src/finbrain/endpoints/reddit_mentions.py +73 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/endpoints/screener.py +14 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/plotting.py +4 -4
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain_python.egg-info/PKG-INFO +5 -7
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/tests/test_integration.py +5 -8
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/tests/test_plotting.py +32 -37
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/tests/test_reddit_mentions.py +6 -12
- finbrain_python-0.2.2/src/finbrain/aio/endpoints/reddit_mentions.py +0 -79
- finbrain_python-0.2.2/src/finbrain/endpoints/reddit_mentions.py +0 -123
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/.gitattributes +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/.github/workflows/ci.yml +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/.github/workflows/release.yml +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/.gitignore +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/LICENSE +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/RELEASE.md +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/examples/async_example.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/examples/transactions_plotting_example.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/pyproject.toml +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/setup.cfg +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/__init__.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/aio/__init__.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/aio/client.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/aio/endpoints/__init__.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/aio/endpoints/_utils.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/aio/endpoints/analyst_ratings.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/aio/endpoints/app_ratings.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/aio/endpoints/available.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/aio/endpoints/corporate_lobbying.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/aio/endpoints/house_trades.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/aio/endpoints/insider_transactions.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/aio/endpoints/linkedin_data.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/aio/endpoints/news.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/aio/endpoints/options.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/aio/endpoints/predictions.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/aio/endpoints/recent.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/aio/endpoints/senate_trades.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/aio/endpoints/sentiments.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/client.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/endpoints/__init__.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/endpoints/_utils.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/endpoints/analyst_ratings.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/endpoints/app_ratings.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/endpoints/available.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/endpoints/corporate_lobbying.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/endpoints/house_trades.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/endpoints/insider_transactions.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/endpoints/linkedin_data.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/endpoints/news.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/endpoints/options.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/endpoints/predictions.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/endpoints/recent.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/endpoints/senate_trades.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/endpoints/sentiments.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/exceptions.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/py.typed +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain_python.egg-info/SOURCES.txt +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain_python.egg-info/dependency_links.txt +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain_python.egg-info/requires.txt +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain_python.egg-info/top_level.txt +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/tests/__init__.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/tests/conftest.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/tests/test_analyst_ratings.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/tests/test_app_ratings.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/tests/test_async_client.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/tests/test_available.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/tests/test_corporate_lobbying.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/tests/test_envelope.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/tests/test_house_trades.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/tests/test_insider_transactions.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/tests/test_linkedin_data.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/tests/test_news.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/tests/test_options.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/tests/test_predictions.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/tests/test_recent.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/tests/test_screener.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/tests/test_senate_trades.py +0 -0
- {finbrain_python-0.2.2 → finbrain_python-0.2.3}/tests/test_sentiments.py +0 -0
|
@@ -5,15 +5,23 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.2.3] - 2026-03-17
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- **Reddit Mentions Screener**: Moved from `fb.reddit_mentions.screener()` to `fb.screener.reddit_mentions()` for consistency with other screener endpoints
|
|
13
|
+
- **Plotting rename**: `fb.plot.reddit_mentions_screener()` renamed to `fb.plot.reddit_mentions_top()` to better reflect the chart's purpose (top N most mentioned tickers)
|
|
14
|
+
|
|
8
15
|
## [0.2.2] - 2026-03-17
|
|
9
16
|
|
|
10
17
|
### Added
|
|
11
18
|
|
|
12
19
|
- **Reddit Mentions Endpoint**: `fb.reddit_mentions.ticker("TSLA")` — fetch per-subreddit mention counts with full timestamps (sampled every 4 hours) (`/reddit-mentions/{SYMBOL}`)
|
|
13
|
-
- **Reddit Mentions Screener**: `fb.reddit_mentions
|
|
14
|
-
- **Reddit Mentions Plotting**: `fb.plot.reddit_mentions()` — stacked bars per subreddit overlaid on a price chart; `fb.plot.
|
|
20
|
+
- **Reddit Mentions Screener**: `fb.screener.reddit_mentions()` — cross-ticker Reddit mentions with aggregated totals and per-subreddit breakdowns (`/screener/reddit-mentions`)
|
|
21
|
+
- **Reddit Mentions Plotting**: `fb.plot.reddit_mentions()` — stacked bars per subreddit overlaid on a price chart; `fb.plot.reddit_mentions_top()` — horizontal stacked bar chart of top N most mentioned tickers
|
|
15
22
|
- **Async Reddit Mentions**: Full async support via `AsyncRedditMentionsAPI`
|
|
16
|
-
- **Reddit Mentions Tests**: Unit tests
|
|
23
|
+
- **Reddit Mentions Tests**: Unit tests, integration tests, and functional plotting tests
|
|
24
|
+
- **Plotting Test Coverage**: Added functional tests for all 11 plotting methods
|
|
17
25
|
|
|
18
26
|
## [0.2.1] - 2026-03-12
|
|
19
27
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: finbrain-python
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: Official Python client for the FinBrain API
|
|
5
5
|
Author-email: Ahmet Salim Bilgin <ahmet@finbrain.tech>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -105,9 +105,6 @@ fb.reddit_mentions.ticker("TSLA",
|
|
|
105
105
|
date_to="2026-03-17",
|
|
106
106
|
as_dataframe=True)
|
|
107
107
|
|
|
108
|
-
# screener — cross-ticker Reddit mentions
|
|
109
|
-
fb.reddit_mentions.screener(market="S&P 500", limit=100, as_dataframe=True)
|
|
110
|
-
|
|
111
108
|
# ---------- insider transactions ----------
|
|
112
109
|
fb.insider_transactions.ticker("AMZN", as_dataframe=True)
|
|
113
110
|
|
|
@@ -139,6 +136,7 @@ fb.news.ticker("AMZN", limit=20, as_dataframe=True)
|
|
|
139
136
|
fb.screener.sentiment(market="S&P 500", as_dataframe=True)
|
|
140
137
|
fb.screener.predictions_daily(limit=100, as_dataframe=True)
|
|
141
138
|
fb.screener.insider_trading(limit=50)
|
|
139
|
+
fb.screener.reddit_mentions(limit=100, as_dataframe=True)
|
|
142
140
|
|
|
143
141
|
# ---------- recent data ----------
|
|
144
142
|
fb.recent.news(limit=100, as_dataframe=True)
|
|
@@ -264,10 +262,10 @@ fb.plot.reddit_mentions("TSLA",
|
|
|
264
262
|
```python
|
|
265
263
|
# ---------- Reddit Mentions Screener Chart (no price data needed) ----------
|
|
266
264
|
# Stacked horizontal bar chart of top 15 most mentioned tickers
|
|
267
|
-
fb.plot.
|
|
265
|
+
fb.plot.reddit_mentions_top(market="S&P 500")
|
|
268
266
|
|
|
269
267
|
# Customize the number of tickers shown
|
|
270
|
-
fb.plot.
|
|
268
|
+
fb.plot.reddit_mentions_top(top_n=10, region="US")
|
|
271
269
|
```
|
|
272
270
|
|
|
273
271
|
**Price Data Requirements:**
|
|
@@ -314,13 +312,13 @@ fb = FinBrainClient() # reads from FINBRAIN_API_KEY env var
|
|
|
314
312
|
| Senate trades | `client.senate_trades.ticker()` | `/congress/senate/{SYMBOL}` |
|
|
315
313
|
| Corporate lobbying | `client.corporate_lobbying.ticker()` | `/lobbying/{SYMBOL}` |
|
|
316
314
|
| Reddit mentions | `client.reddit_mentions.ticker()` | `/reddit-mentions/{SYMBOL}` |
|
|
317
|
-
| | `client.reddit_mentions.screener()` | `/screener/reddit-mentions` |
|
|
318
315
|
| Insider transactions | `client.insider_transactions.ticker()` | `/insider-trading/{SYMBOL}` |
|
|
319
316
|
| LinkedIn | `client.linkedin_data.ticker()` | `/linkedin/{SYMBOL}` |
|
|
320
317
|
| Options – Put/Call | `client.options.put_call()` | `/put-call-ratio/{SYMBOL}` |
|
|
321
318
|
| Screener | `client.screener.sentiment()` | `/screener/sentiment` |
|
|
322
319
|
| | `client.screener.predictions_daily()` | `/screener/predictions/daily` |
|
|
323
320
|
| | `client.screener.insider_trading()` | `/screener/insider-trading` |
|
|
321
|
+
| | `client.screener.reddit_mentions()` | `/screener/reddit-mentions` |
|
|
324
322
|
| | ... and 8 more screener methods | |
|
|
325
323
|
| Recent | `client.recent.news()` | `/recent/news` |
|
|
326
324
|
| | `client.recent.analyst_ratings()` | `/recent/analyst-ratings` |
|
|
@@ -79,9 +79,6 @@ fb.reddit_mentions.ticker("TSLA",
|
|
|
79
79
|
date_to="2026-03-17",
|
|
80
80
|
as_dataframe=True)
|
|
81
81
|
|
|
82
|
-
# screener — cross-ticker Reddit mentions
|
|
83
|
-
fb.reddit_mentions.screener(market="S&P 500", limit=100, as_dataframe=True)
|
|
84
|
-
|
|
85
82
|
# ---------- insider transactions ----------
|
|
86
83
|
fb.insider_transactions.ticker("AMZN", as_dataframe=True)
|
|
87
84
|
|
|
@@ -113,6 +110,7 @@ fb.news.ticker("AMZN", limit=20, as_dataframe=True)
|
|
|
113
110
|
fb.screener.sentiment(market="S&P 500", as_dataframe=True)
|
|
114
111
|
fb.screener.predictions_daily(limit=100, as_dataframe=True)
|
|
115
112
|
fb.screener.insider_trading(limit=50)
|
|
113
|
+
fb.screener.reddit_mentions(limit=100, as_dataframe=True)
|
|
116
114
|
|
|
117
115
|
# ---------- recent data ----------
|
|
118
116
|
fb.recent.news(limit=100, as_dataframe=True)
|
|
@@ -238,10 +236,10 @@ fb.plot.reddit_mentions("TSLA",
|
|
|
238
236
|
```python
|
|
239
237
|
# ---------- Reddit Mentions Screener Chart (no price data needed) ----------
|
|
240
238
|
# Stacked horizontal bar chart of top 15 most mentioned tickers
|
|
241
|
-
fb.plot.
|
|
239
|
+
fb.plot.reddit_mentions_top(market="S&P 500")
|
|
242
240
|
|
|
243
241
|
# Customize the number of tickers shown
|
|
244
|
-
fb.plot.
|
|
242
|
+
fb.plot.reddit_mentions_top(top_n=10, region="US")
|
|
245
243
|
```
|
|
246
244
|
|
|
247
245
|
**Price Data Requirements:**
|
|
@@ -288,13 +286,13 @@ fb = FinBrainClient() # reads from FINBRAIN_API_KEY env var
|
|
|
288
286
|
| Senate trades | `client.senate_trades.ticker()` | `/congress/senate/{SYMBOL}` |
|
|
289
287
|
| Corporate lobbying | `client.corporate_lobbying.ticker()` | `/lobbying/{SYMBOL}` |
|
|
290
288
|
| Reddit mentions | `client.reddit_mentions.ticker()` | `/reddit-mentions/{SYMBOL}` |
|
|
291
|
-
| | `client.reddit_mentions.screener()` | `/screener/reddit-mentions` |
|
|
292
289
|
| Insider transactions | `client.insider_transactions.ticker()` | `/insider-trading/{SYMBOL}` |
|
|
293
290
|
| LinkedIn | `client.linkedin_data.ticker()` | `/linkedin/{SYMBOL}` |
|
|
294
291
|
| Options – Put/Call | `client.options.put_call()` | `/put-call-ratio/{SYMBOL}` |
|
|
295
292
|
| Screener | `client.screener.sentiment()` | `/screener/sentiment` |
|
|
296
293
|
| | `client.screener.predictions_daily()` | `/screener/predictions/daily` |
|
|
297
294
|
| | `client.screener.insider_trading()` | `/screener/insider-trading` |
|
|
295
|
+
| | `client.screener.reddit_mentions()` | `/screener/reddit-mentions` |
|
|
298
296
|
| | ... and 8 more screener methods | |
|
|
299
297
|
| Recent | `client.recent.news()` | `/recent/news` |
|
|
300
298
|
| | `client.recent.analyst_ratings()` | `/recent/analyst-ratings` |
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
import pandas as pd
|
|
3
|
+
import datetime as _dt
|
|
4
|
+
from typing import TYPE_CHECKING, Dict, Any, List
|
|
5
|
+
|
|
6
|
+
from ._utils import to_datestr
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from ..client import AsyncFinBrainClient
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class AsyncRedditMentionsAPI:
|
|
13
|
+
"""Async wrapper for /reddit-mentions and /screener/reddit-mentions endpoints."""
|
|
14
|
+
|
|
15
|
+
def __init__(self, client: "AsyncFinBrainClient") -> None:
|
|
16
|
+
self._c = client
|
|
17
|
+
|
|
18
|
+
async def ticker(
|
|
19
|
+
self,
|
|
20
|
+
symbol: str,
|
|
21
|
+
*,
|
|
22
|
+
date_from: _dt.date | str | None = None,
|
|
23
|
+
date_to: _dt.date | str | None = None,
|
|
24
|
+
limit: int | None = None,
|
|
25
|
+
as_dataframe: bool = False,
|
|
26
|
+
) -> Dict[str, Any] | pd.DataFrame:
|
|
27
|
+
"""Fetch Reddit mention counts for a symbol across subreddits (async)."""
|
|
28
|
+
params: Dict[str, str] = {}
|
|
29
|
+
if date_from:
|
|
30
|
+
params["startDate"] = to_datestr(date_from)
|
|
31
|
+
if date_to:
|
|
32
|
+
params["endDate"] = to_datestr(date_to)
|
|
33
|
+
if limit is not None:
|
|
34
|
+
params["limit"] = str(limit)
|
|
35
|
+
|
|
36
|
+
path = f"reddit-mentions/{symbol.upper()}"
|
|
37
|
+
|
|
38
|
+
data: Dict[str, Any] = await self._c._request("GET", path, params=params)
|
|
39
|
+
|
|
40
|
+
if as_dataframe:
|
|
41
|
+
rows: List[Dict[str, Any]] = data.get("data", [])
|
|
42
|
+
df = pd.DataFrame(rows)
|
|
43
|
+
if not df.empty and "date" in df.columns:
|
|
44
|
+
df["date"] = pd.to_datetime(df["date"])
|
|
45
|
+
df.set_index("date", inplace=True)
|
|
46
|
+
return df
|
|
47
|
+
|
|
48
|
+
return data
|
|
@@ -208,3 +208,17 @@ class AsyncScreenerAPI:
|
|
|
208
208
|
"""Screen monthly (12-month) predictions across tickers."""
|
|
209
209
|
params = self._build_params(limit=limit, market=market, region=region)
|
|
210
210
|
return await self._get("screener/predictions/monthly", params, as_dataframe)
|
|
211
|
+
|
|
212
|
+
# ── reddit mentions ────────────────────────────────────────
|
|
213
|
+
|
|
214
|
+
async def reddit_mentions(
|
|
215
|
+
self,
|
|
216
|
+
*,
|
|
217
|
+
limit: int | None = None,
|
|
218
|
+
market: str | None = None,
|
|
219
|
+
region: str | None = None,
|
|
220
|
+
as_dataframe: bool = False,
|
|
221
|
+
) -> List[Dict[str, Any]] | pd.DataFrame:
|
|
222
|
+
"""Screen Reddit mention counts across tickers (async)."""
|
|
223
|
+
params = self._build_params(limit=limit, market=market, region=region)
|
|
224
|
+
return await self._get("screener/reddit-mentions", params, as_dataframe)
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
import pandas as pd
|
|
3
|
+
import datetime as _dt
|
|
4
|
+
from typing import TYPE_CHECKING, Dict, Any, List
|
|
5
|
+
|
|
6
|
+
from ._utils import to_datestr
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING: # imported only by type-checkers
|
|
9
|
+
from ..client import FinBrainClient
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class RedditMentionsAPI:
|
|
13
|
+
"""
|
|
14
|
+
Endpoints
|
|
15
|
+
---------
|
|
16
|
+
``/reddit-mentions/<TICKER>`` - Reddit mention counts per subreddit.
|
|
17
|
+
``/screener/reddit-mentions`` - cross-ticker Reddit mentions screener.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
# ------------------------------------------------------------------ #
|
|
21
|
+
def __init__(self, client: "FinBrainClient") -> None:
|
|
22
|
+
self._c = client # reference to the parent client
|
|
23
|
+
|
|
24
|
+
# ------------------------------------------------------------------ #
|
|
25
|
+
def ticker(
|
|
26
|
+
self,
|
|
27
|
+
symbol: str,
|
|
28
|
+
*,
|
|
29
|
+
date_from: _dt.date | str | None = None,
|
|
30
|
+
date_to: _dt.date | str | None = None,
|
|
31
|
+
limit: int | None = None,
|
|
32
|
+
as_dataframe: bool = False,
|
|
33
|
+
) -> Dict[str, Any] | pd.DataFrame:
|
|
34
|
+
"""
|
|
35
|
+
Fetch Reddit mention counts for *symbol* across subreddits.
|
|
36
|
+
|
|
37
|
+
Parameters
|
|
38
|
+
----------
|
|
39
|
+
symbol :
|
|
40
|
+
Ticker symbol; auto-upper-cased.
|
|
41
|
+
date_from, date_to :
|
|
42
|
+
Optional ISO dates (``YYYY-MM-DD``) bounding the returned rows.
|
|
43
|
+
limit :
|
|
44
|
+
Maximum number of records to return (1-500).
|
|
45
|
+
as_dataframe :
|
|
46
|
+
If *True*, return a **pandas.DataFrame** indexed by ``date``;
|
|
47
|
+
otherwise return the raw JSON dict.
|
|
48
|
+
|
|
49
|
+
Returns
|
|
50
|
+
-------
|
|
51
|
+
dict | pandas.DataFrame
|
|
52
|
+
"""
|
|
53
|
+
params: Dict[str, str] = {}
|
|
54
|
+
if date_from:
|
|
55
|
+
params["startDate"] = to_datestr(date_from)
|
|
56
|
+
if date_to:
|
|
57
|
+
params["endDate"] = to_datestr(date_to)
|
|
58
|
+
if limit is not None:
|
|
59
|
+
params["limit"] = str(limit)
|
|
60
|
+
|
|
61
|
+
path = f"reddit-mentions/{symbol.upper()}"
|
|
62
|
+
|
|
63
|
+
data: Dict[str, Any] = self._c._request("GET", path, params=params)
|
|
64
|
+
|
|
65
|
+
if as_dataframe:
|
|
66
|
+
rows: List[Dict[str, Any]] = data.get("data", [])
|
|
67
|
+
df = pd.DataFrame(rows)
|
|
68
|
+
if not df.empty and "date" in df.columns:
|
|
69
|
+
df["date"] = pd.to_datetime(df["date"])
|
|
70
|
+
df.set_index("date", inplace=True)
|
|
71
|
+
return df
|
|
72
|
+
|
|
73
|
+
return data
|
|
@@ -213,3 +213,17 @@ class ScreenerAPI:
|
|
|
213
213
|
"""Screen monthly (12-month) predictions across tickers."""
|
|
214
214
|
params = self._build_params(limit=limit, market=market, region=region)
|
|
215
215
|
return self._get("screener/predictions/monthly", params, as_dataframe)
|
|
216
|
+
|
|
217
|
+
# ── reddit mentions ────────────────────────────────────────
|
|
218
|
+
|
|
219
|
+
def reddit_mentions(
|
|
220
|
+
self,
|
|
221
|
+
*,
|
|
222
|
+
limit: int | None = None,
|
|
223
|
+
market: str | None = None,
|
|
224
|
+
region: str | None = None,
|
|
225
|
+
as_dataframe: bool = False,
|
|
226
|
+
) -> List[Dict[str, Any]] | pd.DataFrame:
|
|
227
|
+
"""Screen Reddit mention counts across tickers."""
|
|
228
|
+
params = self._build_params(limit=limit, market=market, region=region)
|
|
229
|
+
return self._get("screener/reddit-mentions", params, as_dataframe)
|
|
@@ -1057,7 +1057,7 @@ class _PlotNamespace:
|
|
|
1057
1057
|
# --------------------------------------------------------------------- #
|
|
1058
1058
|
# Reddit Mentions Screener → stacked horizontal bars (top N tickers) #
|
|
1059
1059
|
# --------------------------------------------------------------------- #
|
|
1060
|
-
def
|
|
1060
|
+
def reddit_mentions_top(
|
|
1061
1061
|
self,
|
|
1062
1062
|
*,
|
|
1063
1063
|
top_n: int = 15,
|
|
@@ -1091,20 +1091,20 @@ class _PlotNamespace:
|
|
|
1091
1091
|
Plotly template name.
|
|
1092
1092
|
**kwargs
|
|
1093
1093
|
Additional arguments passed to
|
|
1094
|
-
:meth:`FinBrainClient.reddit_mentions
|
|
1094
|
+
:meth:`FinBrainClient.screener.reddit_mentions`.
|
|
1095
1095
|
|
|
1096
1096
|
Returns
|
|
1097
1097
|
-------
|
|
1098
1098
|
plotly.graph_objects.Figure or str or None
|
|
1099
1099
|
"""
|
|
1100
|
-
data = self._fb.reddit_mentions
|
|
1100
|
+
data = self._fb.screener.reddit_mentions(
|
|
1101
1101
|
market=market,
|
|
1102
1102
|
region=region,
|
|
1103
1103
|
limit=limit,
|
|
1104
1104
|
**kwargs,
|
|
1105
1105
|
)
|
|
1106
1106
|
|
|
1107
|
-
rows = data.get("data", [])
|
|
1107
|
+
rows = data if isinstance(data, list) else data.get("data", [])
|
|
1108
1108
|
if not rows:
|
|
1109
1109
|
raise ValueError("No screener data returned")
|
|
1110
1110
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: finbrain-python
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: Official Python client for the FinBrain API
|
|
5
5
|
Author-email: Ahmet Salim Bilgin <ahmet@finbrain.tech>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -105,9 +105,6 @@ fb.reddit_mentions.ticker("TSLA",
|
|
|
105
105
|
date_to="2026-03-17",
|
|
106
106
|
as_dataframe=True)
|
|
107
107
|
|
|
108
|
-
# screener — cross-ticker Reddit mentions
|
|
109
|
-
fb.reddit_mentions.screener(market="S&P 500", limit=100, as_dataframe=True)
|
|
110
|
-
|
|
111
108
|
# ---------- insider transactions ----------
|
|
112
109
|
fb.insider_transactions.ticker("AMZN", as_dataframe=True)
|
|
113
110
|
|
|
@@ -139,6 +136,7 @@ fb.news.ticker("AMZN", limit=20, as_dataframe=True)
|
|
|
139
136
|
fb.screener.sentiment(market="S&P 500", as_dataframe=True)
|
|
140
137
|
fb.screener.predictions_daily(limit=100, as_dataframe=True)
|
|
141
138
|
fb.screener.insider_trading(limit=50)
|
|
139
|
+
fb.screener.reddit_mentions(limit=100, as_dataframe=True)
|
|
142
140
|
|
|
143
141
|
# ---------- recent data ----------
|
|
144
142
|
fb.recent.news(limit=100, as_dataframe=True)
|
|
@@ -264,10 +262,10 @@ fb.plot.reddit_mentions("TSLA",
|
|
|
264
262
|
```python
|
|
265
263
|
# ---------- Reddit Mentions Screener Chart (no price data needed) ----------
|
|
266
264
|
# Stacked horizontal bar chart of top 15 most mentioned tickers
|
|
267
|
-
fb.plot.
|
|
265
|
+
fb.plot.reddit_mentions_top(market="S&P 500")
|
|
268
266
|
|
|
269
267
|
# Customize the number of tickers shown
|
|
270
|
-
fb.plot.
|
|
268
|
+
fb.plot.reddit_mentions_top(top_n=10, region="US")
|
|
271
269
|
```
|
|
272
270
|
|
|
273
271
|
**Price Data Requirements:**
|
|
@@ -314,13 +312,13 @@ fb = FinBrainClient() # reads from FINBRAIN_API_KEY env var
|
|
|
314
312
|
| Senate trades | `client.senate_trades.ticker()` | `/congress/senate/{SYMBOL}` |
|
|
315
313
|
| Corporate lobbying | `client.corporate_lobbying.ticker()` | `/lobbying/{SYMBOL}` |
|
|
316
314
|
| Reddit mentions | `client.reddit_mentions.ticker()` | `/reddit-mentions/{SYMBOL}` |
|
|
317
|
-
| | `client.reddit_mentions.screener()` | `/screener/reddit-mentions` |
|
|
318
315
|
| Insider transactions | `client.insider_transactions.ticker()` | `/insider-trading/{SYMBOL}` |
|
|
319
316
|
| LinkedIn | `client.linkedin_data.ticker()` | `/linkedin/{SYMBOL}` |
|
|
320
317
|
| Options – Put/Call | `client.options.put_call()` | `/put-call-ratio/{SYMBOL}` |
|
|
321
318
|
| Screener | `client.screener.sentiment()` | `/screener/sentiment` |
|
|
322
319
|
| | `client.screener.predictions_daily()` | `/screener/predictions/daily` |
|
|
323
320
|
| | `client.screener.insider_trading()` | `/screener/insider-trading` |
|
|
321
|
+
| | `client.screener.reddit_mentions()` | `/screener/reddit-mentions` |
|
|
324
322
|
| | ... and 8 more screener methods | |
|
|
325
323
|
| Recent | `client.recent.news()` | `/recent/news` |
|
|
326
324
|
| | `client.recent.analyst_ratings()` | `/recent/analyst-ratings` |
|
|
@@ -319,19 +319,16 @@ class TestRedditMentions:
|
|
|
319
319
|
assert "_all" in df["subreddit"].values
|
|
320
320
|
|
|
321
321
|
def test_screener_raw(self, fb):
|
|
322
|
-
data = fb.reddit_mentions
|
|
323
|
-
assert isinstance(data,
|
|
324
|
-
assert
|
|
325
|
-
|
|
326
|
-
assert isinstance(rows, list)
|
|
327
|
-
assert len(rows) > 0
|
|
328
|
-
row = rows[0]
|
|
322
|
+
data = fb.screener.reddit_mentions()
|
|
323
|
+
assert isinstance(data, list)
|
|
324
|
+
assert len(data) > 0
|
|
325
|
+
row = data[0]
|
|
329
326
|
assert "symbol" in row
|
|
330
327
|
assert "totalMentions" in row
|
|
331
328
|
assert "subreddits" in row
|
|
332
329
|
|
|
333
330
|
def test_screener_dataframe(self, fb):
|
|
334
|
-
df = fb.reddit_mentions
|
|
331
|
+
df = fb.screener.reddit_mentions(as_dataframe=True)
|
|
335
332
|
assert isinstance(df, pd.DataFrame)
|
|
336
333
|
assert len(df) > 0
|
|
337
334
|
|
|
@@ -152,19 +152,17 @@ class MockRedditMentionsClient:
|
|
|
152
152
|
}).set_index("date")
|
|
153
153
|
return df
|
|
154
154
|
|
|
155
|
+
class screener:
|
|
155
156
|
@staticmethod
|
|
156
|
-
def
|
|
157
|
-
return
|
|
158
|
-
"
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
],
|
|
166
|
-
"summary": {},
|
|
167
|
-
}
|
|
157
|
+
def reddit_mentions(*args, **kwargs):
|
|
158
|
+
return [
|
|
159
|
+
{"symbol": "TSLA", "name": "Tesla", "date": "2024-01-01T08:00:00Z",
|
|
160
|
+
"totalMentions": 120, "subreddits": {"wallstreetbets": 85, "stocks": 12}},
|
|
161
|
+
{"symbol": "AAPL", "name": "Apple", "date": "2024-01-01T08:00:00Z",
|
|
162
|
+
"totalMentions": 45, "subreddits": {"wallstreetbets": 30, "stocks": 8}},
|
|
163
|
+
{"symbol": "NVDA", "name": "NVIDIA", "date": "2024-01-01T08:00:00Z",
|
|
164
|
+
"totalMentions": 80, "subreddits": {"wallstreetbets": 60, "stocks": 5}},
|
|
165
|
+
]
|
|
168
166
|
|
|
169
167
|
|
|
170
168
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -480,11 +478,11 @@ def test_reddit_mentions_as_json():
|
|
|
480
478
|
assert isinstance(result, str)
|
|
481
479
|
|
|
482
480
|
|
|
483
|
-
# ──
|
|
481
|
+
# ── reddit_mentions_top ──────────────────────────────────────────────
|
|
484
482
|
|
|
485
|
-
def
|
|
483
|
+
def test_reddit_mentions_top_plot():
|
|
486
484
|
plot = _PlotNamespace(MockRedditMentionsClient())
|
|
487
|
-
fig = plot.
|
|
485
|
+
fig = plot.reddit_mentions_top(show=False)
|
|
488
486
|
|
|
489
487
|
assert isinstance(fig, go.Figure)
|
|
490
488
|
# 2 subreddits → 2 bar traces (stocks, wallstreetbets)
|
|
@@ -499,9 +497,9 @@ def test_reddit_mentions_screener_plot():
|
|
|
499
497
|
assert symbols[0] == "AAPL" # lowest mentions
|
|
500
498
|
|
|
501
499
|
|
|
502
|
-
def
|
|
500
|
+
def test_reddit_mentions_top_top_n():
|
|
503
501
|
plot = _PlotNamespace(MockRedditMentionsClient())
|
|
504
|
-
fig = plot.
|
|
502
|
+
fig = plot.reddit_mentions_top(top_n=2, show=False)
|
|
505
503
|
|
|
506
504
|
assert isinstance(fig, go.Figure)
|
|
507
505
|
# Only top 2 tickers
|
|
@@ -512,43 +510,40 @@ def test_reddit_mentions_screener_top_n():
|
|
|
512
510
|
assert "AAPL" not in symbols
|
|
513
511
|
|
|
514
512
|
|
|
515
|
-
def
|
|
513
|
+
def test_reddit_mentions_top_empty_data():
|
|
516
514
|
class EmptyScreenerClient:
|
|
517
|
-
class
|
|
515
|
+
class screener:
|
|
518
516
|
@staticmethod
|
|
519
|
-
def
|
|
520
|
-
return
|
|
517
|
+
def reddit_mentions(*args, **kwargs):
|
|
518
|
+
return []
|
|
521
519
|
|
|
522
520
|
plot = _PlotNamespace(EmptyScreenerClient())
|
|
523
521
|
with pytest.raises(ValueError, match="No screener data returned"):
|
|
524
|
-
plot.
|
|
522
|
+
plot.reddit_mentions_top(show=False)
|
|
525
523
|
|
|
526
524
|
|
|
527
|
-
def
|
|
525
|
+
def test_reddit_mentions_top_as_json():
|
|
528
526
|
plot = _PlotNamespace(MockRedditMentionsClient())
|
|
529
|
-
result = plot.
|
|
527
|
+
result = plot.reddit_mentions_top(show=False, as_json=True)
|
|
530
528
|
assert isinstance(result, str)
|
|
531
529
|
|
|
532
530
|
|
|
533
|
-
def
|
|
531
|
+
def test_reddit_mentions_top_latest_snapshot():
|
|
534
532
|
"""Verify that only the latest snapshot per ticker is used."""
|
|
535
533
|
|
|
536
534
|
class MultiSnapshotClient:
|
|
537
|
-
class
|
|
535
|
+
class screener:
|
|
538
536
|
@staticmethod
|
|
539
|
-
def
|
|
540
|
-
return
|
|
541
|
-
"
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
],
|
|
547
|
-
"summary": {},
|
|
548
|
-
}
|
|
537
|
+
def reddit_mentions(*args, **kwargs):
|
|
538
|
+
return [
|
|
539
|
+
{"symbol": "TSLA", "date": "2024-01-01T04:00:00Z",
|
|
540
|
+
"totalMentions": 50, "subreddits": {"wsb": 30}},
|
|
541
|
+
{"symbol": "TSLA", "date": "2024-01-01T08:00:00Z",
|
|
542
|
+
"totalMentions": 120, "subreddits": {"wsb": 85}},
|
|
543
|
+
]
|
|
549
544
|
|
|
550
545
|
plot = _PlotNamespace(MultiSnapshotClient())
|
|
551
|
-
fig = plot.
|
|
546
|
+
fig = plot.reddit_mentions_top(show=False)
|
|
552
547
|
|
|
553
548
|
# Should use the 08:00 snapshot (120 mentions), not 04:00 (50)
|
|
554
549
|
assert fig.data[0].x == (85,) # wsb=85 from the latest snapshot
|
|
@@ -117,11 +117,10 @@ def test_reddit_mentions_screener_raw_ok(client, _activate_responses):
|
|
|
117
117
|
|
|
118
118
|
stub_json(_activate_responses, "GET", path, payload)
|
|
119
119
|
|
|
120
|
-
data = client.reddit_mentions
|
|
121
|
-
assert isinstance(data
|
|
122
|
-
assert data[
|
|
123
|
-
assert data[
|
|
124
|
-
assert data["summary"]["totalTickers"] == 1
|
|
120
|
+
data = client.screener.reddit_mentions()
|
|
121
|
+
assert isinstance(data, list)
|
|
122
|
+
assert data[0]["symbol"] == "TSLA"
|
|
123
|
+
assert data[0]["totalMentions"] == 120
|
|
125
124
|
|
|
126
125
|
|
|
127
126
|
# ─────────── screener DataFrame ─────────────────────────────────────────
|
|
@@ -155,14 +154,9 @@ def test_reddit_mentions_screener_dataframe_ok(client, _activate_responses):
|
|
|
155
154
|
|
|
156
155
|
stub_json(_activate_responses, "GET", path, payload)
|
|
157
156
|
|
|
158
|
-
df = client.reddit_mentions
|
|
157
|
+
df = client.screener.reddit_mentions(as_dataframe=True)
|
|
159
158
|
|
|
160
159
|
assert isinstance(df, pd.DataFrame)
|
|
161
160
|
assert len(df) == 2
|
|
162
|
-
assert df.index.name == "
|
|
163
|
-
assert pd.api.types.is_datetime64_any_dtype(df.index)
|
|
164
|
-
# Verify timestamps preserve time component (UTC-aware from ISO Z suffix)
|
|
165
|
-
assert pd.Timestamp("2026-03-17 08:00:00", tz="UTC") in df.index
|
|
166
|
-
assert pd.Timestamp("2026-03-17 12:00:00", tz="UTC") in df.index
|
|
161
|
+
assert df.index.name == "symbol"
|
|
167
162
|
assert "totalMentions" in df.columns
|
|
168
|
-
assert "symbol" in df.columns
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
import pandas as pd
|
|
3
|
-
import datetime as _dt
|
|
4
|
-
from typing import TYPE_CHECKING, Dict, Any, List
|
|
5
|
-
|
|
6
|
-
from ._utils import to_datestr
|
|
7
|
-
|
|
8
|
-
if TYPE_CHECKING:
|
|
9
|
-
from ..client import AsyncFinBrainClient
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class AsyncRedditMentionsAPI:
|
|
13
|
-
"""Async wrapper for /reddit-mentions and /screener/reddit-mentions endpoints."""
|
|
14
|
-
|
|
15
|
-
def __init__(self, client: "AsyncFinBrainClient") -> None:
|
|
16
|
-
self._c = client
|
|
17
|
-
|
|
18
|
-
async def ticker(
|
|
19
|
-
self,
|
|
20
|
-
symbol: str,
|
|
21
|
-
*,
|
|
22
|
-
date_from: _dt.date | str | None = None,
|
|
23
|
-
date_to: _dt.date | str | None = None,
|
|
24
|
-
limit: int | None = None,
|
|
25
|
-
as_dataframe: bool = False,
|
|
26
|
-
) -> Dict[str, Any] | pd.DataFrame:
|
|
27
|
-
"""Fetch Reddit mention counts for a symbol across subreddits (async)."""
|
|
28
|
-
params: Dict[str, str] = {}
|
|
29
|
-
if date_from:
|
|
30
|
-
params["startDate"] = to_datestr(date_from)
|
|
31
|
-
if date_to:
|
|
32
|
-
params["endDate"] = to_datestr(date_to)
|
|
33
|
-
if limit is not None:
|
|
34
|
-
params["limit"] = str(limit)
|
|
35
|
-
|
|
36
|
-
path = f"reddit-mentions/{symbol.upper()}"
|
|
37
|
-
|
|
38
|
-
data: Dict[str, Any] = await self._c._request("GET", path, params=params)
|
|
39
|
-
|
|
40
|
-
if as_dataframe:
|
|
41
|
-
rows: List[Dict[str, Any]] = data.get("data", [])
|
|
42
|
-
df = pd.DataFrame(rows)
|
|
43
|
-
if not df.empty and "date" in df.columns:
|
|
44
|
-
df["date"] = pd.to_datetime(df["date"])
|
|
45
|
-
df.set_index("date", inplace=True)
|
|
46
|
-
return df
|
|
47
|
-
|
|
48
|
-
return data
|
|
49
|
-
|
|
50
|
-
async def screener(
|
|
51
|
-
self,
|
|
52
|
-
*,
|
|
53
|
-
limit: int | None = None,
|
|
54
|
-
market: str | None = None,
|
|
55
|
-
region: str | None = None,
|
|
56
|
-
as_dataframe: bool = False,
|
|
57
|
-
) -> Dict[str, Any] | pd.DataFrame:
|
|
58
|
-
"""Get recent Reddit mention counts across all tickers (async)."""
|
|
59
|
-
params: Dict[str, str] = {}
|
|
60
|
-
if limit is not None:
|
|
61
|
-
params["limit"] = str(limit)
|
|
62
|
-
if market:
|
|
63
|
-
params["market"] = market
|
|
64
|
-
if region:
|
|
65
|
-
params["region"] = region
|
|
66
|
-
|
|
67
|
-
data: Dict[str, Any] = await self._c._request(
|
|
68
|
-
"GET", "screener/reddit-mentions", params=params
|
|
69
|
-
)
|
|
70
|
-
|
|
71
|
-
if as_dataframe:
|
|
72
|
-
rows: List[Dict[str, Any]] = data.get("data", [])
|
|
73
|
-
df = pd.DataFrame(rows)
|
|
74
|
-
if not df.empty and "date" in df.columns:
|
|
75
|
-
df["date"] = pd.to_datetime(df["date"])
|
|
76
|
-
df.set_index("date", inplace=True)
|
|
77
|
-
return df
|
|
78
|
-
|
|
79
|
-
return data
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
import pandas as pd
|
|
3
|
-
import datetime as _dt
|
|
4
|
-
from typing import TYPE_CHECKING, Dict, Any, List
|
|
5
|
-
|
|
6
|
-
from ._utils import to_datestr
|
|
7
|
-
|
|
8
|
-
if TYPE_CHECKING: # imported only by type-checkers
|
|
9
|
-
from ..client import FinBrainClient
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class RedditMentionsAPI:
|
|
13
|
-
"""
|
|
14
|
-
Endpoints
|
|
15
|
-
---------
|
|
16
|
-
``/reddit-mentions/<TICKER>`` - Reddit mention counts per subreddit.
|
|
17
|
-
``/screener/reddit-mentions`` - cross-ticker Reddit mentions screener.
|
|
18
|
-
"""
|
|
19
|
-
|
|
20
|
-
# ------------------------------------------------------------------ #
|
|
21
|
-
def __init__(self, client: "FinBrainClient") -> None:
|
|
22
|
-
self._c = client # reference to the parent client
|
|
23
|
-
|
|
24
|
-
# ------------------------------------------------------------------ #
|
|
25
|
-
def ticker(
|
|
26
|
-
self,
|
|
27
|
-
symbol: str,
|
|
28
|
-
*,
|
|
29
|
-
date_from: _dt.date | str | None = None,
|
|
30
|
-
date_to: _dt.date | str | None = None,
|
|
31
|
-
limit: int | None = None,
|
|
32
|
-
as_dataframe: bool = False,
|
|
33
|
-
) -> Dict[str, Any] | pd.DataFrame:
|
|
34
|
-
"""
|
|
35
|
-
Fetch Reddit mention counts for *symbol* across subreddits.
|
|
36
|
-
|
|
37
|
-
Parameters
|
|
38
|
-
----------
|
|
39
|
-
symbol :
|
|
40
|
-
Ticker symbol; auto-upper-cased.
|
|
41
|
-
date_from, date_to :
|
|
42
|
-
Optional ISO dates (``YYYY-MM-DD``) bounding the returned rows.
|
|
43
|
-
limit :
|
|
44
|
-
Maximum number of records to return (1-500).
|
|
45
|
-
as_dataframe :
|
|
46
|
-
If *True*, return a **pandas.DataFrame** indexed by ``date``;
|
|
47
|
-
otherwise return the raw JSON dict.
|
|
48
|
-
|
|
49
|
-
Returns
|
|
50
|
-
-------
|
|
51
|
-
dict | pandas.DataFrame
|
|
52
|
-
"""
|
|
53
|
-
params: Dict[str, str] = {}
|
|
54
|
-
if date_from:
|
|
55
|
-
params["startDate"] = to_datestr(date_from)
|
|
56
|
-
if date_to:
|
|
57
|
-
params["endDate"] = to_datestr(date_to)
|
|
58
|
-
if limit is not None:
|
|
59
|
-
params["limit"] = str(limit)
|
|
60
|
-
|
|
61
|
-
path = f"reddit-mentions/{symbol.upper()}"
|
|
62
|
-
|
|
63
|
-
data: Dict[str, Any] = self._c._request("GET", path, params=params)
|
|
64
|
-
|
|
65
|
-
if as_dataframe:
|
|
66
|
-
rows: List[Dict[str, Any]] = data.get("data", [])
|
|
67
|
-
df = pd.DataFrame(rows)
|
|
68
|
-
if not df.empty and "date" in df.columns:
|
|
69
|
-
df["date"] = pd.to_datetime(df["date"])
|
|
70
|
-
df.set_index("date", inplace=True)
|
|
71
|
-
return df
|
|
72
|
-
|
|
73
|
-
return data
|
|
74
|
-
|
|
75
|
-
# ------------------------------------------------------------------ #
|
|
76
|
-
def screener(
|
|
77
|
-
self,
|
|
78
|
-
*,
|
|
79
|
-
limit: int | None = None,
|
|
80
|
-
market: str | None = None,
|
|
81
|
-
region: str | None = None,
|
|
82
|
-
as_dataframe: bool = False,
|
|
83
|
-
) -> Dict[str, Any] | pd.DataFrame:
|
|
84
|
-
"""
|
|
85
|
-
Get recent Reddit mention counts across all tickers.
|
|
86
|
-
|
|
87
|
-
Parameters
|
|
88
|
-
----------
|
|
89
|
-
limit :
|
|
90
|
-
Maximum number of records to return (1-20000).
|
|
91
|
-
market :
|
|
92
|
-
Filter by market name (e.g. ``"S&P 500"``, ``"NASDAQ"``).
|
|
93
|
-
region :
|
|
94
|
-
Filter by region (e.g. ``"US"``, ``"Europe"``).
|
|
95
|
-
as_dataframe :
|
|
96
|
-
If *True*, return a **pandas.DataFrame** indexed by ``date``;
|
|
97
|
-
otherwise return the raw JSON dict.
|
|
98
|
-
|
|
99
|
-
Returns
|
|
100
|
-
-------
|
|
101
|
-
dict | pandas.DataFrame
|
|
102
|
-
"""
|
|
103
|
-
params: Dict[str, str] = {}
|
|
104
|
-
if limit is not None:
|
|
105
|
-
params["limit"] = str(limit)
|
|
106
|
-
if market:
|
|
107
|
-
params["market"] = market
|
|
108
|
-
if region:
|
|
109
|
-
params["region"] = region
|
|
110
|
-
|
|
111
|
-
data: Dict[str, Any] = self._c._request(
|
|
112
|
-
"GET", "screener/reddit-mentions", params=params
|
|
113
|
-
)
|
|
114
|
-
|
|
115
|
-
if as_dataframe:
|
|
116
|
-
rows: List[Dict[str, Any]] = data.get("data", [])
|
|
117
|
-
df = pd.DataFrame(rows)
|
|
118
|
-
if not df.empty and "date" in df.columns:
|
|
119
|
-
df["date"] = pd.to_datetime(df["date"])
|
|
120
|
-
df.set_index("date", inplace=True)
|
|
121
|
-
return df
|
|
122
|
-
|
|
123
|
-
return data
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/aio/endpoints/analyst_ratings.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/aio/endpoints/corporate_lobbying.py
RENAMED
|
File without changes
|
|
File without changes
|
{finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/aio/endpoints/insider_transactions.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/endpoints/corporate_lobbying.py
RENAMED
|
File without changes
|
|
File without changes
|
{finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain/endpoints/insider_transactions.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{finbrain_python-0.2.2 → finbrain_python-0.2.3}/src/finbrain_python.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|