Python SDK for Delta Exchange India — perpetual futures broker with bracket orders and OHLCV candle history
Project description
deltain
Python SDK for Delta Exchange India — the INR-settled perpetual futures exchange. Built from scratch with a clean abstract broker interface, automatic retry logic, and a full live integration test suite verified against the Delta Exchange testnet.
pip install deltain
Features
| Capability | Details |
|---|---|
| Market & Limit Orders | IOC market orders, GTC limit orders |
| Stop-Loss Orders | Standalone stop-loss with close_on_trigger |
| Bracket Orders | Entry + SL + TP in a single atomic API call |
| OHLCV Candle History | 1-minute candles, auto-paginated across any date range |
| Bracket Support Check | is_bracket_order_supported() per symbol |
| Order Status & Cancel | Query by client_order_id, idempotent cancel |
| Auto-reconnect | Retries on 502 Bad Gateway and connection errors |
| Testnet / Mainnet | Single flag to switch environments |
| Abstract Base Class | Broker ABC so you can swap exchanges without changing strategy code |
Installation
pip install deltain
Requirements: Python >= 3.10, requests >= 2.28
Or install from source:
git clone https://github.com/friendmanjur/delta-exchange-india-sdk.git
cd delta-exchange-india-sdk
pip install .
Quick Start
from deltain import DeltaBroker
broker = DeltaBroker(
api_key = "YOUR_KEY",
api_secret = "YOUR_SECRET",
testnet = True, # flip to False for live trading
)
broker.login()
# Live price
price = broker.get_price("BTCUSD")
print(f"BTCUSD: {price:.2f}")
# Market order
fill = broker.place_market_order("BTCUSD", "buy", qty=1)
# Bracket order - entry + stop-loss + take-profit in one call
broker.place_bracket_order(
symbol = "BTCUSD",
side = "buy",
qty = 1,
limit_price = price,
stop_loss_price = round(price * 0.95, 1),
take_profit_price = round(price * 1.05, 1),
oid = "my-signal-001",
)
# 1-minute candles - auto-paginated, any range
import time
now = (int(time.time()) // 60) * 60
candles = broker.get_one_minute_candles(
exchange = "delta_india",
symbol = "BTCUSD",
start_epoch = now - 7 * 24 * 3600, # 7 days
end_epoch = now,
)
print(f"Fetched {len(candles)} candles")
API Reference
DeltaBroker(api_key, api_secret, testnet=False, timeout=10, retry_delay=1.0)
| Method | Description |
|---|---|
login() |
Verify credentials against /v2/profile. Must be called first. |
get_price(symbol) |
Returns the current mark price as a float. |
place_market_order(symbol, side, qty, oid=None) |
IOC market order. Returns average fill price. |
place_stoploss_order(symbol, side, qty, price, oid) |
GTC stop-loss market order. |
place_target_order(symbol, side, qty, price, oid) |
GTC reduce-only limit order. |
place_bracket_order(symbol, side, qty, limit_price, stop_loss_price, take_profit_price, ...) |
Atomic bracket order. Returns {"delta_id", "avg_fill", "status"}. |
get_order_status(oid) |
Returns {"status", "price", "raw_state"}. Status: OPEN TRIGGERED CANCELLED UNKNOWN. |
cancel_order(oid) |
Idempotent cancel - safe to call on already-closed orders. |
is_bracket_order_supported(symbol) |
True for perpetual/dated futures. Never raises. |
get_one_minute_candles(exchange, symbol, start_epoch, end_epoch) |
Paginated 1-min OHLCV. Returns list of {"time", "open", "high", "low", "close", "volume"}. |
is_connected() |
Ping - returns True if credentials are valid and exchange is reachable. |
relogin() |
Re-authenticate without creating a new broker instance. |
place_bracket_order full signature
broker.place_bracket_order(
symbol = "BTCUSD",
side = "buy", # "buy" or "sell"
qty = 1,
limit_price = 67000.0, # entry limit price
stop_loss_price = 63650.0, # SL trigger price
take_profit_price = 70350.0, # TP trigger price
stop_loss_limit_price = None, # optional - market SL if omitted
take_profit_limit_price = None, # optional - market TP if omitted
stop_trigger_method = "last_traded_price", # or "mark_price" / "index_price"
oid = "signal-btc-001", # optional client_order_id
)
get_one_minute_candles boundary alignment rule
Delta Exchange applies an asymmetric rounding rule to timestamps, discovered and verified via 32 live boundary tests:
aligned_start = ceil(start / 60) * 60 <- CEILING
aligned_end = floor(end / 60) * 60 <- FLOOR
Always align your timestamps to minute boundaries for predictable results:
# Correct - always align first
start = (your_epoch // 60) * 60
end = (your_epoch // 60) * 60
| Start offset | End offset | Candles returned |
|---|---|---|
:00 |
:00 to :59 |
1 candle (the :00 candle) |
:00 |
:60 |
2 candles |
:01 to :59 |
less than :60 |
0 candles - start ceils past end |
:01 to :59 |
:60 to :119 |
1 candle (only the :60 candle) |
Abstract Broker Interface
Write strategy code once, swap the exchange later:
from deltain import Broker
class MyOtherBroker(Broker):
def get_price(self, symbol): ...
def place_market_order(self, symbol, side, qty): ...
def place_stoploss_order(self, symbol, side, qty, price, oid): ...
def place_target_order(self, symbol, side, qty, price, oid): ...
def place_bracket_order(self, symbol, side, qty, limit_price,
stop_loss_price, take_profit_price, ...): ...
def get_order_status(self, oid): ...
def cancel_order(self, oid): ...
# is_bracket_order_supported() defaults to True
# get_one_minute_candles() raises NotImplementedError until overridden
Tests
All tests run against testnet only - no live funds are ever used.
export DELTA_API_KEY="your_testnet_key"
export DELTA_API_SECRET="your_testnet_secret"
# Bracket order tests
python3 tests/test_bracket_order.py
# Candle stress tests
python3 tests/stress_test_candles.py
# Run specific groups
python3 tests/stress_test_candles.py single multi
python3 tests/stress_test_candles.py pagination
python3 tests/stress_test_candles.py edge
| Test file | Assertions | What is covered |
|---|---|---|
test_bracket_order.py |
24 | Login guard, position pre-flight, bracket lifecycle, SL/TP child visibility, idempotent cancel |
stress_test_candles.py |
400+ | Schema, OHLC sanity, pagination up to 30 days, multi-symbol, 32 second-boundary combinations |
Project Structure
delta-exchange-india-sdk/
├── deltain/
│ ├── __init__.py
│ └── broker.py <- Broker ABC + DeltaBroker (820 lines)
├── tests/
│ ├── test_bracket_order.py
│ └── stress_test_candles.py
├── examples/
│ └── quickstart.py
├── pyproject.toml
├── CHANGELOG.md
├── LICENSE
└── README.md
Environment Variables
| Variable | Description |
|---|---|
DELTA_API_KEY |
Your Delta Exchange India API key |
DELTA_API_SECRET |
Your Delta Exchange India API secret |
Get testnet credentials at testnet.delta.exchange.
Security
- Never commit credentials. Use environment variables or a secrets manager.
.gitignoreexcludes.envandsecrets.py.- All tests are hard-coded to
testnet=True.
Changelog
See CHANGELOG.md.
License
MIT - see LICENSE.
Acknowledgements
Built on the Delta Exchange India REST API. Retry and connection patterns ported from the Shoonya C++ trading system.
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 Distributions
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 deltain-1.0.0-py3-none-any.whl.
File metadata
- Download URL: deltain-1.0.0-py3-none-any.whl
- Upload date:
- Size: 19.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
18cc43a296b689a6b3e1787264f2ff516b48b04a055d5c4c446cb9e3b406fb5e
|
|
| MD5 |
1d241e7d2cb980a901c9a364311129ec
|
|
| BLAKE2b-256 |
21f906de4884b6dcf30c885e8721a5ffed117dcdc6a52902b7e5873092f333d0
|