第2章:链上数据基础设施

做量化交易,第一件事是什么?不是写策略,不是调参数,而是——你得先能连上链。

我刚开始做DeFi量化时,就犯过这个错。策略写得飞起,回测数据漂亮得不行,结果一上线,连节点都连不上。嗯,那感觉,就像你准备好了所有食材,却发现没开煤气灶。

这一章,我们就来聊聊链上数据的基础设施。说白了,就是你怎么跟区块链“对话”。

2.1 节点服务商:Infura、Alchemy、QuickNode

自己跑一个全节点?理论上可以,但实操上,我劝你慎重。以太坊全节点现在要几个TB的硬盘,同步一次得花好几天。而且,你还要保证它24小时在线,不能断电断网。

所以,绝大多数量化工程师都会选择节点服务商。它们帮你把节点跑好,你只需要调用API就行。

2.1.1 三大主流服务商对比

服务商 免费层 特点 适合场景
Infura 10万请求/天 老牌,生态最成熟,文档齐全 入门学习、小规模项目
Alchemy 3亿计算单元/月 功能丰富,有WebSocket推送,历史数据查询 中大规模量化策略
QuickNode 按需付费 速度快,全球节点分布广,支持多链 高频交易、多链套利
我的建议: 刚开始学,用Infura就够了。但如果你要做实盘,我个人更推荐Alchemy。为什么?因为它的历史数据API特别好用,你不需要自己从头扫描区块。

2.1.2 如何选择?

其实没有绝对的好坏。我见过有人用Infura做高频交易,也见过有人用QuickNode只做数据归档。关键看你的需求:

  • 请求量:如果每秒请求超过100次,免费层肯定不够,得付费。
  • 延迟:做套利的话,延迟就是生命。QuickNode在这一点上确实有优势。
  • 数据丰富度:Alchemy的“交易收据”和“日志”查询,比Infura强不少。
避坑指南: 我曾经因为没注意Infura的免费层限制,结果策略跑着跑着突然断连。后来才发现,是请求量超了。所以,上线前一定要算好你的请求量,该付费就付费。

2.2 RPC接口调用基础

RPC,全称Remote Procedure Call,远程过程调用。听起来高大上,其实就是一个接口。你发一个请求过去,它给你返回数据。

以太坊的RPC接口,说白了就是一套JSON-RPC协议。你发一个JSON格式的请求,它返回一个JSON格式的响应。

2.2.1 最常用的几个RPC方法

  • eth_blockNumber:获取最新区块号。这是你判断链是否同步的基础。
  • eth_getBalance:查询地址余额。注意,单位是Wei,不是ETH。
  • eth_call:调用合约的只读方法。比如查一个Uniswap池子的储备量。
  • eth_getLogs:获取事件日志。这是做链上数据分析的核心。
  • eth_sendRawTransaction:发送已签名的交易。做交易执行时必用。
核心要点: 做量化,你90%的请求都会集中在eth_calleth_getLogs上。前者用来查状态,后者用来抓事件。

2.2.2 一个简单的RPC调用示例

假设你想查一下某个地址的ETH余额。用curl命令就能搞定:

curl -X POST https://mainnet.infura.io/v3/YOUR_PROJECT_ID \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "eth_getBalance",
    "params": ["0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18", "latest"],
    "id": 1
  }'

返回结果长这样:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x29c4c4f8b3c0000"
}

这个结果是以Wei为单位的十六进制数。换算成ETH,就是0.1888 ETH左右。

小技巧: 我习惯在写代码前,先用curl测试一下RPC接口。这样能快速确认接口是否通,参数是否正确。别一上来就写Python代码,调试起来麻烦。

2.3 Web3.py与ethers.js入门

直接调RPC接口太原始了。在实际项目中,我们会用封装好的库。Python生态里,Web3.py是首选;JavaScript生态里,ethers.js是主流。

2.3.1 Web3.py:Python量化者的标配

我个人主要用Python做量化,所以Web3.py用得最多。它把RPC调用封装成了Python函数,用起来很顺手。

安装:

pip install web3

连接节点:

from web3 import Web3

# 连接Infura
w3 = Web3(Web3.HTTPProvider('https://mainnet.infura.io/v3/YOUR_PROJECT_ID'))

# 检查是否连接成功
print(w3.is_connected())  # 返回True就对了

查询余额:

address = '0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18'
balance = w3.eth.get_balance(address)
print(f"余额: {w3.from_wei(balance, 'ether')} ETH")

调用合约方法:

# 以USDT合约为例
usdt_contract = w3.eth.contract(
    address='0xdAC17F958D2ee523a2206206994597C13D831ec7',
    abi=USDT_ABI  # 需要提前获取ABI
)

# 查询某个地址的USDT余额
balance = usdt_contract.functions.balanceOf('0x...').call()
print(f"USDT余额: {balance}")
注意: 调用合约方法时,一定要有ABI。没有ABI,你没法知道合约有哪些函数。我一般从Etherscan上复制ABI,或者用eth_getContractABI接口获取。

2.3.2 ethers.js:前端与Node.js的利器

如果你做的是前端量化工具,或者用Node.js写脚本,ethers.js会更合适。它比Web3.js更轻量,API设计也更现代。

安装:

npm install ethers

连接节点:

const { ethers } = require("ethers");

// 连接Alchemy
const provider = new ethers.providers.JsonRpcProvider(
  'https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY'
);

// 检查连接
provider.getBlockNumber().then(console.log);

查询余额:

const address = '0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18';
const balance = await provider.getBalance(address);
console.log(`余额: ${ethers.utils.formatEther(balance)} ETH`);

调用合约方法:

const usdtContract = new ethers.Contract(
  '0xdAC17F958D2ee523a2206206994597C13D831ec7',
  USDT_ABI,
  provider
);

const balance = await usdtContract.balanceOf('0x...');
console.log(`USDT余额: ${ethers.utils.formatUnits(balance, 6)}`);
我的经验: 如果你做的是纯后端量化,用Web3.py就够了。但如果你需要做实时数据展示,或者写一个交易面板,ethers.js配合React会非常舒服。

2.4 本章知识体系图

下面这张图,帮你理清这一章的核心逻辑:

链上数据基础设施知识体系 区块链节点(以太坊主网) 节点服务商 RPC接口 WebSocket推送 Infura(入门) Alchemy(推荐) QuickNode(高频) 自建节点(高级) Web3.py(Python) ethers.js(JavaScript) 链上数据查询 → 量化策略执行 → 交易监控

这张图展示了从区块链节点到最终量化应用的完整链路。你想想看,每一步都环环相扣。节点服务商是桥梁,RPC是语言,Web3.py和ethers.js是你的工具。

总结一下: 做DeFi量化,你得先搞定数据基础设施。选一个靠谱的节点服务商,学会RPC调用,再掌握一个开发库。这三步走完,你就能跟链上数据“对话”了。

专注资料整理