Repository structure¶
The repository is an installable Python library with its documentation, its local database containers and the notes that explain it. All library code lives under src/tradingmachine, so the repository root is not importable and the library must be installed, with pip install -e ".[docs,development]", before it can be used.
The tree¶
The annotated tree below shows every directory and the files that matter. The 53 synthetic order modules and the 14 analysis modules are summarised rather than listed one by one.
tradingmachine/
├── pyproject.toml the library's metadata, its 7 dependencies, the docs and development extras
├── requirements.txt the pinned development environment, not read by the library
├── README.md
├── docker-compose.yml Redis, MongoDB and TimescaleDB on host ports 2002 to 2004
├── mkdocs.yml this site's configuration: theme, nav, plugins, mkdocstrings options
├── CLAUDE.md a dense description of the library for AI assistants
├── .github/workflows/docs.yml builds the site on every push and pull request, publishes from main
├── scripts/ documentation build tooling, deliberately outside the package
│ ├── gen_ref_pages.py writes one reference page per module at build time
│ └── documentation_hooks.py filters the one griffe warning a strict build would fail on
├── docs/ this site
│ ├── index.md Home
│ ├── get-started/ installation, configuration, first steps
│ ├── python-api/ one page per group of members, Kite Connect style
│ ├── asset-classes/ one page per family module
│ ├── analysis/ indicators, patterns, statistics, signals and backtests
│ ├── architecture/ layers, the instrument model, the order engine, design choices
│ ├── project/ this tab
│ ├── assets/diagrams/ the animated SVG diagrams, included with snippets
│ └── stylesheets/extra.css every custom class the pages use
├── .claude/notes/ one sidecar note per file, mirroring the tree, holding the reasoning
└── src/tradingmachine/
├── __init__.py the package docstring and __version__, imports nothing else
├── accounts/
│ └── account.py Account, whose flatten is UBI's account-wide kill switch
├── asset_baskets/
│ ├── asset_basket.py AssetBasket, the shared base, which inherits the 14 analysis classes
│ ├── basket_member.py BasketMember, one instrument with a weight, a quantity, or neither
│ ├── portfolio.py Portfolio, which can place and rebalance orders
│ ├── watchlist.py Watchlist
│ ├── index.py Index, the constituents of an index
│ ├── exchange_traded_fund_constituents.py
│ ├── mutual_fund_constituents.py
│ ├── basket_store.py BasketStore, the asset_baskets collection in MongoDB
│ ├── basket_csv_importer.py BasketCsvImporter, which fills the store from a CSV file
│ ├── member_resolver.py MemberResolver, which builds every member in one request
│ └── exceptions.py AssetBasketError and its 3 subclasses
├── assets/
│ ├── instruments.py Instrument, TradeableInstrument, NonTradeableInstrument,
│ │ Derivative, Futures, Option, IndexFutures, IndexOption
│ ├── option_pricing.py BlackScholes and Black76, the maths behind implied volatility and greeks
│ ├── equities.py 6 equity-family classes
│ ├── fixed_income.py 6 fixed income classes
│ ├── commodities.py 6 commodity classes
│ ├── currencies.py 6 currency classes
│ ├── funds.py ExchangeTradedFund, InvestmentTrust
│ ├── mutual_funds.py MutualFund
│ ├── exceptions.py InstrumentError and its 37 subclasses
│ └── analysis/
│ ├── price_analysis.py PriceAnalysis, the shared base
│ └── 14 modules one analysis class each, inherited by Instrument and AssetBasket
├── orders/
│ ├── __init__.py the table of UBI type, module and class
│ ├── synthetic_order.py SyntheticOrder, the shared base
│ ├── order_candidate.py OrderCandidate, one leg of a multi-instrument order
│ ├── exposure_watch.py ExposureWatch, one watched instrument of an exposure hedge
│ └── 53 modules one synthetic order type each, such as bracket.py
├── unified_broker_interface/
│ ├── client.py UnifiedBrokerInterface, the only code that speaks HTTP
│ └── exceptions.py one error class per HTTP status UBI returns
└── utilities/
└── configuration.py Configuration, which reads the environment and .env lazily
site/, .venv/, .env and the build outputs are also present on a working machine, and .gitignore keeps all of them out of git.
Module counts¶
The table below counts the Python files and lines in each package, measured on 2026-09-29. The counts include each package's __init__.py.
| Package | Python files | Lines | What it holds | Third-party imports |
|---|---|---|---|---|
tradingmachine |
1 | 17 | The package docstring and __version__ |
none |
tradingmachine.accounts |
2 | 133 | Account |
pandas |
tradingmachine.asset_baskets |
12 | 3,112 | AssetBasket, the five kinds of basket, their store, importer and errors |
pandas, pymongo |
tradingmachine.assets |
10 | 8,569 | The instrument classes, the 27 family classes, the option pricing models and their errors | pandas |
tradingmachine.assets.analysis |
16 | 8,964 | PriceAnalysis and the 14 analysis classes |
talib, backtesting, numpy, pandas |
tradingmachine.orders |
57 | 7,078 | SyntheticOrder, two helper classes and 53 order types |
pandas, for type hints only |
tradingmachine.unified_broker_interface |
3 | 507 | UnifiedBrokerInterface and its 13 exception classes |
requests, pymongo |
tradingmachine.utilities |
2 | 133 | Configuration |
dotenv |
| Total | 103 | 28,513 |
The chart below shows the same line counts, which makes it plain that the library's weight is in its instruments and their analysis, not in its plumbing.
.claude/notes/ holds 104 notes. Every source module has one except the five __init__.py files that hold no reasoning worth recording: the top-level one and those of assets, assets.analysis, unified_broker_interface and utilities. The other six notes cover mkdocs.yml, pyproject.toml, docker-compose.yml, the two scripts and the documentation workflow.
Which package imports which¶
The diagram below shows every import from one package of the library into another, read from the import lines in the source. An arrow means "imports", and the dashed arrow is an import made inside a method body rather than at the top of the file. Apart from that one, the dependencies run one way only, from the objects you use down to the client and the configuration.
flowchart TB
AC["accounts<br/>Account"]
BK["asset_baskets<br/>5 kinds of basket, store"]
OR["orders<br/>53 synthetic order types"]
AS["assets<br/>instruments, 27 family classes, exceptions"]
AN["assets.analysis<br/>14 analysis classes"]
UC["unified_broker_interface<br/>client, exceptions"]
UT["utilities<br/>configuration"]
AC -->|"assets.instruments"| AS
AC -->|"unified_broker_interface.client"| UC
BK -->|"assets.instruments"| AS
BK -->|"14 analysis modules"| AN
BK -->|"client"| UC
BK -->|"configuration"| UT
AS -.->|"basket_store, inside constituents"| BK
OR -->|"assets.instruments"| AS
AS -->|"14 analysis modules"| AN
AS -->|"client, exceptions"| UC
UC -->|"configuration"| UT
Four details of the graph are worth knowing.
ordersdoes not importunified_broker_interface. A synthetic order sends itself throughTradeableInstrument.place_order, so the shared client applies to it without any code of its own, and itscancel()andparentgo through the instrument's parent members in the same way.accountsimportsassets.instrumentsonly to callInstrument.shared_unified_broker_interface(), so that anAccountshares the instruments' client instead of logging them out with a second one.assetsandasset_basketsimport each other, which would be a circular import if both imports ran when the files load. SoNonTradeableInstrument.constituents,ExchangeTradedFund.constituentsandMutualFund.constituentsimportbasket_storeinside the property's body, when it is first read, and the type hints that nameAssetBasketsit underif TYPE_CHECKING:. Importingassetstherefore never loadsasset_baskets.- Inside
assets, every family module importsinstrumentsandexceptions, andinstrumentsalone imports the fourteen analysis modules.asset_baskets.asset_basketimports the same fourteen, so a basket inherits exactly what an instrument does. Insideorders, every type importssynthetic_order, and the multi-instrument types also importorder_candidateorexposure_watch.
The package __init__.py files import nothing from the library, and the top-level one imports only importlib.metadata to read the version, so import tradingmachine never reaches for the network, the databases or the .env file. Import the module you need, such as from tradingmachine.assets import equities.