pypsx-toolkit 3.0.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.
- pypsx_toolkit/__init__.py +304 -0
- pypsx_toolkit/__init__.pyi +99 -0
- pypsx_toolkit/analysis/__init__.py +222 -0
- pypsx_toolkit/analysis/__init__.pyi +348 -0
- pypsx_toolkit/api.pyi +294 -0
- pypsx_toolkit/core/__init__.py +6 -0
- pypsx_toolkit/core/errors.pyi +38 -0
- pypsx_toolkit/core/stream.pyi +66 -0
- pypsx_toolkit/endpoints/__init__.py +1 -0
- pypsx_toolkit/endpoints/constants.py +121 -0
- pypsx_toolkit/format/__init__.py +1 -0
- pypsx_toolkit/market.pyi +158 -0
- pypsx_toolkit/models.py +224 -0
- pypsx_toolkit/models.pyi +199 -0
- pypsx_toolkit/py.typed +0 -0
- pypsx_toolkit/ticker.pyi +237 -0
- pypsx_toolkit-3.0.0.dist-info/METADATA +744 -0
- pypsx_toolkit-3.0.0.dist-info/RECORD +22 -0
- pypsx_toolkit-3.0.0.dist-info/WHEEL +5 -0
- pypsx_toolkit-3.0.0.dist-info/entry_points.txt +2 -0
- pypsx_toolkit-3.0.0.dist-info/licenses/LICENSE +17 -0
- pypsx_toolkit-3.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,744 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pypsx-toolkit
|
|
3
|
+
Version: 3.0.0
|
|
4
|
+
Summary: Pakistan Stock Exchange (PSX) data library with yfinance-like API
|
|
5
|
+
Author-email: PyPSX Team <contact@pypsx.dev>
|
|
6
|
+
Maintainer-email: PyPSX Team <contact@pypsx.dev>
|
|
7
|
+
License: Copyright (c) 2026 PyPSX Team. All rights reserved.
|
|
8
|
+
|
|
9
|
+
This software and associated documentation files (the "Software") are the
|
|
10
|
+
proprietary property of PyPSX Team. Unauthorized copying, modification,
|
|
11
|
+
distribution, sublicensing, or use of this Software, via any medium, is
|
|
12
|
+
strictly prohibited without the prior written permission of PyPSX Team.
|
|
13
|
+
|
|
14
|
+
No license, express or implied, to any intellectual property rights is
|
|
15
|
+
granted by this document.
|
|
16
|
+
|
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
22
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
23
|
+
DEALINGS IN THE SOFTWARE.
|
|
24
|
+
|
|
25
|
+
Project-URL: Homepage, https://pypsx.com
|
|
26
|
+
Project-URL: Documentation, https://markets.pypsx.com/docs
|
|
27
|
+
Project-URL: Changelog, https://markets.pypsx.com/docs/changelog
|
|
28
|
+
Keywords: psx,pakistan,stock,finance,data,api,pandas,yfinance,market-data
|
|
29
|
+
Classifier: Development Status :: 4 - Beta
|
|
30
|
+
Classifier: Intended Audience :: Developers
|
|
31
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
32
|
+
Classifier: License :: Other/Proprietary License
|
|
33
|
+
Classifier: Operating System :: OS Independent
|
|
34
|
+
Classifier: Programming Language :: Python :: 3
|
|
35
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
39
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
40
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
41
|
+
Classifier: Topic :: Office/Business :: Financial
|
|
42
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
43
|
+
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
44
|
+
Requires-Python: >=3.8
|
|
45
|
+
Description-Content-Type: text/markdown
|
|
46
|
+
License-File: LICENSE
|
|
47
|
+
Requires-Dist: requests>=2.31.0
|
|
48
|
+
Requires-Dist: beautifulsoup4>=4.12.0
|
|
49
|
+
Requires-Dist: lxml>=4.9.0
|
|
50
|
+
Requires-Dist: pandas>=2.0.0
|
|
51
|
+
Requires-Dist: loguru>=0.7.0
|
|
52
|
+
Requires-Dist: numpy>=1.24.0
|
|
53
|
+
Provides-Extra: plot
|
|
54
|
+
Requires-Dist: matplotlib>=3.5.0; extra == "plot"
|
|
55
|
+
Requires-Dist: seaborn>=0.11.0; extra == "plot"
|
|
56
|
+
Provides-Extra: dev
|
|
57
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
58
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
59
|
+
Requires-Dist: requests-mock>=1.10.0; extra == "dev"
|
|
60
|
+
Requires-Dist: black>=23.0.0; extra == "dev"
|
|
61
|
+
Requires-Dist: flake8>=6.0.0; extra == "dev"
|
|
62
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
63
|
+
Requires-Dist: isort>=5.12.0; extra == "dev"
|
|
64
|
+
Provides-Extra: all
|
|
65
|
+
Requires-Dist: pypsx-toolkit[dev,plot]; extra == "all"
|
|
66
|
+
Dynamic: license-file
|
|
67
|
+
|
|
68
|
+
# PyPSX - Pakistan Stock Exchange Data Library (v3)
|
|
69
|
+
|
|
70
|
+
A clean, simple Python library to fetch and analyze Pakistan Stock Exchange (PSX) data from official DPS endpoints. Get real-time market data, historical prices, and powerful analysis tools all in one package.
|
|
71
|
+
|
|
72
|
+
## Installation
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
pip install pypsx
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Quick Start
|
|
79
|
+
|
|
80
|
+
### Basic Usage - Get Stock Information
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
import pypsx
|
|
84
|
+
|
|
85
|
+
# Create a ticker object for any stock symbol
|
|
86
|
+
ticker = pypsx.PSXTicker("OGDC") # or use pypsx.Ticker("OGDC")
|
|
87
|
+
|
|
88
|
+
# Get company information
|
|
89
|
+
info = ticker.info
|
|
90
|
+
print(f"Company: {info.get('Sector')}")
|
|
91
|
+
print(f"Current Price: {info.get('Current')}")
|
|
92
|
+
|
|
93
|
+
# Get comprehensive snapshot data (OHLCV, bid/ask, circuit breaker, ranges, ratios, etc.)
|
|
94
|
+
snapshot = ticker.snapshot
|
|
95
|
+
print(f"Open: {snapshot.get('REG', {}).get('Open')}")
|
|
96
|
+
print(f"High: {snapshot.get('REG', {}).get('High')}")
|
|
97
|
+
print(f"52-Week Range: {snapshot.get('REG', {}).get('52-WEEK RANGE ^')}")
|
|
98
|
+
print(f"P/E Ratio: {snapshot.get('REG', {}).get('P/E Ratio (TTM) **')}")
|
|
99
|
+
|
|
100
|
+
# Get market watch data for this stock
|
|
101
|
+
market_data = ticker.market_watch()
|
|
102
|
+
print(market_data)
|
|
103
|
+
|
|
104
|
+
# Get historical price data (1 year)
|
|
105
|
+
history = ticker.history(period="1y", interval="1d")
|
|
106
|
+
print(history.head())
|
|
107
|
+
|
|
108
|
+
# Get recent intraday trades (last 2 days)
|
|
109
|
+
intraday = ticker.intraday()
|
|
110
|
+
print(intraday.head())
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Market Data
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
import pypsx
|
|
117
|
+
|
|
118
|
+
# Get full market watch (all stocks)
|
|
119
|
+
# Note: Different endpoints return different symbol counts
|
|
120
|
+
# Market Watch: ~486 symbols (includes all actively traded)
|
|
121
|
+
# Trading Board: ~479 symbols (order book data)
|
|
122
|
+
market_watch = pypsx.market_watch()
|
|
123
|
+
print(f"Total stocks in market watch: {len(market_watch)}")
|
|
124
|
+
|
|
125
|
+
# Get top performers
|
|
126
|
+
performers = pypsx.top_performers()
|
|
127
|
+
print("Top Gainers:")
|
|
128
|
+
print(performers["top_gainers"].head())
|
|
129
|
+
|
|
130
|
+
print("Top Decliners:")
|
|
131
|
+
print(performers["top_decliners"].head())
|
|
132
|
+
|
|
133
|
+
print("Most Active:")
|
|
134
|
+
print(performers["top_actives"].head())
|
|
135
|
+
|
|
136
|
+
# Get sector summary
|
|
137
|
+
sectors = pypsx.sector_summary()
|
|
138
|
+
print(sectors.head())
|
|
139
|
+
|
|
140
|
+
# Get all available stock symbols from trading board
|
|
141
|
+
# get_symbols() returns a list of clean symbols (without suffixes XD, NC, XR)
|
|
142
|
+
symbols_list = pypsx.get_symbols()
|
|
143
|
+
print(f"Total symbols: {len(symbols_list)}")
|
|
144
|
+
|
|
145
|
+
# To get DataFrame with Symbol, Name, Tag columns (Tag shows suffix if present)
|
|
146
|
+
from endpoints.trading_board import get_symbols as get_symbols_df
|
|
147
|
+
symbols_df = get_symbols_df() # Returns DataFrame with Symbol, Name, Tag columns
|
|
148
|
+
print(f"Total symbols (DataFrame): {len(symbols_df)}")
|
|
149
|
+
print(symbols_df.head())
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Historical Data
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
import pypsx
|
|
156
|
+
|
|
157
|
+
# Get 1 year of historical data for a stock
|
|
158
|
+
ticker = pypsx.PSXTicker("OGDC")
|
|
159
|
+
history = ticker.history(period="1y", interval="1d")
|
|
160
|
+
|
|
161
|
+
# Get full OHLCV data for specific date range
|
|
162
|
+
full_data = ticker.get_historical(start_date="2024-01-01", end_date="2024-12-31")
|
|
163
|
+
print(full_data.head())
|
|
164
|
+
|
|
165
|
+
# Download multiple symbols at once
|
|
166
|
+
df = pypsx.download(["OGDC", "PPL", "KEL"], period="6mo", interval="1d")
|
|
167
|
+
print(df.head())
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Indices and Sectors
|
|
171
|
+
|
|
172
|
+
```python
|
|
173
|
+
import pypsx
|
|
174
|
+
|
|
175
|
+
# Get all indices overview
|
|
176
|
+
indices = pypsx.get_indices()
|
|
177
|
+
print(indices.head())
|
|
178
|
+
|
|
179
|
+
# Get constituents of an index (e.g., KSE100)
|
|
180
|
+
kse100 = pypsx.index_constituents("KSE100")
|
|
181
|
+
print(f"KSE100 has {len(kse100)} constituents")
|
|
182
|
+
print(kse100.head())
|
|
183
|
+
|
|
184
|
+
# Get sector information
|
|
185
|
+
sectors = pypsx.sector_summary()
|
|
186
|
+
print(sectors.head())
|
|
187
|
+
|
|
188
|
+
# Get complete indices breakdown with statistics
|
|
189
|
+
indices_breakdown = pypsx.get_indices_breakdown()
|
|
190
|
+
print(f"Total indices: {indices_breakdown['total_indices']}")
|
|
191
|
+
print(f"Total unique symbols: {indices_breakdown['unique_symbols']}")
|
|
192
|
+
for idx, count, stats in indices_breakdown['indices'][:5]:
|
|
193
|
+
print(f"{idx}: {count} symbols (Current: {stats.get('current', 'N/A')})")
|
|
194
|
+
|
|
195
|
+
# Get complete sector breakdown with company counts and averages
|
|
196
|
+
sector_breakdown = pypsx.get_sector_breakdown()
|
|
197
|
+
print(f"\nTotal sectors: {sector_breakdown['total_sectors']}")
|
|
198
|
+
print(f"Total companies: {sector_breakdown['total_companies']}")
|
|
199
|
+
for sector in sector_breakdown['sectors'][:5]:
|
|
200
|
+
name = sector['name']
|
|
201
|
+
count = sector['company_count']
|
|
202
|
+
avg_price = sector['averages'].get('current', 'N/A')
|
|
203
|
+
print(f"{name}: {count} companies (Avg Price: {avg_price})")
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Main Features
|
|
207
|
+
|
|
208
|
+
### 1. Stock Information (`PSXTicker`)
|
|
209
|
+
|
|
210
|
+
Create a ticker object for any stock symbol:
|
|
211
|
+
|
|
212
|
+
```python
|
|
213
|
+
ticker = pypsx.PSXTicker("OGDC")
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
**Available Properties:**
|
|
217
|
+
- `ticker.info` - Get company information (price, sector, volume, etc.)
|
|
218
|
+
- `ticker.snapshot` - Get comprehensive snapshot data from all tabs (OHLCV, bid/ask, circuit breaker, ranges, ratios, etc.)
|
|
219
|
+
|
|
220
|
+
**Available Methods:**
|
|
221
|
+
- `ticker.market_watch()` - Get current market watch row for this stock
|
|
222
|
+
- `ticker.sector()` - Get sector-level information
|
|
223
|
+
- `ticker.history(period="1y", interval="1d")` - Get historical data
|
|
224
|
+
- `ticker.intraday()` - Get intraday trades (last ~2 days)
|
|
225
|
+
- `ticker.get_historical(start_date, end_date)` - Get full OHLCV data for date range
|
|
226
|
+
- `ticker.dividends()` - Get dividend information (external source)
|
|
227
|
+
- `ticker.announcements()` - Get company announcements
|
|
228
|
+
- `ticker.orderbook()` - Get trading board data (bid/ask prices)
|
|
229
|
+
|
|
230
|
+
### 2. Market Data Functions
|
|
231
|
+
|
|
232
|
+
```python
|
|
233
|
+
# Full market watch
|
|
234
|
+
market_watch = pypsx.market_watch()
|
|
235
|
+
|
|
236
|
+
# Top performers
|
|
237
|
+
performers = pypsx.top_performers() # Returns dict with "top_gainers", "top_decliners", "top_actives"
|
|
238
|
+
|
|
239
|
+
# Sector summary
|
|
240
|
+
sectors = pypsx.sector_summary()
|
|
241
|
+
|
|
242
|
+
# Trading board (order book)
|
|
243
|
+
orderbook = pypsx.trading_board()
|
|
244
|
+
|
|
245
|
+
# Get detailed quote data for a symbol (OHLCV, bid/ask, PE ratio, 52-week range, etc.)
|
|
246
|
+
quote = pypsx.get_quote("OGDC")
|
|
247
|
+
print(quote)
|
|
248
|
+
|
|
249
|
+
# Get quotes for multiple symbols
|
|
250
|
+
quotes = pypsx.get_quote_batch(["OGDC", "PPL", "KEL"])
|
|
251
|
+
for symbol, quote_df in quotes.items():
|
|
252
|
+
if quote_df is not None:
|
|
253
|
+
print(f"{symbol}: {quote_df}")
|
|
254
|
+
|
|
255
|
+
# Get company fundamentals (business description, financials, ratios, equity profile)
|
|
256
|
+
fundamentals = pypsx.get_company_fundamentals("OGDC")
|
|
257
|
+
print(fundamentals.head())
|
|
258
|
+
# Returns DataFrame with CATEGORY, METRIC, VALUE columns
|
|
259
|
+
# Categories include: Profile, Governance, Financials Annual, Financials Quarterly, Ratios, Equity Profile
|
|
260
|
+
|
|
261
|
+
# Get all symbols
|
|
262
|
+
symbols = pypsx.get_symbols()
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### 3. Batch Downloads
|
|
266
|
+
|
|
267
|
+
```python
|
|
268
|
+
# Download multiple symbols at once
|
|
269
|
+
df = pypsx.download(["OGDC", "PPL", "KEL"], period="1y", interval="1d")
|
|
270
|
+
print(df.head())
|
|
271
|
+
|
|
272
|
+
# Get intraday data for multiple symbols
|
|
273
|
+
intraday_multi = pypsx.get_intraday_multiple(["OGDC", "PPL"])
|
|
274
|
+
print(intraday_multi.head())
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
## Charting and Visualization
|
|
278
|
+
|
|
279
|
+
PyPSX includes powerful charting capabilities to visualize stock data:
|
|
280
|
+
|
|
281
|
+
### Price Charts
|
|
282
|
+
|
|
283
|
+
```python
|
|
284
|
+
import matplotlib.pyplot as plt
|
|
285
|
+
from endpoints.charts import create_price_chart, create_technical_analysis_chart
|
|
286
|
+
|
|
287
|
+
# Create a candlestick chart
|
|
288
|
+
fig = create_price_chart("OGDC", period="1y", chart_type="candlestick")
|
|
289
|
+
plt.show()
|
|
290
|
+
|
|
291
|
+
# Create a line chart
|
|
292
|
+
fig = create_price_chart("PPL", period="6mo", chart_type="line")
|
|
293
|
+
plt.show()
|
|
294
|
+
|
|
295
|
+
# Create technical analysis chart with indicators
|
|
296
|
+
fig = create_technical_analysis_chart("OGDC", period="1y")
|
|
297
|
+
plt.show()
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### Comparison Charts
|
|
301
|
+
|
|
302
|
+
```python
|
|
303
|
+
from endpoints.charts import create_multi_symbol_chart, create_index_comparison_chart
|
|
304
|
+
|
|
305
|
+
# Compare multiple stocks
|
|
306
|
+
fig = create_multi_symbol_chart(["OGDC", "PPL", "KEL"], period="1y")
|
|
307
|
+
plt.show()
|
|
308
|
+
|
|
309
|
+
# Compare indices
|
|
310
|
+
fig = create_index_comparison_chart(["KSE100", "KMI30"], period="1y")
|
|
311
|
+
plt.show()
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### Correlation Analysis
|
|
315
|
+
|
|
316
|
+
```python
|
|
317
|
+
from endpoints.charts import create_correlation_heatmap
|
|
318
|
+
|
|
319
|
+
# Create correlation heatmap
|
|
320
|
+
fig = create_correlation_heatmap(["OGDC", "PPL", "KEL", "PSO"], period="1y")
|
|
321
|
+
plt.show()
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
**Available Chart Functions:**
|
|
325
|
+
- `create_price_chart(symbol, period, chart_type)` - Price charts (candlestick, line, OHLC)
|
|
326
|
+
- `create_technical_analysis_chart(symbol, period)` - Charts with technical indicators
|
|
327
|
+
- `create_multi_symbol_chart(symbols, period)` - Compare multiple stocks
|
|
328
|
+
- `create_index_comparison_chart(indices, period)` - Compare indices
|
|
329
|
+
- `create_correlation_heatmap(symbols, period)` - Correlation analysis
|
|
330
|
+
|
|
331
|
+
## Analysis and Statistics
|
|
332
|
+
|
|
333
|
+
PyPSX includes comprehensive analysis tools for stock data:
|
|
334
|
+
|
|
335
|
+
### Statistical Analysis
|
|
336
|
+
|
|
337
|
+
```python
|
|
338
|
+
from pypsx.analysis import returns, volatility, correlation, sharpe_ratio
|
|
339
|
+
|
|
340
|
+
ticker = pypsx.PSXTicker("OGDC")
|
|
341
|
+
df = ticker.history(period="1y")
|
|
342
|
+
|
|
343
|
+
# Calculate returns
|
|
344
|
+
rets = returns(df)
|
|
345
|
+
print(rets.head())
|
|
346
|
+
|
|
347
|
+
# Calculate volatility
|
|
348
|
+
vol = volatility(df)
|
|
349
|
+
print(vol.head())
|
|
350
|
+
|
|
351
|
+
# Calculate Sharpe ratio
|
|
352
|
+
sharpe = sharpe_ratio(df)
|
|
353
|
+
print(f"Sharpe Ratio: {sharpe:.3f}")
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
### Technical Indicators
|
|
357
|
+
|
|
358
|
+
```python
|
|
359
|
+
# Import indicators
|
|
360
|
+
from analysis import moving_average, rsi, macd, bollinger_bands, exponential_moving_average
|
|
361
|
+
# Or: from pypsx.analysis import moving_average, rsi, macd, bollinger_bands
|
|
362
|
+
|
|
363
|
+
ticker = pypsx.PSXTicker("OGDC")
|
|
364
|
+
df = ticker.history(period="1y")
|
|
365
|
+
|
|
366
|
+
# Moving averages
|
|
367
|
+
df['SMA20'] = moving_average(df, window=20)
|
|
368
|
+
df['EMA12'] = exponential_moving_average(df, window=12)
|
|
369
|
+
|
|
370
|
+
# RSI (supports both 'period' and 'window' parameter names)
|
|
371
|
+
df['RSI'] = rsi(df, period=14)
|
|
372
|
+
|
|
373
|
+
# MACD
|
|
374
|
+
macd_line, signal, histogram = macd(df)
|
|
375
|
+
df['MACD'] = macd_line
|
|
376
|
+
df['Signal'] = signal
|
|
377
|
+
|
|
378
|
+
# Bollinger Bands
|
|
379
|
+
ma, upper, lower = bollinger_bands(df, window=20)
|
|
380
|
+
df['BB_Upper'] = upper
|
|
381
|
+
df['BB_Lower'] = lower
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
### Automated Insights
|
|
385
|
+
|
|
386
|
+
```python
|
|
387
|
+
# Import insight functions
|
|
388
|
+
from analysis import interpret_stock, quick_analysis
|
|
389
|
+
# Or: from pypsx.analysis import interpret_stock, quick_analysis
|
|
390
|
+
|
|
391
|
+
ticker = pypsx.PSXTicker("OGDC")
|
|
392
|
+
df = ticker.history(period="1y")
|
|
393
|
+
|
|
394
|
+
# Generate comprehensive insights
|
|
395
|
+
insights = interpret_stock(df, "OGDC")
|
|
396
|
+
print("Insights:")
|
|
397
|
+
for insight in insights['insights']:
|
|
398
|
+
print(f" - {insight}")
|
|
399
|
+
|
|
400
|
+
# Quick analysis
|
|
401
|
+
analysis = quick_analysis(df, "OGDC")
|
|
402
|
+
print(f"Trading Signal: {analysis['trading_signal']}")
|
|
403
|
+
print(f"Sharpe Ratio: {analysis['key_metrics']['sharpe_ratio']:.3f}")
|
|
404
|
+
print(f"Max Drawdown: {analysis['key_metrics']['max_drawdown']:.3f}")
|
|
405
|
+
print(f"Total Return: {analysis['key_metrics']['total_return']:.2%}")
|
|
406
|
+
|
|
407
|
+
# Get trading signals directly
|
|
408
|
+
from analysis import generate_trading_signals
|
|
409
|
+
signals = generate_trading_signals(df, "OGDC")
|
|
410
|
+
print(f"Primary Signal: {signals['primary_signal']}")
|
|
411
|
+
print(f"Confidence: {signals['confidence']:.2%}")
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
**Available Analysis Functions:**
|
|
415
|
+
|
|
416
|
+
All analysis functions are available from the `analysis` package:
|
|
417
|
+
|
|
418
|
+
- **Statistics**: `returns()`, `volatility()`, `correlation()`, `beta()`, `correlation_matrix()`
|
|
419
|
+
- **Indicators**: `moving_average()`, `rsi()`, `macd()`, `bollinger_bands()`, `stochastic()`, `williams_r()`, `atr()`, `adx()`, `cci()`, `obv()`, `vwap()`
|
|
420
|
+
- **Performance**: `sharpe_ratio()`, `sortino_ratio()`, `calmar_ratio()`, `drawdown()`, `max_drawdown()`, `information_ratio()`, `treynor_ratio()`
|
|
421
|
+
- **Insights**: `interpret_stock()`, `quick_analysis()`, `portfolio_analysis()`, `market_sentiment_analysis()`, `generate_trading_signals()`
|
|
422
|
+
|
|
423
|
+
Import them like: `from analysis import sharpe_ratio, rsi` or `from pypsx.analysis import sharpe_ratio, rsi`
|
|
424
|
+
|
|
425
|
+
## Market Analysis and Breakdowns
|
|
426
|
+
|
|
427
|
+
### Indices Breakdown
|
|
428
|
+
|
|
429
|
+
Get a comprehensive breakdown of all PSX indices with constituent counts and statistics:
|
|
430
|
+
|
|
431
|
+
```python
|
|
432
|
+
import pypsx
|
|
433
|
+
|
|
434
|
+
# Get indices breakdown
|
|
435
|
+
breakdown = pypsx.get_indices_breakdown()
|
|
436
|
+
|
|
437
|
+
print(f"Total Indices: {breakdown['total_indices']}")
|
|
438
|
+
print(f"Total Symbols Analyzed: {breakdown['total_symbols_analyzed']}")
|
|
439
|
+
print(f"Unique Symbols: {breakdown['unique_symbols']}")
|
|
440
|
+
|
|
441
|
+
# Print breakdown
|
|
442
|
+
for idx, count, stats in breakdown['indices']:
|
|
443
|
+
current = stats.get('current', 'N/A')
|
|
444
|
+
change_pct = stats.get('percentage_change', 'N/A')
|
|
445
|
+
print(f"{idx}: {count} symbols (Current: {current}, Change: {change_pct}%)")
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
**Output includes:**
|
|
449
|
+
- Total number of indices
|
|
450
|
+
- Constituent count for each index
|
|
451
|
+
- Index statistics (Current value, Change, Change %)
|
|
452
|
+
- Total symbols analyzed (with duplicates across indices)
|
|
453
|
+
- Unique symbols across all indices
|
|
454
|
+
|
|
455
|
+
**Example Output:**
|
|
456
|
+
```
|
|
457
|
+
PSX Indices Summary
|
|
458
|
+
|
|
459
|
+
**Total Indices in PSX: 18 unique indices**
|
|
460
|
+
|
|
461
|
+
Complete Breakdown:
|
|
462
|
+
|
|
463
|
+
1. *ALLSHR* - 549 symbols (Current: 98254.73, Change: 2590.07, Change %: 2.71%)
|
|
464
|
+
2. *KMIALLSHR* - 259 symbols (Current: 64179.60, Change: 1496.52, Change %: 2.39%)
|
|
465
|
+
3. *KSE100* - 100 symbols (Current: 161631.73, Change: 4898.86, Change %: 3.13%)
|
|
466
|
+
...
|
|
467
|
+
|
|
468
|
+
*Total symbols analyzed: 1217* across all indices.
|
|
469
|
+
|
|
470
|
+
*Total unique symbols: 549* across all indices.
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
### Sector Breakdown
|
|
474
|
+
|
|
475
|
+
Get a comprehensive breakdown of all PSX sectors with company counts and computed averages:
|
|
476
|
+
|
|
477
|
+
```python
|
|
478
|
+
import pypsx
|
|
479
|
+
|
|
480
|
+
# Get sector breakdown
|
|
481
|
+
breakdown = pypsx.get_sector_breakdown()
|
|
482
|
+
|
|
483
|
+
print(f"Total Sectors: {breakdown['total_sectors']}")
|
|
484
|
+
print(f"Total Companies: {breakdown['total_companies']}")
|
|
485
|
+
|
|
486
|
+
# Print breakdown
|
|
487
|
+
for sector in breakdown['sectors'][:10]: # Top 10 sectors
|
|
488
|
+
name = sector['name']
|
|
489
|
+
count = sector['company_count']
|
|
490
|
+
code = sector['code']
|
|
491
|
+
avg_price = sector['averages'].get('current', 0)
|
|
492
|
+
avg_change = sector['averages'].get('change_%', 0)
|
|
493
|
+
advances = sector['advances']
|
|
494
|
+
declines = sector['declines']
|
|
495
|
+
|
|
496
|
+
print(f"{name} (Code: {code}):")
|
|
497
|
+
print(f" Companies: {count}")
|
|
498
|
+
print(f" Avg Price: {avg_price:.2f}")
|
|
499
|
+
print(f" Avg Change %: {avg_change:.2f}%")
|
|
500
|
+
print(f" Advances: {advances}, Declines: {declines}")
|
|
501
|
+
print()
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
**Output includes:**
|
|
505
|
+
- Total number of sectors
|
|
506
|
+
- Company count per sector
|
|
507
|
+
- Average prices, volumes, changes per sector
|
|
508
|
+
- Sector-level statistics (advances, declines, turnover)
|
|
509
|
+
- Total companies across all sectors
|
|
510
|
+
|
|
511
|
+
**Example Output:**
|
|
512
|
+
```
|
|
513
|
+
PSX Sectorwise Summary
|
|
514
|
+
|
|
515
|
+
**Total Sectors in PSX: 37 unique sectors**
|
|
516
|
+
|
|
517
|
+
Complete Breakdown:
|
|
518
|
+
|
|
519
|
+
1. *TEXTILE SPINNING* (Code: 830) - 46 companies (Avg Price: 78.31, Avg Volume: 435833) [Advances: 24, Declines: 14, Turnover: 20048323]
|
|
520
|
+
2. *TEXTILE COMPOSITE* (Code: 829) - 39 companies (Avg Price: 192.50, Avg Volume: 254652) [Advances: 25, Declines: 8, Turnover: 9931432]
|
|
521
|
+
3. *INV. BANKS / INV. COS. / SECURITIES COS.* (Code: 813) - 35 companies (Avg Price: 756.90, Avg Volume: 2230213) [Advances: 30, Declines: 2, Turnover: 77778422]
|
|
522
|
+
...
|
|
523
|
+
|
|
524
|
+
*Total companies analyzed: 486* across all sectors.
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
## Advanced Usage
|
|
528
|
+
|
|
529
|
+
### Company Information
|
|
530
|
+
|
|
531
|
+
```python
|
|
532
|
+
import pypsx
|
|
533
|
+
|
|
534
|
+
ticker = pypsx.PSXTicker("OGDC")
|
|
535
|
+
|
|
536
|
+
# Get detailed quote data (includes OHLCV, bid/ask prices, PE ratio, 52-week range, VAR, etc.)
|
|
537
|
+
quote = pypsx.get_quote("OGDC")
|
|
538
|
+
print(quote)
|
|
539
|
+
# Output includes: OPEN, HIGH, LOW, VOLUME, BID_PRICE, ASK_PRICE, PE_RATIO, VAR, HAIRCUT, etc.
|
|
540
|
+
|
|
541
|
+
# Get quotes for multiple symbols
|
|
542
|
+
quotes = pypsx.get_quote_batch(["OGDC", "PPL", "KEL"])
|
|
543
|
+
for symbol, quote_df in quotes.items():
|
|
544
|
+
if quote_df is not None:
|
|
545
|
+
print(f"{symbol} Quote:")
|
|
546
|
+
print(quote_df)
|
|
547
|
+
|
|
548
|
+
# Get company fundamentals (business description, financials, ratios, equity profile)
|
|
549
|
+
fundamentals = pypsx.get_company_fundamentals("OGDC")
|
|
550
|
+
print(fundamentals.head())
|
|
551
|
+
|
|
552
|
+
# Get comprehensive snapshot data from all tabs (most holistic approach)
|
|
553
|
+
snapshot = pypsx.get_snapshot("BOP")
|
|
554
|
+
print(snapshot['REG']) # REG tab contains: OHLCV, circuit breaker, ranges, bid/ask, ratios, etc.
|
|
555
|
+
# Or use ticker.snapshot property:
|
|
556
|
+
ticker = pypsx.PSXTicker("BOP")
|
|
557
|
+
snap = ticker.snapshot
|
|
558
|
+
print(f"Open: {snap['REG']['Open']}")
|
|
559
|
+
print(f"52-Week Range: {snap['REG']['52-WEEK RANGE ^']}")
|
|
560
|
+
|
|
561
|
+
# Get announcements
|
|
562
|
+
announcements = ticker.announcements()
|
|
563
|
+
print(announcements.head())
|
|
564
|
+
|
|
565
|
+
# Get dividends
|
|
566
|
+
dividends = ticker.dividends()
|
|
567
|
+
print(dividends)
|
|
568
|
+
|
|
569
|
+
# Get order book
|
|
570
|
+
orderbook = ticker.orderbook()
|
|
571
|
+
print(orderbook)
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
### Custom Date Ranges
|
|
575
|
+
|
|
576
|
+
```python
|
|
577
|
+
ticker = pypsx.PSXTicker("OGDC")
|
|
578
|
+
|
|
579
|
+
# Get historical data for specific date range
|
|
580
|
+
historical = ticker.get_historical(
|
|
581
|
+
start_date="2024-01-01",
|
|
582
|
+
end_date="2024-12-31"
|
|
583
|
+
)
|
|
584
|
+
print(historical.head())
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
## Data Sources
|
|
588
|
+
|
|
589
|
+
PyPSX uses official Pakistan Stock Exchange DPS endpoints:
|
|
590
|
+
- Market Watch: `https://dps.psx.com.pk/market-watch`
|
|
591
|
+
- Sector Summary: `https://dps.psx.com.pk/sector-summary/sectorwise`
|
|
592
|
+
- Indices: `https://dps.psx.com.pk/indices/{INDEX}`
|
|
593
|
+
- Trading Board: `https://dps.psx.com.pk/trading-board/REG/main`
|
|
594
|
+
- Performers: `https://dps.psx.com.pk/performers`
|
|
595
|
+
- Timeseries: `https://dps.psx.com.pk/timeseries/int/{SYMBOL}`, `.../eod/{SYMBOL}`
|
|
596
|
+
- Historical OHLCV: `https://dps.psx.com.pk/historical`
|
|
597
|
+
|
|
598
|
+
## Examples
|
|
599
|
+
|
|
600
|
+
### Example 1: Find Top Volume Stocks
|
|
601
|
+
|
|
602
|
+
```python
|
|
603
|
+
import pypsx
|
|
604
|
+
|
|
605
|
+
# Get market watch
|
|
606
|
+
mw = pypsx.market_watch()
|
|
607
|
+
|
|
608
|
+
# Sort by volume and get top 5
|
|
609
|
+
top_volume = mw.nlargest(5, "Volume")[['Current', 'Change %', 'Volume']]
|
|
610
|
+
print(top_volume)
|
|
611
|
+
```
|
|
612
|
+
|
|
613
|
+
### Example 2: Compare Stock Performance
|
|
614
|
+
|
|
615
|
+
```python
|
|
616
|
+
import pypsx
|
|
617
|
+
from endpoints.charts import create_multi_symbol_chart
|
|
618
|
+
import matplotlib.pyplot as plt
|
|
619
|
+
|
|
620
|
+
# Compare three stocks
|
|
621
|
+
fig = create_multi_symbol_chart(["OGDC", "PPL", "KEL"], period="6mo")
|
|
622
|
+
plt.show()
|
|
623
|
+
|
|
624
|
+
# Save chart to file
|
|
625
|
+
fig = create_multi_symbol_chart(["OGDC", "PPL"], period="1y", save_path="comparison.png")
|
|
626
|
+
```
|
|
627
|
+
|
|
628
|
+
### Example 3: Technical Analysis
|
|
629
|
+
|
|
630
|
+
```python
|
|
631
|
+
import pypsx
|
|
632
|
+
from analysis import rsi, macd, bollinger_bands
|
|
633
|
+
import pandas as pd
|
|
634
|
+
|
|
635
|
+
ticker = pypsx.PSXTicker("OGDC")
|
|
636
|
+
df = ticker.history(period="1y")
|
|
637
|
+
|
|
638
|
+
# Add technical indicators
|
|
639
|
+
df['RSI'] = rsi(df, period=14)
|
|
640
|
+
macd_line, signal, _ = macd(df)
|
|
641
|
+
df['MACD'] = macd_line
|
|
642
|
+
df['Signal'] = signal
|
|
643
|
+
|
|
644
|
+
ma, upper, lower = bollinger_bands(df)
|
|
645
|
+
df['BB_Upper'] = upper
|
|
646
|
+
df['BB_Lower'] = lower
|
|
647
|
+
|
|
648
|
+
# Simple trading signal (SMA crossover)
|
|
649
|
+
df['SMA20'] = df['CLOSE'].rolling(20).mean()
|
|
650
|
+
df['SMA50'] = df['CLOSE'].rolling(50).mean()
|
|
651
|
+
df['Signal'] = (df['SMA20'] > df['SMA50']).astype(int)
|
|
652
|
+
|
|
653
|
+
print(df[['CLOSE', 'RSI', 'MACD', 'Signal']].tail())
|
|
654
|
+
```
|
|
655
|
+
|
|
656
|
+
### Example 4: Portfolio Analysis
|
|
657
|
+
|
|
658
|
+
```python
|
|
659
|
+
import pypsx
|
|
660
|
+
from analysis import portfolio_analysis
|
|
661
|
+
|
|
662
|
+
# Create a portfolio
|
|
663
|
+
portfolio = {
|
|
664
|
+
"OGDC": pypsx.PSXTicker("OGDC").history(period="1y"),
|
|
665
|
+
"PPL": pypsx.PSXTicker("PPL").history(period="1y"),
|
|
666
|
+
"PPL": pypsx.PSXTicker("PPL").history(period="1y")
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
# Analyze portfolio
|
|
670
|
+
analysis = portfolio_analysis(portfolio)
|
|
671
|
+
print(f"Portfolio Sharpe Ratio: {analysis['sharpe_ratio']:.3f}")
|
|
672
|
+
print(f"Portfolio Volatility: {analysis['volatility']:.3f}")
|
|
673
|
+
```
|
|
674
|
+
|
|
675
|
+
## API Reference
|
|
676
|
+
|
|
677
|
+
### PSXTicker Class
|
|
678
|
+
|
|
679
|
+
```python
|
|
680
|
+
ticker = pypsx.PSXTicker(symbol: str)
|
|
681
|
+
|
|
682
|
+
# Properties
|
|
683
|
+
ticker.info # Dict with company info
|
|
684
|
+
ticker.snapshot # Dict with comprehensive snapshot data from all tabs
|
|
685
|
+
ticker.fast_info # Quick metrics dict
|
|
686
|
+
|
|
687
|
+
# Methods
|
|
688
|
+
ticker.history(period="1y", interval="1d") # Historical data
|
|
689
|
+
ticker.intraday() # Intraday trades
|
|
690
|
+
ticker.get_historical(start_date, end_date) # Full OHLCV data
|
|
691
|
+
ticker.market_watch() # Market watch row
|
|
692
|
+
ticker.sector() # Sector information
|
|
693
|
+
ticker.orderbook() # Trading board data
|
|
694
|
+
ticker.dividends() # DataFrame with dividends
|
|
695
|
+
ticker.announcements() # DataFrame with announcements
|
|
696
|
+
```
|
|
697
|
+
|
|
698
|
+
### Market Functions
|
|
699
|
+
|
|
700
|
+
```python
|
|
701
|
+
pypsx.market_watch() # Full market watch DataFrame
|
|
702
|
+
pypsx.top_performers() # Dict: {top_gainers, top_decliners, top_actives}
|
|
703
|
+
pypsx.sector_summary() # Sector summary DataFrame
|
|
704
|
+
pypsx.get_indices() # Indices overview DataFrame
|
|
705
|
+
pypsx.get_indices_breakdown() # Complete indices breakdown with counts and stats
|
|
706
|
+
pypsx.get_sector_breakdown() # Complete sector breakdown with company counts and averages
|
|
707
|
+
pypsx.get_symbols() # List of all stock symbols
|
|
708
|
+
pypsx.trading_board() # Trading board DataFrame
|
|
709
|
+
|
|
710
|
+
# Quote functions - Get detailed quote data (OHLCV, bid/ask, PE ratio, 52-week range, etc.)
|
|
711
|
+
pypsx.get_quote(symbol) # Get detailed quote for a single symbol
|
|
712
|
+
pypsx.get_quote_batch(symbols) # Get quotes for multiple symbols (returns dict)
|
|
713
|
+
|
|
714
|
+
# Company fundamentals - Get comprehensive company data (business description, financials, ratios, etc.)
|
|
715
|
+
pypsx.get_company_fundamentals(symbol) # Get company fundamentals (returns DataFrame)
|
|
716
|
+
|
|
717
|
+
# Snapshot - Get comprehensive snapshot data from all tabs (most holistic approach)
|
|
718
|
+
pypsx.get_snapshot(symbol) # Get snapshot data from all tabs (returns dict with tab names as keys)
|
|
719
|
+
# Or use ticker.snapshot property for easier access
|
|
720
|
+
```
|
|
721
|
+
|
|
722
|
+
### Download Functions
|
|
723
|
+
|
|
724
|
+
```python
|
|
725
|
+
pypsx.download(symbols, period="1y", interval="1d") # Batch download
|
|
726
|
+
pypsx.get_intraday_multiple(symbols) # Multiple intraday
|
|
727
|
+
pypsx.get_historical(symbol, start_date, end_date) # Historical OHLCV
|
|
728
|
+
```
|
|
729
|
+
|
|
730
|
+
## Backward Compatibility
|
|
731
|
+
|
|
732
|
+
The library maintains backward compatibility:
|
|
733
|
+
- `pypsx.Ticker` is an alias for `pypsx.PSXTicker`
|
|
734
|
+
- `pypsx.PSXSymbol` is also available (legacy)
|
|
735
|
+
|
|
736
|
+
## Notes
|
|
737
|
+
|
|
738
|
+
- **Dividends**: PSX doesn't provide a dividends endpoint. The `dividends` property uses an external data source.
|
|
739
|
+
- **Data Availability**: Some data may not be available when the market is closed.
|
|
740
|
+
- **Symbol Names**: Use official PSX symbols (e.g., "OGDC", "PPL", "KEL").
|
|
741
|
+
|
|
742
|
+
## License
|
|
743
|
+
|
|
744
|
+
Proprietary — All rights reserved. Unauthorized use, copying, or distribution is prohibited.
|