Trading Machine¶
tradingmachine is a Python library that turns Indian market instruments into objects you can ask questions of and trade through. You write Equity("nse", "RELIANCE"), and that object gives you its candles, its live quote, its order book, over 200 kinds of technical analysis and performance measures, its orders, its positions and its holdings. Instruments can also be gathered into baskets, such as a portfolio, a watchlist or an index, which are analysed the same way. Underneath, every question goes to the Unified Broker Interface (UBI), which combines ten stock brokers into one account.
Start here¶
The site is split into tabs along the top. Most readers want the first card, which lists every class and member of the library on one page.
-
Python API
Every public member, one group per page, with parameters, examples captured from a real UBI, return values and exceptions.
-
Get started
Install the library, start its three databases, point it at UBI, and run a first session.
-
Asset classes
The 27 instrument classes across equities, fixed income, commodities, currencies, funds and mutual funds, and what each can and cannot do.
-
Analysis
TA-Lib indicators, candlestick patterns, statistics, crossovers, a backtest and performance measures such as the Sharpe ratio, inherited by every instrument and every basket.
-
Architecture
The layers from your program down to the brokers, how UBI places orders, and why the library is built the way it is.
-
Project
The repository's layout, how to add an asset class, and how this site is built and published.
A first taste¶
The example below looks up one share and reads three things from it. The output was captured from a local UBI on Saturday 2026-09-26, so the prices are Friday's close, and the DataFrame is trimmed to its first two rows.
1226.0
exchange segment interval datetime open high low close volume oi price_factor
0 nse nse_equities day 2026-09-16 00:00:00+05:30 1243.0 1255.0 1240.0 1240.0 10023997 None 1.0
1 nse nse_equities day 2026-09-17 00:00:00+05:30 1244.8 1253.4 1238.5 1243.9 7752895 None 1.0
['RELIABLE', 'RELIANCE', 'RELIGARE', 'RELINFRA']
last_price has no brackets because it only reports a value, so it is a property. prices has brackets because it takes arguments, so it is a method. The whole library follows that rule.
The library in numbers¶
The table below counts what the library holds today, so you can judge the size of each part before you read about it.
| What | Count | Where |
|---|---|---|
| Instrument classes | 27 | src/tradingmachine/assets/, in six family modules |
| Kinds of asset basket | 5 | src/tradingmachine/asset_baskets/, one module each |
| Synthetic order classes | 53 | src/tradingmachine/orders/, one module each |
| Analysis methods inherited by every instrument and basket | 209 | src/tradingmachine/assets/analysis/, in fourteen classes |
Price wrappers such as buy_at_best_bid_price |
32 | TradeableInstrument in src/tradingmachine/assets/instruments.py |
| Exception classes | 55 | 38 in assets/exceptions.py, 13 in unified_broker_interface/exceptions.py, 4 in asset_baskets/exceptions.py |
| Python modules | 103 | src/tradingmachine/, counting each package's __init__.py |
What the library adds to UBI¶
UBI already answers every question the library asks, over HTTP. The comparison below shows what the library adds on top, using the same order written both ways.
import requests
base_url = "http://127.0.0.1:8080"
session = requests.post(
f"{base_url}/api/session/connect",
headers={"api-key": API_KEY, "api-secret": API_SECRET},
).json()
headers = {"access-token": session["access-token"]}
details = requests.get(
f"{base_url}/api/instruments/details",
headers=headers,
params={"exchange": "nse", "segment": "nse_equities", "symbol": "RELIANCE"},
).json()
requests.post(
f"{base_url}/api/orders/place",
headers=headers,
json={
"instrument_id": details["instrument_id"],
"transaction_type": "buy",
"order_type": "limit",
"product": "cnc",
"after_market": False,
"dry_run": False,
"quantity": 1,
"price_reference": {"kind": "bid_level", "level": 1},
},
)
The library looks the instrument up once, keeps the one shared login alive and renews it when UBI answers HTTP 401, and turns each error status into a named exception. It deliberately does not cache anything, round prices or check lot sizes, because UBI does all three.
Orders are real
Every member that places an order sends it through UBI to a real broker, with real money. The Orders page explains dry_run, which asks UBI to check an order and show what it would send, without sending it.