WebSocket 汇率数据:如何剔除过期行情

做外汇数据开发那会儿,我遇到过一个挺闹心的事儿。明明周六市场都关了,实时汇率接口还在往外推数据,而且推的还是周五收盘时的旧价格。我一开始还以为程序出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字段,还要看数据生成时间。如果数据时间离当前时间超过阈值,直接丢弃。

区分推送类型
有些接口会告知数据是"实时"还是"历史回放"。订阅时留意这个字段,非交易日的推送多半是回放数据。

做了这些改造后,我的系统安静多了。警报只在工作日触发,周末再也没有莫名其妙的通知。

回过头看,实时汇率接口推送旧数据这个事,其实不完全是接口的问题。市场本身就有交易和非交易的区别,接口只是忠实地把最新值重复发出来。关键还是我们开发者要懂得怎么判断数据是否有效,在代码里加上合理的过滤逻辑。数据进来先过滤,比后面补救要省心得多。

相关推荐
中微极客14 小时前
多智能体编排实战:CrewAI vs AutoGen(2026版)
大数据·网络·人工智能
小王C语言14 小时前
【3. 基于 Vibe Coding 的 OJ 平台】. 构建仓库、环境准备、需求梳理、安装依赖
网络·c++
新手unity自用笔记15 小时前
unity网络基础_1
网络·unity·游戏引擎
小王C语言15 小时前
【8.进行接口测试】:通过 curl 进行接口自动化测试 / 通过 python 程序进行接口自动化测试
网络·c++
一条大祥脚15 小时前
26杭电暑期第三场 DP|费用流|分解质因子|数论|贪心|图论|期望|无穷级数
网络·图论·网络流·无穷级数·费用流
早睡早起身体好12315 小时前
为什么 Network 中会出现两个同名请求?——CORS 预检请求学习笔记
网络·笔记·学习·网络安全
daad77716 小时前
记录matlab状态机demo
java·网络·matlab
paopaokaka_luck16 小时前
基于springboot3+vue3的智能文库平台(AI智能搜索、AI智能汇总、实时在线状态展示、多格式文档预览与富文本编辑、Echarts图形化分析)
前端·网络·spring boot·网络协议·echarts
Yang961117 小时前
告别“慢工出细活”:如何平衡光纤熔接的速度与精度?
网络
Nebula_g18 小时前
Java实现本地Socket通信(四)
网络