Skip to main content
Pytest Status

An async Python library to fetch data from https://tsetmc.com/ built on top of Polars.

Installation

Requires Python 3.13 or later.

pip install tsetmc

Overview

Let’s start with a simple script:

import asyncio

from tsetmc.instruments import Instrument


async def main():
    inst = await Instrument.from_l18('فملی')
    info = await inst.info()
    print(info)


asyncio.run(main())

The Instrument class provides many methods for getting information about an instrument. The following code blocks try to demonstrate some of its capabilities.

Note: You need an asyncio capable REPL, like python -m asyncio or IPython, to run the following code samples, otherwise you’ll have to run them inside an async function like the sample code above.

>>> from tsetmc.instruments import Instrument
>>> inst = await Instrument.from_l18('فملی')
>>> await inst.info()
{'eps': {'epsValue': None,
  'estimatedEPS': '721',
  'sectorPE': 12.02,
  'psr': 1472.8279},
 'sector': {'dEven': 0, 'cSecVal': '27 ', 'lSecVal': 'فلزات اساسی'},
 'staticThreshold': {'insCode': None,
  'dEven': 0,
  'hEven': 0,
  'psGelStaMax': 8270.0,
  'psGelStaMin': 7190.0},
 'minWeek': 7630.0,
 'maxWeek': 7970.0,
 'minYear': 4630.0,
 'maxYear': 10670.0,
 'qTotTran5JAvg': 179233329.0,
 'kAjCapValCpsIdx': '43',
 'dEven': 0,
 'topInst': 1,
 'faraDesc': '',
 'contractSize': 0,
 'nav': 0.0,
 'underSupervision': 0,
 'cValMne': None,
 'lVal18': 'S*I. N. C. Ind.',
 'cSocCSAC': None,
 'lSoc30': None,
 'yMarNSC': None,
 'yVal': '300',
 'insCode': '35425587644337450',
 'lVal30': 'ملی\u200c صنایع\u200c مس\u200c ایران\u200c',
 'lVal18AFC': 'فملی',
 'flow': 1,
 'cIsin': 'IRO1MSMI0000',
 'zTitad': 600000000000.0,
 'baseVol': 15584416,
 'instrumentID': 'IRO1MSMI0001',
 'cgrValCot': 'N1',
 'cComVal': '1',
 'lastDate': 0,
 'sourceID': 0,
 'flowTitle': 'بازار بورس',
 'cgrValCotTitle': 'بازار اول (تابلوی اصلی) بورس'}

Getting the latest price information:

>>> await inst.closing_price_info()
{'instrumentState': {'idn': 0,
  'dEven': 0,
  'hEven': 0,
  'insCode': None,
  'cEtaval': 'A ',
  'realHeven': 0,
  'underSupervision': 0,
  'cEtavalTitle': 'مجاز'},
 'instrument': None,
 'lastHEven': 170725,
 'finalLastDate': 20230524,
 'nvt': 0.0,
 'mop': 0,
 'thirtyDayClosingHistory': None,
 'priceChange': 0.0,
 'priceMin': 7630.0,
 'priceMax': 7900.0,
 'priceYesterday': 7730.0,
 'priceFirst': 7750.0,
 'last': True,
 'id': 0,
 'insCode': '0',
 'dEven': 20230524,
 'hEven': 170725,
 'pClosing': 7700.0,
 'iClose': False,
 'yClose': False,
 'pDrCotVal': 7670.0,
 'zTotTran': 7206.0,
 'qTotTran5J': 84108817.0,
 'qTotCap': 648015842640.0}

Getting the daily trade history for the last n days: (as a Polars LazyFrame, resolved using .collect())

>>> lf = await inst.daily_closing_price(n=2)
>>> lf.collect()
shape: (2, 17)
┌─────────────┬──────────┬──────────┬───┬──────────┬────────────┬──────────────┐
│ priceChange ┆ priceMin ┆ priceMax ┆ … ┆ zTotTran ┆ qTotTran5J ┆ qTotCap      │
│ ---         ┆ ---      ┆ ---      ┆   ┆ ---      ┆ ---        ┆ ---          │
│ f64         ┆ f64      ┆ f64      ┆   ┆ f64      ┆ f64        ┆ f64          │
╞═════════════╪══════════╪══════════╪═══╪══════════╪════════════╪══════════════╡
│ 30.0        ┆ 7490.0   ┆ 7600.0   ┆ … ┆ 4555.0   ┆ 7.5649965e ┆ 5.689944e+11 │
│ 10.0        ┆ 7500.0   ┆ 7590.0   ┆ … ┆ 4614.0   ┆ 8.3570336e ┆ 6.276337e+11 │
└─────────────┴──────────┴──────────┴───┴──────────┴────────────┴──────────────┘

Getting adjusted daily prices:

