4. Python网络编程基础:Socket编程、HTTP请求、WebSocket协议基础

做量化交易,说白了就是跟数据打交道。而数据从哪来?网络。你写的策略再牛,拿不到行情数据也是白搭。这一章,我们就来聊聊Python网络编程里最核心的三个东西:Socket、HTTP和WebSocket。

我个人习惯把网络编程比作「打电话」。Socket就是电话线,HTTP是你说「喂,你好」,WebSocket则是你俩一直通着话,随时能聊。嗯,这个比喻虽然糙,但道理不差。

4.1 Socket编程:最底层的「电话线」

Socket是网络通信的基石。几乎所有上层协议(HTTP、FTP、WebSocket)底层都是Socket。说白了,它就是两个程序之间的一条数据通道。

我在项目中遇到过一个问题:用Socket接收期货行情,结果数据老是丢包。后来发现是缓冲区设得太小了。你想想看,行情数据一秒刷几十次,缓冲区不够用,数据自然就丢了。

核心要点:Socket编程分为TCP和UDP两种。期货行情通常用UDP(速度快,允许少量丢包),交易指令用TCP(必须可靠)。

TCP Socket 示例(客户端)

import socket

# 创建TCP Socket
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('127.0.0.1', 8888))

# 发送数据
client.send(b'Hello, 行情服务器!')

# 接收数据
data = client.recv(1024)
print(f'收到: {data.decode()}')

client.close()

UDP Socket 示例(接收行情)

import socket

# 创建UDP Socket
udp_client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# 绑定到本地端口(模拟接收行情)
udp_client.bind(('0.0.0.0', 9999))

while True:
    data, addr = udp_client.recvfrom(65535)  # 最大UDP包大小
    print(f'来自 {addr} 的行情数据: {data[:50]}...')

避坑指南:我曾经在UDP接收时没设超时,结果程序卡死了一整天。记得用 socket.settimeout() 设置超时时间。

4.2 HTTP请求:RESTful API的敲门砖

HTTP请求大家应该不陌生。获取历史K线、查询账户信息,基本都是通过HTTP。Python里最常用的就是 requests 库,简单到令人发指。

但这里有个坑:很多量化平台的HTTP接口有频率限制。我见过有人写了个死循环去拉数据,结果IP直接被封了。嗯,这种事我也干过。

GET请求示例

import requests

url = 'https://api.xxx.com/v1/kline'
params = {
    'symbol': 'BTCUSDT',
    'interval': '1h',
    'limit': 100
}

resp = requests.get(url, params=params, timeout=5)
if resp.status_code == 200:
    data = resp.json()
    print(f'获取到 {len(data)} 条K线数据')
else:
    print(f'请求失败: {resp.status_code}')

POST请求示例(带认证)

import requests

url = 'https://api.xxx.com/v1/order'
headers = {
    'X-API-Key': 'your_api_key',
    'Content-Type': 'application/json'
}
payload = {
    'symbol': 'BTCUSDT',
    'side': 'BUY',
    'quantity': 0.01
}

resp = requests.post(url, json=payload, headers=headers)
print(resp.json())

注意:千万别把API Key硬编码在代码里!我习惯用环境变量或配置文件来管理。你想想看,代码一上传到GitHub,Key就全暴露了。

4.3 WebSocket协议:实时行情的「高速公路」

HTTP有个致命缺点:你得主动去问服务器「有数据吗?」。服务器说「没有」,你就得等一会儿再问。这叫轮询,效率极低。

WebSocket就不一样了。客户端和服务器建立连接后,服务器可以主动推数据过来。期货行情一秒几十次变化,用WebSocket再合适不过。

我记得第一次用WebSocket接期货行情时,看到数据哗哗地流进来,那种感觉——嗯,就像打开了水龙头。

WebSocket客户端示例

import websocket
import json

def on_message(ws, message):
    """收到消息时的回调"""
    data = json.loads(message)
    print(f'最新行情: {data["price"]}')

def on_error(ws, error):
    print(f'发生错误: {error}')

def on_close(ws, close_status_code, close_msg):
    print('连接已关闭')

def on_open(ws):
    """连接建立后,订阅行情"""
    subscribe_msg = {
        'op': 'subscribe',
        'args': ['btcusdt@ticker']
    }
    ws.send(json.dumps(subscribe_msg))
    print('已订阅BTCUSDT实时行情')

# 创建WebSocket连接
ws = websocket.WebSocketApp(
    'wss://stream.xxx.com/ws',
    on_open=on_open,
    on_message=on_message,
    on_error=on_error,
    on_close=on_close
)

# 启动连接(阻塞运行)
ws.run_forever()

实战技巧:WebSocket连接可能会断开。我习惯在 on_close 里加个自动重连逻辑,比如等待5秒后重新连接。毕竟行情不能断。

4.4 三种方式对比

特性 Socket (TCP/UDP) HTTP WebSocket
通信模式 双向 请求-响应 双向实时
适用场景 低延迟行情、交易指令 历史数据、账户查询 实时行情、订单推送
连接开销 高(每次请求新建连接) 中(一次连接持续使用)
数据格式 二进制/自定义 JSON/XML JSON/二进制
可靠性 TCP可靠,UDP不可靠 可靠 可靠(基于TCP)

4.5 知识体系总览

下面这张图,是我梳理的本章知识结构。你可以把它当作一张地图,随时回来对照。

Python网络编程基础 - 知识体系 网络编程基础 Socket 编程 TCP / UDP 低延迟行情传输 自定义协议解析 HTTP 请求 GET / POST RESTful API 历史数据获取 WebSocket 全双工通信 实时行情推送 自动重连机制 选择原则:实时性要求高 → WebSocket / UDP;历史数据 → HTTP

好了,这一章的内容就到这。Socket、HTTP、WebSocket这三个东西,你只要搞懂了,后面写行情采集程序就会顺手很多。记住一点:没有最好的协议,只有最合适的场景。

专注资料整理