@ backtest- kit/ minio (英语)
MNIO(S3) + Redis 持久性 反测试- kit交换默认文件存储 S3 对象作为真理的来源 与 重做为时间顺序索引 - 耐用、可复制、无图谋 一个
setup()呼叫和零战略代码更改。 。 。 .

📚 文档 • 妇女 参考执行情况 • 妇女 GitHub 图像
npm install @backtest-kit/minio backtest-kit minio ioredis
import { setup } from '@backtest-kit/minio';
setup(); // reads connection settings from env; call once before any trading operation
那个单调重播 15个 反测试孩子的 IPersist*Instance 与MinIO(真相来源)订立合同,对最新第一批列名采用雷迪斯定时索引。 你的策略代码不变.
为什么
内置的文件适配器和完整的数据库之间 是一个异国情调但刻意的中间点 S3为单个对象提供了强烈的读后写一致性,而每个记录的后试键-kit键是其上下文的一个纯函数——所以写作耐久性合同中包含有平庸的对象语义,没有交易,根本没有计划:
默认文件 ./dump/ | MinIO + Redis( 此软件包) | @backtest-kit/mongo 编号 : @backtest-kit/pg | |
|---|---|---|---|
| 基础设施 | 无 | 2个集装箱 | 数据库 + Redis 缓存 |
| 真相来源 | 本地磁盘上的 JSON 文件 | S3桶中的 JSON 对象 | 行/文档 |
| 重复操作( O) | 单机主机, 手动备份 | S3语义:版本,复制, mc mirror寿命周期 | DB 工具:垃圾堆、复制品 |
| 最新名单 | 目录扫描 | Redis 分钟索引, O( 限制) | ORDER BY … LIMIT, O(log n) 键 |
| 点为 (candles) | fs.readFile | 1到3分钟 | b -- -- 树木调查 0.1 - 1毫秒 |
| 甜点 | 本地运行, CI | 肥胖的JSON快照,廉价的无约束档案,S3-内地以下 | 数以亿计的蜡烛,特别的SQL/汇总 |
当您想要S3级耐用性和零计划管理时选择这个变体,但是一个完整的DBMS会超能力. 如果你的蜡烛 成长成亿万,拿 pg编号 :mongo 相反,b-trees赢得了这一工作量.
- 🪣 MinIO 后端 所有15个
IPersist*Instance作为JSON对象在单一S3桶中执行的合同. - 🔑 决定对象键 ——每一个键都是其上下文的纯函数,所以上调就是一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一
PUT:不读出前写出,不重复键相竞. - ⚡ 通过 Redis 更新的首个上市 ——每分钟Redis指数解答O(限制)中"最后创建的",独立于桶大小.
- 🛡️ 头部保护 ——影响决策的适配器存储模拟
when。 。 。 . - 🔌 零战略变化 - 降级
setup()进入您的入口; 其他一切保持不变.
配置
明确参数和环境变量
import { setup } from '@backtest-kit/minio';
setup({
CC_MINIO_ENDPOINT: 'minio', CC_MINIO_PORT: 9000,
CC_MINIO_ACCESSKEY: 'minioadmin', CC_MINIO_SECRETKEY: 'secret',
CC_REDIS_HOST: 'redis', CC_REDIS_PORT: 6379, CC_REDIS_PASSWORD: 'secret',
});
| 变量 | 默认 | 说明 |
|---|---|---|
CC_MINIO_ENDPOINT | localhost | MinIO / S3 端点主机 |
CC_MINIO_PORT | 9000 | MinIO / S3 端口 |
CC_MINIO_ACCESSKEY | minioadmin | MinIO 访问密钥 |
CC_MINIO_SECRETKEY | minioadmin | MiniO 密钥 |
CC_REDIS_HOST | 127.0.0.1 | Redis 主机 |
CC_REDIS_PORT | 6379 | Redis 端口 |
CC_REDIS_USER | (空虚) | Redis 用户名 |
CC_REDIS_PASSWORD | (空虚) | 重写密码 |
转至的值 setup() 编号 : setConfig() 永远优于地狱之地 在CLI内部,放 setup() 内 config/setup.config.ts ——当存在时, CLI 跳过其默认的文件适应器注册和您的配置本身的持久性.
API 参考
| 导出 | 说明 |
|---|---|
setup(config?) | 配置 财务报告和审定财务报表 在一个呼叫中登记所有15个适配器。 何时读取 config 省略. |
install() | 仅登记适配器——当配置已经通过 setConfig/env. (原始内容存档于2018-09-26). |
setConfig(config) | 运行时覆盖单个连接参数. |
getConfig() | 当前合并配置( env + 任何) setConfig (原始内容存档于2017-03-25). overse. |
setLogger(logger) | 用您自己的执行替换内部记录器 . |
getMinio() | 连接的MINO Client (懒惰的单子). |
getRedis() | 相接的ioredis实例(lazy singleton). |
waitForInit() | 门先接接接基础设施准备状态(Redis ping;MinIO客户端每桶可连接懒散. |
BaseStorage | S3对象存储原始的每个数据服务扩展——为您自己的桶再用. |
BaseMap | 时间排序索引背后的Redis按键映射原始. |
15个适配器
每个适配器在后试-吻上覆盖一个持久性槽. 万事俱备 一个MinIO桶 backtest-kit ——每个实体得到一个根文件夹,对象密钥是实体被处理的复合上下文密钥.
| 适配器 | 文件夹 | 对象密钥 |
|---|---|---|
| 蜡烛 | candle-items/ | exchange/symbol/interval/timestamp |
| 信号 | signal-items/ | symbol/strategy/exchange |
| 时间表 | schedule-items/ | symbol/strategy/exchange |
| 风险 | risk-items/ | riskName/exchange |
| 部分 | partial-items/ | symbol/strategy/exchange/signalId |
| 断面 | breakeven-items/ | symbol/strategy/exchange/signalId |
| 存储 | storage-items/ | backtest/signalId 页:1 |
| 通知 | notification-items/ | backtest/⟲ts_notificationId 页:1 |
| 日志 | log-items/ | ⟲ts_entryId 页:1 |
| 措施 | measure-items/ | bucket/entryKey |
| 间隔 | interval-items/ | bucket/entryKey |
| 内存 | memory-items/ | signalId/bucket/memoryId |
| 近期 | recent-items/ | symbol/strategy/exchange/frame/backtest |
| 状态 | state-items/ | signalId/bucket |
| 预算 | budget-items/ | strategy/exchange/frame/backtest/name |
| 会议 | session-items/ | strategy/exchange/frame/symbol/backtest |
⟲ts =倒转时间戳(MAX_SAFE_INTEGER − ms,零加法):简单词典 S3 列出产量 最新的第一个 没有排序。 * = 也保留在Redis时间指数中的实体(见下文).
写语义——不可变,可变,可被物理删除
- 蜡烛是永恒的 ——先写取胜;插入为 a
stat+ 键PUT成对,所以重复写一个相同的(exchange, symbol, interval, timestamp)成本为1个头部,从不下载或重写正文(历史上的OHLCV从未改变). - 日志/ 通知条目是不可改变的事件 ——库在每个写上重新发送整个累积列表,所以一个在编过程的FIFO封装的持久键索引跳过
PUT完全当密钥已经存在时:在稳定状态下重新发送零成本网络. - 所有其他对象重写对象 – – – 写作 – 写作 – 写作 – 写作 – 写作 – 写作 – 写作 – 写作 – 写作 – 写作 – 写作 – 写作 – 写作 – 写作 – 写作 – 写作 – 写作 – 写作 – 写作 – 写作 – 写作
PUT在稳定的上下文键下. - 测量 / 间隔 / 内存 物理删除 —— 说
removed: true翻译为:DELETE而不是一块墓碑.listKeys然后是纯正的前缀列表, 零正文读取, 并读取已删除的条目返回null通过建筑.
如何运作
在没有数据库的情况下写入耐用性
反测试 - kit有一个 写长期合同: 之后 writeXData(...) 返回,下一个 readXData(...) 必须看到正写值。 S3为单个对象提供了很强的读后写一致性,因此合同中持有的是普通对象语义——不需要交易:
- 决定密钥. 每个记录的对象密钥都是其上下文的纯函数(
symbol/strategy/exchange/…),所以上升是一个单一的同能PUT——不读出前写出,不重复键相竞. - 不可移动的实体永远不会重写. 蜡烛使用a
stat+ 键PUT只插入对; 日志条目和通知跳过PUT当密钥已经存在时 . - 书写顺序:MineIO先出,Redis后出. 二者相撞会留下一个可以按键读取但无法被列出的物体——从来就不是一无所取的奇幻条目.
removed意味着缺席. 软删除实体(Measure, Interval, Memory) 物理删除对象而不是写出墓碑.
// src/lib/services/data/CandleDataService.ts — insert-only, one stat + one PUT
public create = async (dto: ICandleDto): Promise<ICandleRow> => {
const key = GET_STORAGE_KEY_FN(dto.exchangeName, dto.symbol, dto.interval, dto.timestamp);
const row: ICandleRow = { id: key, ...dto, /* dates */ };
if (await this.has(key)) return row; // candles are immutable — no body download
await this.set(key, row);
return row;
};
重做为时间顺序索引
S3可以只按词典顺序列出密钥,不能不走出"桶"就回答"所创造的最后". 对于需要最新列名的三个实体(记录、通知、储存),a *ConnectionService 维持 Redis 索引 :
- 每分钟1个Redis SET数字 :
<entity>-connection:<aligned-minute>• 物体名称.register()是一个单一管道(SADD+ 键SETNX楼下标记)。 时间戳是分钟相通的,因此在一分钟内通过构造来重新登记. listNewest(limit, prefix)从当前分钟后向后走 - 直接按键检查,不SCAN在键盘空间。 在1,000个管道中探测分钟;廉价SCARD通过跳过空分钟而不转移单个成员;热分钟(快速回放将许多记录打入一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一站一SSCAN提前退出时limit。 。 。 .- 冷指数回落. 如果Redis被冲出,列表会倒回"桶列表"(倒数-时间戳键已经是最新一档)并让索引回暖.
稳定状态成本 readLogData 启动时: 1 RTT 用于地板+ 1–2 管道 RTT + Q-200 点为身体获取—— 独立于桶所持有的物体数量.
// src/lib/services/data/LogDataService.ts — read path
const names = await this.logConnectionService.listNewest(LIST_LIMIT);
if (names.length) {
for (const name of names) rows.push(await this.get<ILogRow>(name));
} else {
for await (const value of this.values("", LIST_LIMIT)) { /* fallback + re-warm */ }
}
存储层的外观偏差保护
数据影响决策的适配器(风险、部分、断层、最近、状态、预算、会话、记忆、间隔)存储 when 模拟时间戳以毫秒表示——与有效载荷并列,因此,反测试-基特可以验证没有读取返回数据 未来 模拟时间. 措施豁免 因为它缓存了 LLM / 外部- API 响应, 其中的外观- ahead 偏差没有意义 .
内部架构( 完整源图)
图层文件( F)
公众表面 —— 说 functions/setup.ts (单位:千美元)setup编号 :install编号 :setLogger, (中文(简体) ), config/params.ts (单位:千美元)setConfig编号 :getConfig, (中文(简体) ), index.ts 再出口+ getMinio编号 :getRedis编号 :waitForInit编号 :BaseStorage编号 :BaseMap。 。 。 .
适配类 (单位:千美元)classes/Persist*Instance.ts)——各执行一回试-吻 IPersist*Instance 合同及其域名代表 数据服务: PersistCandleInstance, (中文(简体) ), PersistSignalInstance, (中文(简体) ), PersistScheduleInstance, (中文(简体) ), PersistRiskInstance, (中文(简体) ), PersistPartialInstance, (中文(简体) ), PersistBreakevenInstance, (中文(简体) ), PersistStorageInstance, (中文(简体) ), PersistNotificationInstance, (中文(简体) ), PersistLogInstance, (中文(简体) ), PersistMeasureInstance, (中文(简体) ), PersistIntervalInstance, (中文(简体) ), PersistMemoryInstance, (中文(简体) ), PersistRecentInstance, (中文(简体) ), PersistStateInstance, (中文(简体) ), PersistBudgetInstance, (中文(简体) ), PersistSessionInstance。 。 。 .
服务层 (单位:千美元)lib/services/:
base/—— 说MinioService(Lazy MinIO客户端,确保一触即发),RedisService(懒驴),LoggerService。 。 。 .data/一个*DataService每个域:顶部的对象键构建器和上行/查找/列表逻辑BaseStorage。 。 。 .connection/—— 说LogConnectionService, (中文(简体) ),NotificationConnectionService, (中文(简体) ),StorageConnectionService: 每分钟Redis时间指数(register编号 :listNewest) (中文(简体) ).
共享原始物 (单位:千美元)lib/common/(b) —— BaseStorage (S3对象存储模式每一次数据服务再利用: bucket/parent-folder 名称解析, JSON set编号 :get编号 :has编号 :delete,批号 clear,流线 keys编号 :values编号 :iterate和 BaseMap (Redis键映射模式每一次连接服务回用).
DI 配置 —— 说 lib/core/{di,provide,types}.ts (IoC集装箱接线数据/连接/基地服务), lib/index.ts (集装箱靴子), config/{minio,redis,params}.ts (连接建设者+合并参数), schema/*.schema.ts (存储行形状), interfaces/Logger.interface.ts。 。 。 .
* 贡献
叉/ PR 打开 GitHub 图像。 。 。 .
许可证
麻省理工学院 特立奥尔斯基平板电脑