问:我用Python接WebSocket获取美股实时tick数据,但消息体里没有一个字段告诉我这是盘前、盘中还是盘后。如果不区分阶段,策略会受到很大干扰。有什么稳健的判断方式吗?
答:我来分享一下我的实战经验。当初做交易机器人时也卡在这个地方,后来总结了两套方案,可以覆盖绝大多数场景。
方案一:基于时间戳自行换算
美股行情api通常都会返回每条tick的时间戳。你只需要把时间戳转成美东时间,然后对照下表判断。
| 阶段 | 美东时间 | 数据特征 |
|---|---|---|
| 盘前 | 04:00-09:30 | 成交稀疏,跳动偏随机 |
| 盘中 | 09:30-16:00 | 成交密集,价格连续 |
| 盘后 | 16:00-20:00 | 波动受消息影响明显 |
具体实现可以参考这段代码:
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 hours
if t.hour < 9 or (t.hour == 9 and t.minute < 30):
return "pre"
# Regular market
if t.hour < 16:
return "regular"
# After-hours session
return "after"记得处理好夏令时,用pytz的US/Eastern就可以自动适应。
方案二:读取交易状态字段
如果你用的数据源比较完善,有些会在WebSocket消息里直接给出sessionType之类的字段。这样的话,就不需要自己转换时区。但我建议还是用几天的数据做一下边界验证,因为不同提供商对9:30:00这个节点的归属定义可能略有不同。
落地建议
我目前在用的实时流处理中,以AllTick的WebSocket数据作为输入,就是采用第一种方案。在on_message回调里对每条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 market stream
ws = websocket.WebSocketApp("wss://ws.alltick.co/stock", on_message=on_message)
ws.run_forever()把时段标签作为基础字段沉淀下来,后续无论是做实时风控还是生成K线,都可以直接按标签过滤,避免盘前噪声和盘后情绪单误导策略。从维护成本上看,集中一处处理也比在每个策略里散落时区判断要高效得多。希望对你有所帮助。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用。你还可以使用@来通知其他用户。