Python SDK for TSETMC
Project description
orbo
Python SDK for TSETMC — Tehran Stock Exchange data.
فارسی | English
orbo gives you clean, typed, Pandas-friendly access to every public data feed on TSETMC: daily OHLCV history, intraday tick trades, the order-book update stream, option chains, market indices, real/legal client-type flows, and live session data — all with Jalali dates, price-adjustment built-in, and retry logic out of the box.
import orbo
# Search and fetch
stock = orbo.Instrument("شپنا")
df = stock.history(adjust=True) # adjusted daily OHLCV — Jalali dates
stats = stock.stats() # returns, skewness, kurtosis, tail type
# Intraday order-flow
session = stock.intraday("20260628")
classified = orbo.TradeSideEngine().classify(session.trades, session.orderbook)
footprint = orbo.FootprintEngine().build(classified)
print(footprint.summary()) # POC, delta, buy%, classified%
# Live snapshot
snap = stock.live()
print(snap.price[["close","last_price","time"]])
print(snap.orderbook) # 5-level live book
# Option chain
chain = orbo.OptionChain.fetch()
df = chain.for_expiry("اهرم", "1405-04-31")
# Market indices
idx = orbo.find_index("شاخص كل")
df = idx.history()
Installation
pip install orbo
Requires Python ≥ 3.11.
Dependencies: httpx, pandas, pydantic, jdatetime, pyarrow.
VPN required in Iran. TSETMC's CDN API (
cdn.tsetmc.com) is accessible from inside Iran without VPN. Outside Iran, a VPN pointed at a domestic IP is needed.
Quickstart
1 — Daily price history
import orbo
stock = orbo.Instrument("فملی") # resolve by symbol
df = stock.history() # full OHLCV history, Jalali dates
df = stock.history(adjust=True) # price-adjusted (dividends + capital increases)
df = stock.history(count=30) # last 30 trading days
print(df[["date","close","volume"]].tail())
2 — Descriptive statistics and return distribution
stats = stock.stats(adjust=True)
print(stats.descriptive) # mean, median, std, min, max, range
print(stats.distribution) # skewness, kurtosis, tail_type, is_fat_tail
print(stats.monthly) # compounded monthly returns
print(stats.cumulative.iloc[-1]) # total return since first day
3 — Intraday tick data and order flow
session = stock.intraday("20260628")
df_trades = session.trades # tick-by-tick trades, sorted by trade_no
df_ob = session.orderbook # incremental order-book update stream
df_pt = session.price_tape # official closing price tape
df_ct = session.client_type # real vs legal buy/sell breakdown
df_sh = session.shareholders # major shareholders
4 — Aggressor-side classification (Lee-Ready)
classified = orbo.TradeSideEngine().classify(
session.trades,
session.orderbook, # enables Quote Rule; falls back to Tick Rule
)
# each row gains: side ("buy"|"sell"|"unknown"), method ("quote"|"tick"|"tick_carry")
5 — Footprint chart data
result = orbo.FootprintEngine().build(classified)
print(result.poc_price) # Point of Control
print(result.total_delta) # net buying pressure
print(result.bars) # per-price: buy_vol, sell_vol, delta, imbalance
6 — Option chain
chain = orbo.OptionChain.fetch() # all markets
chain = orbo.OptionChain.fetch(1) # TSE only
print(chain.underlyings) # ["اهرم", "توان", ...]
df = chain.for_expiry("اهرم", "1405-04-31") # one strike table
print(chain.summary()) # n_strikes, OI per expiry
chain.refresh() # re-fetch live prices
7 — Market indices
# All indices snapshot
df = orbo.index_snapshot()
# One index by name
idx = orbo.find_index("شاخص كل")
df = idx.history() # full daily history, Jalali dates
df = idx.today() # intraday time series
df = idx.companies() # constituent stocks with live prices
# Statistics on index history
stats = idx.stats()
8 — Live data
snap = orbo.Instrument("شپنا").live() # fetches 4 endpoints in one connection
snap.price # current session price (same schema as today())
snap.trades # all trades so far today
snap.orderbook # 5-level full snapshot (not incremental)
snap.client_type # real/legal flows for the session
9 — Batch intraday (multiple days with retry)
sessions, failed = orbo.fetch_intraday_range(
inscode = "7745894403636165",
dates = ["20260622", "20260623", "20260624", "20260625"],
fields = ["trades", "orderbook"],
)
if failed:
print("Could not fetch:", failed)
Architecture
orbo/
├── clients/ HTTP layer — httpx wrappers with retry
├── data/ transformers — raw JSON → typed DataFrames
├── engines/ pure computation — no network, no I/O
│ ├── adjustment.py cumulative price adjustment (Lee-Ready)
│ ├── trade_side.py aggressor classification (Quote + Tick Rule)
│ ├── footprint.py per-price buy/sell aggregation
│ ├── daily_stats.py return series + distribution stats
│ └── intra_stats.py intraday VWAP + distribution
├── models/ Pydantic domain objects
├── registry/ local instrument lookup (Parquet cache)
├── history/ InstrumentHistory — daily OHLCV
├── intraday/ IntradaySession — tick data per day
├── index/ MarketIndex — TSE/OTC indices
├── option_chain/ OptionChain — listed option contracts
└── instrument.py Instrument — unified high-level API
Design principles:
- Engines are pure functions on DataFrames — no network, no files, fully testable.
- Transformers own all field renaming and Jalali date conversion — nothing else does.
- Every HTTP client retries automatically (3 attempts, exponential backoff).
insCodeanddEvenare never trusted from the API when they arrive null — the caller injects them.
Supported Endpoints
| Category | Endpoint | orbo method |
|---|---|---|
| Daily OHLCV | GetClosingPriceDailyList | stock.history() |
| Live price | GetClosingPriceInfo | stock.today(), stock.live().price |
| Price adjustment | GetPriceAdjustList | stock.history(adjust=True) |
| Capital increases | GetInstrumentShareChange | stock.history(adjust=True) |
| Intraday trades | GetTradeHistory | session.trades |
| Live trades | GetTrade | stock.live().trades |
| Order book (history) | BestLimits/{date} | session.orderbook |
| Order book (live) | BestLimits | stock.live().orderbook |
| Price tape | GetClosingPriceHistory | session.price_tape |
| Client type (history) | GetClientTypeHistory | session.client_type |
| Client type (live) | GetClientType | stock.live().client_type |
| Shareholders | Shareholder | session.shareholders |
| Trading status | GetInstrumentStateAll | stock.state() |
| Option chain | GetInstrumentOptionMarketWatch | OptionChain.fetch() |
| Index snapshot | GetIndexB1LastAll | orbo.index_snapshot() |
| Index history | GetIndexB2History | idx.history() |
| Index intraday | GetIndexB1LastDay | idx.today() |
| Index companies | GetIndexCompany | idx.companies() |
| Instrument search | GetInstrumentSearch | orbo.search("فملی") |
What's coming
orbo-quant — a separate analytical library that reads from orbo and adds:
- Black-Scholes pricing and Greeks (Δ, Γ, Θ, Vega, Rho)
- Implied volatility solver
- IV surface construction
- Option strategy builder and P&L diagrams
- Portfolio optimization
orbo intentionally stays focused on data access. Analytics live in orbo-quant.
Development
git clone https://github.com/your-username/orbo
cd orbo
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest tests/ -v
License
MIT © 2026
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file orbo-0.1.1.tar.gz.
File metadata
- Download URL: orbo-0.1.1.tar.gz
- Upload date:
- Size: 71.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9b91c7e82e9917b8bf157a8689b043d3e3b75df7fcbd62730bd10ff80505dd0b
|
|
| MD5 |
d78887c7e2dbf5db036e1d15f704e4a4
|
|
| BLAKE2b-256 |
a54a199b7ff8b6e73076f53dff51f5f9f132d5f050773f06428eb17bb89240e2
|
File details
Details for the file orbo-0.1.1-py3-none-any.whl.
File metadata
- Download URL: orbo-0.1.1-py3-none-any.whl
- Upload date:
- Size: 65.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7b0a009771d2a00a14c84953d68f97acca1605bf470391697e547d4fe7f331fd
|
|
| MD5 |
b078238eb0da060d50776f78299553b9
|
|
| BLAKE2b-256 |
89391c40cdcb242c5ac1677419fad59ab8fc47ee36c4cc071acb2fb3428a5185
|