>>> lf = await inst.price_history(adjusted=True)
>>> lf.collect()
shape: (3192, 7)
┌────────────┬───────┬───────┬───────┬───────┬───────────┬───────┐
│ date       ┆ pmax  ┆ pmin  ┆ pf    ┆ pl    ┆ tvol      ┆ pc    │
│ ---        ┆ ---   ┆ ---   ┆ ---   ┆ ---   ┆ ---       ┆ ---   │
│ datetime   ┆ i64   ┆ i64   ┆ i64   ┆ i64   ┆ i64       ┆ i64   │
╞════════════╪═══════╪═══════╪═══════╪═══════╪═══════════╪═══════╡
│ 2007-02-04 ┆ 45    ┆ 41    ┆ 45    ┆ 42    ┆ 172898994 ┆ 42    │
│ 2007-02-05 ┆ 43    ┆ 43    ┆ 43    ┆ 43    ┆ 10826496  ┆ 43    │
│ …          ┆ …     ┆ …     ┆ …     ┆ …     ┆ …         ┆ …     │
│ 2021-07-17 ┆ 12960 ┆ 12550 ┆ 12800 ┆ 12640 ┆ 68542961  ┆ 12750 │
│ 2021-07-18 ┆ 12880 ┆ 12530 ┆ 12600 ┆ 12630 ┆ 88106162  ┆ 12650 │
└────────────┴───────┴───────┴───────┴───────┴───────────┴───────┘

Getting intraday data for a specific date:

>>> lf = await inst.on_date(20210704).states()
>>> lf.collect()
shape: (1, 10)
┌─────┬───────┬───────┬─────────┬───┬─────────┬───────────┬──────────────────┬──────────────┐
│ idn ┆ dEven ┆ hEven ┆ insCode ┆ … ┆ cEtaval ┆ realHeven ┆ underSupervision ┆ cEtavalTitle │
│ --- ┆ ---   ┆ ---   ┆ ---     ┆   ┆ ---     ┆ ---       ┆ ---              ┆ ---          │
│ i64 ┆ i64   ┆ i64   ┆ str     ┆   ┆ str     ┆ i64       ┆ i64              ┆ null         │
╞═════╪═══════╪═══════╪═════════╪═══╪═════════╪═══════════╪══════════════════╪══════════════╡
│ 0   ┆ 0     ┆ 1     ┆ 0       ┆ … ┆ A       ┆ 94838     ┆ 0                ┆ null         │
└─────┴───────┴───────┴─────────┴───┴─────────┴───────────┴──────────────────┴──────────────┘

Searching for an instrument:

>>> await Instrument.from_search('چادرملو')
Instrument(18027801615184692, 'کچاد')

The instruments.price_adjustments function gets all the price adjustments for a specified flow.

The market_watch module contains several functions to fetch market watch data. They include:

  • market_watch_init

  • market_watch_plus

  • closing_price_all

  • client_type_all

  • key_stats

  • ombud_messages

  • status_changes

Use market_watch.MarketWatch for watching the market. Here is how:

from asyncio import gather, run

import polars as pl

from tsetmc.market_watch import MarketWatch


async def listen_to_update_events(market_watch):
    while True:
        await market_watch.update_event.wait()
        # market_watch elements are exposed as a Polars LazyFrame
        lf = market_watch.lf
        print(
            lf.filter(pl.col('ins_code') == '35425587644337450')
            .select('pl')
            .collect()
            .item()
        )


async def main():
    market_watch = MarketWatch()
    await gather(
        market_watch.start(),
        listen_to_update_events(market_watch),
    )


run(main())

There are many other functions and methods that are not covered here. Explore the codebase to learn more.

To keep the offline dataset up-to-date, run the tsetmc.dataset.update() function periodically (e.g., daily). This dataset acts as a cache for basic information about common instruments.

If you are interested in other information available on tsetmc.com that this library has no API for, please open an issue for them.

See also

Metadata

Release files for tsetmc 5.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tsetmc 5.1.0
File Size Uploaded Provenance
tsetmc-5.1.0.tar.gz 107.4 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for tsetmc 5.1.0
File Interpreter ABI Platform
tsetmc-5.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 217.5 kB

Release files / tsetmc-5.1.0.tar.gz

Download URL tsetmc-5.1.0.tar.gz
Size 107.4 kB
Tags Source
SHA-256 checksum
How to use checksums
3215a3abb525c606e15e7812e4ce6a9335999e61e73fb30a6a5c0c745a8ab1f2
BLAKE2b-256 checksum
How to use checksums
3d260f11fda23837cfc02680e0f989354e825ec7af750bc3740b23df9af3b2d9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / tsetmc-5.1.0-py3-none-any.whl

Download URL tsetmc-5.1.0-py3-none-any.whl
Size 110.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8b7d1deaa4a3432188a4c14cc4f061d2e9b88bb1936d4e5cdda8a409cd320eb8
BLAKE2b-256 checksum
How to use checksums
858344828d1484f84ea2c67a901a9f1a393bf1dc47bda8c35142029e11d41bd8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Security for tsetmc 5.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

5.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page