把成交磁带聚合为分桶 OHLCV K 线
Aggregate a Trade Tape Into Per-Bucket OHLCV Bars
开始编码一条行情聚合管线接收按时间戳升序排好的成交磁带,需要在固定时间网格上输出 OHLCV K 线(open / high / low / close / volume),供画图与指标计算使用。每条成交是 [timestamp, price, size],其中 timestamp 是整数(秒级 epoch,单调非递减——允许多笔同 timestamp)。网格步长是 bar_W 秒:桶 k 覆盖半开区间 [k * bar_W, (k+1) * bar_W),所以恰好落在右边界 (k+1) * bar_W 上的成交属于桶 k+1,而不是桶 k。
请实现 solution(trades: list[list[float]], bar_W: int) -> list[list[float]]。对每个至少有一笔成交的桶,输出 [bar_start, open, high, low, close, volume],其中:
bar_start是该桶的左边界k * bar_W(整数)。open是桶内按磁带顺序的 第一笔 成交价。close是桶内按磁带顺序的 最后一笔 成交价。high与low分别是桶内所有成交价的严格 max 和 min。volume是 size 之和。
没有成交的桶整段 跳过——不会写零成交占位行。输出按 bar_start 升序排列。trades == [] 时返回 []。bar_W ≥ 1 由调用方保证;超出该前置条件的行为未定义。
例
trades = [
[0, 100.0, 5],
[2, 101.0, 3],
[5, 99.5, 4],
[5, 100.5, 2],
[9, 102.0, 1],
]
bar_W = 5solution(trades, bar_W) 返回:
[[0, 100.0, 101.0, 100.0, 101.0, 8],
[5, 99.5, 102.0, 99.5, 102.0, 7]]第一个桶 [0, 5) 含 t=0 与 t=2 的两笔成交:open 是 100.0(按磁带顺序的第一笔),close 是 101.0(最后一笔),high 是 101.0,low 是 100.0,volume 是 5+3=8。第二个桶 [5, 10) 含 t=5、t=5、t=9 三笔:两笔同 t=5 按磁带顺序裁决,所以 open 是 99.5(首笔进桶),close 是 102.0(末笔出桶);high 是 102.0,low 是 99.5,volume 是 4+2+1=7。
实践背景
tick-to-bar 聚合是几乎每一套回测器与实时管线的第一步:原始成交在时间上不规则到达,但画图、信号计算与绝大多数指标算式都假设规则的时间网格。半开区间约定 [k * bar_W, (k+1) * bar_W) 的作用,就是避免一笔正好落在 K 线边界上的成交被同时计入相邻两根 K 线。空桶整段跳过——而不是用零成交占位行去填满——可以让产出在低成交标的上保持稠密(一整个交易段大部分桶都为空时尤其重要);下游需要规则网格的消费者可以自行补 padding。
约束条件
- 0 ≤ len(trades) ≤ 2000;bar_W 为整数,1 ≤ bar_W ≤ 100000。算法仍应保持 O(N) 复杂度,从而在更大 N 下依旧能在时限内通过。
- 每条成交是 3 元素列表 `[timestamp, price, size]`,其中 `timestamp` 为非负整数(秒),`price` 为正浮点数,`size` 为正整数。磁带按 `timestamp` 单调非递减(允许多笔同 timestamp)。
- 桶 k 覆盖半开区间 `[k * bar_W, (k+1) * bar_W)`,k 是非负整数;timestamp 等于 `(k+1) * bar_W` 的成交属于桶 `k+1`。
- 对每个至少有一笔成交的桶,输出 `[bar_start, open, high, low, close, volume]`;其中 bar_start 等于 `k * bar_W`(整数),open/high/low/close 为浮点数,volume 为整数。
- open 取桶内按磁带顺序的 **第一笔** 成交价、close 取 **最后一笔**;high/low 是桶内所有成交价的严格 max/min;volume 是 size 之和。
- 没有成交的桶整段 **跳过**——不要写零成交占位行。输出按 `bar_start` 升序,长度恰好等于非空桶的数量。
- `trades == []` 时返回 `[]`。`bar_W ≥ 1` 由调用方保证;函数不需要做参数校验(不测试任何抛异常的契约)。
样例
Case 1 · statement-example: two non-empty bars, ties at t=5 resolve by tape order
输入: [[[0,100,5],[2,101,3],[5,99.5,4],[5,100.5,2],[9,102,1]],5]
期望: [[0,100,101,100,101,8],[5,99.5,102,99.5,102,7]]
题面例题:第一个桶 [0,5) 由 t=0、t=2 两笔组成,open=100.0、close=101.0、volume=8;第二个桶 [5,10) 由 t=5、t=5、t=9 三笔组成,按磁带顺序首笔 99.5 设 open、末笔 102.0 设 close,volume=4+2+1=7。
Case 2 · typical: empty bucket between two active ones is silently skipped
输入: [[[1,50,2],[3,51,1],[12,60,5]],5]
期望: [[0,50,51,50,51,3],[10,60,60,60,60,5]]
桶 [0,5) 与 桶 [10,15) 都有成交但中间的桶 [5,10) 为空——空桶不写占位行,输出长度恰为 2。
最近提交
还没有提交记录。
编码区
实现 solution(...)。本地运行当前支持 Python 可见样例;服务端提交会运行可见样例和隐藏测试。
默认展示公开样例。点击「运行样例」后会在这里显示实际输出;点击「提交评测」会进入隐藏测试。
Case 1 · statement-example: two non-empty bars, ties at t=5 resolve by tape order
输入: [[[0,100,5],[2,101,3],[5,99.5,4],[5,100.5,2],[9,102,1]],5]
期望: [[0,100,101,100,101,8],[5,99.5,102,99.5,102,7]]
题面例题:第一个桶 [0,5) 由 t=0、t=2 两笔组成,open=100.0、close=101.0、volume=8;第二个桶 [5,10) 由 t=5、t=5、t=9 三笔组成,按磁带顺序首笔 99.5 设 open、末笔 102.0 设 close,volume=4+2+1=7。
Case 2 · typical: empty bucket between two active ones is silently skipped
输入: [[[1,50,2],[3,51,1],[12,60,5]],5]
期望: [[0,50,51,50,51,3],[10,60,60,60,60,5]]
桶 [0,5) 与 桶 [10,15) 都有成交但中间的桶 [5,10) 为空——空桶不写占位行,输出长度恰为 2。