backtest-kit 2.3.2 → 2.3.3
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 +28 -9
- package/build/index.cjs +622 -67
- package/build/index.mjs +622 -68
- package/package.json +1 -2
- package/types.d.ts +349 -5
package/README.md
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
[](https://deepwiki.com/tripolskypetr/backtest-kit)
|
|
10
10
|
[](https://npmjs.org/package/backtest-kit)
|
|
11
11
|
[]()
|
|
12
|
+
[](https://github.com/tripolskypetr/backtest-kit/actions/workflows/webpack.yml)
|
|
12
13
|
|
|
13
14
|
Build reliable trading systems: backtest on historical data, deploy live bots with recovery, and optimize strategies using LLMs like Ollama.
|
|
14
15
|
|
|
@@ -226,25 +227,41 @@ temporal time context to your strategies.
|
|
|
226
227
|
- Adapter must return exactly `limit` candles
|
|
227
228
|
- Sequential timestamps: `since + i * stepMs` for i = 0..limit-1
|
|
228
229
|
|
|
230
|
+
**How `since` is calculated from `when`:**
|
|
231
|
+
- `when` = current execution context time (from AsyncLocalStorage)
|
|
232
|
+
- `alignedWhen` = `Math.floor(when / stepMs) * stepMs` (aligned down to interval boundary)
|
|
233
|
+
- `since` = `alignedWhen - limit * stepMs` (go back `limit` candles from aligned when)
|
|
234
|
+
|
|
235
|
+
**Boundary semantics (inclusive/exclusive):**
|
|
236
|
+
- `since` is always **inclusive** — first candle has `timestamp === since`
|
|
237
|
+
- Exactly `limit` candles are returned
|
|
238
|
+
- Last candle has `timestamp === since + (limit - 1) * stepMs` — **inclusive**
|
|
239
|
+
- For `getCandles`: `alignedWhen` is **exclusive** — candle at that timestamp is NOT included (it's a pending/incomplete candle)
|
|
240
|
+
- For `getRawCandles`: `eDate` is **exclusive** — candle at that timestamp is NOT included (it's a pending/incomplete candle)
|
|
241
|
+
- For `getNextCandles`: `alignedWhen` is **inclusive** — first candle starts at `alignedWhen` (it's the current candle for backtest, already closed in historical data)
|
|
242
|
+
|
|
229
243
|
- `getCandles(symbol, interval, limit)` - Returns exactly `limit` candles
|
|
230
244
|
- Aligns `when` down to interval boundary
|
|
231
245
|
- Calculates `since = alignedWhen - limit * stepMs`
|
|
232
|
-
-
|
|
233
|
-
-
|
|
246
|
+
- **since — inclusive**, first candle.timestamp === since
|
|
247
|
+
- **alignedWhen — exclusive**, candle at alignedWhen is NOT returned
|
|
248
|
+
- Range: `[since, alignedWhen)` — half-open interval
|
|
249
|
+
- Example: `getCandles("BTCUSDT", "1m", 100)` returns 100 candles ending before aligned when
|
|
234
250
|
|
|
235
251
|
- `getNextCandles(symbol, interval, limit)` - Returns exactly `limit` candles (backtest only)
|
|
236
252
|
- Aligns `when` down to interval boundary
|
|
237
253
|
- `since = alignedWhen` (starts from aligned when, going forward)
|
|
238
|
-
-
|
|
254
|
+
- **since — inclusive**, first candle.timestamp === since
|
|
255
|
+
- Range: `[alignedWhen, alignedWhen + limit * stepMs)` — half-open interval
|
|
239
256
|
- Throws error in live mode to prevent look-ahead bias
|
|
240
|
-
- Example: `getNextCandles("BTCUSDT", "1m", 10)` returns next 10 candles
|
|
257
|
+
- Example: `getNextCandles("BTCUSDT", "1m", 10)` returns next 10 candles starting from aligned when
|
|
241
258
|
|
|
242
259
|
- `getRawCandles(symbol, interval, limit?, sDate?, eDate?)` - Flexible parameter combinations:
|
|
243
|
-
- `(limit)` - since = alignedWhen - limit * stepMs
|
|
244
|
-
- `(limit, sDate)` - since = align(sDate), returns `limit` candles forward
|
|
245
|
-
- `(limit, undefined, eDate)` - since = align(eDate) - limit * stepMs
|
|
246
|
-
- `(undefined, sDate, eDate)` - since = align(sDate), limit calculated from range
|
|
247
|
-
- `(limit, sDate, eDate)` - since = align(sDate), returns `limit` candles
|
|
260
|
+
- `(limit)` - since = alignedWhen - limit * stepMs, range `[since, alignedWhen)`
|
|
261
|
+
- `(limit, sDate)` - since = align(sDate), returns `limit` candles forward, range `[since, since + limit * stepMs)`
|
|
262
|
+
- `(limit, undefined, eDate)` - since = align(eDate) - limit * stepMs, **eDate — exclusive**, range `[since, eDate)`
|
|
263
|
+
- `(undefined, sDate, eDate)` - since = align(sDate), limit calculated from range, **sDate — inclusive, eDate — exclusive**, range `[sDate, eDate)`
|
|
264
|
+
- `(limit, sDate, eDate)` - since = align(sDate), returns `limit` candles, **sDate — inclusive**
|
|
248
265
|
- All combinations respect look-ahead bias protection (eDate/endTime <= when)
|
|
249
266
|
|
|
250
267
|
**Persistent Cache:**
|
|
@@ -293,6 +310,8 @@ since = alignedWhen - 4 * stepMs
|
|
|
293
310
|
// [3] timestamp = 1704066300000 (23:45)
|
|
294
311
|
```
|
|
295
312
|
|
|
313
|
+
**Pending candle exclusion:** The candle at `00:00:00` (alignedWhen) is NOT included in the result. At `when=00:12:00`, this candle covers the period `[00:00, 00:15)` and is still open (pending). Pending candles have incomplete OHLCV data that would distort technical indicators. Only fully closed candles are returned.
|
|
314
|
+
|
|
296
315
|
**Validation is applied consistently across:**
|
|
297
316
|
- ✅ `getCandles()` - validates first timestamp and count
|
|
298
317
|
- ✅ `getNextCandles()` - validates first timestamp and count
|