C# 如何过滤股票数据中Extended Trading Hours时段的盘后交易数据
美股常规交易时段数据高效筛选方案
实现思路
不需要遍历每条Aggregate做时区转换,仅需提前生成目标日期范围内所有常规交易日的交易时段Unix时间戳区间,后续筛选仅做数值比较,性能相比单条转换提升2个数量级以上。
具体实现
1. 前置处理:生成交易时段区间
// 定义PST时区,Windows环境用"Pacific Standard Time",Linux/macOS环境用"America/Los_Angeles" TimeZoneInfo pstZone = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time"); // 生成所有交易日的常规时段Unix时间戳区间(仅需执行一次,次数等于交易日总数) List<(long StartMsec, long EndMsec)> tradingSessionRanges = new(); for (DateTime date = aggrParams.FromDate.Date; date <= aggrParams.ToDate.Date; date = date.AddDays(1)) { // 跳过周末(美股周六周日休市) if (date.DayOfWeek is DayOfWeek.Saturday or DayOfWeek.Sunday) continue; // 构造当日PST时区交易起止时间 DateTime pstStart = new DateTime(date.Year, date.Month, date.Day, 9, 30, 0); DateTime pstEnd = new DateTime(date.Year, date.Month, date.Day, 16, 0, 0); // 转UTC后生成Unix毫秒时间戳,自动处理PST/PDT夏令时切换 long startMsec = new DateTimeOffset(TimeZoneInfo.ConvertTimeToUtc(pstStart, pstZone)).ToUnixTimeMilliseconds(); long endMsec = new DateTimeOffset(TimeZoneInfo.ConvertTimeToUtc(pstEnd, pstZone)).ToUnixTimeMilliseconds(); tradingSessionRanges.Add((startMsec, endMsec)); }
注意:如果你的
FromDate/ToDate是PST时区的日期,需要将你已有的时间戳转换代码修改为以下写法,保证时间基准一致:long unixTimeMsecFromDate = new DateTimeOffset(TimeZoneInfo.ConvertTimeToUtc(aggrParams.FromDate, pstZone)).ToUnixTimeMilliseconds(); long unixTimeMsecToDate = new DateTimeOffset(TimeZoneInfo.ConvertTimeToUtc(aggrParams.ToDate, pstZone)).ToUnixTimeMilliseconds();
2. LINQ筛选常规交易时段数据
普通版本(适配任意顺序的Aggregate列表)
List<Aggregate> regularTradingData = allAggregates .Where(aggr => { long ts = (long)aggr.UnixTimestamp; // 先过滤整体时间范围,快速排除无效数据 if (ts < unixTimeMsecFromDate || ts > unixTimeMsecToDate) return false; // 判断是否落在任意常规交易时段内 return tradingSessionRanges.Any(r => ts >= r.StartMsec && ts < r.EndMsec); }).ToList();
优化版本(适配已按时间戳升序排序的Aggregate列表)
如果你的原始数据已经按时间戳升序排列,可通过二分查找进一步降低判断开销:
long[] sessionStartTimes = tradingSessionRanges.Select(r => r.StartMsec).ToArray(); List<Aggregate> regularTradingData = new(); foreach (var aggr in allAggregates) { long ts = (long)aggr.UnixTimestamp; if (ts < unixTimeMsecFromDate || ts > unixTimeMsecToDate) continue; // 二分查找匹配最近的交易时段 int index = Array.BinarySearch(sessionStartTimes, ts); index = index < 0 ? ~index - 1 : index; if (index >= 0 && ts < tradingSessionRanges[index].EndMsec) regularTradingData.Add(aggr); }
补充说明
Aggregate中定义的UnixTimestamp为decimal类型,由于Unix毫秒时间戳为整数,转换为long不会出现精度损失- 若需要排除美股法定节假日,可在生成交易时段区间的逻辑中增加节假日判断,跳过休市日期即可
- 整个方案仅在生成区间时做时区转换,转换次数等于查询范围内的交易日数量,远低于逐行转换的次数,适合大数据量场景
内容的提问来源于stack exchange,提问作者Leon
相关产品推荐
相关产品推荐

