C# 实现德指 DAX 期货 WebSocket 实时行情监听

摘要

欧洲市场量化监控系统中,德国 DAX 指数期货是核心观测标的。本文基于 C# ClientWebSocket 实现完整的长连接监听客户端,包含心跳保活、断线自动重连、行情结构化解析,适合.NET 技术栈项目集成,数据源采用脉动行情数据 API。

关键词:C#;WebSocket;德指 DAX;欧洲期货;实时行情

一、业务背景

德指 DAX 期货跟踪德国 DAX30 指数,是欧洲股市的核心风向标。很多.NET 技术栈的量化系统对接长连接行情时,容易踩心跳缺失、断连无重连、同步阻塞等坑。 本文采用异步 WebSocket 实现,全程非阻塞,支持 7×24 小时稳定运行。

品种编码:ZY_DAX 德指期货

二、环境说明

基于.NET 6+ 原生 ClientWebSocket 实现,无需第三方依赖。

三、完整实现代码

vbnet 复制代码
using System;
using System.Net.WebSockets;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;

namespace DaxQuoteClient
{
    public class DaxWsClient
    {
        // WebSocket服务地址,仅代码内配置
        private const string WsUrl = "ws://39.107.99.235/ws";
        private const string Symbol = "ZY_DAX";
        private const int HeartbeatInterval = 10000; // 10秒心跳
        private const int ReconnectDelay = 3000; // 重连延迟3秒
        
        private ClientWebSocket _ws;
        private CancellationTokenSource _cts;
        private Timer _heartbeatTimer;

        public async Task StartAsync()
        {
            _cts = new CancellationTokenSource();
            await ConnectAsync();
        }

        private async Task ConnectAsync()
        {
            try
            {
                _ws = new ClientWebSocket();
                await _ws.ConnectAsync(new Uri(WsUrl), _cts.Token);
                Console.WriteLine("WebSocket连接成功,订阅德指DAX行情");
                
                // 发送订阅报文
                var subMsg = $"{{\"Key\":\"{Symbol}\"}}";
                await SendAsync(subMsg);
                
                // 启动心跳定时器
                _heartbeatTimer = new Timer(HeartbeatCallback, null, HeartbeatInterval, HeartbeatInterval);
                
                // 启动接收循环
                _ = ReceiveLoopAsync();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"连接失败:{ex.Message},{ReconnectDelay}ms后重连");
                await Task.Delay(ReconnectDelay);
                await ConnectAsync();
            }
        }

        private async void HeartbeatCallback(object state)
        {
            try
            {
                var ping = $"{{\"ping\":{DateTimeOffset.Now.ToUnixTimeSeconds()}}}";
                await SendAsync(ping);
            }
            catch
            {
                // 心跳失败触发重连
                _ = ReconnectAsync();
            }
        }

        private async Task ReceiveLoopAsync()
        {
            var buffer = new byte[4096];
            while (_ws.State == WebSocketState.Open && !_cts.IsCancellationRequested)
            {
                try
                {
                    var result = await _ws.ReceiveAsync(new ArraySegment<byte>(buffer), _cts.Token);
                    if (result.MessageType == WebSocketMessageType.Text)
                    {
                        var message = Encoding.UTF8.GetString(buffer, 0, result.Count);
                        HandleMessage(message);
                    }
                    else if (result.MessageType == WebSocketMessageType.Close)
                    {
                        await _ws.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, _cts.Token);
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"接收异常:{ex.Message}");
                    break;
                }
            }
            // 退出循环触发重连
            _ = ReconnectAsync();
        }

        private void HandleMessage(string message)
        {
            try
            {
                using var doc = JsonDocument.Parse(message);
                if (!doc.RootElement.TryGetProperty("body", out var body))
                    return;
                
                var stockCode = body.GetProperty("StockCode").GetString();
                var price = body.GetProperty("Price").GetString();
                var high = body.GetProperty("High").GetString();
                var low = body.GetProperty("Low").GetString();
                var time = body.GetProperty("Time").GetString();
                
                Console.WriteLine($"[{time}] {stockCode} 最新价:{price} 最高:{high} 最低:{low}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"解析异常:{ex.Message}");
            }
        }

        private async Task SendAsync(string message)
        {
            var bytes = Encoding.UTF8.GetBytes(message);
            await _ws.SendAsync(new ArraySegment<byte>(bytes), WebSocketMessageType.Text, true, _cts.Token);
        }

        private async Task ReconnectAsync()
        {
            _heartbeatTimer?.Dispose();
            _ws?.Dispose();
            Console.WriteLine($"连接断开,{ReconnectDelay}ms后自动重连");
            await Task.Delay(ReconnectDelay);
            await ConnectAsync();
        }

        public void Stop()
        {
            _cts.Cancel();
            _heartbeatTimer?.Dispose();
            _ws?.Dispose();
        }
    }

    class Program
    {
        static async Task Main(string[] args)
        {
            var client = new DaxWsClient();
            await client.StartAsync();
            
            Console.WriteLine("按任意键退出");
            Console.ReadKey();
            client.Stop();
        }
    }
}

四、核心返回字段

字段 说明
StockCode 品种编码
Price 最新价格
Open 开盘价
LastClose 昨结算价
High 日内最高价
Low 日内最低价
Diff 涨跌额
DiffRate 涨跌幅
Time 行情更新时间

五、开发注意事项

  1. 采用异步接收循环,避免同步阻塞导致的界面卡死或线程浪费;
  2. 10 秒定时心跳,防止服务端主动断开空闲连接;
  3. 所有异常都会触发重连逻辑,保证 7×24 小时稳定运行;
  4. 德指交易时间对应欧洲时区,国内夜间波动较大,业务告警注意时区;
  5. 生产环境建议替换 Console 输出为日志框架,比如 Serilog。

六、总结

本文基于.NET 原生 WebSocket 实现德指 DAX 期货实时行情监听,包含完整的心跳、重连、解析逻辑,无需第三方依赖,可直接集成到.NET 量化系统、行情大屏中。修改品种编码即可快速适配其他欧洲期货品种。

相关推荐
CoderYanger18 分钟前
Java EE 进阶:4.Spring Web MVC 入门(第一弹)
java·开发语言·前端·spring·面试·java-ee·mvc
估值探索者32 分钟前
【Python量化选股流水线 #04】选股器好不好用?「昨日候选→今日表现」回看验收
开发语言·python·股票数据·股票数据api接口
万年咸鱼1 小时前
WebSocket、Socket 与 HTTP 的区别详解
websocket·网络协议·http
爱喝热水的呀哈喽2 小时前
HEJIAN RESEARCH
开发语言·matlab
白露与泡影2 小时前
后端 Java 面试核心八股汇总|高频面试题 + 解析,覆盖基础到进阶
java·开发语言·面试
xifangge20252 小时前
基于 JavaScript 实现 CNC 数控切削参数与螺纹公差纯前端核算引擎
开发语言·前端·javascript
“AI国潮设计-小江”2 小时前
【AIGC实战】Python+SDXL批量生成「潮汕英歌舞冰淇淋蛋糕&红桃粿咖啡」IP,固定角色形象批量出甜品商业效果图
开发语言·人工智能·python·prompt·aigc
Da Da 泓2 小时前
[项目] --- 基于websocket的网页五子棋(可多用户)
网络·websocket·网络协议·多线程·项目
\光辉岁月/2 小时前
3.包装类
java·开发语言·包装类
波力海苔夹心脆6753 小时前
VisionMaster 两级位置修正实战:塑料外壳与金属件装配角度检测
经验分享·计算机视觉·c#·visionmaster·海康机器人·位置修正