Production-grade simulated broker for NSE/BSE paper trading
Project description
PaperTrade-India
A production-grade simulated broker for NSE & BSE paper trading.
Realistic Indian-market order execution — fees, T+1 settlement, tick/lot/band rules, and live prices — behind a clean, Alpaca-style Python API.
Overview
No Indian broker offers a programmatic paper-trading API. PaperTrade-India fills that gap: a simulated NSE/BSE broker that models the parts of real trading that actually move your P&L — statutory fees, T+1 settlement, price bands, slippage, and market impact — while exposing the same method surface as an Alpaca-style trading client, so you can build and test strategies without touching real capital or rewriting your code.
from papertrade_india import IndiaPaperBroker
broker = IndiaPaperBroker(initial_capital=1_000_000)
order = broker.buy("RELIANCE", 10)
print(order.filled_avg_price, order.fees_paid)
Status: alpha (pre-1.0). The public API is stable enough to build on, but minor releases may introduce breaking changes until 1.0.
Why
| Platform | Paper trading | API access |
|---|---|---|
| Zerodha Kite | ❌ | ❌ |
| Upstox | ⚠️ mock only | ⚠️ mock only |
| Angel One SmartAPI | ❌ | ❌ |
| Dhan / Fyers / Shoonya | ❌ | ❌ |
| papertrade-india | ✅ | ✅ |
Features
Execution realism — all on by default, so a fresh broker behaves like a real retail account:
- Indian fee model — brokerage, STT, exchange charges, GST, SEBI charges, stamp duty, and DP charges, configurable per broker and date-versioned for mid-year statutory changes.
- T+1 settlement with deliverable-quantity enforcement, plus same-day
intraday round-trips via
ProductType.INTRADAYand 15:15 auto-square-off. - Tick / lot / price-band rules — orders snap to the symbol's tick and are rejected outside the daily band.
- Order types — market, limit,
STOP_MARKET,STOP_LIMIT, andBRACKETwith full OCO semantics. - Synthetic L2 order book — uses real provider depth when available, with queue-position tracking and Almgren-style market impact.
- Slippage, latency, and random-rejection simulation for stress-testing strategy robustness.
- Mark-to-bid valuation for realistic unrealized P&L.
Data — a pluggable MarketDataProvider layer:
- Built-in providers:
yfinance,jugaad-data,stooq,nse-bhavcopy(official EOD),nsepython,alphavantage,twelvedata,finnhub, plus live broker feedsupstoxanddhan(real bid/ask + market depth). - Per-provider circuit breakers, median aggregation across sources,
a first-wins
resilient_feed()helper, and a name registry. - Live NSE/BSE holiday calendar from the exchange-published API, cached with an offline fallback.
Engineering & safety
- Thread-safe SQLite persistence (WAL, atomic transactions, versioned migrations).
- Session-phase awareness (PRE_OPEN / REGULAR / POST_CLOSE / CLOSED).
- Risk controls: kill switch, symbol whitelist, per-order and per-position notional caps.
- Idempotency keys, an immutable cash ledger with an invariant check, broker fee presets (Zerodha, Upstox, Groww, Angel One, ICICIdirect), a symbol master with delisting, corporate actions (splits + dividends), and a persisted event log with an in-process observability bus.
- Multi-account support, an optional CLI, and an optional MCP server so LLM agents can trade through tool calls.
Installation
pip install papertrade-india # core
pip install 'papertrade-india[jugaad]' # + NSE-direct fallback data
pip install 'papertrade-india[cli]' # + Typer/Rich CLI
pip install 'papertrade-india[mcp]' # + MCP server
pip install 'papertrade-india[dev]' # + tests and linting
Requires Python 3.10+.
Quickstart
from papertrade_india import IndiaPaperBroker
broker = IndiaPaperBroker(initial_capital=1_000_000)
# Market buy (inside NSE trading hours)
order = broker.buy("RELIANCE", 10)
print(order.filled_avg_price, order.fees_paid)
# Inspect state
for position in broker.get_positions():
print(position.symbol, position.qty, position.unrealized_pl)
account = broker.get_account()
print(f"Equity: ₹{account.equity:,.2f} Cash: ₹{account.cash:,.2f}")
# Realize P&L
broker.sell("RELIANCE", 10)
The full getting-started walkthrough and a worked example for every
feature — limit orders, multiple accounts, risk controls, live data feeds,
realism configuration, and more — live in QUICKSTART.md.
Runnable scripts are in examples/.
Configuration
Provide your own broker credentials and data-provider keys via a .env
file — see .env.example. Everything is optional: with no
keys set, the broker uses the free yfinance → jugaad-data fallback chain
and works out of the box. API keys unlock live broker feeds and
higher-rate data sources.
Fee model
Defaults match a typical discount-broker delivery account:
| Component | Default rate | Applies to |
|---|---|---|
| Brokerage | ₹0 | Both sides (delivery) |
| STT | 0.1% | Both sides |
| Exchange charge | 0.00322% (NSE) / 0.00375% (BSE) | Both sides |
| GST | 18% on (brokerage + exchange) | Both sides |
| SEBI charges | ₹10 per crore | Both sides |
| Stamp duty | 0.015% | Buy only |
| DP charge | ₹13.5 | Sell only |
Override any field via FeeConfig, or use a named preset, to model
intraday or full-service brokers.
Scope & limitations
The simulator is intentionally focused on cash equity, delivery, long-only trading. It is a faithful behavioral simulator, not an exchange replica:
| Limitation | Notes |
|---|---|
| Synthetic order book, not a real matching engine | Uses real provider depth when available; accurate for retail order sizes. True queue priority isn't reproducible from retail data. |
| Snapshot prices, not a tick stream | Fills price off the latest snapshot — negligible at daily/swing cadence. |
| Corporate actions applied manually | Via apply_split / apply_dividend. |
| No margin, leverage, or short selling | Cash, long-only by design. |
| No options or F&O | Equity only. |
Contributing
Issues and pull requests are welcome. Install the dev extras and run the test suite before submitting:
pip install -e '.[dev]'
pytest
ruff check src tests
License
MIT — use it however you want.
Disclaimer
This is a simulated broker; it does not place real trades. It is not investment advice. Always verify calculations against your actual broker's contract notes before relying on the simulator's outputs for tax, compliance, or investment decisions.
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 papertrade_india-0.1.0.dev0.tar.gz.
File metadata
- Download URL: papertrade_india-0.1.0.dev0.tar.gz
- Upload date:
- Size: 230.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
26ad0ba3378c8aff28140d3dc27114b69d753ca9922f71cb3e0201120412a8c8
|
|
| MD5 |
7443fd8a20e354a1be3b924572df1482
|
|
| BLAKE2b-256 |
0684e0c337d85c42af18e04969d877371799563e60748e44aa363ba1eaf29ca6
|
Provenance
The following attestation bundles were made for papertrade_india-0.1.0.dev0.tar.gz:
Publisher:
publish.yml on Mirzabaig313/PaperTrade-India
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
papertrade_india-0.1.0.dev0.tar.gz -
Subject digest:
26ad0ba3378c8aff28140d3dc27114b69d753ca9922f71cb3e0201120412a8c8 - Sigstore transparency entry: 2079850154
- Sigstore integration time:
-
Permalink:
Mirzabaig313/PaperTrade-India@35a722493a26d69ca8a102b9508264b536f1235a -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Mirzabaig313
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@35a722493a26d69ca8a102b9508264b536f1235a -
Trigger Event:
release
-
Statement type:
File details
Details for the file papertrade_india-0.1.0.dev0-py3-none-any.whl.
File metadata
- Download URL: papertrade_india-0.1.0.dev0-py3-none-any.whl
- Upload date:
- Size: 195.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c5146ac6fbbce608addefd5440eff1bcde8cc45f1c5a9298de47cd90550b06bc
|
|
| MD5 |
fccbffb9bd975a913d19c2e2dd70dca2
|
|
| BLAKE2b-256 |
f35582ea11e1cbbc6d097708b51ba029f2a5a05a5e16d84ddd057be6a9def817
|
Provenance
The following attestation bundles were made for papertrade_india-0.1.0.dev0-py3-none-any.whl:
Publisher:
publish.yml on Mirzabaig313/PaperTrade-India
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
papertrade_india-0.1.0.dev0-py3-none-any.whl -
Subject digest:
c5146ac6fbbce608addefd5440eff1bcde8cc45f1c5a9298de47cd90550b06bc - Sigstore transparency entry: 2079850180
- Sigstore integration time:
-
Permalink:
Mirzabaig313/PaperTrade-India@35a722493a26d69ca8a102b9508264b536f1235a -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Mirzabaig313
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@35a722493a26d69ca8a102b9508264b536f1235a -
Trigger Event:
release
-
Statement type: