bdshare 1.2.0__tar.gz → 1.2.2__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.
- {bdshare-1.2.0 → bdshare-1.2.2}/CHANGELOG.md +25 -0
- {bdshare-1.2.0/bdshare.egg-info → bdshare-1.2.2}/PKG-INFO +140 -25
- {bdshare-1.2.0 → bdshare-1.2.2}/README.md +109 -24
- {bdshare-1.2.0 → bdshare-1.2.2}/bdshare/__init__.py +10 -32
- {bdshare-1.2.0 → bdshare-1.2.2}/bdshare/_version.py +1 -1
- bdshare-1.2.2/bdshare/mcp_server.py +197 -0
- {bdshare-1.2.0 → bdshare-1.2.2}/bdshare/stock/market.py +151 -123
- {bdshare-1.2.0 → bdshare-1.2.2}/bdshare/stock/news.py +79 -73
- {bdshare-1.2.0 → bdshare-1.2.2}/bdshare/stock/trading.py +85 -94
- bdshare-1.2.2/bdshare/util/helper.py +356 -0
- bdshare-1.2.2/bdshare/util/sectigo_dv_r36.pem +36 -0
- {bdshare-1.2.0 → bdshare-1.2.2}/bdshare/util/vars.py +4 -3
- {bdshare-1.2.0 → bdshare-1.2.2/bdshare.egg-info}/PKG-INFO +140 -25
- {bdshare-1.2.0 → bdshare-1.2.2}/bdshare.egg-info/SOURCES.txt +4 -0
- bdshare-1.2.2/bdshare.egg-info/entry_points.txt +2 -0
- {bdshare-1.2.0 → bdshare-1.2.2}/bdshare.egg-info/requires.txt +7 -0
- {bdshare-1.2.0 → bdshare-1.2.2}/setup.cfg +13 -2
- bdshare-1.2.2/tests/test_market.py +172 -0
- bdshare-1.2.2/tests/test_polars.py +351 -0
- {bdshare-1.2.0 → bdshare-1.2.2}/tests/test_trading.py +1 -1
- bdshare-1.2.0/bdshare/util/helper.py +0 -236
- bdshare-1.2.0/tests/test_market.py +0 -214
- {bdshare-1.2.0 → bdshare-1.2.2}/LICENSE +0 -0
- {bdshare-1.2.0 → bdshare-1.2.2}/bdshare/stock/__init__.py +0 -0
- {bdshare-1.2.0 → bdshare-1.2.2}/bdshare/util/__init__.py +0 -0
- {bdshare-1.2.0 → bdshare-1.2.2}/bdshare/util/cache.py +0 -0
- {bdshare-1.2.0 → bdshare-1.2.2}/bdshare/util/cons.py +0 -0
- {bdshare-1.2.0 → bdshare-1.2.2}/bdshare/util/proxy.py +0 -0
- {bdshare-1.2.0 → bdshare-1.2.2}/bdshare/util/session.py +0 -0
- {bdshare-1.2.0 → bdshare-1.2.2}/bdshare/util/store.py +0 -0
- {bdshare-1.2.0 → bdshare-1.2.2}/bdshare/util/tickers.py +0 -0
- {bdshare-1.2.0 → bdshare-1.2.2}/bdshare/util/upass.py +0 -0
- {bdshare-1.2.0 → bdshare-1.2.2}/bdshare.egg-info/dependency_links.txt +0 -0
- {bdshare-1.2.0 → bdshare-1.2.2}/bdshare.egg-info/not-zip-safe +0 -0
- {bdshare-1.2.0 → bdshare-1.2.2}/bdshare.egg-info/top_level.txt +0 -0
- {bdshare-1.2.0 → bdshare-1.2.2}/pyproject.toml +0 -0
- {bdshare-1.2.0 → bdshare-1.2.2}/tests/__init__.py +0 -0
- {bdshare-1.2.0 → bdshare-1.2.2}/tests/test_news.py +0 -0
|
@@ -6,6 +6,31 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
|
6
6
|
Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
8
|
---
|
|
9
|
+
## [1.2.2] - 2026-07-22
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
- Optional `as_polars=True` parameter across all data-fetching functions to return `polars.DataFrame` instead of `pandas.DataFrame` (requires `pip install bdshare[polars]`)
|
|
13
|
+
- `get_market_status()` — current market status (Open, Closed, Holiday, etc.)
|
|
14
|
+
- `get_top_twenty_shares()` — top twenty shares by traded volume
|
|
15
|
+
- MCP ([Model Context Protocol](https://modelcontextprotocol.io/)) server (`bdshare/mcp_server.py`) exposing 15 tools so AI agents (Claude Desktop, Claude Code, etc.) can call live DSE data directly; install with `pip install bdshare[mcp]`, run with `bdshare-mcp`
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
- Renamed `get_top_gainers_losers()` → `get_top_ten_gainers_losers()`; returned columns changed from `symbol, ltp, change` to `symbol, close, high, low, ycp, change`
|
|
19
|
+
|
|
20
|
+
### Removed
|
|
21
|
+
- `get_sector_performance()` (module function and `BDShare.get_sector_performance()`) — no aliased replacement; use `get_top_twenty_shares()` instead
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
- Bundled the missing Sectigo DV R36 intermediate certificate so requests to dsebd.org verify correctly instead of relying on an incomplete chain
|
|
25
|
+
- Corrected `DSE_ALT_URL` fallback domain to `dse.com.bd`
|
|
26
|
+
- `get_corporate_announcements()` and `get_price_sensitive_news()` always raised `BDShareError` — the row parser assumed each news item was one `<tr>` with 4 `<td>`s, but DSE renders each field (`Trading Code:`, `News Title:`, `News:`, `Post Date:`) as its own `<th>`/`<td>` row pair
|
|
27
|
+
- `as_polars=True` could crash with `unexpected value while building Series of type String; found value of type Float64: NaN` on tables mixing strings and missing values (e.g. `get_company_info()`); NaN now converts to a proper polars null instead
|
|
28
|
+
- Corrected `usage.rst`/README documentation that had `get_historical_data()`/`get_basic_historical_data()` mislabeled as the deprecated aliases — `get_hist_data()`/`get_basic_hist_data()` are the deprecated ones
|
|
29
|
+
|
|
30
|
+
## [1.2.1] - 2026-02-22
|
|
31
|
+
|
|
32
|
+
### Added
|
|
33
|
+
- Added code filter on market index
|
|
9
34
|
|
|
10
35
|
## [1.2.0] - 2026-02-21
|
|
11
36
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bdshare
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.2
|
|
4
4
|
Summary: A utility for crawling historical and Real-time Quotes of DSE(Dhaka Stock Exchange)
|
|
5
5
|
Author: Raisul Islam
|
|
6
6
|
Author-email: raisul.me@gmail.com
|
|
@@ -11,10 +11,15 @@ Requires-Python: >=3.9
|
|
|
11
11
|
Description-Content-Type: text/markdown
|
|
12
12
|
License-File: LICENSE
|
|
13
13
|
Requires-Dist: requests
|
|
14
|
+
Requires-Dist: certifi
|
|
14
15
|
Requires-Dist: beautifulsoup4
|
|
15
16
|
Requires-Dist: html5lib
|
|
16
17
|
Requires-Dist: pandas
|
|
17
18
|
Requires-Dist: lxml
|
|
19
|
+
Provides-Extra: polars
|
|
20
|
+
Requires-Dist: polars; extra == "polars"
|
|
21
|
+
Provides-Extra: mcp
|
|
22
|
+
Requires-Dist: mcp>=1.0.0; extra == "mcp"
|
|
18
23
|
Dynamic: license-file
|
|
19
24
|
|
|
20
25
|
# bdshare
|
|
@@ -44,6 +49,7 @@ Dynamic: license-file
|
|
|
44
49
|
- [Error Handling](#error-handling)
|
|
45
50
|
- [API Reference](#api-reference)
|
|
46
51
|
- [Examples](#examples)
|
|
52
|
+
- [Using bdshare with AI Agents (MCP Server)](#using-bdshare-with-ai-agents-mcp-server)
|
|
47
53
|
- [Contributing](#contributing)
|
|
48
54
|
- [Roadmap](#roadmap)
|
|
49
55
|
- [Disclaimer](#disclaimer)
|
|
@@ -71,14 +77,14 @@ Dependencies installed automatically: `pandas`, `requests`, `beautifulsoup4`, `l
|
|
|
71
77
|
## Quick Start
|
|
72
78
|
|
|
73
79
|
```python
|
|
74
|
-
from bdshare import get_current_trade_data,
|
|
80
|
+
from bdshare import get_current_trade_data, get_historical_data
|
|
75
81
|
|
|
76
82
|
# Live prices for all instruments
|
|
77
83
|
df = get_current_trade_data()
|
|
78
84
|
print(df.head())
|
|
79
85
|
|
|
80
86
|
# Historical data for a specific symbol
|
|
81
|
-
df =
|
|
87
|
+
df = get_historical_data('2024-01-01', '2024-01-31', 'GP')
|
|
82
88
|
print(df.head())
|
|
83
89
|
```
|
|
84
90
|
|
|
@@ -130,7 +136,7 @@ print(codes['symbol'].tolist())
|
|
|
130
136
|
### Historical Data
|
|
131
137
|
|
|
132
138
|
```python
|
|
133
|
-
from bdshare import
|
|
139
|
+
from bdshare import get_historical_data, get_basic_historical_data, get_close_price_data
|
|
134
140
|
import datetime as dt
|
|
135
141
|
|
|
136
142
|
start = '2024-01-01'
|
|
@@ -138,39 +144,46 @@ end = '2024-03-31'
|
|
|
138
144
|
|
|
139
145
|
# Full historical data (ltp, open, high, low, close, volume, trade, value…)
|
|
140
146
|
# Indexed by date, sorted newest-first
|
|
141
|
-
df =
|
|
147
|
+
df = get_historical_data(start, end, 'ACI')
|
|
142
148
|
|
|
143
149
|
# Simplified OHLCV — sorted oldest-first, ready for TA libraries
|
|
144
|
-
df =
|
|
150
|
+
df = get_basic_historical_data(start, end, 'ACI')
|
|
145
151
|
|
|
146
152
|
# Set date as index explicitly
|
|
147
|
-
df =
|
|
153
|
+
df = get_basic_historical_data(start, end, 'ACI', index='date')
|
|
148
154
|
|
|
149
155
|
# Rolling 2-year window
|
|
150
156
|
end = dt.date.today()
|
|
151
157
|
start = end - dt.timedelta(days=2 * 365)
|
|
152
|
-
df =
|
|
158
|
+
df = get_basic_historical_data(str(start), str(end), 'GP')
|
|
153
159
|
|
|
154
160
|
# Close prices only
|
|
155
161
|
df = get_close_price_data(start, end, 'ACI')
|
|
156
162
|
```
|
|
157
163
|
|
|
158
|
-
> **Column order note:** `
|
|
164
|
+
> **Column order note:** `get_basic_historical_data` intentionally returns OHLCV in standard order
|
|
159
165
|
> (`open`, `high`, `low`, `close`, `volume`) to be compatible with libraries like `ta`, `pandas-ta`, and `backtrader`.
|
|
166
|
+
>
|
|
167
|
+
> **Deprecated aliases:** `get_hist_data()` and `get_basic_hist_data()` still work but emit a
|
|
168
|
+
> `DeprecationWarning` — migrate to `get_historical_data()` / `get_basic_historical_data()`.
|
|
160
169
|
|
|
161
170
|
### Market & Index Data
|
|
162
171
|
|
|
163
172
|
```python
|
|
164
173
|
from bdshare import (
|
|
174
|
+
get_market_status,
|
|
165
175
|
get_market_info,
|
|
166
176
|
get_market_info_more_data,
|
|
167
177
|
get_market_depth_data,
|
|
168
178
|
get_latest_pe,
|
|
169
|
-
|
|
170
|
-
|
|
179
|
+
get_top_ten_gainers_losers,
|
|
180
|
+
get_top_twenty_shares,
|
|
171
181
|
get_company_info,
|
|
172
182
|
)
|
|
173
183
|
|
|
184
|
+
# Current market status: Open, Closed, Holiday, etc.
|
|
185
|
+
status = get_market_status()
|
|
186
|
+
|
|
174
187
|
# Last 30 days of market summary (DSEX, DSES, DS30, DGEN, volumes, market cap)
|
|
175
188
|
df = get_market_info()
|
|
176
189
|
|
|
@@ -183,11 +196,11 @@ df = get_market_depth_data('ACI')
|
|
|
183
196
|
# P/E ratios for all listed companies
|
|
184
197
|
df = get_latest_pe()
|
|
185
198
|
|
|
186
|
-
# Sector-wise performance
|
|
187
|
-
df = get_sector_performance()
|
|
188
|
-
|
|
189
199
|
# Top 10 gainers and losers (adjust limit as needed)
|
|
190
|
-
df =
|
|
200
|
+
df = get_top_ten_gainers_losers(limit=10)
|
|
201
|
+
|
|
202
|
+
# Top 20 shares by traded volume (adjust limit as needed)
|
|
203
|
+
df = get_top_twenty_shares(limit=20)
|
|
191
204
|
|
|
192
205
|
# Detailed company profile
|
|
193
206
|
tables = get_company_info('GP')
|
|
@@ -213,13 +226,13 @@ df = get_all_news('2024-01-01', '2024-03-31', 'GP') # Filtered by date + symbol
|
|
|
213
226
|
### Saving to CSV
|
|
214
227
|
|
|
215
228
|
```python
|
|
216
|
-
from bdshare import
|
|
229
|
+
from bdshare import get_basic_historical_data, Store
|
|
217
230
|
import datetime as dt
|
|
218
231
|
|
|
219
232
|
end = dt.date.today()
|
|
220
233
|
start = end - dt.timedelta(days=365)
|
|
221
234
|
|
|
222
|
-
df =
|
|
235
|
+
df = get_basic_historical_data(str(start), str(end), 'GP')
|
|
223
236
|
Store(df).save() # saves to current directory as a CSV
|
|
224
237
|
```
|
|
225
238
|
|
|
@@ -249,9 +262,11 @@ bd.get_market_summary() # DSEX/DSES/DS30 indices + stats (1-
|
|
|
249
262
|
bd.get_company_profile('ACI') # Company profile (1-hr TTL)
|
|
250
263
|
bd.get_latest_pe_ratios() # All P/E ratios (1-hr TTL)
|
|
251
264
|
bd.get_top_movers(limit=10) # Top gainers/losers (5-min TTL)
|
|
252
|
-
bd.get_sector_performance() # Sector breakdown (5-min TTL)
|
|
253
265
|
```
|
|
254
266
|
|
|
267
|
+
`get_market_status()` and `get_top_twenty_shares()` don't have `BDShare` wrapper methods yet —
|
|
268
|
+
call the module-level functions directly (see [API Reference](#api-reference)).
|
|
269
|
+
|
|
255
270
|
### Trading methods
|
|
256
271
|
|
|
257
272
|
```python
|
|
@@ -313,22 +328,26 @@ Common causes of `BDShareError`:
|
|
|
313
328
|
| `get_current_trade_data(symbol?)` | `symbol: str` | DataFrame | Live prices (all or one symbol) |
|
|
314
329
|
| `get_dsex_data(symbol?)` | `symbol: str` | DataFrame | DSEX index entries |
|
|
315
330
|
| `get_current_trading_code()` | — | DataFrame | All tradeable symbols |
|
|
316
|
-
| `
|
|
317
|
-
| `
|
|
331
|
+
| `get_historical_data(start, end, code?)` | `str, str, str` | DataFrame | Full historical OHLCV |
|
|
332
|
+
| `get_basic_historical_data(start, end, code?, index?)` | `str, str, str, str` | DataFrame | Simplified OHLCV (TA-ready) |
|
|
318
333
|
| `get_close_price_data(start, end, code?)` | `str, str, str` | DataFrame | Close + prior close |
|
|
319
334
|
| `get_last_trade_price_data()` | — | DataFrame | Last trade from DSE text file |
|
|
320
335
|
|
|
336
|
+
Deprecated aliases (removed in 2.0.0): `get_hist_data()` → `get_historical_data()`,
|
|
337
|
+
`get_basic_hist_data()` → `get_basic_historical_data()`.
|
|
338
|
+
|
|
321
339
|
### Market Functions
|
|
322
340
|
|
|
323
341
|
| Function | Parameters | Returns | Description |
|
|
324
342
|
|---|---|---|---|
|
|
343
|
+
| `get_market_status()` | — | str | Current market status (Open, Closed, Holiday, etc.) |
|
|
325
344
|
| `get_market_info()` | — | DataFrame | 30-day market summary |
|
|
326
345
|
| `get_market_info_more_data(start, end)` | `str, str` | DataFrame | Historical market summary |
|
|
327
346
|
| `get_market_depth_data(symbol)` | `str` | DataFrame | Order book (buy/sell depth) |
|
|
328
347
|
| `get_latest_pe()` | — | DataFrame | P/E ratios for all companies |
|
|
329
348
|
| `get_company_info(symbol)` | `str` | list[DataFrame] | Detailed company tables |
|
|
330
|
-
| `
|
|
331
|
-
| `
|
|
349
|
+
| `get_top_ten_gainers_losers(limit?)` | `int` (default 10) | DataFrame | Top movers by price change |
|
|
350
|
+
| `get_top_twenty_shares(limit?)` | `int` (default 20) | DataFrame | Top shares by traded volume |
|
|
332
351
|
|
|
333
352
|
### News Functions
|
|
334
353
|
|
|
@@ -420,13 +439,83 @@ with BDShare() as bd:
|
|
|
420
439
|
### Fetch and screen top gainers above 5 %
|
|
421
440
|
|
|
422
441
|
```python
|
|
423
|
-
from bdshare import
|
|
442
|
+
from bdshare import get_top_ten_gainers_losers
|
|
424
443
|
|
|
425
|
-
df =
|
|
444
|
+
df = get_top_ten_gainers_losers(limit=20)
|
|
426
445
|
big_movers = df[df['change'] > 5]
|
|
427
|
-
print(big_movers[['symbol', '
|
|
446
|
+
print(big_movers[['symbol', 'close', 'change']])
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
---
|
|
450
|
+
|
|
451
|
+
## Using bdshare with AI Agents (MCP Server)
|
|
452
|
+
|
|
453
|
+
bdshare ships an [MCP](https://modelcontextprotocol.io/) server so AI agents running in
|
|
454
|
+
**another program** — Claude Desktop, Claude Code, or any other MCP-compatible client —
|
|
455
|
+
can call live DSE data as tools, without you writing any glue code.
|
|
456
|
+
|
|
457
|
+
### Install
|
|
458
|
+
|
|
459
|
+
```bash
|
|
460
|
+
pip install "bdshare[mcp]"
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
### Run
|
|
464
|
+
|
|
465
|
+
```bash
|
|
466
|
+
bdshare-mcp
|
|
467
|
+
# or
|
|
468
|
+
python -m bdshare.mcp_server
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
By default it speaks MCP over stdio, which is what desktop/CLI agent clients expect.
|
|
472
|
+
|
|
473
|
+
### Connect it to a client
|
|
474
|
+
|
|
475
|
+
**Claude Code:**
|
|
476
|
+
|
|
477
|
+
```bash
|
|
478
|
+
claude mcp add bdshare -- bdshare-mcp
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
**Claude Desktop** (`claude_desktop_config.json`):
|
|
482
|
+
|
|
483
|
+
```json
|
|
484
|
+
{
|
|
485
|
+
"mcpServers": {
|
|
486
|
+
"bdshare": {
|
|
487
|
+
"command": "bdshare-mcp"
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
}
|
|
428
491
|
```
|
|
429
492
|
|
|
493
|
+
Any other MCP client is configured the same way — point it at the `bdshare-mcp` command
|
|
494
|
+
(or `python -m bdshare.mcp_server`), stdio transport.
|
|
495
|
+
|
|
496
|
+
### What the agent gets
|
|
497
|
+
|
|
498
|
+
15 tools covering the same data this README documents — `market_status`,
|
|
499
|
+
`market_summary`, `market_summary_range`, `market_depth`, `latest_pe_ratios`,
|
|
500
|
+
`top_ten_gainers_losers`, `top_twenty_shares`, `company_info`, `current_trades`,
|
|
501
|
+
`dsex_index`, `trading_codes`, `historical_data`, `basic_historical_data`, `news`,
|
|
502
|
+
`agm_news`. Each tool returns JSON — `DataFrame`s are converted to lists of row
|
|
503
|
+
records — and a `BDShareError` (bad symbol, DSE outage, parse failure) surfaces as a
|
|
504
|
+
clean tool error message instead of a raw traceback.
|
|
505
|
+
|
|
506
|
+
### Notes for agent use
|
|
507
|
+
|
|
508
|
+
- **No caching in the MCP server itself.** Every tool call scrapes dsebd.org live. If
|
|
509
|
+
your agent calls the same tool repeatedly in one turn (e.g. checking a price several
|
|
510
|
+
times), consider fronting it with the `BDShare` client's caching in a custom
|
|
511
|
+
wrapper — the bundled server intentionally stays stateless and simple.
|
|
512
|
+
- **Rate limits are the agent's responsibility.** The `BDShare` OOP client has a
|
|
513
|
+
built-in 5 calls/second limiter; the MCP tools call the plain module-level functions,
|
|
514
|
+
which don't. Avoid tight loops of tool calls.
|
|
515
|
+
- Source: [`bdshare/mcp_server.py`](bdshare/mcp_server.py) — a plain
|
|
516
|
+
[`FastMCP`](https://github.com/modelcontextprotocol/python-sdk) server, easy to fork
|
|
517
|
+
if you want a different tool surface.
|
|
518
|
+
|
|
430
519
|
---
|
|
431
520
|
|
|
432
521
|
## Contributing
|
|
@@ -456,6 +545,7 @@ Please open an issue before submitting a pull request for significant changes. S
|
|
|
456
545
|
- [x] `BDShareError` for clean error handling
|
|
457
546
|
- [x] Unified `get_news()` dispatcher
|
|
458
547
|
- [x] Rate limiter and response caching
|
|
548
|
+
- [x] MCP server for AI agent integration
|
|
459
549
|
|
|
460
550
|
---
|
|
461
551
|
|
|
@@ -482,6 +572,31 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
|
482
572
|
Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
483
573
|
|
|
484
574
|
---
|
|
575
|
+
## [1.2.2] - 2026-07-22
|
|
576
|
+
|
|
577
|
+
### Added
|
|
578
|
+
- Optional `as_polars=True` parameter across all data-fetching functions to return `polars.DataFrame` instead of `pandas.DataFrame` (requires `pip install bdshare[polars]`)
|
|
579
|
+
- `get_market_status()` — current market status (Open, Closed, Holiday, etc.)
|
|
580
|
+
- `get_top_twenty_shares()` — top twenty shares by traded volume
|
|
581
|
+
- MCP ([Model Context Protocol](https://modelcontextprotocol.io/)) server (`bdshare/mcp_server.py`) exposing 15 tools so AI agents (Claude Desktop, Claude Code, etc.) can call live DSE data directly; install with `pip install bdshare[mcp]`, run with `bdshare-mcp`
|
|
582
|
+
|
|
583
|
+
### Changed
|
|
584
|
+
- Renamed `get_top_gainers_losers()` → `get_top_ten_gainers_losers()`; returned columns changed from `symbol, ltp, change` to `symbol, close, high, low, ycp, change`
|
|
585
|
+
|
|
586
|
+
### Removed
|
|
587
|
+
- `get_sector_performance()` (module function and `BDShare.get_sector_performance()`) — no aliased replacement; use `get_top_twenty_shares()` instead
|
|
588
|
+
|
|
589
|
+
### Fixed
|
|
590
|
+
- Bundled the missing Sectigo DV R36 intermediate certificate so requests to dsebd.org verify correctly instead of relying on an incomplete chain
|
|
591
|
+
- Corrected `DSE_ALT_URL` fallback domain to `dse.com.bd`
|
|
592
|
+
- `get_corporate_announcements()` and `get_price_sensitive_news()` always raised `BDShareError` — the row parser assumed each news item was one `<tr>` with 4 `<td>`s, but DSE renders each field (`Trading Code:`, `News Title:`, `News:`, `Post Date:`) as its own `<th>`/`<td>` row pair
|
|
593
|
+
- `as_polars=True` could crash with `unexpected value while building Series of type String; found value of type Float64: NaN` on tables mixing strings and missing values (e.g. `get_company_info()`); NaN now converts to a proper polars null instead
|
|
594
|
+
- Corrected `usage.rst`/README documentation that had `get_historical_data()`/`get_basic_historical_data()` mislabeled as the deprecated aliases — `get_hist_data()`/`get_basic_hist_data()` are the deprecated ones
|
|
595
|
+
|
|
596
|
+
## [1.2.1] - 2026-02-22
|
|
597
|
+
|
|
598
|
+
### Added
|
|
599
|
+
- Added code filter on market index
|
|
485
600
|
|
|
486
601
|
## [1.2.0] - 2026-02-21
|
|
487
602
|
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
- [Error Handling](#error-handling)
|
|
26
26
|
- [API Reference](#api-reference)
|
|
27
27
|
- [Examples](#examples)
|
|
28
|
+
- [Using bdshare with AI Agents (MCP Server)](#using-bdshare-with-ai-agents-mcp-server)
|
|
28
29
|
- [Contributing](#contributing)
|
|
29
30
|
- [Roadmap](#roadmap)
|
|
30
31
|
- [Disclaimer](#disclaimer)
|
|
@@ -52,14 +53,14 @@ Dependencies installed automatically: `pandas`, `requests`, `beautifulsoup4`, `l
|
|
|
52
53
|
## Quick Start
|
|
53
54
|
|
|
54
55
|
```python
|
|
55
|
-
from bdshare import get_current_trade_data,
|
|
56
|
+
from bdshare import get_current_trade_data, get_historical_data
|
|
56
57
|
|
|
57
58
|
# Live prices for all instruments
|
|
58
59
|
df = get_current_trade_data()
|
|
59
60
|
print(df.head())
|
|
60
61
|
|
|
61
62
|
# Historical data for a specific symbol
|
|
62
|
-
df =
|
|
63
|
+
df = get_historical_data('2024-01-01', '2024-01-31', 'GP')
|
|
63
64
|
print(df.head())
|
|
64
65
|
```
|
|
65
66
|
|
|
@@ -111,7 +112,7 @@ print(codes['symbol'].tolist())
|
|
|
111
112
|
### Historical Data
|
|
112
113
|
|
|
113
114
|
```python
|
|
114
|
-
from bdshare import
|
|
115
|
+
from bdshare import get_historical_data, get_basic_historical_data, get_close_price_data
|
|
115
116
|
import datetime as dt
|
|
116
117
|
|
|
117
118
|
start = '2024-01-01'
|
|
@@ -119,39 +120,46 @@ end = '2024-03-31'
|
|
|
119
120
|
|
|
120
121
|
# Full historical data (ltp, open, high, low, close, volume, trade, value…)
|
|
121
122
|
# Indexed by date, sorted newest-first
|
|
122
|
-
df =
|
|
123
|
+
df = get_historical_data(start, end, 'ACI')
|
|
123
124
|
|
|
124
125
|
# Simplified OHLCV — sorted oldest-first, ready for TA libraries
|
|
125
|
-
df =
|
|
126
|
+
df = get_basic_historical_data(start, end, 'ACI')
|
|
126
127
|
|
|
127
128
|
# Set date as index explicitly
|
|
128
|
-
df =
|
|
129
|
+
df = get_basic_historical_data(start, end, 'ACI', index='date')
|
|
129
130
|
|
|
130
131
|
# Rolling 2-year window
|
|
131
132
|
end = dt.date.today()
|
|
132
133
|
start = end - dt.timedelta(days=2 * 365)
|
|
133
|
-
df =
|
|
134
|
+
df = get_basic_historical_data(str(start), str(end), 'GP')
|
|
134
135
|
|
|
135
136
|
# Close prices only
|
|
136
137
|
df = get_close_price_data(start, end, 'ACI')
|
|
137
138
|
```
|
|
138
139
|
|
|
139
|
-
> **Column order note:** `
|
|
140
|
+
> **Column order note:** `get_basic_historical_data` intentionally returns OHLCV in standard order
|
|
140
141
|
> (`open`, `high`, `low`, `close`, `volume`) to be compatible with libraries like `ta`, `pandas-ta`, and `backtrader`.
|
|
142
|
+
>
|
|
143
|
+
> **Deprecated aliases:** `get_hist_data()` and `get_basic_hist_data()` still work but emit a
|
|
144
|
+
> `DeprecationWarning` — migrate to `get_historical_data()` / `get_basic_historical_data()`.
|
|
141
145
|
|
|
142
146
|
### Market & Index Data
|
|
143
147
|
|
|
144
148
|
```python
|
|
145
149
|
from bdshare import (
|
|
150
|
+
get_market_status,
|
|
146
151
|
get_market_info,
|
|
147
152
|
get_market_info_more_data,
|
|
148
153
|
get_market_depth_data,
|
|
149
154
|
get_latest_pe,
|
|
150
|
-
|
|
151
|
-
|
|
155
|
+
get_top_ten_gainers_losers,
|
|
156
|
+
get_top_twenty_shares,
|
|
152
157
|
get_company_info,
|
|
153
158
|
)
|
|
154
159
|
|
|
160
|
+
# Current market status: Open, Closed, Holiday, etc.
|
|
161
|
+
status = get_market_status()
|
|
162
|
+
|
|
155
163
|
# Last 30 days of market summary (DSEX, DSES, DS30, DGEN, volumes, market cap)
|
|
156
164
|
df = get_market_info()
|
|
157
165
|
|
|
@@ -164,11 +172,11 @@ df = get_market_depth_data('ACI')
|
|
|
164
172
|
# P/E ratios for all listed companies
|
|
165
173
|
df = get_latest_pe()
|
|
166
174
|
|
|
167
|
-
# Sector-wise performance
|
|
168
|
-
df = get_sector_performance()
|
|
169
|
-
|
|
170
175
|
# Top 10 gainers and losers (adjust limit as needed)
|
|
171
|
-
df =
|
|
176
|
+
df = get_top_ten_gainers_losers(limit=10)
|
|
177
|
+
|
|
178
|
+
# Top 20 shares by traded volume (adjust limit as needed)
|
|
179
|
+
df = get_top_twenty_shares(limit=20)
|
|
172
180
|
|
|
173
181
|
# Detailed company profile
|
|
174
182
|
tables = get_company_info('GP')
|
|
@@ -194,13 +202,13 @@ df = get_all_news('2024-01-01', '2024-03-31', 'GP') # Filtered by date + symbol
|
|
|
194
202
|
### Saving to CSV
|
|
195
203
|
|
|
196
204
|
```python
|
|
197
|
-
from bdshare import
|
|
205
|
+
from bdshare import get_basic_historical_data, Store
|
|
198
206
|
import datetime as dt
|
|
199
207
|
|
|
200
208
|
end = dt.date.today()
|
|
201
209
|
start = end - dt.timedelta(days=365)
|
|
202
210
|
|
|
203
|
-
df =
|
|
211
|
+
df = get_basic_historical_data(str(start), str(end), 'GP')
|
|
204
212
|
Store(df).save() # saves to current directory as a CSV
|
|
205
213
|
```
|
|
206
214
|
|
|
@@ -230,9 +238,11 @@ bd.get_market_summary() # DSEX/DSES/DS30 indices + stats (1-
|
|
|
230
238
|
bd.get_company_profile('ACI') # Company profile (1-hr TTL)
|
|
231
239
|
bd.get_latest_pe_ratios() # All P/E ratios (1-hr TTL)
|
|
232
240
|
bd.get_top_movers(limit=10) # Top gainers/losers (5-min TTL)
|
|
233
|
-
bd.get_sector_performance() # Sector breakdown (5-min TTL)
|
|
234
241
|
```
|
|
235
242
|
|
|
243
|
+
`get_market_status()` and `get_top_twenty_shares()` don't have `BDShare` wrapper methods yet —
|
|
244
|
+
call the module-level functions directly (see [API Reference](#api-reference)).
|
|
245
|
+
|
|
236
246
|
### Trading methods
|
|
237
247
|
|
|
238
248
|
```python
|
|
@@ -294,22 +304,26 @@ Common causes of `BDShareError`:
|
|
|
294
304
|
| `get_current_trade_data(symbol?)` | `symbol: str` | DataFrame | Live prices (all or one symbol) |
|
|
295
305
|
| `get_dsex_data(symbol?)` | `symbol: str` | DataFrame | DSEX index entries |
|
|
296
306
|
| `get_current_trading_code()` | — | DataFrame | All tradeable symbols |
|
|
297
|
-
| `
|
|
298
|
-
| `
|
|
307
|
+
| `get_historical_data(start, end, code?)` | `str, str, str` | DataFrame | Full historical OHLCV |
|
|
308
|
+
| `get_basic_historical_data(start, end, code?, index?)` | `str, str, str, str` | DataFrame | Simplified OHLCV (TA-ready) |
|
|
299
309
|
| `get_close_price_data(start, end, code?)` | `str, str, str` | DataFrame | Close + prior close |
|
|
300
310
|
| `get_last_trade_price_data()` | — | DataFrame | Last trade from DSE text file |
|
|
301
311
|
|
|
312
|
+
Deprecated aliases (removed in 2.0.0): `get_hist_data()` → `get_historical_data()`,
|
|
313
|
+
`get_basic_hist_data()` → `get_basic_historical_data()`.
|
|
314
|
+
|
|
302
315
|
### Market Functions
|
|
303
316
|
|
|
304
317
|
| Function | Parameters | Returns | Description |
|
|
305
318
|
|---|---|---|---|
|
|
319
|
+
| `get_market_status()` | — | str | Current market status (Open, Closed, Holiday, etc.) |
|
|
306
320
|
| `get_market_info()` | — | DataFrame | 30-day market summary |
|
|
307
321
|
| `get_market_info_more_data(start, end)` | `str, str` | DataFrame | Historical market summary |
|
|
308
322
|
| `get_market_depth_data(symbol)` | `str` | DataFrame | Order book (buy/sell depth) |
|
|
309
323
|
| `get_latest_pe()` | — | DataFrame | P/E ratios for all companies |
|
|
310
324
|
| `get_company_info(symbol)` | `str` | list[DataFrame] | Detailed company tables |
|
|
311
|
-
| `
|
|
312
|
-
| `
|
|
325
|
+
| `get_top_ten_gainers_losers(limit?)` | `int` (default 10) | DataFrame | Top movers by price change |
|
|
326
|
+
| `get_top_twenty_shares(limit?)` | `int` (default 20) | DataFrame | Top shares by traded volume |
|
|
313
327
|
|
|
314
328
|
### News Functions
|
|
315
329
|
|
|
@@ -401,13 +415,83 @@ with BDShare() as bd:
|
|
|
401
415
|
### Fetch and screen top gainers above 5 %
|
|
402
416
|
|
|
403
417
|
```python
|
|
404
|
-
from bdshare import
|
|
418
|
+
from bdshare import get_top_ten_gainers_losers
|
|
405
419
|
|
|
406
|
-
df =
|
|
420
|
+
df = get_top_ten_gainers_losers(limit=20)
|
|
407
421
|
big_movers = df[df['change'] > 5]
|
|
408
|
-
print(big_movers[['symbol', '
|
|
422
|
+
print(big_movers[['symbol', 'close', 'change']])
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
---
|
|
426
|
+
|
|
427
|
+
## Using bdshare with AI Agents (MCP Server)
|
|
428
|
+
|
|
429
|
+
bdshare ships an [MCP](https://modelcontextprotocol.io/) server so AI agents running in
|
|
430
|
+
**another program** — Claude Desktop, Claude Code, or any other MCP-compatible client —
|
|
431
|
+
can call live DSE data as tools, without you writing any glue code.
|
|
432
|
+
|
|
433
|
+
### Install
|
|
434
|
+
|
|
435
|
+
```bash
|
|
436
|
+
pip install "bdshare[mcp]"
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
### Run
|
|
440
|
+
|
|
441
|
+
```bash
|
|
442
|
+
bdshare-mcp
|
|
443
|
+
# or
|
|
444
|
+
python -m bdshare.mcp_server
|
|
409
445
|
```
|
|
410
446
|
|
|
447
|
+
By default it speaks MCP over stdio, which is what desktop/CLI agent clients expect.
|
|
448
|
+
|
|
449
|
+
### Connect it to a client
|
|
450
|
+
|
|
451
|
+
**Claude Code:**
|
|
452
|
+
|
|
453
|
+
```bash
|
|
454
|
+
claude mcp add bdshare -- bdshare-mcp
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
**Claude Desktop** (`claude_desktop_config.json`):
|
|
458
|
+
|
|
459
|
+
```json
|
|
460
|
+
{
|
|
461
|
+
"mcpServers": {
|
|
462
|
+
"bdshare": {
|
|
463
|
+
"command": "bdshare-mcp"
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
Any other MCP client is configured the same way — point it at the `bdshare-mcp` command
|
|
470
|
+
(or `python -m bdshare.mcp_server`), stdio transport.
|
|
471
|
+
|
|
472
|
+
### What the agent gets
|
|
473
|
+
|
|
474
|
+
15 tools covering the same data this README documents — `market_status`,
|
|
475
|
+
`market_summary`, `market_summary_range`, `market_depth`, `latest_pe_ratios`,
|
|
476
|
+
`top_ten_gainers_losers`, `top_twenty_shares`, `company_info`, `current_trades`,
|
|
477
|
+
`dsex_index`, `trading_codes`, `historical_data`, `basic_historical_data`, `news`,
|
|
478
|
+
`agm_news`. Each tool returns JSON — `DataFrame`s are converted to lists of row
|
|
479
|
+
records — and a `BDShareError` (bad symbol, DSE outage, parse failure) surfaces as a
|
|
480
|
+
clean tool error message instead of a raw traceback.
|
|
481
|
+
|
|
482
|
+
### Notes for agent use
|
|
483
|
+
|
|
484
|
+
- **No caching in the MCP server itself.** Every tool call scrapes dsebd.org live. If
|
|
485
|
+
your agent calls the same tool repeatedly in one turn (e.g. checking a price several
|
|
486
|
+
times), consider fronting it with the `BDShare` client's caching in a custom
|
|
487
|
+
wrapper — the bundled server intentionally stays stateless and simple.
|
|
488
|
+
- **Rate limits are the agent's responsibility.** The `BDShare` OOP client has a
|
|
489
|
+
built-in 5 calls/second limiter; the MCP tools call the plain module-level functions,
|
|
490
|
+
which don't. Avoid tight loops of tool calls.
|
|
491
|
+
- Source: [`bdshare/mcp_server.py`](bdshare/mcp_server.py) — a plain
|
|
492
|
+
[`FastMCP`](https://github.com/modelcontextprotocol/python-sdk) server, easy to fork
|
|
493
|
+
if you want a different tool surface.
|
|
494
|
+
|
|
411
495
|
---
|
|
412
496
|
|
|
413
497
|
## Contributing
|
|
@@ -437,6 +521,7 @@ Please open an issue before submitting a pull request for significant changes. S
|
|
|
437
521
|
- [x] `BDShareError` for clean error handling
|
|
438
522
|
- [x] Unified `get_news()` dispatcher
|
|
439
523
|
- [x] Rate limiter and response caching
|
|
524
|
+
- [x] MCP server for AI agent integration
|
|
440
525
|
|
|
441
526
|
---
|
|
442
527
|
|