Exercise · m00_trader_tax.py
Tax on a mixed trading year, and F&O turnover
not run yet
Not saved: sign up to keep your code"""Exercise: tax on a mixed trading year, and F&O turnover (notes §0.7).
Implement every function, then run from the repo root:
cd exercises && .venv/bin/python -m pytest modules/M00-market-on-ramp/tests/test_m00_trader_tax.py
A deliberately simplified model of an Indian resident individual's tax year.
It encodes only the rules stated in the notes; it is not tax advice.
Rules to encode
1. Capital gains (listed equity, STT paid). Short-term loss offsets short-term
gain, then long-term gain. Long-term loss offsets only long-term gain.
Unabsorbed capital losses are carried forward.
2. Business income. Speculative (intraday) and non-speculative (F&O) results
are computed separately. A non-speculative loss may be set off against
speculative profit; a speculative loss may not be set off against anything
except speculative profit, and is carried forward.
3. A non-speculative loss left after step 2 is set off against capital gains in
the order rates["setoff_order"] (default ("stcg", "ltcg")), but never
against salary. What remains is carried forward.
4. Tax = slab tax on (salary + positive business income)
+ stcg_rate * net STCG + ltcg_rate * max(0, net LTCG - ltcg_exemption).
Ignored: rebate, surcharge, cess, use of unexhausted basic exemption against
special-rate gains, brought-forward losses, other deductions.
rates dict keys: "slabs" (list of (upper_limit, rate), last upper = inf),
"stcg_rate", "ltcg_rate", "ltcg_exemption", optional "setoff_order".
"""
from __future__ import annotations
import math
from typing import Sequence
def slab_tax(income: float, slabs: Sequence[tuple[float, float]]) -> float:
"""Progressive tax: each slice of income between consecutive upper limits
is taxed at that slice's rate. slabs = [(400000, 0.0), (800000, 0.05), ..., (inf, 0.30)].
Income <= 0 gives 0.
"""
raise NotImplementedError
def fno_turnover(trade_pnls: Sequence[float], option_sell_premiums: Sequence[float] = (), include_premium: bool = False) -> float:
"""Turnover for tax-audit purposes as described in the notes: sum of
|profit or loss| over all closed trades. With include_premium=True, also add
the premium received on options sold (the older reading, for comparison)."""
raise NotImplementedError
def tax_mixed_year(salary: float, stcg: float, ltcg: float, intraday: float, fno: float, rates: dict) -> dict:
"""Apply rules 1-4 of the module docstring. Return a dict with keys
"slab_income", "business_income", "stcg_taxable", "ltcg_taxable" (after the
exemption), "slab_tax", "stcg_tax", "ltcg_tax", "total_tax",
"cf_speculative", "cf_business", "cf_stcl", "cf_ltcl".
"""
raise NotImplementedError
NEW_REGIME_2026 = {
"slabs": [
(400_000, 0.00),
(800_000, 0.05),
(1_200_000, 0.10),
(1_600_000, 0.15),
(2_000_000, 0.20),
(2_400_000, 0.25),
(math.inf, 0.30),
],
"stcg_rate": 0.20,
"ltcg_rate": 0.125,
"ltcg_exemption": 125_000,
}
No runs yet
The stub's functions raise
NotImplementedError until you write them. Fill in one, press
Run tests, and watch its tests turn green.Reference solution
Available after your first run, with an account approved for code runs.