@backtest-kit/mongo 0.0.1

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 ADDED
@@ -0,0 +1,150 @@
1
+ <img src="https://github.com/tripolskypetr/backtest-kit/raw/refs/heads/master/assets/consciousness.svg" height="45px" align="right">
2
+
3
+ # ðŸ’ū @backtest-kit/mongo
4
+
5
+ > MongoDB + Redis persistence adapter for backtest-kit. Swaps the default file-based storage for a production-grade backend — one `setup()` call, no changes to strategy code.
6
+
7
+ ![screenshot](https://raw.githubusercontent.com/tripolskypetr/backtest-kit/HEAD/assets/screenshots/screenshot16.png)
8
+
9
+ [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/tripolskypetr/backtest-kit)
10
+ [![npm](https://img.shields.io/npm/v/@backtest-kit/mongo.svg?style=flat-square)](https://npmjs.org/package/@backtest-kit/mongo)
11
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-blue)]()
12
+
13
+ 📚 **[Backtest Kit Docs](https://backtest-kit.github.io/documents/article_07_ai_news_trading_signals.html)** | 🌟 **[GitHub](https://github.com/tripolskypetr/backtest-kit)**
14
+
15
+ > **New to backtest-kit?** The fastest way to get a real, production-ready setup is to clone the [reference implementation](https://github.com/tripolskypetr/backtest-kit/tree/master/example) — a fully working news-sentiment AI trading system with LLM forecasting, multi-timeframe data, and a documented February 2026 backtest. Start there instead of from scratch.
16
+
17
+ ## 🚀 Installation
18
+
19
+ ```bash
20
+ npm install @backtest-kit/mongo backtest-kit
21
+ ```
22
+
23
+ ## 📖 Usage
24
+
25
+ ### Quick Start
26
+
27
+ ```typescript
28
+ import { setup } from '@backtest-kit/mongo';
29
+
30
+ // Reads connection settings from environment variables.
31
+ // Call once before any trading operations.
32
+ setup();
33
+ ```
34
+
35
+ ### Explicit connection parameters
36
+
37
+ ```typescript
38
+ import { setup } from '@backtest-kit/mongo';
39
+
40
+ setup({
41
+ CC_MONGO_CONNECTION_STRING: 'mongodb://mongo:27017/mydb',
42
+ CC_REDIS_HOST: 'redis',
43
+ CC_REDIS_PORT: 6379,
44
+ CC_REDIS_PASSWORD: 'secret',
45
+ });
46
+ ```
47
+
48
+ ## 📋 API Reference
49
+
50
+ | Export | Description |
51
+ |--------|-------------|
52
+ | **`setup(config?)`** | Configure and register all 15 adapters in one call. Reads from env vars when `config` is omitted. |
53
+ | **`install()`** | Register adapters only — use when configuration was already applied via `setConfig` or env vars. |
54
+ | **`setConfig(config)`** | Override individual connection parameters at runtime. |
55
+ | **`getConfig()`** | Returns the current merged configuration (env vars + any `setConfig` overrides). |
56
+ | **`setLogger(logger)`** | Replace the internal logger with your own implementation. |
57
+ | **`getMongo()`** | Returns the connected Mongoose instance (lazy singleton). |
58
+ | **`getRedis()`** | Returns the connected ioredis instance (lazy singleton). |
59
+
60
+ ## ⚙ïļ Environment Variables
61
+
62
+ | Variable | Default | Description |
63
+ |----------|---------|-------------|
64
+ | `CC_MONGO_CONNECTION_STRING` | `mongodb://localhost:27017/backtest-kit?wtimeoutMS=15000` | MongoDB connection string |
65
+ | `CC_REDIS_HOST` | `127.0.0.1` | Redis host |
66
+ | `CC_REDIS_PORT` | `6379` | Redis port |
67
+ | `CC_REDIS_USER` | _(empty)_ | Redis username |
68
+ | `CC_REDIS_PASSWORD` | _(empty)_ | Redis password |
69
+
70
+ Values passed to `setup()` or `setConfig()` always take precedence over environment variables.
71
+
72
+ ## 🗂ïļ Adapters
73
+
74
+ Each adapter covers one persistence slot in backtest-kit. The table shows what it stores and which fields form its unique index in MongoDB:
75
+
76
+ | Adapter | MongoDB collection | Unique index |
77
+ |---------|--------------------|--------------|
78
+ | **Candle** | `candle-items` | `symbol + interval + timestamp` |
79
+ | **Signal** | `signal-items` | `symbol + strategyName + exchangeName` |
80
+ | **Schedule** | `schedule-items` | `symbol + strategyName + exchangeName` |
81
+ | **Risk** | `risk-items` | `riskName + exchangeName` |
82
+ | **Partial** | `partial-items` | `symbol + strategyName + exchangeName + signalId` |
83
+ | **Breakeven** | `breakeven-items` | `symbol + strategyName + exchangeName + signalId` |
84
+ | **Storage** | `storage-items` | `backtest + signalId` |
85
+ | **Notification** | `notification-items` | `backtest + notificationId` |
86
+ | **Log** | `log-items` | `entryId` |
87
+ | **Measure** | `measure-items` | `bucket + entryKey` |
88
+ | **Interval** | `interval-items` | `bucket + entryKey` |
89
+ | **Memory** | `memory-items` | `signalId + bucketName + memoryId` |
90
+ | **Recent** | `recent-items` | `symbol + strategyName + exchangeName + frameName + backtest` |
91
+ | **State** | `state-items` | `signalId + bucketName` |
92
+ | **Session** | `session-items` | `strategyName + exchangeName + frameName` |
93
+
94
+ Candle records are **immutable** — the first write wins, subsequent writes to the same `(symbol, interval, timestamp)` are silently ignored via `$setOnInsert`. All other adapters use `$set`, so each write replaces the previous value.
95
+
96
+ Measure, Interval, and Memory support **soft delete** — calling `removeMeasureData` / `removeIntervalData` / `removeMemoryData` sets `removed: true` on the document instead of deleting it. Listing operations filter on `removed: false`.
97
+
98
+ ## âœĻ Features
99
+
100
+ - 🗄ïļ **MongoDB backend**: all 15 `IPersist*Instance` contracts from backtest-kit implemented with Mongoose
101
+ - ⚡ **O(1) reads via Redis**: every context-key lookup goes through ioredis — one `GET` + one `findById`, no B-tree scans
102
+ - 🔒 **Atomic writes**: `findOneAndUpdate` with `upsert: true` guarantees read-after-write correctness with no race conditions
103
+ - ðŸ›Ąïļ **Look-ahead bias protection**: adapters that affect signal logic store the simulation timestamp so backtest-kit can enforce temporal correctness
104
+ - ðŸŠĶ **Soft delete**: Measure, Interval, and Memory records are never physically removed — they carry a `removed` flag instead
105
+ - 🔌 **Zero strategy changes**: drop `setup()` into your entry point, everything else stays the same
106
+
107
+ ## ⚡ How O(1) Reads Work
108
+
109
+ Every domain has two layers: a **DbService** that talks to MongoDB and a **CacheService** that talks to Redis.
110
+
111
+ When the strategy reads state for a given context key (e.g. `symbol + strategyName + exchangeName` for a signal), the DbService first asks Redis for the MongoDB `_id`. If it exists, the document is fetched directly by `_id` — two O(1) operations total. On a cache miss it falls back to a regular indexed MongoDB query, then writes the `_id` to Redis so the next call is instant.
112
+
113
+ ```
114
+ read signal for (BTCUSDT, my_strategy, binance)
115
+ │
116
+ ├─ Redis GET → hit → Mongo findById(_id) ← O(1) + O(1)
117
+ │
118
+ └─ Redis GET → miss → Mongo findOne(filter) → Redis SET → return
119
+ ```
120
+
121
+ After every write the Redis entry is updated in the same call, so a write followed immediately by a read always hits the cache.
122
+
123
+ ## 🔒 Atomic Writes
124
+
125
+ `backtest-kit` requires that once `write*Data()` returns, the very next `read*Data()` must see the new value. Every write is a single `findOneAndUpdate` round-trip to MongoDB:
126
+
127
+ ```typescript
128
+ const document = await SignalModel.findOneAndUpdate(
129
+ { symbol, strategyName, exchangeName },
130
+ { $set: { payload } },
131
+ { upsert: true, new: true, setDefaultsOnInsert: true },
132
+ );
133
+ await signalCacheService.setSignalId(readTransform(document.toJSON()));
134
+ ```
135
+
136
+ The filter matches the unique compound index, so MongoDB rejects any concurrent duplicate insert at the storage-engine level. The returned document is immediately written to Redis, making the next read O(1) with the fresh data.
137
+
138
+ ## ðŸ›Ąïļ Look-Ahead Bias Protection
139
+
140
+ Adapters whose data influences trading decisions (Risk, Partial, Breakeven, Recent, State, Session, Memory, Interval) store `when: Number` — the simulation timestamp in milliseconds — alongside the payload. This lets backtest-kit verify that no read returns data that was written at a future simulation time.
141
+
142
+ Measure is exempt because it caches LLM and external API responses, where look-ahead bias is not meaningful.
143
+
144
+ ## ðŸĪ Contribute
145
+
146
+ Fork/PR on [GitHub](https://github.com/tripolskypetr/backtest-kit).
147
+
148
+ ## 📜 License
149
+
150
+ MIT ÂĐ [tripolskypetr](https://github.com/tripolskypetr)