Skip to content

Instantly share code, notes, and snippets.

@5j9
Last active September 29, 2026 03:43
Show Gist options
  • Select an option

  • Save 5j9/bec9342ae5097af3912cfd42aedf5a1f to your computer and use it in GitHub Desktop.

Select an option

Save 5j9/bec9342ae5097af3912cfd42aedf5a1f to your computer and use it in GitHub Desktop.
CLI tool to calculate the return percentage of a TSETMC instrument
# /// script
# requires-python = ">=3.14"
# dependencies = [
# "cyclopts",
# "jdatetime",
# "polars",
# "tsetmc",
# ]
# ///
"""
CLI tool to calculate the return percentage of a TSETMC instrument
over a given Jalali date range.
Usage:
uv run path/to/script.py --l18 شتاب --from 1405-03-31 --to 1405-06-31
"""
from datetime import date
from typing import Annotated
from cyclopts import App, Parameter, Token
from jdatetime import date as jdate
from polars import col
from tsetmc.instruments import Instrument
def price_on_or_before(history, target_date: date) -> tuple[date, int]:
row = (
history.filter(col('date') <= target_date)
.sort('date', descending=True)
.select('date', 'pc')
.head(1)
.collect()
)
if row.is_empty():
raise ValueError(f'No price history before {target_date}')
return row['date'][0], row['pc'][0]
async def get_return(
l18: str,
start_date: date,
end_date: date,
) -> tuple[date, int, date, int, float]:
instrument = await Instrument.from_l18(l18)
history = await instrument.price_history()
actual_start_date, start_price = price_on_or_before(history, start_date)
actual_end_date, end_price = price_on_or_before(history, end_date)
return_pct = (end_price / start_price - 1) * 100
return (
actual_start_date,
start_price,
actual_end_date,
end_price,
return_pct,
)
app = App()
def parse_jdate(type_: type[jdate], tokens: list[Token]) -> jdate:
return type_.fromisoformat(tokens[0].value)
JDate = Annotated[
jdate,
Parameter(
converter=parse_jdate,
n_tokens=1,
accepts_keys=False,
),
]
@app.default
async def main(
*,
l18: str,
from_: JDate,
to: JDate,
) -> None:
"""
Calculate the return percentage of a TSETMC instrument.
"""
(
actual_start_date,
start_price,
actual_end_date,
end_price,
return_pct,
) = await get_return(l18, from_.togregorian(), to.togregorian())
print(f'Instrument: {l18}')
print(f'Period: {from_.isoformat()} → {to.isoformat()}')
print(f'Actual: {actual_start_date} → {actual_end_date}')
print(f'Prices: {start_price:,} → {end_price:,}')
print(f'Return: {return_pct:.2f}%')
if __name__ == '__main__':
app()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment