本文作者:咔咔

C语言如何高效获取股票实时数据?

咔咔 2025-12-04 1 抢沙发
C语言如何高效获取股票实时数据?摘要: 核心思路无论使用哪种方法,核心思路都是:选择一个数据源:免费的(如 Alpha Vantage, Yahoo Finance)、付费的(如 Bloomberg, Reuters)或...

核心思路

无论使用哪种方法,核心思路都是:

  1. 选择一个数据源:免费的(如 Alpha Vantage, Yahoo Finance)、付费的(如 Bloomberg, Reuters)或自建的行情服务器。
  2. 选择一个网络库:用于在 C 程序中发送 HTTP 请求或建立 WebSocket 连接。
  3. 解析返回的数据:数据通常是 JSON 或 CSV 格式,需要用相应的解析库来提取你需要的信息(如股票代码、价格、成交量等)。

使用 cURL + JSON-C (推荐,最通用)

这种方法非常适合从 REST API 获取数据,cURL 是一个强大的命令行工具和库,用于传输数据;JSON-C 是一个用于解析 JSON 数据的 C 语言库。

C语言如何高效获取股票实时数据?
(图片来源网络,侵删)

步骤 1: 安装必要的库

在 Linux (如 Ubuntu/Debian) 上:

sudo apt-get update
sudo apt-get install libcurl4-openssl-dev libjson-c-dev

在 macOS (使用 Homebrew) 上:

brew install curl json-c

步骤 2: 编写 C 代码

我们将使用 Alpha Vantage 的免费 API 作为数据源,你需要先在 Alpha Vantage 注册一个免费的 API Key。

get_stock_price.c

C语言如何高效获取股票实时数据?
(图片来源网络,侵删)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
#include <json-c/json.h>
// 用于存储从 cURL 接收到的数据的结构体
struct MemoryStruct {
  char *memory;
  size_t size;
};
// cURL 的回调函数,用于接收数据
static size_t
WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
  size_t realsize = size * nmemb;
  struct MemoryStruct *mem = (struct MemoryStruct *)userp;
  char *ptr = realloc(mem->memory, mem->size + realsize + 1);
  if(!ptr) {
    /* out of memory! */
    printf("not enough memory (realloc returned NULL)\n");
    return 0;
  }
  mem->memory = ptr;
  memcpy(&(mem->memory[mem->size]), contents, realsize);
  mem->size += realsize;
  mem->memory[mem->size] = 0;
  return realsize;
}
int main(void)
{
  CURL *curl;
  CURLcode res;
  // 替换成你自己的 Alpha Vantage API Key
  const char *api_key = "YOUR_API_KEY"; 
  const char *symbol = "IBM";
  char url[256];
  // 构建请求 URL
  snprintf(url, sizeof(url), "https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol=%s&apikey=%s", symbol, api_key);
  struct MemoryStruct chunk;
  chunk.memory = malloc(1);  // 会有 realloc 来扩展
  chunk.size = 0;
  curl_global_init(CURL_GLOBAL_ALL);
  curl = curl_easy_init();
  if(curl) {
    curl_easy_setopt(curl, CURLOPT_URL, url);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
    curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl-agent/1.0");
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L); // 设置超时为10秒
    // 执行请求
    res = curl_easy_perform(curl);
    // 检查错误
    if(res != CURLE_OK) {
      fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
    } else {
      // 解析 JSON 数据
      struct json_object *parsed_json;
      struct json_object *json_price;
      struct json_object *json_symbol;
      struct json_object *json_timestamp;
      parsed_json = json_tokener_parse(chunk.memory);
      if (parsed_json != NULL) {
        // 获取 "Global Quote" 对象
        struct json_object *global_quote;
        if (json_object_object_get_ex(parsed_json, "Global Quote", &global_quote)) {
          // 从 "Global Quote" 中提取字段
          if (json_object_object_get_ex(global_quote, "05. price", &json_price) &&
              json_object_object_get_ex(global_quote, "01. symbol", &json_symbol) &&
              json_object_object_get_ex(global_quote, "07. latest trading day", &json_timestamp)) {
            printf("股票代码: %s\n", json_object_get_string(json_symbol));
            printf("当前价格: %s\n", json_object_get_string(json_price));
            printf("最新交易日: %s\n", json_object_get_string(json_timestamp));
          } else {
            fprintf(stderr, "无法从 JSON 中找到所需字段,\n");
            // 检查是否是 API 错误
            struct json_object *json_error;
            if (json_object_object_get_ex(parsed_json, "Error Message", &json_error)) {
                fprintf(stderr, "API 错误: %s\n", json_object_get_string(json_error));
            }
          }
        } else {
          fprintf(stderr, "JSON 中未找到 'Global Quote' 对象,\n");
        }
        json_object_put(parsed_json); // 释放 JSON 对象
      } else {
        fprintf(stderr, "JSON 解析失败,\n");
      }
    }
    // 清理
    curl_easy_cleanup(curl);
  }
  free(chunk.memory);
  curl_global_cleanup();
  return 0;
}

步骤 3: 编译和运行

# 编译时需要链接 cURL 和 JSON-C 库
gcc get_stock_price.c -o get_stock_price -lcurl -ljson-c
# 运行程序 (记得替换 YOUR_API_KEY)
./get_stock_price

输出示例:

股票代码: IBM
当前价格: 152.55
最新交易日: 2025-10-27

使用 WebSocket 实现实时推送 (更高级)

对于真正的“实时”数据,轮询 API(如方法一)会有延迟,更好的方式是使用 WebSocket,服务器会在数据更新时主动推送给你,这比客户端不断请求要高效得多。

我们将使用 libwebsockets 库。

步骤 1: 安装 libwebsockets

在 Linux (Ubuntu/Debian) 上:

C语言如何高效获取股票实时数据?
(图片来源网络,侵删)
sudo apt-get install libwebsockets-dev

步骤 2: 编写 C 代码

注意: 免费的 WebSocket 数据源较少且不稳定,这里我们以一个示例性的场景进行演示,实际使用时需要找到可靠的股票 WebSocket 服务。

realtime_stock_ws.c

#include <libwebsockets.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 自定义协议结构体
struct session_data {
    int count;
};
// 回调函数,处理 WebSocket 事件
static callback_function(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) {
    struct session_data *data = (struct session_data *)user;
    char buf[256];
    int n;
    switch (reason) {
        case LWS_CALLBACK_ESTABLISHED:
            // 连接建立
            printf("连接到服务器成功!\n");
            data->count = 0;
            // 可以在这里发送订阅消息
            // n = sprintf(buf, "subscribe{\"symbol\":\"AAPL\"}");
            // lws_write(wsi, buf, n, LWS_WRITE_TEXT);
            break;
        case LWS_CALLBACK_RECEIVE:
            // 接收到数据
            printf("收到数据 (%zu bytes): %.*s\n", len, (int)len, (char *)in);
            // 这里可以添加 JSON 解析逻辑来处理实时数据
            // 使用 json-c 解析 in 指向的数据
            break;
        case LWS_CALLBACK_CLOSED:
            // 连接关闭
            printf("连接已关闭,\n");
            break;
        default:
            break;
    }
    return 0;
}
// 定义协议
static const struct lws_protocols protocols[] = {
    {
        "stock-protocol", // 协议名称
        callback_function, // 回调函数
        sizeof(struct session_data), // 每个会话的大小
    },
    { NULL, NULL, 0, 0 } // 结束标记
};
int main(void) {
    struct lws_context *context;
    struct lws_client *client;
    const char *address = "wss://api.example.com/stocks"; // 替换为真实的 WebSocket 地址
    int port = 443;
    const char *path = "/";
    const char *host = address;
    const char *origin = "http://localhost";
    // 创建 WebSocket 上下文
    context = lws_create_context(0, NULL, protocols, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL);
    if (!context) {
        fprintf(stderr, "lws_create_context failed\n");
        return 1;
    }
    // 创建客户端连接
    client = lws_client_connect_via_info(context, address, port, path, host, origin, protocols[0].name, NULL);
    if (!client) {
        fprintf(stderr, "lws_client_connect_via_info failed\n");
        return 1;
    }
    // 主循环
    while (1) {
        lws_service(context, 50); // 50ms 超时
        // 在这里可以添加其他逻辑,比如定时重连等
    }
    // 清理
    lws_context_destroy(context);
    return 0;
}

步骤 3: 编译和运行

# 编译时需要链接 libwebsockets
gcc realtime_stock_ws.c -o realtime_stock_ws -lwebsockets
# 运行
./realtime_stock_ws

使用专门的金融数据库 API (如 TWS/IB)

如果你是专业交易者,可能会使用 Interactive Brokers (IB) 的 Trader Workstation (TWS) 或 Gateway,他们提供了 C++ API,但可以通过封装或特定方式在 C 中使用。

特点:

  • 极低延迟:专为高频交易设计。
  • 功能强大:可以获取几乎所有金融产品的实时数据、下单、管理账户等。
  • 复杂度高:需要理解 IB 的协议和 API,设置也相对复杂。

基本流程:

  1. 下载并安装 TWS 或 IB Gateway。
  2. 启动它们并启用 API 连接(在设置中配置端口)。
  3. 在 C 程序中使用 IB 提供的 C++ SDK(需要 C++ 编译器)或通过 socket 编程模拟其协议进行连接,这超出了简单教程的范围,但是一个非常重要的专业方向。

总结与对比

方法 优点 缺点 适用场景
cURL + JSON-C 简单、通用、易于实现、资料多 有延迟(轮询)、非真正的实时 学习、个人项目、非高频数据需求
WebSocket 真正的实时、高效、低延迟 找到免费稳定的源较难、库学习曲线稍陡 需要实时数据的应用、监控仪表盘
TWS/IB API 极低延迟、功能全面、专业 非常复杂、需要付费账户、设置繁琐 专业交易、算法交易、高频交易

给初学者的建议: 从 方法一 (cURL + JSON-C) 开始,它能让你完整地走通“获取网络数据 -> 解析数据 -> 使用数据”的整个流程,是学习 C 语言网络编程和数据处理的最佳起点,当你对实时性有更高要求时,再转向 方法二 (WebSocket)

文章版权及转载声明

作者:咔咔本文地址:https://www.jits.cn/content/19904.html发布于 2025-12-04
文章转载或复制请以超链接形式并注明出处杰思科技・AI 股讯

阅读
分享

发表评论

快捷回复:

评论列表 (暂无评论,1人围观)参与讨论

还没有评论,来说两句吧...