backtest-kit 9.8.4 โ 10.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +98 -1
- package/build/index.cjs +669 -177
- package/build/index.mjs +666 -178
- package/package.json +1 -1
- package/types.d.ts +481 -1
package/README.md
CHANGED
|
@@ -71,13 +71,14 @@ Install the core library and peer dependencies manually. Use this approach when
|
|
|
71
71
|
|
|
72
72
|
- ๐ **Production-Ready**: Seamless switch between backtest/live modes; identical code across environments.
|
|
73
73
|
- ๐พ **Crash-Safe**: Atomic persistence recovers states after crashes, preventing duplicates or losses.
|
|
74
|
-
- โ
**Validation**: Checks signals for TP/SL logic, risk/reward ratios, and portfolio limits.
|
|
74
|
+
- โ
**Validation**: Checks signals for TP/SL logic, risk/reward ratios, whipsaw protection and portfolio limits.
|
|
75
75
|
- ๐ **Efficient Execution**: Streaming architecture for large datasets; VWAP pricing for realism.
|
|
76
76
|
- ๐ค **AI Integration**: LLM-powered strategy generation (Optimizer) with multi-timeframe analysis.
|
|
77
77
|
- ๐ **Reports & Metrics**: Auto Markdown reports with PNL, Sharpe Ratio, win rate, and more.
|
|
78
78
|
- ๐ก๏ธ **Risk Management**: Custom rules for position limits, time windows, and multi-strategy coordination.
|
|
79
79
|
- ๐ **Pluggable**: Custom data sources (CCXT), persistence (file/Redis), and sizing calculators.
|
|
80
80
|
- ๐๏ธ **Transactional Live Orders**: Broker adapter intercepts every trade mutation before internal state changes โ exchange rejection rolls back the operation atomically.
|
|
81
|
+
- โฐ **Built-in Crontab**: Register periodic or fire-once jobs that fire on virtual-time boundaries with singleshot coordination across parallel backtests โ one handler invocation per boundary, no double-fires.
|
|
81
82
|
- ๐งช **Tested**: 520+ unit/integration tests for validation, recovery, and events.
|
|
82
83
|
- ๐ **Self hosted**: Zero dependency on third-party node_modules or platforms; run entirely in your own environment.
|
|
83
84
|
|
|
@@ -1267,6 +1268,80 @@ Broker.enable();
|
|
|
1267
1268
|
|
|
1268
1269
|
Signal open/close events are routed automatically via an internal event bus once `Broker.enable()` is called. **No manual wiring needed.** All other operations (`partialProfit`, `trailingStop`, `breakeven`, `averageBuy`) are intercepted explicitly before the corresponding state mutation.
|
|
1269
1270
|
|
|
1271
|
+
### ๐ How Cron Works
|
|
1272
|
+
|
|
1273
|
+
`Cron` is a periodic / fire-once scheduler that runs in **virtual time** โ the same time stream your strategies see in backtest mode. Handlers fire on candle-interval boundaries (`1m`, `5m`, `1h`, `1d`, โฆ) and are coordinated across parallel `Backtest.background(symbol, ...)` runs so the same boundary never produces two concurrent invocations.
|
|
1274
|
+
|
|
1275
|
+
**Public API:**
|
|
1276
|
+
- **`Cron.register({ name, interval?, symbols?, handler })`** โ register a job. Returns a disposer. Re-registering the same `name` replaces the previous entry and bumps an internal generation counter (late writes from old handlers are ignored).
|
|
1277
|
+
- **`Cron.enable()`** โ subscribe `Cron` to the engine's lifecycle subjects (`beforeStart`, `idlePing`, `activePing`, `schedulePing`). Wrapped in `singleshot`; call once at startup.
|
|
1278
|
+
- **`Cron.disable()`** โ tear down the subscriptions installed by `enable()`. Safe to call multiple times and before `enable()`.
|
|
1279
|
+
- **`Cron.unregister(name)`** โ remove a registered job.
|
|
1280
|
+
- **`Cron.clear(symbol?)`** โ clear fire-once marks. `symbol` provided โ fan-out marks for that symbol only; no argument โ all marks. Does **not** touch in-flight handlers.
|
|
1281
|
+
|
|
1282
|
+
**Two modes per `interval`:**
|
|
1283
|
+
- **Periodic** (`interval: "1h"`) โ handler fires once per boundary of that interval.
|
|
1284
|
+
- **Fire-once** (`interval` omitted) โ handler fires on the first matching tick and never again until `clear()` / `unregister` / re-`register`.
|
|
1285
|
+
|
|
1286
|
+
**Two scopes per `symbols`:**
|
|
1287
|
+
- **Global** (`symbols` omitted) โ handler fires once per boundary across all parallel backtests. First symbol to reach the boundary opens the slot; others await the same promise.
|
|
1288
|
+
- **Fan-out** (`symbols: ["BTC", "ETH"]`) โ handler fires once per boundary **per whitelisted symbol**. Each symbol has its own slot.
|
|
1289
|
+
|
|
1290
|
+
<details>
|
|
1291
|
+
<summary>
|
|
1292
|
+
The code
|
|
1293
|
+
</summary>
|
|
1294
|
+
|
|
1295
|
+
```typescript
|
|
1296
|
+
import { Cron, Backtest } from "backtest-kit";
|
|
1297
|
+
|
|
1298
|
+
// Global hourly job โ fires once per virtual hour across all parallel backtests.
|
|
1299
|
+
Cron.register({
|
|
1300
|
+
name: "tg-signal-parser",
|
|
1301
|
+
interval: "1h",
|
|
1302
|
+
handler: async (symbol, when, backtest) => {
|
|
1303
|
+
await parseTelegramSignalsToMongo(when);
|
|
1304
|
+
},
|
|
1305
|
+
});
|
|
1306
|
+
|
|
1307
|
+
// Per-symbol fan-out โ fires once per hour per whitelisted symbol.
|
|
1308
|
+
Cron.register({
|
|
1309
|
+
name: "fetch-funding",
|
|
1310
|
+
interval: "1h",
|
|
1311
|
+
symbols: ["BTCUSDT", "ETHUSDT"],
|
|
1312
|
+
handler: async (symbol, when, backtest) => {
|
|
1313
|
+
await fetchFundingRate(symbol, when);
|
|
1314
|
+
},
|
|
1315
|
+
});
|
|
1316
|
+
|
|
1317
|
+
// Fire-once warm-up โ runs once globally on the very first tick.
|
|
1318
|
+
Cron.register({
|
|
1319
|
+
name: "warm-cache",
|
|
1320
|
+
handler: async (symbol, when, backtest) => {
|
|
1321
|
+
await warmupCache();
|
|
1322
|
+
},
|
|
1323
|
+
});
|
|
1324
|
+
|
|
1325
|
+
// Wire Cron to the engine once at startup. After this every strategy tick is
|
|
1326
|
+
// forwarded into Cron automatically โ no manual listener wiring needed.
|
|
1327
|
+
Cron.enable();
|
|
1328
|
+
|
|
1329
|
+
for (const symbol of ["BTCUSDT", "ETHUSDT", "SOLUSDT", "BNBUSDT", "TRXUSDT"]) {
|
|
1330
|
+
Backtest.background(symbol, { strategyName, exchangeName, frameName });
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1333
|
+
// On shutdown:
|
|
1334
|
+
// Cron.disable();
|
|
1335
|
+
```
|
|
1336
|
+
|
|
1337
|
+
</details>
|
|
1338
|
+
|
|
1339
|
+
#### Internals
|
|
1340
|
+
|
|
1341
|
+
`Cron.enable()` subscribes a single `singlerun`-wrapped handler to four lifecycle subjects (`beforeStart`, `idlePing`, `activePing`, `schedulePing`). `singlerun` merges all four streams into one serial queue, so concurrent ticks on the same `(symbol, virtual-minute)` cannot race to open the same slot. Each incoming tick is **base-aligned to the 1-minute boundary** before any further processing โ lifecycle pings may carry sub-second jitter, but Cron always reasons in whole minutes.
|
|
1342
|
+
|
|
1343
|
+
Coordination keys are built as `${name}:${alignedMs}:${symbol?}:g${generation}`. Parallel backtests that hit the same key share a single in-flight promise (mutex semantics): the first opens the slot and runs the handler, others `await` the same promise and release together. After `.finally()` the slot is removed and the next boundary creates a fresh promise. Fire-once entries additionally record a `_firedOnce` mark on success so subsequent ticks skip them โ a failed handler is **not** marked, so it retries on the next tick. The generation suffix isolates re-registrations: a late write from a still-in-flight handler of a previous `register()` carries the old generation and never collides with the new entry.
|
|
1344
|
+
|
|
1270
1345
|
### ๐ How getCandles Works
|
|
1271
1346
|
|
|
1272
1347
|
backtest-kit uses Node.js `AsyncLocalStorage` to automatically provide
|
|
@@ -1765,6 +1840,28 @@ git clone https://github.com/backtest-kit/backtest-monorepo-parallel.git
|
|
|
1765
1840
|
```
|
|
1766
1841
|
|
|
1767
1842
|
|
|
1843
|
+
### backtest-ollama-crontab
|
|
1844
|
+
|
|
1845
|
+
> **[Explore on GitHub](https://github.com/backtest-kit/backtest-ollama-crontab)** ๐
|
|
1846
|
+
|
|
1847
|
+
The **backtest-ollama-crontab** repository is a TypeScript monorepo template that wires a cloud/local **Ollama** into a trading-signal pipeline as a risk filter, with a **15-minute crontab** ingesting signals from any public Telegram channel. The **same code runs in both live and backtest modes** โ the crontab re-polls live and pulls the entire frame at startup in backtest.
|
|
1848
|
+
|
|
1849
|
+
#### Key Features
|
|
1850
|
+
- ๐ค **Local/Cloud LLM Risk Filter**: Per-signal verdict from local Ollama (`gpt-oss` quantized) returning `riskAction: "skip" | "follow"`, with empirical rules embedded in the system prompt and tunable without recompiling packages
|
|
1851
|
+
- โฐ **Crontab-Driven Ingestion**: `Cron.register(..., interval: "15m")` for live re-polling of the Telegram channel, plus a fire-once `Cron.register(...)` (no `interval`) for backtest-time bulk prepare โ same code path in both modes
|
|
1852
|
+
- ๐ก **Telegram MTProto Crawler**: QR-code session auth, `iterMessages` pull from any public channel into a `parser-items` Mongo collection, regex extraction of `direction / entry / targets / stoploss` into `screen-items`
|
|
1853
|
+
- ๐ง **Outline-Based Risk Logic**: Risk outline ingests 1m/15m candles + a pre-computed metrics packet (`avgRangePct`, `momentum24hPct`) and produces a zod-validated verdict consumed by the strategy
|
|
1854
|
+
- ๐ **Reproducible Backtest Comparison**: same parsed-signal set, two backtests side-by-side โ **+52.22% โ +68.90%** total PNL, Sharpe **+0.309 โ +0.512**, winrate **68% โ 82%**, profit factor **2.73 โ 6.37** with the LLM gate enabled
|
|
1855
|
+
|
|
1856
|
+
#### Use Case
|
|
1857
|
+
Reference for integrating any local LLM into a backtest-kit pipeline as a signal filter, and for combining periodic crontab pulls (live) with one-shot bulk prepare (backtest) via the same `Cron.register` API.
|
|
1858
|
+
|
|
1859
|
+
#### Get Started
|
|
1860
|
+
```bash
|
|
1861
|
+
git clone https://github.com/backtest-kit/backtest-ollama-crontab.git
|
|
1862
|
+
```
|
|
1863
|
+
|
|
1864
|
+
|
|
1768
1865
|
### backtest-kit-redis-mongo-docker
|
|
1769
1866
|
|
|
1770
1867
|
> **[Explore on GitHub](https://github.com/backtest-kit/backtest-kit-redis-mongo-docker)** ๐ณ
|