Skip to content

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.

Your program, the library, UBI and ten brokers Quotes, candles, orders and positions flow from ten brokers into the Unified Broker Interface, through the library's shared client, to the instrument objects and the asset baskets, and from there to your program. Asset baskets are also saved to and loaded from this project's MongoDB. Orders go the other way, from a synthetic order or a portfolio through the shared client to UBI, which sends each one to a broker. tradingmachine sibling project brokers Dhan Flattrade Fyers Groww INDmoney Kotak Shoonya Stoxkart Wisdom Capital Zerodha saved and loaded Your program Instrument objects 27 classes, Equity to MutualFund Synthetic orders 53 classes, one per order type Account flatten, the account-wide kill switch Asset baskets Portfolio, Watchlist, Index, funds Shared UBI client retries once on 401 MongoDB asset_baskets UBI 127.0.0.1:8080 REST API and order engine
Orange dots are quotes, candles, orders and positions coming up from the brokers, through the shared client, to the instrument objects and the asset baskets, and on to your program; the orange dot below the baskets is a basket being saved to or loaded from MongoDB. Blue dots are orders going the other way, from a synthetic order or a portfolio, through UBI to one broker.

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.

    Go to the Python API

  • Get started


    Install the library, start its three databases, point it at UBI, and run a first session.

    Installation

  • Asset classes


    The 27 instrument classes across equities, fixed income, commodities, currencies, funds and mutual funds, and what each can and cannot do.

    Compare the families

  • 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.

    Analyse candles

  • Architecture


    The layers from your program down to the brokers, how UBI places orders, and why the library is built the way it is.

    How it fits together

  • Project


    The repository's layout, how to add an asset class, and how this site is built and published.

    Work on the project

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.

from tradingmachine.assets import equities

reliance = equities.Equity("nse", "RELIANCE")
print(reliance.last_price)
print(reliance.prices(days=10))
print(equities.Equity.search("nse", "RELI", limit=5)["symbol"].tolist())
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.

from tradingmachine.assets import equities

reliance = equities.Equity("nse", "RELIANCE")
reliance.buy_at_best_bid_price(quantity=1, product="cnc")
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.