standx-python-sdk 设计文档 & 测试验收文档
一、设计文档
1.1 项目概述
| 项目 |
内容 |
| 项目名称 |
standx-python-sdk |
| 目标用户 |
Python 开发者、量化交易者、AI Agent |
| Python 版本 |
3.10+ |
| 许可证 |
MIT |
1.2 架构设计
┌─────────────────────────────────────────────────────────────────┐
│ standx-python-sdk │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ User Code │ │ Strategy │ │ Agent │ │
│ │ │ │ Scripts │ │ (AI) │ │
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │ │
│ └───────────────────┼───────────────────┘ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ StandXClient │ │
│ ├─────────────────────────────────────────────────────────┤ │
│ │ market: MarketAPI │ account: AccountAPI │ │
│ │ - ticker() │ - positions() │ │
│ │ - depth() │ - balances() │ │
│ │ - trades() │ - orders() │ │
│ │ - kline() │ - history() │ │
│ │ │ │ │
│ │ order: OrderAPI │ ws: WebSocketAPI │ │
│ │ - create() │ - subscribe_price() │ │
│ │ - cancel() │ - subscribe_depth() │ │
│ │ - cancel_all() │ - subscribe_trade() │ │
│ │ │ - on_order_update() │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ HTTP / WebSocket Layer │ │
│ │ httpx + websockets │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ StandX Exchange API │ │
│ │ REST: https://perps.standx.com │ │
│ │ WS: wss://perps.standx.com/ws-stream/v1 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
1.3 API 设计
1.3.1 StandXClient 主类
class StandXClient:
def __init__(
self,
private_key: str = None, # 钱包私钥
jwt_token: str = None, # 或直接传入 JWT
api_url: str = \"https://perps.standx.com\",
ws_url: str = \"wss://perps.standx.com/ws-stream/v1\",
timeout: float = 30.0,
verbose: bool = False
):
\"\"\"
初始化客户端
Args:
private_key: 钱包私钥 (0x...)
jwt_token: 预生成的 JWT token
api_url: REST API 地址
ws_url: WebSocket 地址
timeout: 请求超时时间 (秒)
verbose: 调试模式
\"\"\"
1.3.2 Market API
class MarketAPI:
async def ticker(self, symbol: str) -> dict:
\"\"\"获取 ticker 数据
Args:
symbol: 交易对 (如 \"BTC-USD\")
Returns:
{
\"symbol\": \"BTC-USD\",
\"last_price\": \"67000.00\",
\"mark_price\": \"67000.00\",
\"index_price\": \"66980.00\",
\"24h_high\": \"68000.00\",
\"24h_low\": \"66000.00\",
\"24h_volume\": \"12345.67\",
\"funding_rate\": \"0.0001\",
\"next_funding_time\": \"2024-01-01T08:00:00Z\"
}
\"\"\"
async def tickers(self) -> list[dict]:
\"\"\"获取所有 ticker\"\"\"
async def depth(self, symbol: str, limit: int = 20) -> dict:
\"\"\"获取订单簿
Args:
symbol: 交易对
limit: 深度数量 (默认 20)
Returns:
{
\"symbol\": \"BTC-USD\",
\"bids\": [[\"67000\", \"1.5\"], [\"66999\", \"2.0\"], ...],
\"asks\": [[\"67001\", \"1.0\"], [\"67002\", \"2.5\"], ...],
\"timestamp\": \"1704067200000\"
}
\"\"\"
async def trades(self, symbol: str, limit: int = 50) -> list[dict]:
\"\"\"获取近期成交\"\"\"
async def kline(
self,
symbol: str,
interval: str = \"1m\",
start_time: int = None,
end_time: int = None,
limit: int = 100
) -> list[dict]:
\"\"\"获取 K 线数据
Args:
symbol: 交易对
interval: 周期 (\"1m\", \"5m\", \"15m\", \"1h\", \"4h\", \"1d\")
start_time: 开始时间 (毫秒)
end_time: 结束时间 (毫秒)
limit: 数量限制
Returns:
[
{
\"time\": 1704067200000,
\"open\": \"67000\",
\"high\": \"67100\",
\"low\": \"66900\",
\"close\": \"67050\",
\"volume\": \"123.45\"
},
...
]
\"\"\"
async def funding(self, symbol: str, limit: int = 10) -> list[dict]:
\"\"\"获取资金费率历史\"\"\"
async def symbols(self) -> list[dict]:
\"\"\"获取所有交易对\"\"\"
1.3.3 Account API
class AccountAPI:
async def balances(self) -> dict:
\"\"\"获取账户余额
Returns:
{
\"total_equity\": \"10000.00\",
\"total_margin\": \"5000.00\",
\"available\": \"8000.00\",
\"pnl_24h\": \"100.00\",
\"wallets\": [
{
\"asset\": \"USD\",
\"balance\": \"5000.00\",
\"available\": \"4000.00\",
\"locked\": \"1000.00\"
}
]
}
\"\"\"
async def positions(self, symbol: str = None) -> list[dict]:
\"\"\"获取持仓
Args:
symbol: 可选,按交易对筛选
Returns:
[
{
\"id\": 12345,
\"symbol\": \"BTC-USD\",
\"side\": \"buy\", # \"buy\" = LONG, \"sell\" = SHORT
\"qty\": \"0.5\",
\"entry_price\": \"66000.00\",
\"mark_price\": \"67000.00\",
\"leverage\": \"10\",
\"margin_mode\": \"cross\",
\"unrealized_pnl\": \"500.00\",
\"roe\": \"10.0\",
\"liq_price\": \"59400.00\",
\"updated_at\": \"2024-01-01T12:00:00Z\"
}
]
\"\"\"
async def orders(
self,
symbol: str = None,
status: str = None,
limit: int = 100
) -> list[dict]:
\"\"\"获取订单
Args:
symbol: 交易对
status: 状态 (\"open\", \"filled\", \"canceled\")
limit: 数量限制
\"\"\"
async def history(
self,
symbol: str = None,
start_time: int = None,
end_time: int = None,
limit: int = 50
) -> list[dict]:
\"\"\"获取历史订单\"\"\"
1.3.4 Order API
class OrderAPI:
async def create(
self,
symbol: str,
side: str, # \"buy\" / \"sell\"
order_type: str, # \"limit\" / \"market\"
qty: str,
price: str = None, # 限价单必需
time_in_force: str = \"gtc\", # \"gtc\" / \"ioc\" / \"fok\"
tp_price: str = None, # 止盈价格
sl_price: str = None # 止损价格
) -> dict:
\"\"\"创建订单
Returns:
{
\"id\": \"order_123456\",
\"symbol\": \"BTC-USD\",
\"side\": \"buy\",
\"order_type\": \"limit\",
\"qty\": \"0.1\",
\"price\": \"67000.00\",
\"status\": \"new\",
\"created_at\": \"2024-01-01T12:00:00Z\"
}
\"\"\"
async def cancel(self, order_id: str, symbol: str) -> dict:
\"\"\"取消订单\"\"\"
async def cancel_all(self, symbol: str = None) -> dict:
\"\"\"取消所有订单\"\"\"
async def get_order(self, order_id: str, symbol: str) -> dict:
\"\"\"查询订单详情\"\"\"
1.3.5 Leverage & Margin API
class LeverageAPI:
async def set_leverage(self, symbol: str, leverage: int) -> dict:
\"\"\"设置杠杆\"\"\"
class MarginAPI:
async def set_margin_mode(self, symbol: str, mode: str) -> dict:
\"\"\"设置保证金模式
Args:
mode: \"cross\" / \"isolated\"
\"\"\"
async def add_margin(self, symbol: str, amount: str) -> dict:
\"\"\"增加保证金\"\"\"
async def remove_margin(self, symbol: str, amount: str) -> dict:
\"\"\"减少保证金\"\"\"
1.3.6 WebSocket API
class WebSocketAPI:
async def connect(self):
\"\"\"建立 WebSocket 连接\"\"\"
async def disconnect(self):
\"\"\"断开连接\"\"\"
# ========== Public Channels ==========
async def subscribe_price(self, symbol: str, callback: callable):
\"\"\"订阅价格更新
Args:
symbol: 交易对
callback: 回调函数 (price: dict) -> None
\"\"\"
async def subscribe_depth(self, symbol: str, callback: callable):
\"\"\"订阅订单簿更新\"\"\"
async def subscribe_trade(self, symbol: str, callback: callable):
\"\"\"订阅成交推送\"\"\"
# ========== Private Channels (需要认证) ==========
async def subscribe_order(self, callback: callable):
\"\"\"订阅订单更新\"\"\"
async def subscribe_position(self, callback: callable):
\"\"\"订阅持仓更新\"\"\"
async def subscribe_balance(self, callback: callable):
\"\"\"订阅余额更新\"\"\"
async def subscribe_fills(self, callback: callable):
\"\"\"订阅成交记录 (用户买卖)\"\"\"
1.4 认证模块
class Auth:
@staticmethod
def generate_jwt(
private_key: str,
wallet_address: str,
permissions: list[str] = [\"trade\", \"view\"],
expiry_days: int = 7
) -> str:
\"\"\"生成 JWT token
Args:
private_key: 钱包私钥
wallet_address: 钱包地址
permissions: 权限列表 [\"trade\", \"view\"]
expiry_days: 过期天数
Returns:
JWT token 字符串
\"\"\"
1.5 策略模板 (可选)
1.5.1 网格策略
class GridStrategy:
def __init__(
self,
client: StandXClient,
symbol: str,
grid_count: int = 10,
grid_range: float = 0.05, # 5% 范围
qty_per_grid: str = \"0.01\"
):
\"\"\"
网格交易策略
Args:
client: StandX 客户端
symbol: 交易对
grid_count: 网格数量
grid_range: 价格范围 (5% = 0.05)
qty_per_grid: 每个网格的数量
\"\"\"
async def start(self):
\"\"\"启动策略\"\"\"
async def stop(self):
\"\"\"停止策略\"\"\"
async def restart(self):
\"\"\"重启策略 (重新平衡网格)\"\"\"
二、测试验收文档
2.1 测试环境
| 环境 |
配置 |
| Python |
3.10, 3.11, 3.12 |
| 测试网络 |
StandX Testnet (如可用) |
| 测试账号 |
测试钱包 + 测试 JWT |
2.2 测试用例
2.2.1 单元测试
| 模块 |
测试项 |
预期结果 |
| Auth |
generate_jwt() 正确生成签名 |
JWT 字符串有效 |
| Auth |
jwt 包含正确权限 |
permissions 匹配 |
| MarketAPI |
ticker() 返回完整数据 |
包含 last_price, mark_price 等 |
| MarketAPI |
depth() 订单簿格式正确 |
bids/asks 数组格式 |
| MarketAPI |
kline() 返回 K 线数据 |
open/high/low/close/volume |
| AccountAPI |
positions() 持仓结构正确 |
包含 qty, entry_price, upnl |
| AccountAPI |
balances() 余额结构正确 |
包含 equity, available |
| OrderAPI |
create() 限价单成功 |
返回 order_id, status=new |
| OrderAPI |
create() 市价单成功 |
返回 order_id, status=filled |
| OrderAPI |
cancel() 取消订单成功 |
status=canceled |
| OrderAPI |
cancel_all() 取消所有成功 |
所有订单 canceled |
| WebSocket |
connect() 连接成功 |
ws.connected = True |
| WebSocket |
subscribe_price() 收到推送 |
callback 收到实时价格 |
2.2.2 集成测试
| 场景 |
测试步骤 |
验收标准 |
| 完整交易流程 |
1. 获取 ticker 2. 下限价单 3. 查询订单 4. 取消订单 |
订单状态正确变更 |
| 持仓管理 |
1. 开多仓 2. 查询持仓 3. 平仓 |
持仓数量正确 |
| WebSocket 实时 |
1. 连接 ws 2. 订阅 price 3. 下单触发成交 4. 收到 fill 推送 |
实时数据正确 |
| 认证过期处理 |
1. 使用过期 jwt 2. 调用 API |
抛出 AuthExpiredError |
2.3 测试用例代码示例
import pytest
import asyncio
from standx import StandXClient
# 测试配置
TEST_PRIVATE_KEY = \"0x...\" # 测试钱包私钥
TEST_SYMBOL = \"BTC-USD\"
@pytest.fixture
def client():
return StandXClient(private_key=TEST_PRIVATE_KEY)
class TestMarketAPI:
@pytest.mark.asyncio
async def test_ticker(self, client):
result = await client.market.ticker(TEST_SYMBOL)
assert \"last_price\" in result
assert \"mark_price\" in result
assert result[\"symbol\"] == TEST_SYMBOL
@pytest.mark.asyncio
async def test_depth(self, client):
result = await client.market.depth(TEST_SYMBOL, limit=10)
assert \"bids\" in result
assert \"asks\" in result
assert len(result[\"bids\"]) <= 10
class TestOrderAPI:
@pytest.mark.asyncio
async def test_create_limit_order(self, client):
# 获取当前价格
ticker = await client.market.ticker(TEST_SYMBOL)
price = float(ticker[\"last_price\"])
# 下限价单
order = await client.order.create(
symbol=TEST_SYMBOL,
side=\"buy\",
order_type=\"limit\",
qty=\"0.001\",
price=str(price * 0.99) # 低于市价
)
assert \"id\" in order
assert order[\"status\"] in [\"new\", \"open\"]
# 清理: 取消订单
await client.order.cancel(order[\"id\"], TEST_SYMBOL)
class TestWebSocket:
@pytest.mark.asyncio
async def test_price_stream(self, client):
prices = []
async def on_price(price):
prices.append(price)
await client.ws.connect()
await client.ws.subscribe_price(TEST_SYMBOL, on_price)
# 等待 5 秒收集数据
await asyncio.sleep(5)
await client.ws.disconnect()
assert len(prices) > 0
assert \"last_price\" in prices[0]
2.4 验收标准
2.4.1 功能验收
| 功能 |
验收条件 |
| 初始化 |
私钥或 JWT 可正常初始化 |
| 市场数据 |
ticker/depth/trades/kline 全部返回正确数据 |
| 账户 |
positions/balances/orders 全部正常 |
| 订单 |
create/cancel/cancel-all 全部正常 |
| WebSocket |
price/depth/trade 订阅全部正常 |
| 认证 |
JWT 生成和验证正确 |
2.4.2 性能验收
| 指标 |
目标 |
| API 响应时间 |
< 1 秒 |
| WebSocket 延迟 |
< 500ms |
| SDK 启动时间 |
< 2 秒 |
| 内存占用 |
< 50MB (空闲) |
2.4.3 错误处理验收
| 场景 |
预期行为 |
| 网络超时 |
抛出 TimeoutError |
| 认证失败 |
抛出 AuthError |
| 订单失败 |
抛出 OrderError 并包含原因 |
| WebSocket 断开 |
自动重连 (最多 3 次) |
| 限价单价格无效 |
抛出 ValidationError |
三、发布计划
| 版本 |
功能 |
状态 |
| 0.1.0 |
MVP - 基础 REST API |
TODO |
| 0.2.0 |
WebSocket 支持 |
TODO |
| 0.3.0 |
策略模板 (网格) |
TODO |
| 1.0.0 |
正式版 |
TODO |
四、后续扩展
standx-python-sdk 设计文档 & 测试验收文档
一、设计文档
1.1 项目概述
1.2 架构设计
1.3 API 设计
1.3.1 StandXClient 主类
1.3.2 Market API
1.3.3 Account API
1.3.4 Order API
1.3.5 Leverage & Margin API
1.3.6 WebSocket API
1.4 认证模块
1.5 策略模板 (可选)
1.5.1 网格策略
二、测试验收文档
2.1 测试环境
2.2 测试用例
2.2.1 单元测试
2.2.2 集成测试
2. 下限价单
3. 查询订单
4. 取消订单
2. 查询持仓
3. 平仓
2. 订阅 price
3. 下单触发成交
4. 收到 fill 推送
2. 调用 API
2.3 测试用例代码示例
2.4 验收标准
2.4.1 功能验收
2.4.2 性能验收
2.4.3 错误处理验收
TimeoutErrorAuthErrorOrderError并包含原因ValidationError三、发布计划
四、后续扩展