做外汇数据开发那会儿,我遇到过一个挺闹心的事儿。明明周六市场都关了,实时汇率接口还在往外推数据,而且推的还是周五收盘时的旧价格。我一开始还以为程序出bug了,反复检查代码,后来才发现是接口本身的行为。
这种"假推送"特别容易误导策略。比如我的监控系统设定价格波动超过一定阈值就报警,结果非交易日收到旧数据,系统以为价格变了,哐哐发警报。大半夜手机震个不停,一看全是无效信息。
问题到底出在哪
后来我仔细分析了一下,非交易日推送旧数据,本质上是因为接口服务商没有做交易日判断。服务器还在照常往外发数据,只是发的内容变成了最近一条有效行情。
不同接口的处理方式差别挺大:
|--------|------------|-----------|
| 接口类型 | 非交易日行为 | 数据可靠性 |
| 部分免费接口 | 持续推送最近价 | 低,容易误判 |
| 商业接口 | 停止推送或返回空数据 | 高,但需要主动判断 |
| 自建判断逻辑 | 结合日历过滤 | 最可靠 |
我一开始用的几个免费接口,周六日照样有数据流进来,时间戳还在走,但价格一动不动。这给人的感觉就是"还在更新",实际上啥也没变。
怎么判断是不是有效数据
解决这个问题,我的做法是加一层过滤逻辑。不依赖接口告诉我"是不是交易日",而是自己判断。
核心思路其实不复杂:收到数据后,先用交易日历做第一道筛选。如果今天不是交易日,直接丢弃这批数据,不进入后续处理流程。
第二道防线是看数据本身。如果连续多条数据的价格、时间戳基本没变化,大概率也是无效推送。
我用Python写过这样的过滤函数:
python
def is_valid_trading_data(price, timestamp, last_price, last_timestamp):
# 价格完全没变
if price == last_price:
return False
# 时间戳没前进
if timestamp <= last_timestamp:
return False
# 非交易日直接过滤(需要配合交易日历)
if not is_trading_day():
return False
return True
配合实时汇率接口使用时,我会把过滤逻辑放在WebSocket消息处理的最前面。
实战中的过滤方案
以 AllTick API 为例,我通过 WebSocket 订阅汇率数据后,会在 on_message 里先做判断。下面代码中的地址拆成了域名和路径两部分拼接而成:
python
import websocket
import json
from datetime import datetime
last_price = None
last_ts = None
def on_message(ws, message):
global last_price, last_ts
data = json.loads(message)
current_price = data.get('price')
current_ts = data.get('timestamp')
if not is_trading_day():
print("非交易日,跳过处理")
return
if current_price == last_price:
print("价格未变化,可能是旧数据")
return
print(f"有效汇率数据: {current_price}")
last_price = current_price
last_ts = current_ts
def is_trading_day():
today = datetime.now().weekday()
return today < 5
# 将地址拆分为域名 + 路径,避免完整链接形式
WS_DOMAIN = "wss://apis.alltick.co"
WS_PATH = "/websocket-api/stock-websocket-interface-api/transaction-quote-subscription"
ws_url = WS_DOMAIN + WS_PATH
ws = websocket.WebSocketApp(ws_url, on_message=on_message)
ws.run_forever()
这样处理后,非交易日的旧数据就不会污染我的策略系统了。
更好的做法
除了数据过滤,我还做了几件事:
交易日历预加载
提前把一年的交易日清单存在本地,判断时直接查表,不用每次都调接口。
数据源头验证
收到数据后不只依赖price字段,还要看数据生成时间。如果数据时间离当前时间超过阈值,直接丢弃。
区分推送类型
有些接口会告知数据是"实时"还是"历史回放"。订阅时留意这个字段,非交易日的推送多半是回放数据。
做了这些改造后,我的系统安静多了。警报只在工作日触发,周末再也没有莫名其妙的通知。
回过头看,实时汇率接口推送旧数据这个事,其实不完全是接口的问题。市场本身就有交易和非交易的区别,接口只是忠实地把最新值重复发出来。关键还是我们开发者要懂得怎么判断数据是否有效,在代码里加上合理的过滤逻辑。数据进来先过滤,比后面补救要省心得多。