yfinance-ir 2026.9.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.
Files changed (40) hide show
  1. yfinance_ir-2026.9.2/LICENSE +21 -0
  2. yfinance_ir-2026.9.2/PKG-INFO +265 -0
  3. yfinance_ir-2026.9.2/README.md +218 -0
  4. yfinance_ir-2026.9.2/pyproject.toml +75 -0
  5. yfinance_ir-2026.9.2/setup.cfg +4 -0
  6. yfinance_ir-2026.9.2/tests/test_crypto.py +162 -0
  7. yfinance_ir-2026.9.2/tests/test_fundamentals.py +163 -0
  8. yfinance_ir-2026.9.2/tests/test_history.py +218 -0
  9. yfinance_ir-2026.9.2/tests/test_http.py +70 -0
  10. yfinance_ir-2026.9.2/tests/test_intraday.py +258 -0
  11. yfinance_ir-2026.9.2/tests/test_live.py +155 -0
  12. yfinance_ir-2026.9.2/tests/test_multi.py +86 -0
  13. yfinance_ir-2026.9.2/tests/test_options.py +119 -0
  14. yfinance_ir-2026.9.2/tests/test_resolver.py +94 -0
  15. yfinance_ir-2026.9.2/tests/test_sci.py +188 -0
  16. yfinance_ir-2026.9.2/yfinance_ir/__init__.py +44 -0
  17. yfinance_ir-2026.9.2/yfinance_ir/_cache.py +114 -0
  18. yfinance_ir-2026.9.2/yfinance_ir/_dates.py +99 -0
  19. yfinance_ir-2026.9.2/yfinance_ir/_http.py +132 -0
  20. yfinance_ir-2026.9.2/yfinance_ir/config.py +51 -0
  21. yfinance_ir-2026.9.2/yfinance_ir/exceptions.py +38 -0
  22. yfinance_ir-2026.9.2/yfinance_ir/fundamentals.py +219 -0
  23. yfinance_ir-2026.9.2/yfinance_ir/history.py +435 -0
  24. yfinance_ir-2026.9.2/yfinance_ir/intraday.py +255 -0
  25. yfinance_ir-2026.9.2/yfinance_ir/multi.py +112 -0
  26. yfinance_ir-2026.9.2/yfinance_ir/py.typed +0 -0
  27. yfinance_ir-2026.9.2/yfinance_ir/resolver.py +263 -0
  28. yfinance_ir-2026.9.2/yfinance_ir/search.py +51 -0
  29. yfinance_ir-2026.9.2/yfinance_ir/sources/__init__.py +1 -0
  30. yfinance_ir-2026.9.2/yfinance_ir/sources/codal.py +119 -0
  31. yfinance_ir-2026.9.2/yfinance_ir/sources/crypto.py +211 -0
  32. yfinance_ir-2026.9.2/yfinance_ir/sources/sci.py +215 -0
  33. yfinance_ir-2026.9.2/yfinance_ir/sources/tgju.py +139 -0
  34. yfinance_ir-2026.9.2/yfinance_ir/sources/tsetmc.py +182 -0
  35. yfinance_ir-2026.9.2/yfinance_ir/ticker.py +569 -0
  36. yfinance_ir-2026.9.2/yfinance_ir.egg-info/PKG-INFO +265 -0
  37. yfinance_ir-2026.9.2/yfinance_ir.egg-info/SOURCES.txt +38 -0
  38. yfinance_ir-2026.9.2/yfinance_ir.egg-info/dependency_links.txt +1 -0
  39. yfinance_ir-2026.9.2/yfinance_ir.egg-info/requires.txt +24 -0
  40. yfinance_ir-2026.9.2/yfinance_ir.egg-info/top_level.txt +1 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Kiyarash Fazeli
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,265 @@
1
+ Metadata-Version: 2.4
2
+ Name: yfinance-ir
3
+ Version: 2026.9.2
4
+ Summary: yfinance-style market data for Iranian markets (TSETMC, Codal, TGJU)
5
+ Author-email: Kiyarash Fazeli <caci96@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/Fazel94/yfinance-ir
8
+ Project-URL: Repository, https://github.com/Fazel94/yfinance-ir
9
+ Project-URL: Issues, https://github.com/Fazel94/yfinance-ir/issues
10
+ Project-URL: Changelog, https://github.com/Fazel94/yfinance-ir/blob/main/CHANGELOG.md
11
+ Keywords: tsetmc,codal,tgju,iran,bourse,stocks,finance
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Financial and Insurance Industry
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Office/Business :: Financial :: Investment
22
+ Requires-Python: >=3.9
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: requests>=2.28
26
+ Requires-Dist: pandas>=1.5
27
+ Requires-Dist: numpy>=1.21
28
+ Requires-Dist: jdatetime>=4
29
+ Requires-Dist: openpyxl>=3.1
30
+ Provides-Extra: dev
31
+ Requires-Dist: pytest; extra == "dev"
32
+ Requires-Dist: responses; extra == "dev"
33
+ Requires-Dist: ruff; extra == "dev"
34
+ Provides-Extra: crypto
35
+ Requires-Dist: ccxt-ir>=4; extra == "crypto"
36
+ Provides-Extra: notebook
37
+ Requires-Dist: matplotlib>=3.8; extra == "notebook"
38
+ Requires-Dist: seaborn>=0.13; extra == "notebook"
39
+ Requires-Dist: scipy>=1.11; extra == "notebook"
40
+ Requires-Dist: statsmodels>=0.14; extra == "notebook"
41
+ Requires-Dist: backtrader>=1.9.78; extra == "notebook"
42
+ Requires-Dist: ipykernel; extra == "notebook"
43
+ Requires-Dist: nbconvert; extra == "notebook"
44
+ Requires-Dist: arabic-reshaper>=3.0; extra == "notebook"
45
+ Requires-Dist: python-bidi>=0.6; extra == "notebook"
46
+ Dynamic: license-file
47
+
48
+ # yfinance-ir
49
+
50
+ [![CI](https://github.com/Fazel94/yfinance-ir/actions/workflows/ci.yml/badge.svg)](https://github.com/Fazel94/yfinance-ir/actions/workflows/ci.yml)
51
+ ![Python](https://img.shields.io/badge/python-3.9%20%7C%203.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-blue)
52
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
53
+
54
+ [فارسی](README.fa.md)
55
+
56
+ <div dir="rtl">
57
+
58
+ داده‌های بازار ایران با رابط آشنای `yfinance`: سهام، صندوق‌ها و شاخص‌های بورس تهران (TSETMC)،
59
+ صورت‌های مالی کدال، دلار، طلا و سکه از TGJU، تورم مرکز آمار ایران و رمزارزها از صرافی‌های ایرانی.
60
+
61
+ </div>
62
+
63
+ `yfinance`-shaped market data for the Iranian markets: TSETMC (equities, ETFs, indices),
64
+ Codal (financial statements), TGJU (FX, gold, coins), the Statistical Centre of Iran (CPI)
65
+ and, with the `crypto` extra, Iranian crypto exchanges through `ccxt-ir`.
66
+
67
+ > **Iranian IP required.** `cdn.tsetmc.com` drops foreign IPs.
68
+
69
+ [![Since Nowruz 1405: which assets beat inflation and which beat the dollar](examples/scoreboard.png)](examples/scoreboard.ipynb)
70
+
71
+ One `history()` call per bar: TSETMC indices, stocks and ETFs, TGJU's dollar, euro, gold
72
+ and coin, Nobitex bitcoin, measured against the SCI CPI and the free-market dollar.
73
+ [`examples/scoreboard.ipynb`](examples/scoreboard.ipynb) draws it, the same race as a
74
+ path since Nowruz and over five years, and a seven-window heatmap of real and dollar
75
+ returns. Charts are in Persian; install from `main` for its two text-shaping extras:
76
+ `pip install "yfinance-ir[crypto,notebook] @ git+https://github.com/Fazel94/yfinance-ir.git"`.
77
+
78
+ Monthly update of this chart: X [@_fazel94](https://x.com/_fazel94)
79
+
80
+
81
+ ## Install
82
+
83
+ ```bash
84
+ pip install "yfinance-ir @ git+https://github.com/Fazel94/yfinance-ir.git@v2026.9.2" # TSETMC + Codal + TGJU + CPI
85
+ pip install "yfinance-ir[crypto] @ git+https://github.com/Fazel94/yfinance-ir.git@v2026.9.2" # adds BTC-IRT / ETH-USDT style pairs
86
+ ```
87
+
88
+ Not on PyPI yet: install from a release tag. Each [GitHub Release](https://github.com/Fazel94/yfinance-ir/releases) also carries the wheel and sdist.
89
+
90
+ ## Quickstart
91
+
92
+ ```python
93
+ import yfinance_ir as yf
94
+
95
+ folad = yf.Ticker("فولاد")
96
+ folad.history(period="1y") # adjusted daily OHLCV
97
+ folad.history(period="5d", interval="5m") # intraday bars rebuilt from TSETMC trades
98
+ folad.info["marketCap"]
99
+ folad.income_stmt # Codal, wide, newest period first
100
+ folad.cashflow # Codal cash-flow statement
101
+ yf.Ticker("اهرم").option_chain() # nearest expiration: calls, puts, underlying
102
+
103
+ yf.download(["فولاد", "فملی"], period="6mo")
104
+ yf.Ticker("USD").history(period="5y") # TGJU dollar, Rial
105
+ yf.Ticker("شاخص کل").history() # TEDPIX
106
+ yf.Ticker("CPI").history() # SCI consumer price index, monthly
107
+ yf.Ticker("BTC-IRT").history() # Nobitex, needs the `crypto` extra
108
+ ```
109
+
110
+ ### Example: فولاد in Rial, USD and real terms
111
+
112
+ [`examples/real_returns.py`](examples/real_returns.py) prices فولاد in TGJU dollars and
113
+ deflates it by the SCI CPI. Both series are forward-filled onto the stock's trading days.
114
+
115
+ ```python
116
+ import pandas as pd
117
+
118
+ folad = yf.Ticker("فولاد").history(period="5y")["Close"]
119
+ usd = yf.Ticker("USD").history(period="5y")["Close"].reindex(folad.index, method="ffill")
120
+ cpi = yf.Ticker("CPI").history(period="5y")["Close"].reindex(folad.index, method="ffill")
121
+
122
+ frame = pd.DataFrame({"Rial": folad, "USD": folad / usd, "Real": folad / cpi * cpi.iloc[-1]})
123
+ print(frame.iloc[-1] / frame.iloc[0] - 1)
124
+ ```
125
+
126
+ Output on 2026-09-21:
127
+
128
+ ```
129
+ فولاد 2021-09-25 -> 2026-09-21 (5.0y)
130
+ total annualised
131
+ Rial +228.1% +26.9%
132
+ USD -60.8% -17.1%
133
+ Real -52.0% -13.7%
134
+ ```
135
+
136
+ [examples/cookbook.ipynb](examples/cookbook.ipynb) runs the recipes of chapters 1, 2 and 7
137
+ of *Python for Finance Cookbook* (returns, CPI deflation, outliers, stylised facts,
138
+ SMA/Bollinger/RSI backtests with backtrader, 1/n portfolio, Monte Carlo efficient frontier)
139
+ on TSETMC stocks and Nobitex crypto pairs. Install its dependencies with
140
+ `pip install "yfinance-ir[crypto,notebook] @ git+https://github.com/Fazel94/yfinance-ir.git@v2026.9.2"`.
141
+
142
+ ## Symbols
143
+
144
+ | You pass | Resolves to | Example |
145
+ |---|---|---|
146
+ | Persian symbol | TSETMC instrument | `Ticker("فولاد")`, `Ticker("اهرم")` |
147
+ | Persian index name | TSETMC index | `Ticker("شاخص کل")` |
148
+ | InsCode (10–20 digits) | TSETMC instrument | `Ticker("46348559193224090")` |
149
+ | TGJU alias or slug | FX / gold / coin | `Ticker("USD")`, `Ticker("geram18")` |
150
+ | `CPI`, `CPI_URBAN`, `CPI_RURAL` | SCI price index | `Ticker("CPI")` |
151
+ | `BASE-IRT` / `BASE-USDT` | crypto pair | `Ticker("BTC-IRT")` |
152
+ | ISIN | cache lookup only, see below | `Ticker("IRO1FOLD0009")` |
153
+
154
+ Persian and Arabic spellings are unified (`ی`/`ي`, `ک`/`ك`, ZWNJ). TGJU aliases and the
155
+ per-source rules are in [docs/data-sources.md](docs/data-sources.md). Resolutions are cached
156
+ in `~/.cache/yfinance_ir/symbols.sqlite`; `yf.cache.clear()` drops them,
157
+ `yf.set_config(cache_dir=...)` moves them.
158
+
159
+ ## Ticker API
160
+
161
+ | Member | Source | Notes |
162
+ |---|---|---|
163
+ | `history(...)` | TSETMC / TGJU / SCI / crypto | daily OHLCV (monthly for CPI), adjusted by default; TSETMC also `1m`–`90m` and `1h` bars rebuilt from trades |
164
+ | `info` | TSETMC | yfinance-style keys: `marketCap`, `trailingPE`, `sharesOutstanding`, … |
165
+ | `dividends`, `splits`, `actions` | TSETMC adjust + share-change | see docs/conventions.md |
166
+ | `orderbook` | TSETMC / exchange | 5 levels, bid/ask price-volume-count |
167
+ | `client_types`, `client_type_history()` | TSETMC | individual vs institutional flow |
168
+ | `major_holders` | TSETMC | > 1 % shareholders |
169
+ | `news` | Codal summaries + TSETMC supervisor messages | |
170
+ | `income_stmt`, `balance_sheet`, `cashflow`, `quarterly_*` | Codal | wide frame, columns = period end |
171
+ | `options`, `option_chain(date)` | TSETMC option market watch | expirations; calls and puts with bid, ask, last, volume, open interest |
172
+ | `monthly_activity()` | Codal | monthly production/sales letters |
173
+
174
+ `Tickers("فولاد فملی")` bundles several tickers. `download([...])` returns the yfinance
175
+ `MultiIndex` layout: `group_by="column"` gives `(Price, Ticker)`, `group_by="ticker"` flips it.
176
+
177
+ ## Compared with other packages
178
+
179
+ | | yfinance-ir | [pytse-client](https://github.com/Glyphack/pytse-client) | [finpy-tse](https://github.com/ARahimiQuant/finpy-tse) | [tehran-stocks](https://github.com/ghodsizadeh/tehran-stocks) |
180
+ |---|---|---|---|---|
181
+ | Sources | TSETMC, Codal, TGJU, SCI CPI, Nobitex (`crypto` extra) | TSETMC | TSETMC, free-market dollar | TSETMC |
182
+ | API shape | yfinance: `Ticker(...).history()`, `download([...])` | `Ticker(...).history` frame, `download(symbols=...)` | `Get_*_History()` functions | SQLAlchemy models + CLI |
183
+ | Adjusted daily history | dividends and capital increases | `adjust=True` | `adjust_price=True` | dividend and share tables, no adjusted series documented |
184
+ | Intraday bars | `1m`–`90m`, `1h`, rebuilt from trades | `30s`–`1h`, aggregated from trade details (`get_trade_details(..., timeframe=)`) | trade and order-book history, no bars | — |
185
+ | Order book, client types | yes | yes | yes | — |
186
+ | Codal statements | income, balance sheet, cash flow, monthly activity | — | — | — |
187
+ | Option chains | yes | — | — | — |
188
+ | FX, gold, coin | TGJU | — | USD only (`Get_USD_RIAL`) | — |
189
+ | CPI | SCI, monthly | — | — | — |
190
+ | Index history | any TSETMC index by name | `FinancialIndex(...).history` | `Get_CWI_History`, `Get_EWI_History`, sector indices | — |
191
+ | Jalali dates | input and output | `include_jdate=True` | `jalali_date=True` | output |
192
+ | Licence | MIT | GPL-3.0 | BSD-3-Clause | MIT |
193
+ | Last commit | 2026-10 | 2025-03 | 2024-04 | 2023-10 |
194
+ | PyPI | not yet, install from a release tag | yes | yes | yes |
195
+
196
+ Checked against each package's README on 2026-10-11; "—" means the README does not document it.
197
+ Corrections welcome as issues.
198
+
199
+ ## Conventions
200
+
201
+ | Topic | Rule |
202
+ |---|---|
203
+ | Prices | TSETMC and TGJU in Rial; `*-IRT` crypto pairs in Toman |
204
+ | Columns | `Open High Low Close Volume Dividends "Stock Splits"`, plus TSETMC `Last`, `Value`, `Count`; `auto_adjust=False` adds `Adj Close` |
205
+ | Dates | Gregorian `DatetimeIndex`; `start`/`end` accept Gregorian, Jalali (`1403-01-01`), `dEven` ints, `date`/`datetime`; `end` exclusive; intraday bars carry a tz-aware `Datetime` index, `Asia/Tehran` for TSETMC and UTC for crypto |
206
+ | Adjustment | Dividend gaps from TSETMC `GetPriceAdjustList`; share-count changes it omits are bonus issues (`old / new`); markers land on the next bar |
207
+ | Non-trading rows | Zero-volume calendar rows while a symbol is suspended are dropped |
208
+ | Errors | `SymbolNotFound`, `BlockedError`, `RateLimitError`, `DataUnavailable`, all subclasses of `YFIRError` |
209
+
210
+ Full definitions: [docs/conventions.md](docs/conventions.md).
211
+
212
+ ## Configuration
213
+
214
+ ```python
215
+ yf.set_config(
216
+ min_interval=0.1, # seconds between requests to the same host
217
+ timeout=20.0, # per-request timeout
218
+ threads=4, # download() workers
219
+ cache_dir=None, # default: $XDG_CACHE_HOME/yfinance_ir
220
+ crypto_exchange="nobitex",
221
+ trust_env=True, # honour HTTP(S)_PROXY
222
+ )
223
+ ```
224
+
225
+ ## Limitations
226
+
227
+ - Intraday bars exist for TSETMC instruments other than indices, span at most 3 months per
228
+ call and cost one request per trading day. Some of TSETMC's backends answer the trade feed
229
+ with HTTP 500 or an empty list; a failed request reconnects to reach another backend, and
230
+ a day still empty after 12 passes (about 3 minutes, long pauses logged at WARNING) raises
231
+ `DataUnavailable`. Other sources: TGJU is daily, crypto `1d`/`1h`, CPI monthly.
232
+ - Option chains have no implied volatility or last-trade date; TSETMC publishes neither.
233
+ - CPI downloads from `amar.org.ir` run with `verify=False` because the server omits its
234
+ intermediate certificate.
235
+ - ISIN lookup only hits the local cache; resolve by symbol or InsCode first.
236
+ - Index history has no open or volume.
237
+ - `ccxt-ir` 4.19.0's `fetch_ohlcv` and `fetch_order_book` are broken; Nobitex is served
238
+ through its public REST API instead, other exchanges re-raise the ccxt error.
239
+
240
+ Reasons and endpoint details: [docs/data-sources.md](docs/data-sources.md).
241
+
242
+ ## Development
243
+
244
+ ```bash
245
+ python -m venv .venv && .venv/bin/pip install -e ".[dev,crypto]"
246
+ .venv/bin/python -m ruff check .
247
+ .venv/bin/python -m pytest # 95 offline tests, replayed fixtures
248
+ .venv/bin/python -m pytest -m live # 12 smoke tests, needs an Iranian IP
249
+ .venv/bin/python tests/capture_fixtures.py # re-record tests/fixtures/
250
+ ```
251
+
252
+ Offline tests run through `responses` against the exact URLs the package calls, so a wrong
253
+ path in `yfinance_ir/sources/` fails a test instead of hitting the network.
254
+
255
+ Versions are CalVer, `YYYY.M.MICRO`. [CHANGELOG.md](CHANGELOG.md) names breaking changes;
256
+ the number does not encode them. See [CONTRIBUTING.md](CONTRIBUTING.md).
257
+
258
+ > **Not affiliated** with yfinance, Yahoo, TSETMC, Codal, TGJU or the Statistical Centre of
259
+ > Iran. The package reads their public endpoints and copies the `yfinance` API shape. No
260
+ > accuracy guarantee, not investment advice; each source's terms of use are your
261
+ > responsibility.
262
+
263
+ ## License
264
+
265
+ MIT, Copyright (c) 2026 Kiyarash Fazeli. See [LICENSE](LICENSE).
@@ -0,0 +1,218 @@
1
+ # yfinance-ir
2
+
3
+ [![CI](https://github.com/Fazel94/yfinance-ir/actions/workflows/ci.yml/badge.svg)](https://github.com/Fazel94/yfinance-ir/actions/workflows/ci.yml)
4
+ ![Python](https://img.shields.io/badge/python-3.9%20%7C%203.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-blue)
5
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
6
+
7
+ [فارسی](README.fa.md)
8
+
9
+ <div dir="rtl">
10
+
11
+ داده‌های بازار ایران با رابط آشنای `yfinance`: سهام، صندوق‌ها و شاخص‌های بورس تهران (TSETMC)،
12
+ صورت‌های مالی کدال، دلار، طلا و سکه از TGJU، تورم مرکز آمار ایران و رمزارزها از صرافی‌های ایرانی.
13
+
14
+ </div>
15
+
16
+ `yfinance`-shaped market data for the Iranian markets: TSETMC (equities, ETFs, indices),
17
+ Codal (financial statements), TGJU (FX, gold, coins), the Statistical Centre of Iran (CPI)
18
+ and, with the `crypto` extra, Iranian crypto exchanges through `ccxt-ir`.
19
+
20
+ > **Iranian IP required.** `cdn.tsetmc.com` drops foreign IPs.
21
+
22
+ [![Since Nowruz 1405: which assets beat inflation and which beat the dollar](examples/scoreboard.png)](examples/scoreboard.ipynb)
23
+
24
+ One `history()` call per bar: TSETMC indices, stocks and ETFs, TGJU's dollar, euro, gold
25
+ and coin, Nobitex bitcoin, measured against the SCI CPI and the free-market dollar.
26
+ [`examples/scoreboard.ipynb`](examples/scoreboard.ipynb) draws it, the same race as a
27
+ path since Nowruz and over five years, and a seven-window heatmap of real and dollar
28
+ returns. Charts are in Persian; install from `main` for its two text-shaping extras:
29
+ `pip install "yfinance-ir[crypto,notebook] @ git+https://github.com/Fazel94/yfinance-ir.git"`.
30
+
31
+ Monthly update of this chart: X [@_fazel94](https://x.com/_fazel94)
32
+
33
+
34
+ ## Install
35
+
36
+ ```bash
37
+ pip install "yfinance-ir @ git+https://github.com/Fazel94/yfinance-ir.git@v2026.9.2" # TSETMC + Codal + TGJU + CPI
38
+ pip install "yfinance-ir[crypto] @ git+https://github.com/Fazel94/yfinance-ir.git@v2026.9.2" # adds BTC-IRT / ETH-USDT style pairs
39
+ ```
40
+
41
+ Not on PyPI yet: install from a release tag. Each [GitHub Release](https://github.com/Fazel94/yfinance-ir/releases) also carries the wheel and sdist.
42
+
43
+ ## Quickstart
44
+
45
+ ```python
46
+ import yfinance_ir as yf
47
+
48
+ folad = yf.Ticker("فولاد")
49
+ folad.history(period="1y") # adjusted daily OHLCV
50
+ folad.history(period="5d", interval="5m") # intraday bars rebuilt from TSETMC trades
51
+ folad.info["marketCap"]
52
+ folad.income_stmt # Codal, wide, newest period first
53
+ folad.cashflow # Codal cash-flow statement
54
+ yf.Ticker("اهرم").option_chain() # nearest expiration: calls, puts, underlying
55
+
56
+ yf.download(["فولاد", "فملی"], period="6mo")
57
+ yf.Ticker("USD").history(period="5y") # TGJU dollar, Rial
58
+ yf.Ticker("شاخص کل").history() # TEDPIX
59
+ yf.Ticker("CPI").history() # SCI consumer price index, monthly
60
+ yf.Ticker("BTC-IRT").history() # Nobitex, needs the `crypto` extra
61
+ ```
62
+
63
+ ### Example: فولاد in Rial, USD and real terms
64
+
65
+ [`examples/real_returns.py`](examples/real_returns.py) prices فولاد in TGJU dollars and
66
+ deflates it by the SCI CPI. Both series are forward-filled onto the stock's trading days.
67
+
68
+ ```python
69
+ import pandas as pd
70
+
71
+ folad = yf.Ticker("فولاد").history(period="5y")["Close"]
72
+ usd = yf.Ticker("USD").history(period="5y")["Close"].reindex(folad.index, method="ffill")
73
+ cpi = yf.Ticker("CPI").history(period="5y")["Close"].reindex(folad.index, method="ffill")
74
+
75
+ frame = pd.DataFrame({"Rial": folad, "USD": folad / usd, "Real": folad / cpi * cpi.iloc[-1]})
76
+ print(frame.iloc[-1] / frame.iloc[0] - 1)
77
+ ```
78
+
79
+ Output on 2026-09-21:
80
+
81
+ ```
82
+ فولاد 2021-09-25 -> 2026-09-21 (5.0y)
83
+ total annualised
84
+ Rial +228.1% +26.9%
85
+ USD -60.8% -17.1%
86
+ Real -52.0% -13.7%
87
+ ```
88
+
89
+ [examples/cookbook.ipynb](examples/cookbook.ipynb) runs the recipes of chapters 1, 2 and 7
90
+ of *Python for Finance Cookbook* (returns, CPI deflation, outliers, stylised facts,
91
+ SMA/Bollinger/RSI backtests with backtrader, 1/n portfolio, Monte Carlo efficient frontier)
92
+ on TSETMC stocks and Nobitex crypto pairs. Install its dependencies with
93
+ `pip install "yfinance-ir[crypto,notebook] @ git+https://github.com/Fazel94/yfinance-ir.git@v2026.9.2"`.
94
+
95
+ ## Symbols
96
+
97
+ | You pass | Resolves to | Example |
98
+ |---|---|---|
99
+ | Persian symbol | TSETMC instrument | `Ticker("فولاد")`, `Ticker("اهرم")` |
100
+ | Persian index name | TSETMC index | `Ticker("شاخص کل")` |
101
+ | InsCode (10–20 digits) | TSETMC instrument | `Ticker("46348559193224090")` |
102
+ | TGJU alias or slug | FX / gold / coin | `Ticker("USD")`, `Ticker("geram18")` |
103
+ | `CPI`, `CPI_URBAN`, `CPI_RURAL` | SCI price index | `Ticker("CPI")` |
104
+ | `BASE-IRT` / `BASE-USDT` | crypto pair | `Ticker("BTC-IRT")` |
105
+ | ISIN | cache lookup only, see below | `Ticker("IRO1FOLD0009")` |
106
+
107
+ Persian and Arabic spellings are unified (`ی`/`ي`, `ک`/`ك`, ZWNJ). TGJU aliases and the
108
+ per-source rules are in [docs/data-sources.md](docs/data-sources.md). Resolutions are cached
109
+ in `~/.cache/yfinance_ir/symbols.sqlite`; `yf.cache.clear()` drops them,
110
+ `yf.set_config(cache_dir=...)` moves them.
111
+
112
+ ## Ticker API
113
+
114
+ | Member | Source | Notes |
115
+ |---|---|---|
116
+ | `history(...)` | TSETMC / TGJU / SCI / crypto | daily OHLCV (monthly for CPI), adjusted by default; TSETMC also `1m`–`90m` and `1h` bars rebuilt from trades |
117
+ | `info` | TSETMC | yfinance-style keys: `marketCap`, `trailingPE`, `sharesOutstanding`, … |
118
+ | `dividends`, `splits`, `actions` | TSETMC adjust + share-change | see docs/conventions.md |
119
+ | `orderbook` | TSETMC / exchange | 5 levels, bid/ask price-volume-count |
120
+ | `client_types`, `client_type_history()` | TSETMC | individual vs institutional flow |
121
+ | `major_holders` | TSETMC | > 1 % shareholders |
122
+ | `news` | Codal summaries + TSETMC supervisor messages | |
123
+ | `income_stmt`, `balance_sheet`, `cashflow`, `quarterly_*` | Codal | wide frame, columns = period end |
124
+ | `options`, `option_chain(date)` | TSETMC option market watch | expirations; calls and puts with bid, ask, last, volume, open interest |
125
+ | `monthly_activity()` | Codal | monthly production/sales letters |
126
+
127
+ `Tickers("فولاد فملی")` bundles several tickers. `download([...])` returns the yfinance
128
+ `MultiIndex` layout: `group_by="column"` gives `(Price, Ticker)`, `group_by="ticker"` flips it.
129
+
130
+ ## Compared with other packages
131
+
132
+ | | yfinance-ir | [pytse-client](https://github.com/Glyphack/pytse-client) | [finpy-tse](https://github.com/ARahimiQuant/finpy-tse) | [tehran-stocks](https://github.com/ghodsizadeh/tehran-stocks) |
133
+ |---|---|---|---|---|
134
+ | Sources | TSETMC, Codal, TGJU, SCI CPI, Nobitex (`crypto` extra) | TSETMC | TSETMC, free-market dollar | TSETMC |
135
+ | API shape | yfinance: `Ticker(...).history()`, `download([...])` | `Ticker(...).history` frame, `download(symbols=...)` | `Get_*_History()` functions | SQLAlchemy models + CLI |
136
+ | Adjusted daily history | dividends and capital increases | `adjust=True` | `adjust_price=True` | dividend and share tables, no adjusted series documented |
137
+ | Intraday bars | `1m`–`90m`, `1h`, rebuilt from trades | `30s`–`1h`, aggregated from trade details (`get_trade_details(..., timeframe=)`) | trade and order-book history, no bars | — |
138
+ | Order book, client types | yes | yes | yes | — |
139
+ | Codal statements | income, balance sheet, cash flow, monthly activity | — | — | — |
140
+ | Option chains | yes | — | — | — |
141
+ | FX, gold, coin | TGJU | — | USD only (`Get_USD_RIAL`) | — |
142
+ | CPI | SCI, monthly | — | — | — |
143
+ | Index history | any TSETMC index by name | `FinancialIndex(...).history` | `Get_CWI_History`, `Get_EWI_History`, sector indices | — |
144
+ | Jalali dates | input and output | `include_jdate=True` | `jalali_date=True` | output |
145
+ | Licence | MIT | GPL-3.0 | BSD-3-Clause | MIT |
146
+ | Last commit | 2026-10 | 2025-03 | 2024-04 | 2023-10 |
147
+ | PyPI | not yet, install from a release tag | yes | yes | yes |
148
+
149
+ Checked against each package's README on 2026-10-11; "—" means the README does not document it.
150
+ Corrections welcome as issues.
151
+
152
+ ## Conventions
153
+
154
+ | Topic | Rule |
155
+ |---|---|
156
+ | Prices | TSETMC and TGJU in Rial; `*-IRT` crypto pairs in Toman |
157
+ | Columns | `Open High Low Close Volume Dividends "Stock Splits"`, plus TSETMC `Last`, `Value`, `Count`; `auto_adjust=False` adds `Adj Close` |
158
+ | Dates | Gregorian `DatetimeIndex`; `start`/`end` accept Gregorian, Jalali (`1403-01-01`), `dEven` ints, `date`/`datetime`; `end` exclusive; intraday bars carry a tz-aware `Datetime` index, `Asia/Tehran` for TSETMC and UTC for crypto |
159
+ | Adjustment | Dividend gaps from TSETMC `GetPriceAdjustList`; share-count changes it omits are bonus issues (`old / new`); markers land on the next bar |
160
+ | Non-trading rows | Zero-volume calendar rows while a symbol is suspended are dropped |
161
+ | Errors | `SymbolNotFound`, `BlockedError`, `RateLimitError`, `DataUnavailable`, all subclasses of `YFIRError` |
162
+
163
+ Full definitions: [docs/conventions.md](docs/conventions.md).
164
+
165
+ ## Configuration
166
+
167
+ ```python
168
+ yf.set_config(
169
+ min_interval=0.1, # seconds between requests to the same host
170
+ timeout=20.0, # per-request timeout
171
+ threads=4, # download() workers
172
+ cache_dir=None, # default: $XDG_CACHE_HOME/yfinance_ir
173
+ crypto_exchange="nobitex",
174
+ trust_env=True, # honour HTTP(S)_PROXY
175
+ )
176
+ ```
177
+
178
+ ## Limitations
179
+
180
+ - Intraday bars exist for TSETMC instruments other than indices, span at most 3 months per
181
+ call and cost one request per trading day. Some of TSETMC's backends answer the trade feed
182
+ with HTTP 500 or an empty list; a failed request reconnects to reach another backend, and
183
+ a day still empty after 12 passes (about 3 minutes, long pauses logged at WARNING) raises
184
+ `DataUnavailable`. Other sources: TGJU is daily, crypto `1d`/`1h`, CPI monthly.
185
+ - Option chains have no implied volatility or last-trade date; TSETMC publishes neither.
186
+ - CPI downloads from `amar.org.ir` run with `verify=False` because the server omits its
187
+ intermediate certificate.
188
+ - ISIN lookup only hits the local cache; resolve by symbol or InsCode first.
189
+ - Index history has no open or volume.
190
+ - `ccxt-ir` 4.19.0's `fetch_ohlcv` and `fetch_order_book` are broken; Nobitex is served
191
+ through its public REST API instead, other exchanges re-raise the ccxt error.
192
+
193
+ Reasons and endpoint details: [docs/data-sources.md](docs/data-sources.md).
194
+
195
+ ## Development
196
+
197
+ ```bash
198
+ python -m venv .venv && .venv/bin/pip install -e ".[dev,crypto]"
199
+ .venv/bin/python -m ruff check .
200
+ .venv/bin/python -m pytest # 95 offline tests, replayed fixtures
201
+ .venv/bin/python -m pytest -m live # 12 smoke tests, needs an Iranian IP
202
+ .venv/bin/python tests/capture_fixtures.py # re-record tests/fixtures/
203
+ ```
204
+
205
+ Offline tests run through `responses` against the exact URLs the package calls, so a wrong
206
+ path in `yfinance_ir/sources/` fails a test instead of hitting the network.
207
+
208
+ Versions are CalVer, `YYYY.M.MICRO`. [CHANGELOG.md](CHANGELOG.md) names breaking changes;
209
+ the number does not encode them. See [CONTRIBUTING.md](CONTRIBUTING.md).
210
+
211
+ > **Not affiliated** with yfinance, Yahoo, TSETMC, Codal, TGJU or the Statistical Centre of
212
+ > Iran. The package reads their public endpoints and copies the `yfinance` API shape. No
213
+ > accuracy guarantee, not investment advice; each source's terms of use are your
214
+ > responsibility.
215
+
216
+ ## License
217
+
218
+ MIT, Copyright (c) 2026 Kiyarash Fazeli. See [LICENSE](LICENSE).
@@ -0,0 +1,75 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "yfinance-ir"
7
+ dynamic = ["version"]
8
+ description = "yfinance-style market data for Iranian markets (TSETMC, Codal, TGJU)"
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = "MIT"
12
+ license-files = ["LICENSE"]
13
+ authors = [{ name = "Kiyarash Fazeli", email = "caci96@gmail.com" }]
14
+ keywords = ["tsetmc", "codal", "tgju", "iran", "bourse", "stocks", "finance"]
15
+ classifiers = [
16
+ "Development Status :: 3 - Alpha",
17
+ "Intended Audience :: Financial and Insurance Industry",
18
+ "Operating System :: OS Independent",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.9",
21
+ "Programming Language :: Python :: 3.10",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Programming Language :: Python :: 3.12",
24
+ "Programming Language :: Python :: 3.13",
25
+ "Topic :: Office/Business :: Financial :: Investment",
26
+ ]
27
+ dependencies = [
28
+ "requests>=2.28",
29
+ "pandas>=1.5",
30
+ "numpy>=1.21",
31
+ "jdatetime>=4",
32
+ "openpyxl>=3.1",
33
+ ]
34
+
35
+ [project.optional-dependencies]
36
+ dev = ["pytest", "responses", "ruff"]
37
+ crypto = ["ccxt-ir>=4"]
38
+ notebook = [
39
+ "matplotlib>=3.8",
40
+ "seaborn>=0.13",
41
+ "scipy>=1.11",
42
+ "statsmodels>=0.14",
43
+ "backtrader>=1.9.78",
44
+ "ipykernel",
45
+ "nbconvert",
46
+ "arabic-reshaper>=3.0",
47
+ "python-bidi>=0.6",
48
+ ]
49
+
50
+ [project.urls]
51
+ Homepage = "https://github.com/Fazel94/yfinance-ir"
52
+ Repository = "https://github.com/Fazel94/yfinance-ir"
53
+ Issues = "https://github.com/Fazel94/yfinance-ir/issues"
54
+ Changelog = "https://github.com/Fazel94/yfinance-ir/blob/main/CHANGELOG.md"
55
+
56
+ [tool.setuptools.dynamic]
57
+ version = { attr = "yfinance_ir.__version__" }
58
+
59
+ [tool.setuptools.packages.find]
60
+ include = ["yfinance_ir*"]
61
+
62
+ [tool.setuptools.package-data]
63
+ yfinance_ir = ["py.typed"]
64
+
65
+ [tool.ruff]
66
+ line-length = 110
67
+ target-version = "py39"
68
+
69
+ [tool.ruff.lint]
70
+ select = ["E", "F", "I", "W"]
71
+
72
+ [tool.pytest.ini_options]
73
+ markers = ["live: hits the real network (requires an Iranian IP)"]
74
+ addopts = '-m "not live"'
75
+ testpaths = ["tests"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+