Documentation Index
Fetch the complete documentation index at: https://mintlify.com/backtest-kit/backtest-monorepo-parallel/llms.txt
Use this file to discover all available pages before exploring further.
backtest-monorepo-parallel is organized as an npm workspaces monorepo. Two publishable packages (@pro/core and @pro/main) handle all shared infrastructure. Strategy files under ./content/ are loaded at runtime by @backtest-kit/cli and are intentionally never bundled into either package. The config/ directory bridges the two worlds — it wires persistence adapters, resolves CJS paths, and initializes the database connections before any strategy code runs.
Workspace layout
The table below maps every top-level directory to its purpose:| Path | Package / role |
|---|---|
packages/core/ | @pro/core — DI container, services, schemas, Redis/Mongo helpers |
packages/main/ | @pro/main — entry point dispatcher, CLI flag reader, mode files |
content/ | Strategy files loaded at runtime by @backtest-kit/cli; never bundled |
config/ | alias.config.ts, loader.config.ts, setup.config.ts — runtime wiring |
docker/ | docker-compose.yaml files for MongoDB and Redis |
scripts/ | linux/build.sh and win/build.bat — per-platform build walkers |
tsconfig.json | Root TypeScript config; maps @pro/core and @pro/main to types.d.ts |
package.json | Root manifest; declares workspaces: ["./packages/*"] and top-level scripts |
The
tsconfig.json include array covers only ./config and ./content — not ./packages. Each package has its own tsconfig.json and is compiled independently by rollup. The root config exists solely to give strategy files and config files correct type-checking through the paths aliases described below.@pro/core: the DI container
All shared services live in packages/core/. The DI runtime is built on di-kit’s createActivator, which returns three primitives tied to a named scope ("pro"):
TYPES symbol registry
Every service is identified by a uniqueSymbol. They are gathered in a single TYPES object:
Service registration
provide.ts maps each symbol to a factory function. The factories are grouped in blocks that mirror the TYPES categories:
ioc assembly and globalThis assignment
packages/core/src/lib/index.ts imports provide.ts (as a side-effect), calls inject<T>() for each service into per-category objects, spreads those objects into the ioc export, calls init() to resolve the container, then assigns ioc to globalThis.core:
packages/core/src/index.ts re-exports the assembled object: export { ioc } from "./lib";. The rollup build bundles this into packages/core/build/index.cjs and emits the global augmentation into packages/core/types.d.ts.
@pro/main: entry point dispatcher
packages/main/ reads CLI flags from getArgs() and conditionally activates one of four mode files:
- Mode A — parallel (--entry)
- Mode B — single-symbol (no --entry)
- Live / Paper / Session
When
--entry is present, backtest.ts reads CC_SYMBOL_LIST (default: 9 USDT pairs) and calls Backtest.background(symbol, …) for each symbol. All contexts run concurrently in the same Node event loop, sharing one Mongo connection pool and one Redis pool.packages/main/src/index.ts re-exports all mode files so the rollup bundle captures every entry point in a single build/index.cjs artifact.
config/ layer
The config/ directory contains three files that run before any strategy code:
alias.config.ts — CJS path resolution
alias.config.ts — CJS path resolution
Maps the npm package names to their built CJS artifacts so This is the runtime complement to the compile-time
@backtest-kit/cli can require() them at runtime:tsconfig.json paths aliases.loader.config.ts — initialization sequence
loader.config.ts — initialization sequence
Imports
@pro/core (triggering the globalThis.core assignment) and @pro/main (registering the mode dispatchers), then waits for the Mongo connection to resolve:waitForInit() resolves once mongoose.connect() inside @backtest-kit/mongo completes. Only after that promise resolves does @backtest-kit/cli begin evaluating strategy files — ensuring core.* is always populated before any strategy code runs.setup.config.ts — persistence adapters
setup.config.ts — persistence adapters
Declares which adapter each backtest-kit subsystem uses. The current split runs Live mode against Mongo (durable) and most Backtest mode adapters against in-memory or local-file stores (fast):
Switching any adapter is one line in this file.
| Subsystem | Live | Backtest |
|---|---|---|
| Session | Persist (Mongo) | Local file |
| Storage | Persist | Memory |
| Recent | Persist | Memory |
| Notification | Persist | Memory |
| Memory | Persist | Local file |
| State | Persist | Local file |
| Markdown | Dummy (no-op) | Dummy |
| Log | JSONL | JSONL |
Build pipeline
Each package builds independently with rollup and emits two artifacts:scripts/linux/build.sh walks ./packages/* and runs npm install && npm run build inside each directory:
npm run build at the root delegates to this script via npm run build:x (or scripts/win/build.bat on Windows via npm run build:win). Both call rollup -c inside each package — @rollup/plugin-typescript compiles the source; rollup-plugin-dts bundles the declarations into the single types.d.ts file.
Zero-import DI via tsconfig.json paths
The compile-time half of the zero-import pattern is a two-line paths configuration in the root tsconfig.json:
Because
types.d.ts contains declare global { var core: typeof ioc }, TypeScript resolves core.* everywhere inside ./config and ./content without any import statement. The strategy author never needs to know that @pro/core exists — core.candleDbService, core.scraperService, and every other service are simply available as global identifiers with full IntelliSense. At runtime, loader.config.ts ensures the same object is present on globalThis before the strategy file is evaluated.Adding new services (scaling pattern)
The monorepo is designed to grow without restructuring. Adding a new service follows a five-step recipe:Register the symbol
Add
xService: Symbol('xService') to TYPES in packages/core/src/lib/core/types.ts.Register the provider
Add
provide(TYPES.xService, () => new XService()) to packages/core/src/lib/core/provide.ts.Expose on ioc
Add
xService: inject<XService>(TYPES.xService) to a per-category object in packages/core/src/lib/index.ts, then spread it into ioc.