You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用R的websocket库对接实时金融数据API的WebSocket服务?

问题描述

我订阅了某API服务商的企业级服务,可通过WebSocket协议获取实时金融数据,但官方文档仅提供Python和NodeJS的使用指引。我希望用R语言的websocket库建立WebSocket连接以流式获取数据,以下是官方提供的Python示例代码:

import websocket
import simplejson as json
import time
import ssl

ws = websocket.WebSocket(sslopt={"cert_reqs": ssl.CERT_NONE})
ws.connect("wss://websockets.financialmodelingprep.com")

login = {
    'event':'login',
    'data': {
        'apiKey': "<key>",
    }
}

subscribe = {
    'event':'subscribe',
    'data': {
        'ticker': "aapl",
    }
}

unsubscribe = {
    'event':'unsubscribe',
    'data': {
        'ticker': "aapl",
    }
}

ws.send(json.dumps(login))
 
time.sleep(1)
 
ws.send(json.dumps(subscribe))
 
time.sleep(1)
 
ws.send(json.dumps(unsubscribe))

while True:
    print(ws.recv())

我尝试使用R的WebSocket$new()函数连接,但始终无法正确建立连接,推测是凭证添加方式有误。我的R代码如下:

WebSocket$new(
  url = 'wss://crypto.financialmodelingprep.com/',
  headers = list(
    login = "{
      'event' = 'login',
      'data' = {'apiKey' : <key>}
    }
  )
)

得到的反馈信息如下:

<WebSocket>
  Public:
    clearAccessLogChannels: function (channels = c("all")) 
    clearErrorLogChannels: function (channels = c("all")) 
    clone: function (deep = FALSE) 
    close: function (code = 1000L, reason = "") 
    connect: function () 
    initialize: function (url, protocols = character(0), headers = NULL, autoConnect = TRUE, 
    onClose: function (callback) 
    onError: function (callback) 
    onMessage: function (callback) 
    onOpen: function (callback) 
    protocol: function () 
    readyState: function () 
    send: function (msg) 
    setAccessLogChannels: function (channels = c("all")) 
    setErrorLogChannels: function (channels = c("all")) 
  Private:
    accessLogChannels: function (channels, stompValue) 
    accessLogChannelValues: none connect disconnect control frame_header frame_paylo ...
    callbacks: environment
    errorLogChannels: function (channels, stompValue) 
    errorLogChannelValues: none devel library info warn rerror fatal all
    getInvoker: function (eventName) 
    pendingConnect: FALSE
    wsObj: externalptr

我参考了相关教程但仍无法解决问题,请问如何在R中成功建立该连接?

解决方案

你的核心错误是把登录消息放在了请求头里,但根据Python示例,登录、订阅这类指令是要在WebSocket连接建立后,通过send()方法发送JSON格式的消息,而非作为请求头传递。另外,Python示例中关闭了SSL证书验证,R中也需要对应设置。

以下是正确的R实现步骤:

  1. 加载必要库并创建WebSocket连接
    先确保安装了websocket和jsonlite包,然后初始化连接并关闭SSL证书验证:

    library(websocket)
    library(jsonlite)
    
    # 初始化WebSocket连接,禁用SSL证书验证
    ws <- WebSocket$new(
      url = "wss://websockets.financialmodelingprep.com",
      ssl_options = list(cert_reqs = 0)  # 对应Python的ssl.CERT_NONE
    )
    
  2. 设置连接回调函数
    WebSocket是异步协议,需通过回调函数处理连接、消息、错误等事件:

    # 连接成功时触发:发送登录和订阅消息
    ws$onOpen(function(event) {
      # 构造登录消息并发送
      login_msg <- toJSON(list(
        event = "login",
        data = list(apiKey = "<your_api_key>")
      ), auto_unbox = TRUE)
      ws$send(login_msg)
      
      # 延迟1秒后发送订阅消息(和Python示例逻辑对齐)
      Sys.sleep(1)
      subscribe_msg <- toJSON(list(
        event = "subscribe",
        data = list(ticker = "aapl")
      ), auto_unbox = TRUE)
      ws$send(subscribe_msg)
    })
    
    # 收到实时数据时触发:打印数据内容
    ws$onMessage(function(event) {
      cat("收到数据:", event$data, "\n")
    })
    
    # 发生错误时触发:打印错误信息
    ws$onError(function(event) {
      cat("错误:", event$message, "\n")
    })
    
    # 连接关闭时触发:提示关闭状态
    ws$onClose(function(event) {
      cat("连接已关闭,状态码:", event$code, "原因:", event$reason, "\n")
    })
    
  3. 保持连接活跃
    R是单线程环境,需通过循环维持会话,避免脚本直接退出:

    # 保持连接运行,直到连接关闭
    while(ws$readyState() == 1) {
      Sys.sleep(1)
    }
    
  4. 取消订阅(可选操作)
    如果需要取消订阅,可在合适时机发送取消指令:

    # 示例:延迟5秒后取消订阅
    Sys.sleep(5)
    unsubscribe_msg <- toJSON(list(
      event = "unsubscribe",
      data = list(ticker = "aapl")
    ), auto_unbox = TRUE)
    ws$send(unsubscribe_msg)
    

关键注意点

  • SSL设置:ssl_options = list(cert_reqs = 0)是对应Python的ssl.CERT_NONE,解决SSL证书验证失败问题。
  • JSON格式:必须用jsonlite::toJSON()将R列表转为标准JSON字符串,auto_unbox = TRUE确保单个值不会被转为数组,符合API要求。
  • 异步逻辑:R的WebSocket实现是异步的,所有消息交互都要通过回调函数完成,和Python的同步写法逻辑不同。

内容的提问来源于stack exchange,提问作者Keith Cozart

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 22:45:33