记得我刚开始自学量化的时候,曾经激动地盯着一大早突然拉升的股票杀进去,结果九点半正式开盘后价格瞬间打回原形——后来才知道那只是盘前流动性不足引发的假突破。这个教训让我下定决心把“时段识别”写进数据接收的第一关。今天我就用一篇学习笔记的方式,带你复现这个技能。
为什么必须要分盘前、盘中、盘后?
美股交易时间其实有三个明显层次:盘前、正常交易时段和盘后。它们之间的波动逻辑、流动性和信息含量完全不同。下面这个表格可以帮你快速建立认知。
| 阶段 | 美东时间 | 数据特征 |
|---|---|---|
| 盘前 | 04:00-09:30 | 成交稀疏,跳动偏随机 |
| 盘中 | 09:30-16:00 | 成交密集,价格连续 |
| 盘后 | 16:00-20:00 | 波动受消息影响明显 |
WebSocket推流的tick数据虽然实时性很好,但绝大多数不会标记当前处于哪个阶段。这就需要我们自己在客户端进行判断。
解法一:从时间戳推算
大部分行情api都会给出每条tick的时间戳。我们可以用pytz把时间戳转成美东时间,然后判断小时和分钟落在哪个区间。
from datetime import datetime
import pytz
# US Eastern timezone
et = pytz.timezone('US/Eastern')
def get_session(ts):
t = datetime.fromtimestamp(ts, et)
# Check pre-market
if t.hour < 9 or (t.hour == 9 and t.minute < 30):
return "pre"
# Regular trading hours
if t.hour < 16:
return "regular"
# After-hours
return "after"
提醒一下,美东夏令时的起始日是个坑,如果你觉得时区处理太麻烦,也可以用支持历史夏令时转换的库来保证准确性。
解法二:利用交易状态字段
有些行情提供方会在WebSocket消息体中显式给出一个状态字段,比如sessionType。这种情况下就不需要自己计算时间,直接映射即可。不过从我的实际测试来看,各家对这个字段的维护标准和边界处理并不统一,最好用历史数据先做一轮验证。
动手接一个实时流试试
我在日常练习和原型开发中常会用到ALLTICK API的实时WebSocket接口,它的推送同时带上了时间戳和价格信息,很适合用来练习。下面这段代码就是在接收到tick后自动打上时段标签并打印出来。
import websocket
import json
from datetime import datetime
import pytz
# US Eastern timezone
et = pytz.timezone('US/Eastern')
def session(ts):
t = datetime.fromtimestamp(ts, et)
if t.hour < 9 or (t.hour == 9 and t.minute < 30):
return "pre"
elif t.hour < 16:
return "regular"
else:
return "after"
def on_message(ws, message):
data = json.loads(message)
s = session(data["timestamp"])
print(f"{data['symbol']} | {s} | {data['price']} | {data['volume']}")
# Connect to WebSocket stream
ws = websocket.WebSocketApp("wss://ws.alltick.co/stock", on_message=on_message)
ws.run_forever()
从学习效率的角度看,一开始就把时段判断封装成函数,比在回测和实盘中到处粘贴时间判断逻辑要高效得多。你也可以把这个功能做成一个独立的工具模块,后续无论是做盘口分析还是构建分钟K线,都能直接复用。
实盘的路上,很多坑都藏在细节里。把盘前、盘中、盘后当作“一级分类”来处理,你的策略就不会再被那些莫名其妙的假信号迷惑了。
共同学习,写下你的评论
评论加载中...
作者其他优质文章
