# Quantum Execute Python SDK
[](https://pypi.org/project/qe-connector/)
[](https://pypi.org/project/qe-connector/)
[](https://opensource.org/licenses/MIT)
这是 Quantum Execute 公共 API 的官方 Python SDK,为开发者提供了一个轻量级、易于使用的接口来访问 Quantum Execute 的交易服务。
## 功能特性
- ✅ 完整的 Quantum Execute API 支持
- ✅ 交易所 API 密钥管理
- ✅ 主订单创建与管理(TWAP、VWAP、POV 等算法)
- ✅ 订单查询和成交明细
- ✅ ListenKey 创建与管理
- ✅ 交易对信息查询
- ✅ 服务器连通性测试
- ✅ 服务器时间同步
- ✅ 安全的 HMAC-SHA256 签名认证
- ✅ 支持生产环境和测试环境
- ✅ 链式调用 API 设计
- ✅ 完整的错误处理
## 安装
```bash
pip install qe-connector
```
或者从源码安装:
```bash
git clone https://github.com/Quantum-Execute/qe-connector-python.git
cd qe-connector-python
pip install -e .
```
## 快速开始
### 初始化客户端
```python
from qe.user import User as Client
import logging
# 配置日志(可选)
logging.basicConfig(level=logging.INFO)
# 创建生产环境客户端
client = Client(
api_key="your-api-key",
api_secret="your-api-secret"
)
# 创建测试环境客户端
client = Client(
api_key="your-api-key",
api_secret="your-api-secret",
base_url="https://testapi.quantumexecute.com"
)
```
### 使用枚举类型(推荐)
SDK 提供了枚举类型来确保类型安全和代码提示。推荐使用枚举而不是字符串:
```python
# 导入枚举类型
from qe.lib import Algorithm, Exchange, MarketType, OrderSide, StrategyType, MarginType
# 可用的枚举值
print("算法类型:", [algo.value for algo in Algorithm]) # ['TWAP', 'VWAP', 'POV']
print("交易所:", [exchange.value for exchange in Exchange]) # ['Binance']
print("市场类型:", [market.value for market in MarketType]) # ['SPOT', 'PERP']
print("订单方向:", [side.value for side in OrderSide]) # ['buy', 'sell']
print("策略类型:", [strategy.value for strategy in StrategyType]) # ['TWAP_1', 'POV']
print("保证金类型:", [margin.value for margin in MarginType]) # ['U']
# 使用枚举创建订单(推荐)
response = client.create_master_order(
algorithm=Algorithm.TWAP, # 而不是 "TWAP"
exchange=Exchange.BINANCE, # 而不是 "Binance"
marketType=MarketType.SPOT, # 而不是 "SPOT"
side=OrderSide.BUY, # 而不是 "buy"
# ... 其他参数
)
```
## API 参考
### 公共接口
#### 服务器连通性测试
##### Ping 服务器
测试与 Quantum Execute 服务器的连通性。
**请求参数:**
| 参数名 | 类型 | 是否必传 | 描述 |
|--------|------|----------|------|
| 无需参数 | - | - | - |
**响应:**
成功时无返回内容,失败时返回错误信息。
**示例代码:**
```python
from qe.status import Status as StatusClient
# 创建状态客户端(无需认证)
status_client = StatusClient()
# 测试服务器连通性
try:
status_client.ping()
print("服务器连接正常")
except Exception as e:
print(f"服务器连接失败: {e}")
```
#### 获取服务器时间
##### 查询服务器时间戳
获取 Quantum Execute 服务器的当前时间戳(毫秒)。
**请求参数:**
| 参数名 | 类型 | 是否必传 | 描述 |
|--------|------|----------|------|
| 无需参数 | - | - | - |
**响应字段:**
| 字段名 | 类型 | 描述 |
|--------|------|------|
| serverTimeMilli | int | 服务器时间戳(毫秒) |
**示例代码:**
```python
from qe.status import Status as StatusClient
import datetime
# 创建状态客户端
status_client = StatusClient()
# 获取服务器时间戳
try:
timestamp = status_client.timestamp()
print(f"服务器时间戳: {timestamp}")
# 转换为可读时间格式
readable_time = datetime.datetime.fromtimestamp(timestamp / 1000)
print(f"服务器时间: {readable_time}")
except Exception as e:
print(f"获取时间戳失败: {e}")
```
#### 交易对管理
##### 查询交易对列表
获取支持的交易对信息,包括现货和合约交易对。
**请求参数:**
| 参数名 | 类型 | 是否必传 | 描述 |
|--------|------|----------|------|
| page | int | 否 | 页码 |
| pageSize | int | 否 | 每页数量 |
| exchange | str | 否 | 交易所名称筛选 |
| marketType | str/TradingPairMarketType | 否 | 市场类型筛选,可选值:SPOT(现货)、FUTURES(合约) |
| isCoin | bool | 否 | 是否为币种筛选 |
**响应字段:**
| 字段名 | 类型 | 描述 |
|--------|------|------|
| items | array | 交易对列表 |
| ├─ id | int | 交易对 ID |
| ├─ symbol | string | 交易对符号(如:BTCUSDT) |
| ├─ baseAsset | string | 基础币种(如:BTC) |
| ├─ quoteAsset | string | 计价币种(如:USDT) |
| ├─ exchange | string | 交易所名称 |
| ├─ marketType | string | 市场类型(SPOT/FUTURES) |
| ├─ contractType | string | 合约类型(仅合约交易对) |
| ├─ deliveryDate | string | 交割日期(仅合约交易对) |
| ├─ status | string | 交易对状态 |
| ├─ createdAt | string | 创建时间 |
| ├─ updatedAt | string | 更新时间 |
| page | int | 当前页码 |
| pageSize | int | 每页数量 |
| total | string | 总数 |
**示例代码:**
```python
from qe.pub import Pub as PubClient
from qe.lib import TradingPairMarketType
# 创建公共客户端(无需认证)
pub_client = PubClient()
# 获取所有交易对
try:
pairs = pub_client.trading_pairs()
print(f"总交易对数量: {pairs.get('total', 0)}")
# 打印前几个交易对信息
for pair in pairs.get('items', [])[:5]:
print(f"""
交易对信息:
符号: {pair['symbol']}
基础币种: {pair['baseAsset']}
计价币种: {pair['quoteAsset']}
交易所: {pair['exchange']}
市场类型: {pair['marketType']}
状态: {pair['status']}
创建时间: {pair['createdAt']}
""")
# 如果是合约交易对,显示额外信息
if pair['marketType'] == 'FUTURES':
print(f" 合约类型: {pair.get('contractType', 'N/A')}")
if pair.get('deliveryDate'):
print(f" 交割日期: {pair['deliveryDate']}")
except Exception as e:
print(f"获取交易对失败: {e}")
# 使用枚举类型筛选(推荐)
try:
# 获取币安现货交易对
spot_pairs = pub_client.trading_pairs(
exchange="Binance",
marketType=TradingPairMarketType.SPOT, # 使用枚举
page=1,
pageSize=10
)
print(f"币安现货交易对数量: {len(spot_pairs.get('items', []))}")
# 获取合约交易对
futures_pairs = pub_client.trading_pairs(
marketType=TradingPairMarketType.FUTURES, # 使用枚举
page=1,
pageSize=20
)
print(f"合约交易对数量: {len(futures_pairs.get('items', []))}")
# 获取币种交易对
coin_pairs = pub_client.trading_pairs(isCoin=True)
print(f"币种交易对数量: {len(coin_pairs.get('items', []))}")
except Exception as e:
print(f"筛选交易对失败: {e}")
# 使用字符串筛选(向后兼容)
try:
# 使用字符串参数
spot_pairs = pub_client.trading_pairs(
exchange="Binance",
marketType="SPOT", # 使用字符串
page=1,
pageSize=5
)
print(f"现货交易对数量: {len(spot_pairs.get('items', []))}")
except Exception as e:
print(f"获取现货交易对失败: {e}")
```
### 交易所 API 管理
#### 查询交易所 API 列表
查询当前用户绑定的所有交易所 API 账户。
**请求参数:**
| 参数名 | 类型 | 是否必传 | 描述 |
|--------|------|----------|------|
| page | int | 否 | 页码 |
| pageSize | int | 否 | 每页数量 |
| exchange | str | 否 | 交易所名称筛选 |
**响应字段:**
| 字段名 | 类型 | 描述 |
|--------|------|------|
| items | array | API 列表 |
| ├─ id | string | API 记录的唯一标识 |
| ├─ createdAt | string | API 添加时间 |
| ├─ accountName | string | 账户名称(如:账户1、账户2) |
| ├─ exchange | string | 交易所名称(如:Binance、OKX、Bybit) |
| ├─ apiKey | string | 交易所 API Key(部分隐藏) |
| ├─ verificationMethod | string | API 验证方式(如:OAuth、API) |
| ├─ balance | float | 账户余额(美元) |
| ├─ status | string | API 状态:正常、异常(不可用) |
| ├─ isValid | bool | API 是否有效 |
| ├─ isTradingEnabled | bool | 是否开启交易权限 |
| ├─ isDefault | bool | 是否为该交易所的默认账户 |
| ├─ isPm | bool | 是否为 Pm 账户 |
| total | int | API 总数 |
| page | int | 当前页码 |
| pageSize | int | 每页显示数量 |
**示例代码:**
```python
# 获取所有交易所 API 密钥
apis = client.list_exchange_apis()
print(f"共有 {apis['total']} 个 API 密钥")
# 打印每个 API 的详细信息
for api in apis['items']:
print(f"""
API 信息:
账户: {api['accountName']}
交易所: {api['exchange']}
状态: {api['status']}
余额: ${api['balance']:.2f}
交易权限: {'开启' if api['isTradingEnabled'] else '关闭'}
是否默认: {'是' if api['isDefault'] else '否'}
是否PM账户: {'是' if api['isPm'] else '否'}
添加时间: {api['createdAt']}
""")
# 带分页和过滤
apis = client.list_exchange_apis(
page=1,
pageSize=10,
exchange="binance"
)
```
### 交易订单管理
#### 创建主订单
创建新的主订单并提交到算法侧执行。
**请求参数:**
| 参数名 | 类型 | 是否必传 | 描述 |
|--------|------|------|------|
| **基础参数** |
| strategyType | string/StrategyType | 是 | 策略类型,可选值:TWAP-1、POV |
| algorithm | string/Algorithm | 是 | 交易算法。strategyType=TWAP-1时,可选值:TWAP、VWAP;strategyType=POV时,可选值:POV |
| exchange | string/Exchange | 是 | 交易所名称,可选值:Binance |
| symbol | string | 是 | 交易对符号(如:BTCUSDT)(可用交易对查询) |
| marketType | string/MarketType | 是 | 可选值:SPOT(现货)、PERP(永续合约) |
| side | string/OrderSide | 是 | 1.如果isTargetPosition=False:side代表交易方向,可选值:buy(买入)、sell(卖出);合约交易时可与reduceOnly组合,reduceOnly=True时:buy代表买入平空,sell代表卖出平多。2.如果isTargetPosition=True:side代表仓位方向,可选值:buy(多头)、sell(空头)。【仅合约交易时需传入】 |
| apiKeyId | string | 是 | 指定使用的 API Key ID,这将决定您本次下单使用哪个交易所账户执行 |
| **数量参数(二选一)** |
| totalQuantity | float64 | 否* | 要交易的总数量,支持字符串表示以避免精度问题,与 orderNotional 二选一,输入范围:>0 |
| orderNotional | float64 | 否* | 按价值下单时的金额,以计价币种为单位(如ETHUSDT为USDT数量),与 totalQuantity 二选一,输入范围:>0 |
| **下单模式参数** |
| isTargetPosition | bool | 否 | 是否为目标仓位下单,默认为 false |
| **时间参数** |
| startTime | string | 否 | 交易执行的启动时间,传入格式:ISO 8601(2025-09-03T01:30:00+08:00),若不传入,则立即执行 |
| executionDuration | int32 | 否 | 订单最大执行时长,分钟,范围>=1 |
| **TWAP/VWAP 算法参数** |
| mustComplete | bool | 否 | 是否一定要在executionDuration之内执行完毕,选false则不会追赶进度,默认:true |
| makerRateLimit | float64 | 否 | 要求maker占比超过该值,输入范围:0-1(输入0.1代表10%),默认:-1(算法智能计算推荐值执行) |
| povLimit | string | 否 | 占市场成交量比例上限,优先级低于mustComplete,输入范围:0-1(输入0.1代表10%),默认:0.8 |
| limitPrice | float64 | 否 | 最高/低允许交易的价格,买入时该字段象征最高买入价,卖出时该字段象征最低卖出价,若市价超出范围则停止交易,范围:>0,默认:-1,代表无限制 |
| upTolerance | string | 否 | 允许超出目标进度的最大容忍度,比如0.1就是执行过程中允许比目标进度超出母单数量的10%,范围:0-1(不含0、1),默认:-1(即无容忍) |
| lowTolerance | string | 否 | 允许落后目标进度的最大容忍度,比如0.1就是执行过程中允许比目标进度落后母单数量的10%,范围:0-1(不含0、1),默认:-1(即无容忍) |
| strictUpBound | bool | 否 | 表达是否追求严格小于uptolerance,开启后可能会把很小的母单也拆的很细,不建议开启,默认:false |
| tailOrderProtection | bool | 否 | 订单余量小于交易所最小发单量时,是否必须taker扫完,如果false,则订单余量小于交易所最小发单量时,订单结束执行;如果true,则订单余量随最近一笔下单全额执行(可能会提高Taker率),默认:true |
| **POV 算法参数** |
| makerRateLimit | float64 | 否 | 要求maker占比超过该值,输入范围:0-1(输入0.1代表10%),默认:-1(算法智能计算推荐值执行) |
| povLimit | string | 否 | 占市场成交量比例上限,输入范围:0-0.5(povMinLimit < max(povLimit-0.01,0)),默认:0 |
| povMinLimit | float64 | 否 | 占市场成交量比例下限,范围:小于max(POVLimit-0.01,0),默认:0(即无下限) |
| limitPrice | float64 | 否 | 最高/低允许交易的价格,买入时该字段象征最高买入价,卖出时该字段象征最低卖出价,若市价超出范围则停止交易,范围:>0,默认:-1,代表无限制 |
| strictUpBound | bool | 否 | 是否追求严格小于povLimit,开启后可能会把很小的母单也拆的很细,比如50u拆成10个5u,不建议开启,算法的每个order会权衡盘口流动性,默认:false |
| tailOrderProtection | bool | 否 | 订单余量小于交易所最小发单量时,是否必须taker扫完,如果false,则订单余量小于交易所最小发单量时,订单结束执行;如果true,则订单余量随最近一笔下单全额执行(可能会提高Taker率),默认:true |
| **其他参数** |
| reduceOnly | bool | 否 | 合约交易时是否仅减仓,默认值:false |
| marginType | string/MarginType | 否 | 合约交易保证金类型,可选值:U(U本位),默认:U(暂时只支持U本位永续合约) |
| notes | string | 否 | 订单备注 |
*注:totalQuantity 和 orderNotional 必须传其中一个,但当 isTargetPosition 为 true 时,totalQuantity 必填代表目标仓位数量且 orderNotional 不可填
**响应字段:**
| 字段名 | 类型 | 描述 |
|--------|------|------|
| masterOrderId | string | 创建成功的主订单 ID |
| success | bool | 创建是否成功 |
| message | string | 创建结果消息 |
**示例代码:**
```python
# 导入枚举类型(推荐方式)
from qe.lib import Algorithm, Exchange, MarketType, OrderSide, StrategyType, MarginType
# TWAP 订单示例 - 使用枚举创建订单(推荐)
response = client.create_master_order(
algorithm=Algorithm.TWAP, # 使用算法枚举
exchange=Exchange.BINANCE, # 使用交易所枚举
symbol="BTCUSDT",
marketType=MarketType.SPOT, # 使用市场类型枚举
side=OrderSide.BUY, # 使用订单方向枚举
apiKeyId="your-api-key-id", # 从 list_exchange_apis 获取
orderNotional="200", # $200 名义价值
strategyType=StrategyType.TWAP_1, # 使用策略类型枚举
startTime="2025-09-02T19:54:34+08:00",
endTime="2025-09-03T01:44:35+08:00",
executionDuration="5", # 5 秒间隔
mustComplete=True, # 必须完成全部订单
worstPrice=-1, # -1 表示无价格限制
upTolerance="-1", # 允许超出容忍度
lowTolerance="-1", # 允许落后容忍度
tailOrderProtection=True, # 尾单保护
notes="测试 TWAP 订单" # 订单备注
)
if response.get('success'):
print(f"主订单创建成功,ID: {response['masterOrderId']}")
else:
print(f"创建失败:{response.get('message')}")
```
**目标仓位下单示例:**
```python
# 目标仓位下单示例 - 买入 1.5 BTC 到目标仓位
response = client.create_master_order(
algorithm=Algorithm.TWAP, # 使用算法枚举
exchange=Exchange.BINANCE, # 使用交易所枚举
symbol="BTCUSDT",
marketType=MarketType.SPOT, # 使用市场类型枚举
side=OrderSide.BUY, # 使用订单方向枚举
apiKeyId="your-api-key-id", # 从 list_exchange_apis 获取
totalQuantity="1.5", # 目标数量 1.5 BTC
isTargetPosition=True, # 启用目标仓位模式
strategyType=StrategyType.TWAP_1, # 使用策略类型枚举
startTime="2025-09-02T19:54:34+08:00",
endTime="2025-09-03T01:44:35+08:00",
executionDuration=60, # 60 分钟
mustComplete=True, # 必须完成全部订单
limitPrice="65000", # 最高价格 $65,000
upTolerance="0.1", # 允许超出 10%
lowTolerance="0.1", # 允许落后 10%
tailOrderProtection=True, # 尾单保护
notes="目标仓位订单示例" # 订单备注
)
if response.get('success'):
print(f"目标仓位订单创建成功,ID: {response['masterOrderId']}")
else:
print(f"创建失败:{response.get('message')}")
```
**POV 合约订单示例:**
```python
# POV 合约订单示例 - 使用枚举
response = client.create_master_order(
algorithm=Algorithm.POV, # POV 算法
exchange=Exchange.BINANCE,
symbol="BTCUSDT",
marketType=MarketType.PERP, # 合约市场
side=OrderSide.SELL, # 卖出
apiKeyId="your-api-key-id",
orderNotional="1000", # $1000 名义价值
strategyType=StrategyType.POV, # POV 策略
startTime="2025-09-02T19:54:34+08:00",
endTime="2025-09-03T01:44:35+08:00",
povLimit=0.2, # 占市场成交量 20%
povMinLimit=0.05, # 最低占市场成交量 5%
marginType=MarginType.U, # U本位保证金
reduceOnly=False,
mustComplete=True,
notes="POV 合约订单示例"
)
if response.get('success'):
print(f"POV 订单创建成功,ID: {response['masterOrderId']}")
```
#### 查询主订单列表
获取用户的主订单列表。
**请求参数:**
| 参数名 | 类型 | 是否必传 | 描述 |
|--------|------|----------|------|
| page | int32 | 否 | 页码 |
| pageSize | int32 | 否 | 每页数量 |
| status | string | 否 | 订单状态筛选,可选值:NEW(执行中)、COMPLETED(已完成) |
| exchange | string | 否 | 交易所名称筛选 |
| symbol | string | 否 | 交易对筛选 |
| startTime | string | 否 | 开始时间筛选 |
| endTime | string | 否 | 结束时间筛选 |
**响应字段:**
| 字段名 | 类型 | 描述 |
|--------|------|------|
| items | array | 主订单列表 |
| ├─ masterOrderId | string | 主订单 ID |
| ├─ algorithm | string | 算法 |
| ├─ algorithmType | string | 算法类型 |
| ├─ exchange | string | 交易所 |
| ├─ symbol | string | 交易对 |
| ├─ marketType | string | 市场类型 |
| ├─ side | string | 买卖方向 |
| ├─ totalQuantity | string | 总数量 |
| ├─ filledQuantity | string | 已成交数量 |
| ├─ averagePrice | float64 | 平均成交价 |
| ├─ status | string | 状态:NEW(创建,未执行)、WAITING(等待中)、PROCESSING(执行中,且未完成)、PAUSED(已暂停)、CANCEL(取消中)、CANCELLED(已取消)、COMPLETED(已完成)、REJECTED(已拒绝)、EXPIRED(已过期)、CANCEL_REJECT(取消被拒绝) |
| ├─ executionDuration | int32 | 执行时长(分钟) |
| ├─ priceLimit | float64 | 价格限制 |
| ├─ startTime | string | 开始时间 |
| ├─ endTime | string | 结束时间 |
| ├─ createdAt | string | 创建时间 |
| ├─ updatedAt | string | 更新时间 |
| ├─ notes | string | 备注 |
| ├─ marginType | string | 保证金类型(U:U本位) |
| ├─ reduceOnly | bool | 是否仅减仓 |
| ├─ strategyType | string | 策略类型 |
| ├─ orderNotional | string | 订单金额(USDT) |
| ├─ mustComplete | bool | 是否必须完成 |
| ├─ makerRateLimit | string | 最低 Maker 率 |
| ├─ povLimit | string | 最大市场成交量占比 |
| ├─ clientId | string | 客户端 ID |
| ├─ date | string | 发单日期(格式:YYYYMMDD) |
| ├─ ticktimeInt | string | 发单时间(格式:093000000 表示 9:30:00.000) |
| ├─ limitPriceString | string | 限价(字符串) |
| ├─ upTolerance | string | 上容忍度 |
| ├─ lowTolerance | string | 下容忍度 |
| ├─ strictUpBound | bool | 严格上界 |
| ├─ ticktimeMs | int64 | 发单时间戳(epoch 毫秒) |
| ├─ category | string | 交易品种(spot 或 perp) |
| ├─ filledAmount | float64 | 成交金额 |
| ├─ totalValue | float64 | 成交总值 |
| ├─ base | string | 基础币种 |
| ├─ quote | string | 计价币种 |
| ├─ completionProgress | float64 | 完成进度(0-1) |
| ├─ reason | string | 原因(如取消原因) |
| total | int32 | 总数 |
| page | int32 | 当前页码 |
| pageSize | int32 | 每页数量 |
**示例代码:**
```python
# 查询所有主订单
orders = client.get_master_orders()
# 带过滤条件查询
orders = client.get_master_orders(
page=1,
pageSize=20,
status="NEW", # 执行中的订单
symbol="BTCUSDT",
startTime="2024-01-01T00:00:00Z",
endTime="2024-01-31T23:59:59Z"
)
# 打印订单详细信息
for order in orders['items']:
print(f"""
订单信息:
ID: {order['masterOrderId']}
算法: {order['algorithm']} ({order.get('strategyType', 'N/A')})
交易对: {order['symbol']} {order['marketType']}
方向: {order['side']}
状态: {order['status']}
完成度: {order['completionProgress'] * 100:.2f}%
平均价格: ${order.get('averagePrice', 0):.2f}
已成交: {order['filledQuantity']} / {order['totalQuantity']}
成交金额: ${order.get('filledAmount', 0):.2f}
创建时间: {order['createdAt']}
发单日期: {order.get('date', 'N/A')}
上容忍度: {order.get('upTolerance', 'N/A')}
下容忍度: {order.get('lowTolerance', 'N/A')}
""")
```
#### 查询成交记录
获取用户的成交记录。
**请求参数:**
| 参数名 | 类型 | 是否必传 | 描述 |
|--------|------|----------|------|
| page | int32 | 否 | 页码 |
| pageSize | int32 | 否 | 每页数量 |
| masterOrderId | string | 否 | 主订单 ID 筛选 |
| subOrderId | string | 否 | 子订单 ID 筛选 |
| symbol | string | 否 | 交易对筛选 |
| startTime | string | 否 | 开始时间筛选 |
| endTime | string | 否 | 结束时间筛选 |
**响应字段:**
| 字段名 | 类型 | 描述 |
|--------|------|------|
| items | array | 成交记录列表 |
| ├─ id | string | 记录 ID |
| ├─ orderCreatedTime | string | 订单创建时间 |
| ├─ masterOrderId | string | 主订单 ID |
| ├─ exchange | string | 交易所 |
| ├─ category | string | 市场类型 |
| ├─ symbol | string | 交易对 |
| ├─ side | string | 方向 |
| ├─ filledValue | float64 | 成交价值 |
| ├─ filledQuantity | string | 成交数量 |
| ├─ avgPrice | float64 | 平均价格 |
| ├─ price | float64 | 成交价格 |
| ├─ fee | float64 | 手续费 |
| ├─ tradingAccount | string | 交易账户 |
| ├─ status | string | 状态 |
| ├─ rejectReason | string | 拒绝原因 |
| ├─ base | string | 基础币种 |
| ├─ quote | string | 计价币种 |
| ├─ type | string | 订单类型 |
| total | int32 | 总数 |
| page | int32 | 当前页码 |
| pageSize | int32 | 每页数量 |
**示例代码:**
```python
# 查询特定主订单的成交明细
fills = client.get_order_fills(
masterOrderId="your-master-order-id",
page=1,
pageSize=50
)
# 查询所有成交
fills = client.get_order_fills(
symbol="BTCUSDT",
startTime="2024-01-01T00:00:00Z",
endTime="2024-01-01T23:59:59Z"
)
# 统计成交信息
total_value = 0
total_fee = 0
for fill in fills['items']:
print(f"""
成交详情:
时间: {fill['orderCreatedTime']}
交易对: {fill['symbol']}
方向: {fill['side']}
成交价格: ${fill['price']:.2f}
成交数量: {fill['filledQuantity']}
成交金额: ${fill['filledValue']:.2f}
手续费: ${fill['fee']:.4f}
账户: {fill['tradingAccount']}
类型: {fill.get('type', 'N/A')}
""")
total_value += fill['filledValue']
total_fee += fill['fee']
print(f"总成交额: ${total_value:.2f}, 总手续费: ${total_fee:.2f}")
```
#### 取消主订单
取消指定的主订单。
**请求参数:**
| 参数名 | 类型 | 是否必传 | 描述 |
|--------|------|----------|------|
| masterOrderId | string | 是 | 要取消的主订单 ID |
| reason | string | 否 | 取消原因 |
**响应字段:**
| 字段名 | 类型 | 描述 |
|--------|------|------|
| success | bool | 取消是否成功 |
| message | string | 取消结果消息 |
**示例代码:**
```python
# 取消订单
response = client.cancel_master_order(
masterOrderId="your-master-order-id",
reason="用户手动取消" # 可选的取消原因
)
if response.get('success'):
print("订单取消成功")
else:
print(f"订单取消失败: {response.get('message')}")
# 批量取消示例
def cancel_all_active_orders(client):
"""取消所有活跃订单"""
orders = client.get_master_orders(status="ACTIVE")
cancelled_count = 0
for order in orders['items']:
try:
response = client.cancel_master_order(
masterOrderId=order['masterOrderId'],
reason="批量取消活跃订单"
)
if response.get('success'):
cancelled_count += 1
print(f"已取消订单: {order['masterOrderId']}")
else:
print(f"取消失败: {order['masterOrderId']} - {response.get('message')}")
except Exception as e:
print(f"取消异常: {order['masterOrderId']} - {str(e)}")
print(f"\n总计取消 {cancelled_count} 个订单")
return cancelled_count
```
#### 创建 ListenKey
创建一个随机的UUID作为ListenKey,绑定当前用户信息,有效期24小时。ListenKey用于WebSocket连接,可以实时接收用户相关的交易数据推送。
**请求参数:**
| 参数名 | 类型 | 是否必传 | 描述 |
|--------|------|----------|------|
| 无需参数 | - | - | - |
**响应字段:**
| 字段名 | 类型 | 描述 |
|--------|------|------|
| listenKey | string | 生成的ListenKey |
| expireAt | string | ListenKey过期时间戳(秒) |
| success | bool | 创建是否成功 |
| message | string | 创建结果消息 |
**示例代码:**
```python
# 创建 ListenKey
result = client.create_listen_key()
if result.get('success'):
print(f"ListenKey创建成功:")
print(f"ListenKey: {result['listenKey']}")
print(f"过期时间: {result['expireAt']}")
# 使用 ListenKey 建立 WebSocket 连接
# ws_url = f"wss://api.quantumexecute.com/ws/{result['listenKey']}"
else:
print(f"ListenKey创建失败:{result.get('message')}")
```
**注意事项:**
- ListenKey 有效期为 24 小时,过期后需要重新创建
- 每个用户同时只能有一个有效的 ListenKey
- ListenKey 用于 WebSocket 连接,可以实时接收交易数据推送
- 建议在应用启动时创建 ListenKey,并在接近过期时重新创建
## 错误处理
SDK 提供了详细的错误信息,包括 API 错误和网络错误:
```python
from qe.error import ClientError, APIError
response = client.create_master_order(
# ... 设置参数
)
if 'error' in response:
# 检查是否为 API 错误
error = response['error']
if isinstance(error, dict) and 'code' in error:
print(f"API 错误 - 代码: {error['code']}, 原因: {error.get('reason')}, 消息: {error.get('message')}")
print(f"TraceID: {error.get('trace_id')}")
# 根据错误代码处理
if error['code'] == 400:
print("请求参数错误")
elif error['code'] == 401:
print("认证失败")
elif error['code'] == 403:
print("权限不足")
elif error['code'] == 429:
print("请求过于频繁")
else:
print(f"其他错误: {error}")
else:
print(f"网络或其他错误: {error}")
```
## 高级配置
### 自定义 HTTP 客户端
```python
import requests
import time
# 创建自定义 HTTP 客户端
session = requests.Session()
session.timeout = 30 # 30 秒超时
session.headers.update({
'User-Agent': 'QE-Python-SDK/1.0.0'
})
client = Client("your-api-key", "your-api-secret")
client.session = session
```
### 使用代理
```python
import requests
proxies = {
'https': 'http://proxy.example.com:8080'
}
client = Client("your-api-key", "your-api-secret")
client.session.proxies.update(proxies)
```
### 时间偏移调整
如果遇到时间戳错误,可以调整客户端的时间偏移:
```python
# 设置时间偏移(毫秒)
client.time_offset = 1000 # 客户端时间比服务器快 1 秒
```
### 请求重试
```python
import time
import math
# 实现简单的重试逻辑
def retry_request(func, max_retries=3):
"""重试请求函数"""
for i in range(max_retries):
try:
return func()
except Exception as e:
if i == max_retries - 1:
raise e
# 检查是否应该重试
if hasattr(e, 'code') and 400 <= e.code < 500:
raise e # 不重试客户端错误
# 指数退避
wait_time = math.pow(2, i)
print(f"请求失败,{wait_time}秒后重试...")
time.sleep(wait_time)
# 使用重试
def create_order_with_retry():
return client.create_master_order(
# ... 设置参数
)
result = retry_request(create_order_with_retry, max_retries=3)
```
## 最佳实践
### 1. API 密钥管理
```python
# 定期检查 API 密钥状态
def check_api_key_status(client):
apis = client.list_exchange_apis()
if not apis.get('items'):
print("获取 API 列表失败")
return
for api in apis['items']:
if not api['isValid']:
print(f"警告: API {api['id']} ({api['accountName']}) 状态异常")
if api['balance'] < 100:
print(f"警告: 账户 {api['accountName']} 余额不足 (${api['balance']:.2f})")
```
### 2. 订单监控
```python
# 监控订单执行状态
def monitor_order(client, master_order_id):
import time
while True:
orders = client.get_master_orders(page=1, pageSize=1)
if not orders['items']:
print("订单不存在")
return
order = orders['items'][0]
print(f"订单进度: {order['completionProgress']*100:.2f}%, 状态: {order['status']}")
if order['status'] == "COMPLETED":
print(f"订单已结束,最终状态: {order['status']}")
return
time.sleep(10) # 每 10 秒检查一次
```
### 3. 批量处理
```python
# 批量获取所有订单
def get_all_orders(client):
all_orders = []
page = 1
page_size = 100
while True:
result = client.get_master_orders(page=page, pageSize=page_size)
all_orders.extend(result['items'])
# 检查是否还有更多数据
if len(result['items']) < page_size:
break
page += 1
return all_orders
```
### 4. ListenKey 管理
```python
import time
from datetime import datetime
# ListenKey 管理器
class ListenKeyManager:
def __init__(self, client):
self.client = client
self.listen_key = None
self.expire_at = None
def create_listen_key(self):
"""创建或刷新 ListenKey"""
result = self.client.create_listen_key()
if not result.get('success'):
raise Exception(f"创建 ListenKey 失败: {result.get('message')}")
self.listen_key = result['listenKey']
self.expire_at = int(result['expireAt'])
print(f"ListenKey 创建成功: {self.listen_key}, 过期时间: {self.expire_at}")
return self.listen_key
def is_expired(self):
"""检查 ListenKey 是否即将过期"""
if not self.expire_at:
return True
# 提前1小时刷新
return time.time() > self.expire_at - 3600
def auto_refresh(self):
"""自动刷新 ListenKey"""
if self.is_expired():
print("ListenKey 即将过期,开始刷新...")
self.create_listen_key()
# 使用示例
manager = ListenKeyManager(client)
listen_key = manager.create_listen_key()
# 定期检查并刷新
while True:
manager.auto_refresh()
time.sleep(1800) # 每30分钟检查一次
```
### 5. WebSocket 实时数据推送
SDK 提供了完整的 WebSocket 服务,可以实时接收交易数据推送,包括主订单状态更新、子订单变化、成交明细等。
#### 创建 WebSocket 服务
```python
import logging
import time
from qe import API, WebSocketService, WebSocketEventHandlers, MasterOrderMessage, OrderMessage, FillMessage
# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
def on_connected():
"""连接成功回调"""
logger.info("WebSocket连接成功")
def on_disconnected():
"""断开连接回调"""
logger.info("WebSocket连接断开")
def on_error(error):
"""错误回调"""
logger.error(f"WebSocket错误: {error}")
def on_status(data):
"""状态消息回调"""
logger.info(f"收到状态消息: {data}")
def on_master_order(message: MasterOrderMessage):
"""主订单消息回调"""
logger.info(f"收到主订单消息:")
logger.info(f" 主订单ID: {message.master_order_id}")
logger.info(f" 客户端ID: {message.client_id}")
logger.info(f" 策略: {message.strategy}")
logger.info(f" 交易对: {message.symbol}")
logger.info(f" 方向: {message.side}")
logger.info(f" 数量: {message.qty}")
logger.info(f" 状态: {message.status}")
logger.info(f" 时间戳: {message.timestamp}")
def on_order(message: OrderMessage):
"""订单消息回调"""
logger.info(f"收到订单消息:")
logger.info(f" 主订单ID: {message.master_order_id}")
logger.info(f" 订单ID: {message.order_id}")
logger.info(f" 交易对: {message.symbol}")
logger.info(f" 方向: {message.side}")
logger.info(f" 价格: {message.price}")
logger.info(f" 数量: {message.quantity}")
logger.info(f" 状态: {message.status}")
logger.info(f" 已成交数量: {message.fill_qty}")
logger.info(f" 剩余数量: {message.quantity_remaining}")
def on_fill(message: FillMessage):
"""成交消息回调"""
logger.info(f"收到成交消息:")
logger.info(f" 主订单ID: {message.master_order_id}")
logger.info(f" 订单ID: {message.order_id}")
logger.info(f" 交易对: {message.symbol}")
logger.info(f" 方向: {message.side}")
logger.info(f" 成交价格: {message.fill_price}")
logger.info(f" 成交数量: {message.filled_qty}")
logger.info(f" 成交时间: {message.fill_time}")
def on_raw_message(message):
"""原始消息回调"""
logger.debug(f"收到原始消息: {message.type} - {message.data}")
def main():
"""主函数"""
# 创建API客户端
api = API(
api_key="your_api_key",
api_secret="your_api_secret",
base_url="https://test.quantumexecute.com"
)
# 创建WebSocket事件处理器
handlers = WebSocketEventHandlers(
on_connected=on_connected,
on_disconnected=on_disconnected,
on_error=on_error,
on_status=on_status,
on_master_order=on_master_order,
on_order=on_order,
on_fill=on_fill,
on_raw_message=on_raw_message
)
# 创建WebSocket服务
ws_service = WebSocketService(api)
ws_service.set_handlers(handlers)
# 设置连接参数
ws_service.set_reconnect_delay(5.0) # 重连延迟5秒
ws_service.set_ping_interval(30.0) # 心跳间隔30秒
ws_service.set_pong_timeout(10.0) # Pong超时10秒
try:
# 获取listen_key
listen_key_result = api.create_listen_key()
if not listen_key_result.get('success'):
logger.error(f"创建ListenKey失败: {listen_key_result.get('message')}")
return
listen_key = listen_key_result['listenKey']
# 连接WebSocket
logger.info("正在连接WebSocket...")
ws_service.connect(listen_key)
# 等待连接建立
time.sleep(2)
if ws_service.is_connected():
logger.info("WebSocket连接已建立,开始接收消息...")
# 保持连接运行
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
logger.info("收到中断信号,正在关闭连接...")
else:
logger.error("WebSocket连接失败")
except Exception as e:
logger.error(f"发生错误: {e}")
finally:
# 关闭WebSocket连接
ws_service.close()
logger.info("WebSocket连接已关闭")
if __name__ == "__main__":
main()
```
#### 消息类型说明
**客户端推送消息类型:**
| 消息类型 | 描述 |
|----------|------|
| data | 数据消息 |
| status | 状态消息 |
| error | 错误消息 |
| master_data | 主订单数据 |
| order_data | 订单数据 |
**第三方消息类型:**
| 消息类型 | 描述 |
|----------|------|
| master_order | 主订单消息 |
| order | 子订单消息 |
| fill | 成交消息 |
#### 配置选项
```python
# 设置重连延迟
ws_service.set_reconnect_delay(10.0) # 10秒
# 设置心跳间隔
ws_service.set_ping_interval(2.0) # 2秒
# 设置Pong超时时间
ws_service.set_pong_timeout(15.0) # 15秒
# 设置日志记录器
import logging
logger = logging.getLogger("websocket")
ws_service.set_logger(logger)
```
#### 连接状态管理
```python
# 检查连接状态
if ws_service.is_connected():
print("WebSocket 已连接")
else:
print("WebSocket 未连接")
# 手动重连
if not ws_service.is_connected():
listen_key = "your-listen-key"
ws_service.connect(listen_key)
```
#### 错误处理
```python
def on_error(error):
"""错误回调"""
logger.error(f"WebSocket 错误: {error}")
# 根据错误类型进行处理
if "connection refused" in str(error).lower():
logger.error("连接被拒绝,可能是服务器不可用")
elif "authentication failed" in str(error).lower():
logger.error("认证失败,请检查 ListenKey 是否有效")
elif "timeout" in str(error).lower():
logger.error("连接超时,请检查网络连接")
```
#### 生产环境使用建议
1. **自动重连机制**:SDK 已内置自动重连功能,无需手动实现
2. **ListenKey 管理**:定期检查 ListenKey 有效性,接近过期时主动刷新
3. **错误监控**:实现完善的错误日志记录和监控
4. **负载均衡**:考虑使用多个 WebSocket 连接分散负载
5. **消息去重**:根据 `messageId` 实现消息去重处理
#### 高级用法示例
```python
class TradingBot:
def __init__(self, api_key, api_secret):
self.api = API(api_key, api_secret)
self.ws_service = None
self.listen_key = None
def start_websocket(self):
"""启动WebSocket连接"""
# 创建ListenKey
result = self.api.create_listen_key()
if not result.get('success'):
raise Exception(f"创建ListenKey失败: {result.get('message')}")
self.listen_key = result['listenKey']
# 创建事件处理器
handlers = WebSocketEventHandlers(
on_connected=self._on_connected,
on_disconnected=self._on_disconnected,
on_error=self._on_error,
on_master_order=self._on_master_order,
on_order=self._on_order,
on_fill=self._on_fill
)
# 创建WebSocket服务
self.ws_service = WebSocketService(self.api)
self.ws_service.set_handlers(handlers)
# 连接
self.ws_service.connect(self.listen_key)
def _on_connected(self):
print("交易机器人已连接")
def _on_disconnected(self):
print("交易机器人连接断开")
def _on_error(self, error):
print(f"交易机器人错误: {error}")
def _on_master_order(self, message):
print(f"主订单更新: {message.master_order_id} - {message.status}")
def _on_order(self, message):
print(f"子订单更新: {message.order_id} - {message.status}")
def _on_fill(self, message):
print(f"成交通知: {message.order_id} - {message.filled_qty} @ {message.fill_price}")
def stop(self):
"""停止WebSocket连接"""
if self.ws_service:
self.ws_service.close()
# 使用示例
bot = TradingBot("your-api-key", "your-api-secret")
bot.start_websocket()
# 保持运行
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
print("正在停止...")
bot.stop()
```
## 常见问题
### 1. 如何获取 API 密钥?
请登录 Quantum Execute 平台,在用户设置中创建 API 密钥。
### 2. 如何处理时间格式?
时间格式使用 ISO 8601 标准,例如:
- UTC 时间:`2024-01-01T10:00:00Z`
- 带时区:`2024-01-01T18:00:00+08:00`
### 3. 订单类型说明
- **TWAP (Time Weighted Average Price)**:时间加权平均价格算法,在指定时间段内平均分配订单
- **VWAP (Volume Weighted Average Price)**:成交量加权平均价格算法,根据市场成交量分布执行订单
- **POV (Percentage of Volume)**:成交量百分比算法,保持占市场成交量的固定比例
### 4. 枚举值说明
**算法类型 (Algorithm):**
| 枚举值 | 描述 |
|--------|------|
| TWAP | TWAP算法 |
| VWAP | VWAP算法 |
| POV | POV算法 |
**市场类型 (MarketType):**
| 枚举值 | 描述 |
|--------|------|
| SPOT | 现货市场 |
| PERP | 合约市场 |
**订单方向 (OrderSide):**
| 枚举值 | 描述 |
|--------|------|
| buy | 买入 |
| sell | 卖出 |
**交易所 (Exchange):**
| 枚举值 | 描述 |
|--------|------|
| Binance | 币安 |
**保证金类型 (MarginType):**
| 枚举值 | 描述 |
|--------|------|
| U | U本位 |
**母单状态 (MasterOrderStatus):**
| 枚举值 | 描述 |
|--------|------|
| NEW | 执行中 |
| COMPLETED | 已完成 |
**交易对市场类型 (TradingPairMarketType):**
| 枚举值 | 描述 |
|--------|------|
| SPOT | 现货品种 |
| FUTURES | 期货品种 |
### 5. 公共接口使用说明
**Status 接口(无需认证):**
- `ping()`: 测试服务器连通性
- `timestamp()`: 获取服务器时间戳
**Pub 接口(无需认证):**
- `trading_pairs()`: 获取交易对列表,支持各种筛选条件
**User 接口(需要认证):**
- 所有交易相关功能都需要有效的 API 密钥
### 6. 枚举类型使用建议
推荐使用枚举类型而不是字符串,这样可以获得:
- 类型安全:编译时检查参数正确性
- 代码提示:IDE 可以提供自动补全
- 避免拼写错误:减少因字符串拼写错误导致的错误
```python
# 推荐使用枚举
from qe.lib import TradingPairMarketType
# 使用枚举
pairs = pub_client.trading_pairs(marketType=TradingPairMarketType.SPOT)
# 不推荐使用字符串
pairs = pub_client.trading_pairs(marketType="SPOT")
```
### 7. WebSocket 相关说明
**WebSocket 连接地址:**
- `wss://test.quantumexecute.com/api/ws?listen_key={listenKey}`
**支持的消息类型:**
- 主订单状态更新(`master_order`)
- 子订单变化(`order`)
- 成交明细(`fill`)
- 系统状态消息(`status`)
- 错误消息(`error`)
**连接管理:**
- SDK 自动处理心跳检测和重连
- 支持自定义重连延迟、心跳间隔等参数
- 提供连接状态查询接口
**消息处理:**
- 支持结构化消息解析
- 提供原始消息访问接口
- 支持自定义错误处理逻辑
**性能优化建议:**
- 避免在消息处理器中执行耗时操作
- 使用异步处理消息,避免阻塞主连接
- 合理设置心跳参数,平衡实时性和资源消耗
**WebSocket 使用示例:**
```python
from qe import API, WebSocketService, WebSocketEventHandlers
# 创建API客户端
api = API("your-api-key", "your-api-secret")
# 创建WebSocket服务
ws_service = WebSocketService(api)
# 设置事件处理器
handlers = WebSocketEventHandlers(
on_connected=lambda: print("连接成功"),
on_disconnected=lambda: print("连接断开"),
on_error=lambda e: print(f"错误: {e}"),
on_master_order=lambda msg: print(f"主订单: {msg.master_order_id}"),
on_order=lambda msg: print(f"子订单: {msg.order_id}"),
on_fill=lambda msg: print(f"成交: {msg.filled_qty}")
)
ws_service.set_handlers(handlers)
# 获取ListenKey并连接
listen_key = api.create_listen_key()['listenKey']
ws_service.connect(listen_key)
# 保持连接
import time
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
ws_service.close()
```
## 贡献指南
欢迎提交 Issue 和 Pull Request!
## 联系我们
- 官网:[https://test.quantumexecute.com](https://test.quantumexecute.com)
- 邮箱:support@quantumexecute.com
- GitHub:[https://github.com/Quantum-Execute/qe-connector-python](https://github.com/Quantum-Execute/qe-connector-python)
Raw data
{
"_id": null,
"home_page": "https://github.com/Quantum-Execute/qe-connector-python",
"name": "qe-connector",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "Quantum-Execute, Public API",
"author": "Quantum-Execute",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/79/fa/3adabd3eb42aeb3f0b538c1913b72564ffdd085f52991df9f7106f4565ff/qe-connector-1.0.6.tar.gz",
"platform": null,
"description": "# Quantum Execute Python SDK\r\n\r\n[](https://pypi.org/project/qe-connector/)\r\n[](https://pypi.org/project/qe-connector/)\r\n[](https://opensource.org/licenses/MIT)\r\n\r\n\u8fd9\u662f Quantum Execute \u516c\u5171 API \u7684\u5b98\u65b9 Python SDK\uff0c\u4e3a\u5f00\u53d1\u8005\u63d0\u4f9b\u4e86\u4e00\u4e2a\u8f7b\u91cf\u7ea7\u3001\u6613\u4e8e\u4f7f\u7528\u7684\u63a5\u53e3\u6765\u8bbf\u95ee Quantum Execute \u7684\u4ea4\u6613\u670d\u52a1\u3002\r\n\r\n## \u529f\u80fd\u7279\u6027\r\n\r\n- \u2705 \u5b8c\u6574\u7684 Quantum Execute API \u652f\u6301\r\n- \u2705 \u4ea4\u6613\u6240 API \u5bc6\u94a5\u7ba1\u7406\r\n- \u2705 \u4e3b\u8ba2\u5355\u521b\u5efa\u4e0e\u7ba1\u7406\uff08TWAP\u3001VWAP\u3001POV \u7b49\u7b97\u6cd5\uff09\r\n- \u2705 \u8ba2\u5355\u67e5\u8be2\u548c\u6210\u4ea4\u660e\u7ec6\r\n- \u2705 ListenKey \u521b\u5efa\u4e0e\u7ba1\u7406\r\n- \u2705 \u4ea4\u6613\u5bf9\u4fe1\u606f\u67e5\u8be2\r\n- \u2705 \u670d\u52a1\u5668\u8fde\u901a\u6027\u6d4b\u8bd5\r\n- \u2705 \u670d\u52a1\u5668\u65f6\u95f4\u540c\u6b65\r\n- \u2705 \u5b89\u5168\u7684 HMAC-SHA256 \u7b7e\u540d\u8ba4\u8bc1\r\n- \u2705 \u652f\u6301\u751f\u4ea7\u73af\u5883\u548c\u6d4b\u8bd5\u73af\u5883\r\n- \u2705 \u94fe\u5f0f\u8c03\u7528 API \u8bbe\u8ba1\r\n- \u2705 \u5b8c\u6574\u7684\u9519\u8bef\u5904\u7406\r\n\r\n## \u5b89\u88c5\r\n\r\n```bash\r\npip install qe-connector\r\n```\r\n\r\n\u6216\u8005\u4ece\u6e90\u7801\u5b89\u88c5\uff1a\r\n\r\n```bash\r\ngit clone https://github.com/Quantum-Execute/qe-connector-python.git\r\ncd qe-connector-python\r\npip install -e .\r\n```\r\n\r\n## \u5feb\u901f\u5f00\u59cb\r\n\r\n### \u521d\u59cb\u5316\u5ba2\u6237\u7aef\r\n\r\n```python\r\nfrom qe.user import User as Client\r\nimport logging\r\n\r\n# \u914d\u7f6e\u65e5\u5fd7\uff08\u53ef\u9009\uff09\r\nlogging.basicConfig(level=logging.INFO)\r\n\r\n# \u521b\u5efa\u751f\u4ea7\u73af\u5883\u5ba2\u6237\u7aef\r\nclient = Client(\r\n api_key=\"your-api-key\",\r\n api_secret=\"your-api-secret\"\r\n)\r\n\r\n# \u521b\u5efa\u6d4b\u8bd5\u73af\u5883\u5ba2\u6237\u7aef\r\nclient = Client(\r\n api_key=\"your-api-key\",\r\n api_secret=\"your-api-secret\",\r\n base_url=\"https://testapi.quantumexecute.com\"\r\n)\r\n```\r\n\r\n### \u4f7f\u7528\u679a\u4e3e\u7c7b\u578b\uff08\u63a8\u8350\uff09\r\n\r\nSDK \u63d0\u4f9b\u4e86\u679a\u4e3e\u7c7b\u578b\u6765\u786e\u4fdd\u7c7b\u578b\u5b89\u5168\u548c\u4ee3\u7801\u63d0\u793a\u3002\u63a8\u8350\u4f7f\u7528\u679a\u4e3e\u800c\u4e0d\u662f\u5b57\u7b26\u4e32\uff1a\r\n\r\n```python\r\n# \u5bfc\u5165\u679a\u4e3e\u7c7b\u578b\r\nfrom qe.lib import Algorithm, Exchange, MarketType, OrderSide, StrategyType, MarginType\r\n\r\n# \u53ef\u7528\u7684\u679a\u4e3e\u503c\r\nprint(\"\u7b97\u6cd5\u7c7b\u578b:\", [algo.value for algo in Algorithm]) # ['TWAP', 'VWAP', 'POV']\r\nprint(\"\u4ea4\u6613\u6240:\", [exchange.value for exchange in Exchange]) # ['Binance']\r\nprint(\"\u5e02\u573a\u7c7b\u578b:\", [market.value for market in MarketType]) # ['SPOT', 'PERP']\r\nprint(\"\u8ba2\u5355\u65b9\u5411:\", [side.value for side in OrderSide]) # ['buy', 'sell']\r\nprint(\"\u7b56\u7565\u7c7b\u578b:\", [strategy.value for strategy in StrategyType]) # ['TWAP_1', 'POV']\r\nprint(\"\u4fdd\u8bc1\u91d1\u7c7b\u578b:\", [margin.value for margin in MarginType]) # ['U']\r\n\r\n# \u4f7f\u7528\u679a\u4e3e\u521b\u5efa\u8ba2\u5355\uff08\u63a8\u8350\uff09\r\nresponse = client.create_master_order(\r\n algorithm=Algorithm.TWAP, # \u800c\u4e0d\u662f \"TWAP\"\r\n exchange=Exchange.BINANCE, # \u800c\u4e0d\u662f \"Binance\"\r\n marketType=MarketType.SPOT, # \u800c\u4e0d\u662f \"SPOT\"\r\n side=OrderSide.BUY, # \u800c\u4e0d\u662f \"buy\"\r\n # ... \u5176\u4ed6\u53c2\u6570\r\n)\r\n```\r\n\r\n## API \u53c2\u8003\r\n\r\n### \u516c\u5171\u63a5\u53e3\r\n\r\n#### \u670d\u52a1\u5668\u8fde\u901a\u6027\u6d4b\u8bd5\r\n\r\n##### Ping \u670d\u52a1\u5668\r\n\r\n\u6d4b\u8bd5\u4e0e Quantum Execute \u670d\u52a1\u5668\u7684\u8fde\u901a\u6027\u3002\r\n\r\n**\u8bf7\u6c42\u53c2\u6570\uff1a**\r\n\r\n| \u53c2\u6570\u540d | \u7c7b\u578b | \u662f\u5426\u5fc5\u4f20 | \u63cf\u8ff0 |\r\n|--------|------|----------|------|\r\n| \u65e0\u9700\u53c2\u6570 | - | - | - |\r\n\r\n**\u54cd\u5e94\uff1a**\r\n\r\n\u6210\u529f\u65f6\u65e0\u8fd4\u56de\u5185\u5bb9\uff0c\u5931\u8d25\u65f6\u8fd4\u56de\u9519\u8bef\u4fe1\u606f\u3002\r\n\r\n**\u793a\u4f8b\u4ee3\u7801\uff1a**\r\n\r\n```python\r\nfrom qe.status import Status as StatusClient\r\n\r\n# \u521b\u5efa\u72b6\u6001\u5ba2\u6237\u7aef\uff08\u65e0\u9700\u8ba4\u8bc1\uff09\r\nstatus_client = StatusClient()\r\n\r\n# \u6d4b\u8bd5\u670d\u52a1\u5668\u8fde\u901a\u6027\r\ntry:\r\n status_client.ping()\r\n print(\"\u670d\u52a1\u5668\u8fde\u63a5\u6b63\u5e38\")\r\nexcept Exception as e:\r\n print(f\"\u670d\u52a1\u5668\u8fde\u63a5\u5931\u8d25: {e}\")\r\n```\r\n\r\n#### \u83b7\u53d6\u670d\u52a1\u5668\u65f6\u95f4\r\n\r\n##### \u67e5\u8be2\u670d\u52a1\u5668\u65f6\u95f4\u6233\r\n\r\n\u83b7\u53d6 Quantum Execute \u670d\u52a1\u5668\u7684\u5f53\u524d\u65f6\u95f4\u6233\uff08\u6beb\u79d2\uff09\u3002\r\n\r\n**\u8bf7\u6c42\u53c2\u6570\uff1a**\r\n\r\n| \u53c2\u6570\u540d | \u7c7b\u578b | \u662f\u5426\u5fc5\u4f20 | \u63cf\u8ff0 |\r\n|--------|------|----------|------|\r\n| \u65e0\u9700\u53c2\u6570 | - | - | - |\r\n\r\n**\u54cd\u5e94\u5b57\u6bb5\uff1a**\r\n\r\n| \u5b57\u6bb5\u540d | \u7c7b\u578b | \u63cf\u8ff0 |\r\n|--------|------|------|\r\n| serverTimeMilli | int | \u670d\u52a1\u5668\u65f6\u95f4\u6233\uff08\u6beb\u79d2\uff09 |\r\n\r\n**\u793a\u4f8b\u4ee3\u7801\uff1a**\r\n\r\n```python\r\nfrom qe.status import Status as StatusClient\r\nimport datetime\r\n\r\n# \u521b\u5efa\u72b6\u6001\u5ba2\u6237\u7aef\r\nstatus_client = StatusClient()\r\n\r\n# \u83b7\u53d6\u670d\u52a1\u5668\u65f6\u95f4\u6233\r\ntry:\r\n timestamp = status_client.timestamp()\r\n print(f\"\u670d\u52a1\u5668\u65f6\u95f4\u6233: {timestamp}\")\r\n \r\n # \u8f6c\u6362\u4e3a\u53ef\u8bfb\u65f6\u95f4\u683c\u5f0f\r\n readable_time = datetime.datetime.fromtimestamp(timestamp / 1000)\r\n print(f\"\u670d\u52a1\u5668\u65f6\u95f4: {readable_time}\")\r\nexcept Exception as e:\r\n print(f\"\u83b7\u53d6\u65f6\u95f4\u6233\u5931\u8d25: {e}\")\r\n```\r\n\r\n#### \u4ea4\u6613\u5bf9\u7ba1\u7406\r\n\r\n##### \u67e5\u8be2\u4ea4\u6613\u5bf9\u5217\u8868\r\n\r\n\u83b7\u53d6\u652f\u6301\u7684\u4ea4\u6613\u5bf9\u4fe1\u606f\uff0c\u5305\u62ec\u73b0\u8d27\u548c\u5408\u7ea6\u4ea4\u6613\u5bf9\u3002\r\n\r\n**\u8bf7\u6c42\u53c2\u6570\uff1a**\r\n\r\n| \u53c2\u6570\u540d | \u7c7b\u578b | \u662f\u5426\u5fc5\u4f20 | \u63cf\u8ff0 |\r\n|--------|------|----------|------|\r\n| page | int | \u5426 | \u9875\u7801 |\r\n| pageSize | int | \u5426 | \u6bcf\u9875\u6570\u91cf |\r\n| exchange | str | \u5426 | \u4ea4\u6613\u6240\u540d\u79f0\u7b5b\u9009 |\r\n| marketType | str/TradingPairMarketType | \u5426 | \u5e02\u573a\u7c7b\u578b\u7b5b\u9009\uff0c\u53ef\u9009\u503c\uff1aSPOT\uff08\u73b0\u8d27\uff09\u3001FUTURES\uff08\u5408\u7ea6\uff09 |\r\n| isCoin | bool | \u5426 | \u662f\u5426\u4e3a\u5e01\u79cd\u7b5b\u9009 |\r\n\r\n**\u54cd\u5e94\u5b57\u6bb5\uff1a**\r\n\r\n| \u5b57\u6bb5\u540d | \u7c7b\u578b | \u63cf\u8ff0 |\r\n|--------|------|------|\r\n| items | array | \u4ea4\u6613\u5bf9\u5217\u8868 |\r\n| \u251c\u2500 id | int | \u4ea4\u6613\u5bf9 ID |\r\n| \u251c\u2500 symbol | string | \u4ea4\u6613\u5bf9\u7b26\u53f7\uff08\u5982\uff1aBTCUSDT\uff09 |\r\n| \u251c\u2500 baseAsset | string | \u57fa\u7840\u5e01\u79cd\uff08\u5982\uff1aBTC\uff09 |\r\n| \u251c\u2500 quoteAsset | string | \u8ba1\u4ef7\u5e01\u79cd\uff08\u5982\uff1aUSDT\uff09 |\r\n| \u251c\u2500 exchange | string | \u4ea4\u6613\u6240\u540d\u79f0 |\r\n| \u251c\u2500 marketType | string | \u5e02\u573a\u7c7b\u578b\uff08SPOT/FUTURES\uff09 |\r\n| \u251c\u2500 contractType | string | \u5408\u7ea6\u7c7b\u578b\uff08\u4ec5\u5408\u7ea6\u4ea4\u6613\u5bf9\uff09 |\r\n| \u251c\u2500 deliveryDate | string | \u4ea4\u5272\u65e5\u671f\uff08\u4ec5\u5408\u7ea6\u4ea4\u6613\u5bf9\uff09 |\r\n| \u251c\u2500 status | string | \u4ea4\u6613\u5bf9\u72b6\u6001 |\r\n| \u251c\u2500 createdAt | string | \u521b\u5efa\u65f6\u95f4 |\r\n| \u251c\u2500 updatedAt | string | \u66f4\u65b0\u65f6\u95f4 |\r\n| page | int | \u5f53\u524d\u9875\u7801 |\r\n| pageSize | int | \u6bcf\u9875\u6570\u91cf |\r\n| total | string | \u603b\u6570 |\r\n\r\n**\u793a\u4f8b\u4ee3\u7801\uff1a**\r\n\r\n```python\r\nfrom qe.pub import Pub as PubClient\r\nfrom qe.lib import TradingPairMarketType\r\n\r\n# \u521b\u5efa\u516c\u5171\u5ba2\u6237\u7aef\uff08\u65e0\u9700\u8ba4\u8bc1\uff09\r\npub_client = PubClient()\r\n\r\n# \u83b7\u53d6\u6240\u6709\u4ea4\u6613\u5bf9\r\ntry:\r\n pairs = pub_client.trading_pairs()\r\n print(f\"\u603b\u4ea4\u6613\u5bf9\u6570\u91cf: {pairs.get('total', 0)}\")\r\n \r\n # \u6253\u5370\u524d\u51e0\u4e2a\u4ea4\u6613\u5bf9\u4fe1\u606f\r\n for pair in pairs.get('items', [])[:5]:\r\n print(f\"\"\"\r\n\u4ea4\u6613\u5bf9\u4fe1\u606f\uff1a\r\n \u7b26\u53f7: {pair['symbol']}\r\n \u57fa\u7840\u5e01\u79cd: {pair['baseAsset']}\r\n \u8ba1\u4ef7\u5e01\u79cd: {pair['quoteAsset']}\r\n \u4ea4\u6613\u6240: {pair['exchange']}\r\n \u5e02\u573a\u7c7b\u578b: {pair['marketType']}\r\n \u72b6\u6001: {pair['status']}\r\n \u521b\u5efa\u65f6\u95f4: {pair['createdAt']}\r\n \"\"\")\r\n \r\n # \u5982\u679c\u662f\u5408\u7ea6\u4ea4\u6613\u5bf9\uff0c\u663e\u793a\u989d\u5916\u4fe1\u606f\r\n if pair['marketType'] == 'FUTURES':\r\n print(f\" \u5408\u7ea6\u7c7b\u578b: {pair.get('contractType', 'N/A')}\")\r\n if pair.get('deliveryDate'):\r\n print(f\" \u4ea4\u5272\u65e5\u671f: {pair['deliveryDate']}\")\r\n \r\nexcept Exception as e:\r\n print(f\"\u83b7\u53d6\u4ea4\u6613\u5bf9\u5931\u8d25: {e}\")\r\n\r\n# \u4f7f\u7528\u679a\u4e3e\u7c7b\u578b\u7b5b\u9009\uff08\u63a8\u8350\uff09\r\ntry:\r\n # \u83b7\u53d6\u5e01\u5b89\u73b0\u8d27\u4ea4\u6613\u5bf9\r\n spot_pairs = pub_client.trading_pairs(\r\n exchange=\"Binance\",\r\n marketType=TradingPairMarketType.SPOT, # \u4f7f\u7528\u679a\u4e3e\r\n page=1,\r\n pageSize=10\r\n )\r\n print(f\"\u5e01\u5b89\u73b0\u8d27\u4ea4\u6613\u5bf9\u6570\u91cf: {len(spot_pairs.get('items', []))}\")\r\n \r\n # \u83b7\u53d6\u5408\u7ea6\u4ea4\u6613\u5bf9\r\n futures_pairs = pub_client.trading_pairs(\r\n marketType=TradingPairMarketType.FUTURES, # \u4f7f\u7528\u679a\u4e3e\r\n page=1,\r\n pageSize=20\r\n )\r\n print(f\"\u5408\u7ea6\u4ea4\u6613\u5bf9\u6570\u91cf: {len(futures_pairs.get('items', []))}\")\r\n \r\n # \u83b7\u53d6\u5e01\u79cd\u4ea4\u6613\u5bf9\r\n coin_pairs = pub_client.trading_pairs(isCoin=True)\r\n print(f\"\u5e01\u79cd\u4ea4\u6613\u5bf9\u6570\u91cf: {len(coin_pairs.get('items', []))}\")\r\n \r\nexcept Exception as e:\r\n print(f\"\u7b5b\u9009\u4ea4\u6613\u5bf9\u5931\u8d25: {e}\")\r\n\r\n# \u4f7f\u7528\u5b57\u7b26\u4e32\u7b5b\u9009\uff08\u5411\u540e\u517c\u5bb9\uff09\r\ntry:\r\n # \u4f7f\u7528\u5b57\u7b26\u4e32\u53c2\u6570\r\n spot_pairs = pub_client.trading_pairs(\r\n exchange=\"Binance\",\r\n marketType=\"SPOT\", # \u4f7f\u7528\u5b57\u7b26\u4e32\r\n page=1,\r\n pageSize=5\r\n )\r\n print(f\"\u73b0\u8d27\u4ea4\u6613\u5bf9\u6570\u91cf: {len(spot_pairs.get('items', []))}\")\r\n \r\nexcept Exception as e:\r\n print(f\"\u83b7\u53d6\u73b0\u8d27\u4ea4\u6613\u5bf9\u5931\u8d25: {e}\")\r\n```\r\n\r\n### \u4ea4\u6613\u6240 API \u7ba1\u7406\r\n\r\n#### \u67e5\u8be2\u4ea4\u6613\u6240 API \u5217\u8868\r\n\r\n\u67e5\u8be2\u5f53\u524d\u7528\u6237\u7ed1\u5b9a\u7684\u6240\u6709\u4ea4\u6613\u6240 API \u8d26\u6237\u3002\r\n\r\n**\u8bf7\u6c42\u53c2\u6570\uff1a**\r\n\r\n| \u53c2\u6570\u540d | \u7c7b\u578b | \u662f\u5426\u5fc5\u4f20 | \u63cf\u8ff0 |\r\n|--------|------|----------|------|\r\n| page | int | \u5426 | \u9875\u7801 |\r\n| pageSize | int | \u5426 | \u6bcf\u9875\u6570\u91cf |\r\n| exchange | str | \u5426 | \u4ea4\u6613\u6240\u540d\u79f0\u7b5b\u9009 |\r\n\r\n**\u54cd\u5e94\u5b57\u6bb5\uff1a**\r\n\r\n| \u5b57\u6bb5\u540d | \u7c7b\u578b | \u63cf\u8ff0 |\r\n|--------|------|------|\r\n| items | array | API \u5217\u8868 |\r\n| \u251c\u2500 id | string | API \u8bb0\u5f55\u7684\u552f\u4e00\u6807\u8bc6 |\r\n| \u251c\u2500 createdAt | string | API \u6dfb\u52a0\u65f6\u95f4 |\r\n| \u251c\u2500 accountName | string | \u8d26\u6237\u540d\u79f0\uff08\u5982\uff1a\u8d26\u62371\u3001\u8d26\u62372\uff09 |\r\n| \u251c\u2500 exchange | string | \u4ea4\u6613\u6240\u540d\u79f0\uff08\u5982\uff1aBinance\u3001OKX\u3001Bybit\uff09 |\r\n| \u251c\u2500 apiKey | string | \u4ea4\u6613\u6240 API Key\uff08\u90e8\u5206\u9690\u85cf\uff09 |\r\n| \u251c\u2500 verificationMethod | string | API \u9a8c\u8bc1\u65b9\u5f0f\uff08\u5982\uff1aOAuth\u3001API\uff09 |\r\n| \u251c\u2500 balance | float | \u8d26\u6237\u4f59\u989d\uff08\u7f8e\u5143\uff09 |\r\n| \u251c\u2500 status | string | API \u72b6\u6001\uff1a\u6b63\u5e38\u3001\u5f02\u5e38\uff08\u4e0d\u53ef\u7528\uff09 |\r\n| \u251c\u2500 isValid | bool | API \u662f\u5426\u6709\u6548 |\r\n| \u251c\u2500 isTradingEnabled | bool | \u662f\u5426\u5f00\u542f\u4ea4\u6613\u6743\u9650 |\r\n| \u251c\u2500 isDefault | bool | \u662f\u5426\u4e3a\u8be5\u4ea4\u6613\u6240\u7684\u9ed8\u8ba4\u8d26\u6237 |\r\n| \u251c\u2500 isPm | bool | \u662f\u5426\u4e3a Pm \u8d26\u6237 |\r\n| total | int | API \u603b\u6570 |\r\n| page | int | \u5f53\u524d\u9875\u7801 |\r\n| pageSize | int | \u6bcf\u9875\u663e\u793a\u6570\u91cf |\r\n\r\n**\u793a\u4f8b\u4ee3\u7801\uff1a**\r\n\r\n```python\r\n# \u83b7\u53d6\u6240\u6709\u4ea4\u6613\u6240 API \u5bc6\u94a5\r\napis = client.list_exchange_apis()\r\nprint(f\"\u5171\u6709 {apis['total']} \u4e2a API \u5bc6\u94a5\")\r\n\r\n# \u6253\u5370\u6bcf\u4e2a API \u7684\u8be6\u7ec6\u4fe1\u606f\r\nfor api in apis['items']:\r\n print(f\"\"\"\r\nAPI \u4fe1\u606f\uff1a\r\n \u8d26\u6237: {api['accountName']}\r\n \u4ea4\u6613\u6240: {api['exchange']}\r\n \u72b6\u6001: {api['status']}\r\n \u4f59\u989d: ${api['balance']:.2f}\r\n \u4ea4\u6613\u6743\u9650: {'\u5f00\u542f' if api['isTradingEnabled'] else '\u5173\u95ed'}\r\n \u662f\u5426\u9ed8\u8ba4: {'\u662f' if api['isDefault'] else '\u5426'}\r\n \u662f\u5426PM\u8d26\u6237: {'\u662f' if api['isPm'] else '\u5426'}\r\n \u6dfb\u52a0\u65f6\u95f4: {api['createdAt']}\r\n \"\"\")\r\n\r\n# \u5e26\u5206\u9875\u548c\u8fc7\u6ee4\r\napis = client.list_exchange_apis(\r\n page=1,\r\n pageSize=10,\r\n exchange=\"binance\"\r\n)\r\n```\r\n\r\n### \u4ea4\u6613\u8ba2\u5355\u7ba1\u7406\r\n\r\n#### \u521b\u5efa\u4e3b\u8ba2\u5355\r\n\r\n\u521b\u5efa\u65b0\u7684\u4e3b\u8ba2\u5355\u5e76\u63d0\u4ea4\u5230\u7b97\u6cd5\u4fa7\u6267\u884c\u3002\r\n\r\n**\u8bf7\u6c42\u53c2\u6570\uff1a**\r\n\r\n| \u53c2\u6570\u540d | \u7c7b\u578b | \u662f\u5426\u5fc5\u4f20 | \u63cf\u8ff0 |\r\n|--------|------|------|------|\r\n| **\u57fa\u7840\u53c2\u6570** |\r\n| strategyType | string/StrategyType | \u662f | \u7b56\u7565\u7c7b\u578b\uff0c\u53ef\u9009\u503c\uff1aTWAP-1\u3001POV |\r\n| algorithm | string/Algorithm | \u662f | \u4ea4\u6613\u7b97\u6cd5\u3002strategyType=TWAP-1\u65f6\uff0c\u53ef\u9009\u503c\uff1aTWAP\u3001VWAP\uff1bstrategyType=POV\u65f6\uff0c\u53ef\u9009\u503c\uff1aPOV |\r\n| exchange | string/Exchange | \u662f | \u4ea4\u6613\u6240\u540d\u79f0\uff0c\u53ef\u9009\u503c\uff1aBinance |\r\n| symbol | string | \u662f | \u4ea4\u6613\u5bf9\u7b26\u53f7\uff08\u5982\uff1aBTCUSDT\uff09\uff08\u53ef\u7528\u4ea4\u6613\u5bf9\u67e5\u8be2\uff09 |\r\n| marketType | string/MarketType | \u662f | \u53ef\u9009\u503c\uff1aSPOT\uff08\u73b0\u8d27\uff09\u3001PERP\uff08\u6c38\u7eed\u5408\u7ea6\uff09 |\r\n| side | string/OrderSide | \u662f | 1.\u5982\u679cisTargetPosition=False\uff1aside\u4ee3\u8868\u4ea4\u6613\u65b9\u5411\uff0c\u53ef\u9009\u503c\uff1abuy\uff08\u4e70\u5165\uff09\u3001sell\uff08\u5356\u51fa\uff09\uff1b\u5408\u7ea6\u4ea4\u6613\u65f6\u53ef\u4e0ereduceOnly\u7ec4\u5408\uff0creduceOnly=True\u65f6\uff1abuy\u4ee3\u8868\u4e70\u5165\u5e73\u7a7a\uff0csell\u4ee3\u8868\u5356\u51fa\u5e73\u591a\u30022.\u5982\u679cisTargetPosition=True\uff1aside\u4ee3\u8868\u4ed3\u4f4d\u65b9\u5411\uff0c\u53ef\u9009\u503c\uff1abuy\uff08\u591a\u5934\uff09\u3001sell\uff08\u7a7a\u5934\uff09\u3002\u3010\u4ec5\u5408\u7ea6\u4ea4\u6613\u65f6\u9700\u4f20\u5165\u3011 |\r\n| apiKeyId | string | \u662f | \u6307\u5b9a\u4f7f\u7528\u7684 API Key ID\uff0c\u8fd9\u5c06\u51b3\u5b9a\u60a8\u672c\u6b21\u4e0b\u5355\u4f7f\u7528\u54ea\u4e2a\u4ea4\u6613\u6240\u8d26\u6237\u6267\u884c |\r\n| **\u6570\u91cf\u53c2\u6570\uff08\u4e8c\u9009\u4e00\uff09** |\r\n| totalQuantity | float64 | \u5426* | \u8981\u4ea4\u6613\u7684\u603b\u6570\u91cf\uff0c\u652f\u6301\u5b57\u7b26\u4e32\u8868\u793a\u4ee5\u907f\u514d\u7cbe\u5ea6\u95ee\u9898\uff0c\u4e0e orderNotional \u4e8c\u9009\u4e00\uff0c\u8f93\u5165\u8303\u56f4\uff1a>0 |\r\n| orderNotional | float64 | \u5426* | \u6309\u4ef7\u503c\u4e0b\u5355\u65f6\u7684\u91d1\u989d\uff0c\u4ee5\u8ba1\u4ef7\u5e01\u79cd\u4e3a\u5355\u4f4d\uff08\u5982ETHUSDT\u4e3aUSDT\u6570\u91cf\uff09\uff0c\u4e0e totalQuantity \u4e8c\u9009\u4e00\uff0c\u8f93\u5165\u8303\u56f4\uff1a>0 |\r\n| **\u4e0b\u5355\u6a21\u5f0f\u53c2\u6570** |\r\n| isTargetPosition | bool | \u5426 | \u662f\u5426\u4e3a\u76ee\u6807\u4ed3\u4f4d\u4e0b\u5355\uff0c\u9ed8\u8ba4\u4e3a false |\r\n| **\u65f6\u95f4\u53c2\u6570** |\r\n| startTime | string | \u5426 | \u4ea4\u6613\u6267\u884c\u7684\u542f\u52a8\u65f6\u95f4\uff0c\u4f20\u5165\u683c\u5f0f\uff1aISO 8601(2025-09-03T01:30:00+08:00)\uff0c\u82e5\u4e0d\u4f20\u5165\uff0c\u5219\u7acb\u5373\u6267\u884c |\r\n| executionDuration | int32 | \u5426 | \u8ba2\u5355\u6700\u5927\u6267\u884c\u65f6\u957f\uff0c\u5206\u949f\uff0c\u8303\u56f4>=1 |\r\n| **TWAP/VWAP \u7b97\u6cd5\u53c2\u6570** |\r\n| mustComplete | bool | \u5426 | \u662f\u5426\u4e00\u5b9a\u8981\u5728executionDuration\u4e4b\u5185\u6267\u884c\u5b8c\u6bd5\uff0c\u9009false\u5219\u4e0d\u4f1a\u8ffd\u8d76\u8fdb\u5ea6\uff0c\u9ed8\u8ba4\uff1atrue |\r\n| makerRateLimit | float64 | \u5426 | \u8981\u6c42maker\u5360\u6bd4\u8d85\u8fc7\u8be5\u503c\uff0c\u8f93\u5165\u8303\u56f4\uff1a0-1\uff08\u8f93\u51650.1\u4ee3\u886810%\uff09\uff0c\u9ed8\u8ba4\uff1a-1(\u7b97\u6cd5\u667a\u80fd\u8ba1\u7b97\u63a8\u8350\u503c\u6267\u884c) |\r\n| povLimit | string | \u5426 | \u5360\u5e02\u573a\u6210\u4ea4\u91cf\u6bd4\u4f8b\u4e0a\u9650\uff0c\u4f18\u5148\u7ea7\u4f4e\u4e8emustComplete\uff0c\u8f93\u5165\u8303\u56f4\uff1a0-1\uff08\u8f93\u51650.1\u4ee3\u886810%\uff09\uff0c\u9ed8\u8ba4\uff1a0.8 |\r\n| limitPrice | float64 | \u5426 | \u6700\u9ad8/\u4f4e\u5141\u8bb8\u4ea4\u6613\u7684\u4ef7\u683c\uff0c\u4e70\u5165\u65f6\u8be5\u5b57\u6bb5\u8c61\u5f81\u6700\u9ad8\u4e70\u5165\u4ef7\uff0c\u5356\u51fa\u65f6\u8be5\u5b57\u6bb5\u8c61\u5f81\u6700\u4f4e\u5356\u51fa\u4ef7\uff0c\u82e5\u5e02\u4ef7\u8d85\u51fa\u8303\u56f4\u5219\u505c\u6b62\u4ea4\u6613\uff0c\u8303\u56f4\uff1a>0\uff0c\u9ed8\u8ba4\uff1a-1\uff0c\u4ee3\u8868\u65e0\u9650\u5236 |\r\n| upTolerance | string | \u5426 | \u5141\u8bb8\u8d85\u51fa\u76ee\u6807\u8fdb\u5ea6\u7684\u6700\u5927\u5bb9\u5fcd\u5ea6\uff0c\u6bd4\u59820.1\u5c31\u662f\u6267\u884c\u8fc7\u7a0b\u4e2d\u5141\u8bb8\u6bd4\u76ee\u6807\u8fdb\u5ea6\u8d85\u51fa\u6bcd\u5355\u6570\u91cf\u768410%\uff0c\u8303\u56f4\uff1a0-1\uff08\u4e0d\u542b0\u30011\uff09\uff0c\u9ed8\u8ba4\uff1a-1\uff08\u5373\u65e0\u5bb9\u5fcd\uff09 |\r\n| lowTolerance | string | \u5426 | \u5141\u8bb8\u843d\u540e\u76ee\u6807\u8fdb\u5ea6\u7684\u6700\u5927\u5bb9\u5fcd\u5ea6\uff0c\u6bd4\u59820.1\u5c31\u662f\u6267\u884c\u8fc7\u7a0b\u4e2d\u5141\u8bb8\u6bd4\u76ee\u6807\u8fdb\u5ea6\u843d\u540e\u6bcd\u5355\u6570\u91cf\u768410%\uff0c\u8303\u56f4\uff1a0-1\uff08\u4e0d\u542b0\u30011\uff09\uff0c\u9ed8\u8ba4\uff1a-1\uff08\u5373\u65e0\u5bb9\u5fcd\uff09 |\r\n| strictUpBound | bool | \u5426 | \u8868\u8fbe\u662f\u5426\u8ffd\u6c42\u4e25\u683c\u5c0f\u4e8euptolerance\uff0c\u5f00\u542f\u540e\u53ef\u80fd\u4f1a\u628a\u5f88\u5c0f\u7684\u6bcd\u5355\u4e5f\u62c6\u7684\u5f88\u7ec6\uff0c\u4e0d\u5efa\u8bae\u5f00\u542f\uff0c\u9ed8\u8ba4\uff1afalse |\r\n| tailOrderProtection | bool | \u5426 | \u8ba2\u5355\u4f59\u91cf\u5c0f\u4e8e\u4ea4\u6613\u6240\u6700\u5c0f\u53d1\u5355\u91cf\u65f6\uff0c\u662f\u5426\u5fc5\u987btaker\u626b\u5b8c\uff0c\u5982\u679cfalse\uff0c\u5219\u8ba2\u5355\u4f59\u91cf\u5c0f\u4e8e\u4ea4\u6613\u6240\u6700\u5c0f\u53d1\u5355\u91cf\u65f6\uff0c\u8ba2\u5355\u7ed3\u675f\u6267\u884c\uff1b\u5982\u679ctrue\uff0c\u5219\u8ba2\u5355\u4f59\u91cf\u968f\u6700\u8fd1\u4e00\u7b14\u4e0b\u5355\u5168\u989d\u6267\u884c\uff08\u53ef\u80fd\u4f1a\u63d0\u9ad8Taker\u7387\uff09\uff0c\u9ed8\u8ba4\uff1atrue |\r\n| **POV \u7b97\u6cd5\u53c2\u6570** |\r\n| makerRateLimit | float64 | \u5426 | \u8981\u6c42maker\u5360\u6bd4\u8d85\u8fc7\u8be5\u503c\uff0c\u8f93\u5165\u8303\u56f4\uff1a0-1\uff08\u8f93\u51650.1\u4ee3\u886810%\uff09\uff0c\u9ed8\u8ba4\uff1a-1(\u7b97\u6cd5\u667a\u80fd\u8ba1\u7b97\u63a8\u8350\u503c\u6267\u884c) |\r\n| povLimit | string | \u5426 | \u5360\u5e02\u573a\u6210\u4ea4\u91cf\u6bd4\u4f8b\u4e0a\u9650\uff0c\u8f93\u5165\u8303\u56f4\uff1a0-0.5\uff08povMinLimit < max(povLimit-0.01,0)\uff09\uff0c\u9ed8\u8ba4\uff1a0 |\r\n| povMinLimit | float64 | \u5426 | \u5360\u5e02\u573a\u6210\u4ea4\u91cf\u6bd4\u4f8b\u4e0b\u9650\uff0c\u8303\u56f4\uff1a\u5c0f\u4e8emax(POVLimit-0.01,0)\uff0c\u9ed8\u8ba4\uff1a0\uff08\u5373\u65e0\u4e0b\u9650\uff09 |\r\n| limitPrice | float64 | \u5426 | \u6700\u9ad8/\u4f4e\u5141\u8bb8\u4ea4\u6613\u7684\u4ef7\u683c\uff0c\u4e70\u5165\u65f6\u8be5\u5b57\u6bb5\u8c61\u5f81\u6700\u9ad8\u4e70\u5165\u4ef7\uff0c\u5356\u51fa\u65f6\u8be5\u5b57\u6bb5\u8c61\u5f81\u6700\u4f4e\u5356\u51fa\u4ef7\uff0c\u82e5\u5e02\u4ef7\u8d85\u51fa\u8303\u56f4\u5219\u505c\u6b62\u4ea4\u6613\uff0c\u8303\u56f4\uff1a>0\uff0c\u9ed8\u8ba4\uff1a-1\uff0c\u4ee3\u8868\u65e0\u9650\u5236 |\r\n| strictUpBound | bool | \u5426 | \u662f\u5426\u8ffd\u6c42\u4e25\u683c\u5c0f\u4e8epovLimit\uff0c\u5f00\u542f\u540e\u53ef\u80fd\u4f1a\u628a\u5f88\u5c0f\u7684\u6bcd\u5355\u4e5f\u62c6\u7684\u5f88\u7ec6\uff0c\u6bd4\u598250u\u62c6\u621010\u4e2a5u\uff0c\u4e0d\u5efa\u8bae\u5f00\u542f\uff0c\u7b97\u6cd5\u7684\u6bcf\u4e2aorder\u4f1a\u6743\u8861\u76d8\u53e3\u6d41\u52a8\u6027\uff0c\u9ed8\u8ba4\uff1afalse |\r\n| tailOrderProtection | bool | \u5426 | \u8ba2\u5355\u4f59\u91cf\u5c0f\u4e8e\u4ea4\u6613\u6240\u6700\u5c0f\u53d1\u5355\u91cf\u65f6\uff0c\u662f\u5426\u5fc5\u987btaker\u626b\u5b8c\uff0c\u5982\u679cfalse\uff0c\u5219\u8ba2\u5355\u4f59\u91cf\u5c0f\u4e8e\u4ea4\u6613\u6240\u6700\u5c0f\u53d1\u5355\u91cf\u65f6\uff0c\u8ba2\u5355\u7ed3\u675f\u6267\u884c\uff1b\u5982\u679ctrue\uff0c\u5219\u8ba2\u5355\u4f59\u91cf\u968f\u6700\u8fd1\u4e00\u7b14\u4e0b\u5355\u5168\u989d\u6267\u884c\uff08\u53ef\u80fd\u4f1a\u63d0\u9ad8Taker\u7387\uff09\uff0c\u9ed8\u8ba4\uff1atrue |\r\n| **\u5176\u4ed6\u53c2\u6570** |\r\n| reduceOnly | bool | \u5426 | \u5408\u7ea6\u4ea4\u6613\u65f6\u662f\u5426\u4ec5\u51cf\u4ed3\uff0c\u9ed8\u8ba4\u503c\uff1afalse |\r\n| marginType | string/MarginType | \u5426 | \u5408\u7ea6\u4ea4\u6613\u4fdd\u8bc1\u91d1\u7c7b\u578b\uff0c\u53ef\u9009\u503c\uff1aU\uff08U\u672c\u4f4d\uff09\uff0c\u9ed8\u8ba4\uff1aU\uff08\u6682\u65f6\u53ea\u652f\u6301U\u672c\u4f4d\u6c38\u7eed\u5408\u7ea6\uff09 |\r\n| notes | string | \u5426 | \u8ba2\u5355\u5907\u6ce8 |\r\n\r\n*\u6ce8\uff1atotalQuantity \u548c orderNotional \u5fc5\u987b\u4f20\u5176\u4e2d\u4e00\u4e2a\uff0c\u4f46\u5f53 isTargetPosition \u4e3a true \u65f6\uff0ctotalQuantity \u5fc5\u586b\u4ee3\u8868\u76ee\u6807\u4ed3\u4f4d\u6570\u91cf\u4e14 orderNotional \u4e0d\u53ef\u586b \r\n\r\n**\u54cd\u5e94\u5b57\u6bb5\uff1a**\r\n\r\n| \u5b57\u6bb5\u540d | \u7c7b\u578b | \u63cf\u8ff0 |\r\n|--------|------|------|\r\n| masterOrderId | string | \u521b\u5efa\u6210\u529f\u7684\u4e3b\u8ba2\u5355 ID |\r\n| success | bool | \u521b\u5efa\u662f\u5426\u6210\u529f |\r\n| message | string | \u521b\u5efa\u7ed3\u679c\u6d88\u606f |\r\n\r\n**\u793a\u4f8b\u4ee3\u7801\uff1a**\r\n\r\n```python\r\n# \u5bfc\u5165\u679a\u4e3e\u7c7b\u578b\uff08\u63a8\u8350\u65b9\u5f0f\uff09\r\nfrom qe.lib import Algorithm, Exchange, MarketType, OrderSide, StrategyType, MarginType\r\n\r\n# TWAP \u8ba2\u5355\u793a\u4f8b - \u4f7f\u7528\u679a\u4e3e\u521b\u5efa\u8ba2\u5355\uff08\u63a8\u8350\uff09\r\nresponse = client.create_master_order(\r\n algorithm=Algorithm.TWAP, # \u4f7f\u7528\u7b97\u6cd5\u679a\u4e3e\r\n exchange=Exchange.BINANCE, # \u4f7f\u7528\u4ea4\u6613\u6240\u679a\u4e3e\r\n symbol=\"BTCUSDT\",\r\n marketType=MarketType.SPOT, # \u4f7f\u7528\u5e02\u573a\u7c7b\u578b\u679a\u4e3e\r\n side=OrderSide.BUY, # \u4f7f\u7528\u8ba2\u5355\u65b9\u5411\u679a\u4e3e\r\n apiKeyId=\"your-api-key-id\", # \u4ece list_exchange_apis \u83b7\u53d6\r\n orderNotional=\"200\", # $200 \u540d\u4e49\u4ef7\u503c\r\n strategyType=StrategyType.TWAP_1, # \u4f7f\u7528\u7b56\u7565\u7c7b\u578b\u679a\u4e3e\r\n startTime=\"2025-09-02T19:54:34+08:00\",\r\n endTime=\"2025-09-03T01:44:35+08:00\",\r\n executionDuration=\"5\", # 5 \u79d2\u95f4\u9694\r\n mustComplete=True, # \u5fc5\u987b\u5b8c\u6210\u5168\u90e8\u8ba2\u5355\r\n worstPrice=-1, # -1 \u8868\u793a\u65e0\u4ef7\u683c\u9650\u5236\r\n upTolerance=\"-1\", # \u5141\u8bb8\u8d85\u51fa\u5bb9\u5fcd\u5ea6\r\n lowTolerance=\"-1\", # \u5141\u8bb8\u843d\u540e\u5bb9\u5fcd\u5ea6\r\n tailOrderProtection=True, # \u5c3e\u5355\u4fdd\u62a4\r\n notes=\"\u6d4b\u8bd5 TWAP \u8ba2\u5355\" # \u8ba2\u5355\u5907\u6ce8\r\n)\r\n\r\nif response.get('success'):\r\n print(f\"\u4e3b\u8ba2\u5355\u521b\u5efa\u6210\u529f\uff0cID: {response['masterOrderId']}\")\r\nelse:\r\n print(f\"\u521b\u5efa\u5931\u8d25\uff1a{response.get('message')}\")\r\n```\r\n\r\n**\u76ee\u6807\u4ed3\u4f4d\u4e0b\u5355\u793a\u4f8b\uff1a**\r\n\r\n```python\r\n# \u76ee\u6807\u4ed3\u4f4d\u4e0b\u5355\u793a\u4f8b - \u4e70\u5165 1.5 BTC \u5230\u76ee\u6807\u4ed3\u4f4d\r\nresponse = client.create_master_order(\r\n algorithm=Algorithm.TWAP, # \u4f7f\u7528\u7b97\u6cd5\u679a\u4e3e\r\n exchange=Exchange.BINANCE, # \u4f7f\u7528\u4ea4\u6613\u6240\u679a\u4e3e\r\n symbol=\"BTCUSDT\",\r\n marketType=MarketType.SPOT, # \u4f7f\u7528\u5e02\u573a\u7c7b\u578b\u679a\u4e3e\r\n side=OrderSide.BUY, # \u4f7f\u7528\u8ba2\u5355\u65b9\u5411\u679a\u4e3e\r\n apiKeyId=\"your-api-key-id\", # \u4ece list_exchange_apis \u83b7\u53d6\r\n totalQuantity=\"1.5\", # \u76ee\u6807\u6570\u91cf 1.5 BTC\r\n isTargetPosition=True, # \u542f\u7528\u76ee\u6807\u4ed3\u4f4d\u6a21\u5f0f\r\n strategyType=StrategyType.TWAP_1, # \u4f7f\u7528\u7b56\u7565\u7c7b\u578b\u679a\u4e3e\r\n startTime=\"2025-09-02T19:54:34+08:00\",\r\n endTime=\"2025-09-03T01:44:35+08:00\",\r\n executionDuration=60, # 60 \u5206\u949f\r\n mustComplete=True, # \u5fc5\u987b\u5b8c\u6210\u5168\u90e8\u8ba2\u5355\r\n limitPrice=\"65000\", # \u6700\u9ad8\u4ef7\u683c $65,000\r\n upTolerance=\"0.1\", # \u5141\u8bb8\u8d85\u51fa 10%\r\n lowTolerance=\"0.1\", # \u5141\u8bb8\u843d\u540e 10%\r\n tailOrderProtection=True, # \u5c3e\u5355\u4fdd\u62a4\r\n notes=\"\u76ee\u6807\u4ed3\u4f4d\u8ba2\u5355\u793a\u4f8b\" # \u8ba2\u5355\u5907\u6ce8\r\n)\r\n\r\nif response.get('success'):\r\n print(f\"\u76ee\u6807\u4ed3\u4f4d\u8ba2\u5355\u521b\u5efa\u6210\u529f\uff0cID: {response['masterOrderId']}\")\r\nelse:\r\n print(f\"\u521b\u5efa\u5931\u8d25\uff1a{response.get('message')}\")\r\n```\r\n\r\n**POV \u5408\u7ea6\u8ba2\u5355\u793a\u4f8b\uff1a**\r\n\r\n```python\r\n# POV \u5408\u7ea6\u8ba2\u5355\u793a\u4f8b - \u4f7f\u7528\u679a\u4e3e\r\nresponse = client.create_master_order(\r\n algorithm=Algorithm.POV, # POV \u7b97\u6cd5\r\n exchange=Exchange.BINANCE,\r\n symbol=\"BTCUSDT\",\r\n marketType=MarketType.PERP, # \u5408\u7ea6\u5e02\u573a\r\n side=OrderSide.SELL, # \u5356\u51fa\r\n apiKeyId=\"your-api-key-id\",\r\n orderNotional=\"1000\", # $1000 \u540d\u4e49\u4ef7\u503c\r\n strategyType=StrategyType.POV, # POV \u7b56\u7565\r\n startTime=\"2025-09-02T19:54:34+08:00\",\r\n endTime=\"2025-09-03T01:44:35+08:00\",\r\n povLimit=0.2, # \u5360\u5e02\u573a\u6210\u4ea4\u91cf 20%\r\n povMinLimit=0.05, # \u6700\u4f4e\u5360\u5e02\u573a\u6210\u4ea4\u91cf 5%\r\n marginType=MarginType.U, # U\u672c\u4f4d\u4fdd\u8bc1\u91d1\r\n reduceOnly=False,\r\n mustComplete=True,\r\n notes=\"POV \u5408\u7ea6\u8ba2\u5355\u793a\u4f8b\"\r\n)\r\n\r\nif response.get('success'):\r\n print(f\"POV \u8ba2\u5355\u521b\u5efa\u6210\u529f\uff0cID: {response['masterOrderId']}\")\r\n```\r\n\r\n#### \u67e5\u8be2\u4e3b\u8ba2\u5355\u5217\u8868\r\n\r\n\u83b7\u53d6\u7528\u6237\u7684\u4e3b\u8ba2\u5355\u5217\u8868\u3002\r\n\r\n**\u8bf7\u6c42\u53c2\u6570\uff1a**\r\n\r\n| \u53c2\u6570\u540d | \u7c7b\u578b | \u662f\u5426\u5fc5\u4f20 | \u63cf\u8ff0 |\r\n|--------|------|----------|------|\r\n| page | int32 | \u5426 | \u9875\u7801 |\r\n| pageSize | int32 | \u5426 | \u6bcf\u9875\u6570\u91cf |\r\n| status | string | \u5426 | \u8ba2\u5355\u72b6\u6001\u7b5b\u9009\uff0c\u53ef\u9009\u503c\uff1aNEW\uff08\u6267\u884c\u4e2d\uff09\u3001COMPLETED\uff08\u5df2\u5b8c\u6210\uff09 |\r\n| exchange | string | \u5426 | \u4ea4\u6613\u6240\u540d\u79f0\u7b5b\u9009 |\r\n| symbol | string | \u5426 | \u4ea4\u6613\u5bf9\u7b5b\u9009 |\r\n| startTime | string | \u5426 | \u5f00\u59cb\u65f6\u95f4\u7b5b\u9009 |\r\n| endTime | string | \u5426 | \u7ed3\u675f\u65f6\u95f4\u7b5b\u9009 |\r\n\r\n**\u54cd\u5e94\u5b57\u6bb5\uff1a**\r\n\r\n| \u5b57\u6bb5\u540d | \u7c7b\u578b | \u63cf\u8ff0 |\r\n|--------|------|------|\r\n| items | array | \u4e3b\u8ba2\u5355\u5217\u8868 |\r\n| \u251c\u2500 masterOrderId | string | \u4e3b\u8ba2\u5355 ID |\r\n| \u251c\u2500 algorithm | string | \u7b97\u6cd5 |\r\n| \u251c\u2500 algorithmType | string | \u7b97\u6cd5\u7c7b\u578b |\r\n| \u251c\u2500 exchange | string | \u4ea4\u6613\u6240 |\r\n| \u251c\u2500 symbol | string | \u4ea4\u6613\u5bf9 |\r\n| \u251c\u2500 marketType | string | \u5e02\u573a\u7c7b\u578b |\r\n| \u251c\u2500 side | string | \u4e70\u5356\u65b9\u5411 |\r\n| \u251c\u2500 totalQuantity | string | \u603b\u6570\u91cf |\r\n| \u251c\u2500 filledQuantity | string | \u5df2\u6210\u4ea4\u6570\u91cf |\r\n| \u251c\u2500 averagePrice | float64 | \u5e73\u5747\u6210\u4ea4\u4ef7 |\r\n| \u251c\u2500 status | string | \u72b6\u6001\uff1aNEW\uff08\u521b\u5efa\uff0c\u672a\u6267\u884c\uff09\u3001WAITING\uff08\u7b49\u5f85\u4e2d\uff09\u3001PROCESSING\uff08\u6267\u884c\u4e2d\uff0c\u4e14\u672a\u5b8c\u6210\uff09\u3001PAUSED\uff08\u5df2\u6682\u505c\uff09\u3001CANCEL\uff08\u53d6\u6d88\u4e2d\uff09\u3001CANCELLED\uff08\u5df2\u53d6\u6d88\uff09\u3001COMPLETED\uff08\u5df2\u5b8c\u6210\uff09\u3001REJECTED\uff08\u5df2\u62d2\u7edd\uff09\u3001EXPIRED\uff08\u5df2\u8fc7\u671f\uff09\u3001CANCEL_REJECT\uff08\u53d6\u6d88\u88ab\u62d2\u7edd\uff09 |\r\n| \u251c\u2500 executionDuration | int32 | \u6267\u884c\u65f6\u957f\uff08\u5206\u949f\uff09 |\r\n| \u251c\u2500 priceLimit | float64 | \u4ef7\u683c\u9650\u5236 |\r\n| \u251c\u2500 startTime | string | \u5f00\u59cb\u65f6\u95f4 |\r\n| \u251c\u2500 endTime | string | \u7ed3\u675f\u65f6\u95f4 |\r\n| \u251c\u2500 createdAt | string | \u521b\u5efa\u65f6\u95f4 |\r\n| \u251c\u2500 updatedAt | string | \u66f4\u65b0\u65f6\u95f4 |\r\n| \u251c\u2500 notes | string | \u5907\u6ce8 |\r\n| \u251c\u2500 marginType | string | \u4fdd\u8bc1\u91d1\u7c7b\u578b\uff08U:U\u672c\u4f4d\uff09 |\r\n| \u251c\u2500 reduceOnly | bool | \u662f\u5426\u4ec5\u51cf\u4ed3 |\r\n| \u251c\u2500 strategyType | string | \u7b56\u7565\u7c7b\u578b |\r\n| \u251c\u2500 orderNotional | string | \u8ba2\u5355\u91d1\u989d\uff08USDT\uff09 |\r\n| \u251c\u2500 mustComplete | bool | \u662f\u5426\u5fc5\u987b\u5b8c\u6210 |\r\n| \u251c\u2500 makerRateLimit | string | \u6700\u4f4e Maker \u7387 |\r\n| \u251c\u2500 povLimit | string | \u6700\u5927\u5e02\u573a\u6210\u4ea4\u91cf\u5360\u6bd4 |\r\n| \u251c\u2500 clientId | string | \u5ba2\u6237\u7aef ID |\r\n| \u251c\u2500 date | string | \u53d1\u5355\u65e5\u671f\uff08\u683c\u5f0f\uff1aYYYYMMDD\uff09 |\r\n| \u251c\u2500 ticktimeInt | string | \u53d1\u5355\u65f6\u95f4\uff08\u683c\u5f0f\uff1a093000000 \u8868\u793a 9:30:00.000\uff09 |\r\n| \u251c\u2500 limitPriceString | string | \u9650\u4ef7\uff08\u5b57\u7b26\u4e32\uff09 |\r\n| \u251c\u2500 upTolerance | string | \u4e0a\u5bb9\u5fcd\u5ea6 |\r\n| \u251c\u2500 lowTolerance | string | \u4e0b\u5bb9\u5fcd\u5ea6 |\r\n| \u251c\u2500 strictUpBound | bool | \u4e25\u683c\u4e0a\u754c |\r\n| \u251c\u2500 ticktimeMs | int64 | \u53d1\u5355\u65f6\u95f4\u6233\uff08epoch \u6beb\u79d2\uff09 |\r\n| \u251c\u2500 category | string | \u4ea4\u6613\u54c1\u79cd\uff08spot \u6216 perp\uff09 |\r\n| \u251c\u2500 filledAmount | float64 | \u6210\u4ea4\u91d1\u989d |\r\n| \u251c\u2500 totalValue | float64 | \u6210\u4ea4\u603b\u503c |\r\n| \u251c\u2500 base | string | \u57fa\u7840\u5e01\u79cd |\r\n| \u251c\u2500 quote | string | \u8ba1\u4ef7\u5e01\u79cd |\r\n| \u251c\u2500 completionProgress | float64 | \u5b8c\u6210\u8fdb\u5ea6\uff080-1\uff09 |\r\n| \u251c\u2500 reason | string | \u539f\u56e0\uff08\u5982\u53d6\u6d88\u539f\u56e0\uff09 |\r\n| total | int32 | \u603b\u6570 |\r\n| page | int32 | \u5f53\u524d\u9875\u7801 |\r\n| pageSize | int32 | \u6bcf\u9875\u6570\u91cf |\r\n\r\n**\u793a\u4f8b\u4ee3\u7801\uff1a**\r\n\r\n```python\r\n# \u67e5\u8be2\u6240\u6709\u4e3b\u8ba2\u5355\r\norders = client.get_master_orders()\r\n\r\n# \u5e26\u8fc7\u6ee4\u6761\u4ef6\u67e5\u8be2\r\norders = client.get_master_orders(\r\n page=1,\r\n pageSize=20,\r\n status=\"NEW\", # \u6267\u884c\u4e2d\u7684\u8ba2\u5355\r\n symbol=\"BTCUSDT\",\r\n startTime=\"2024-01-01T00:00:00Z\",\r\n endTime=\"2024-01-31T23:59:59Z\"\r\n)\r\n\r\n# \u6253\u5370\u8ba2\u5355\u8be6\u7ec6\u4fe1\u606f\r\nfor order in orders['items']:\r\n print(f\"\"\"\r\n\u8ba2\u5355\u4fe1\u606f\uff1a\r\n ID: {order['masterOrderId']}\r\n \u7b97\u6cd5: {order['algorithm']} ({order.get('strategyType', 'N/A')})\r\n \u4ea4\u6613\u5bf9: {order['symbol']} {order['marketType']}\r\n \u65b9\u5411: {order['side']}\r\n \u72b6\u6001: {order['status']}\r\n \u5b8c\u6210\u5ea6: {order['completionProgress'] * 100:.2f}%\r\n \u5e73\u5747\u4ef7\u683c: ${order.get('averagePrice', 0):.2f}\r\n \u5df2\u6210\u4ea4: {order['filledQuantity']} / {order['totalQuantity']}\r\n \u6210\u4ea4\u91d1\u989d: ${order.get('filledAmount', 0):.2f}\r\n \u521b\u5efa\u65f6\u95f4: {order['createdAt']}\r\n \u53d1\u5355\u65e5\u671f: {order.get('date', 'N/A')}\r\n \u4e0a\u5bb9\u5fcd\u5ea6: {order.get('upTolerance', 'N/A')}\r\n \u4e0b\u5bb9\u5fcd\u5ea6: {order.get('lowTolerance', 'N/A')}\r\n \"\"\")\r\n```\r\n\r\n#### \u67e5\u8be2\u6210\u4ea4\u8bb0\u5f55\r\n\r\n\u83b7\u53d6\u7528\u6237\u7684\u6210\u4ea4\u8bb0\u5f55\u3002\r\n\r\n**\u8bf7\u6c42\u53c2\u6570\uff1a**\r\n\r\n| \u53c2\u6570\u540d | \u7c7b\u578b | \u662f\u5426\u5fc5\u4f20 | \u63cf\u8ff0 |\r\n|--------|------|----------|------|\r\n| page | int32 | \u5426 | \u9875\u7801 |\r\n| pageSize | int32 | \u5426 | \u6bcf\u9875\u6570\u91cf |\r\n| masterOrderId | string | \u5426 | \u4e3b\u8ba2\u5355 ID \u7b5b\u9009 |\r\n| subOrderId | string | \u5426 | \u5b50\u8ba2\u5355 ID \u7b5b\u9009 |\r\n| symbol | string | \u5426 | \u4ea4\u6613\u5bf9\u7b5b\u9009 |\r\n| startTime | string | \u5426 | \u5f00\u59cb\u65f6\u95f4\u7b5b\u9009 |\r\n| endTime | string | \u5426 | \u7ed3\u675f\u65f6\u95f4\u7b5b\u9009 |\r\n\r\n**\u54cd\u5e94\u5b57\u6bb5\uff1a**\r\n\r\n| \u5b57\u6bb5\u540d | \u7c7b\u578b | \u63cf\u8ff0 |\r\n|--------|------|------|\r\n| items | array | \u6210\u4ea4\u8bb0\u5f55\u5217\u8868 |\r\n| \u251c\u2500 id | string | \u8bb0\u5f55 ID |\r\n| \u251c\u2500 orderCreatedTime | string | \u8ba2\u5355\u521b\u5efa\u65f6\u95f4 |\r\n| \u251c\u2500 masterOrderId | string | \u4e3b\u8ba2\u5355 ID |\r\n| \u251c\u2500 exchange | string | \u4ea4\u6613\u6240 |\r\n| \u251c\u2500 category | string | \u5e02\u573a\u7c7b\u578b |\r\n| \u251c\u2500 symbol | string | \u4ea4\u6613\u5bf9 |\r\n| \u251c\u2500 side | string | \u65b9\u5411 |\r\n| \u251c\u2500 filledValue | float64 | \u6210\u4ea4\u4ef7\u503c |\r\n| \u251c\u2500 filledQuantity | string | \u6210\u4ea4\u6570\u91cf |\r\n| \u251c\u2500 avgPrice | float64 | \u5e73\u5747\u4ef7\u683c |\r\n| \u251c\u2500 price | float64 | \u6210\u4ea4\u4ef7\u683c |\r\n| \u251c\u2500 fee | float64 | \u624b\u7eed\u8d39 |\r\n| \u251c\u2500 tradingAccount | string | \u4ea4\u6613\u8d26\u6237 |\r\n| \u251c\u2500 status | string | \u72b6\u6001 |\r\n| \u251c\u2500 rejectReason | string | \u62d2\u7edd\u539f\u56e0 |\r\n| \u251c\u2500 base | string | \u57fa\u7840\u5e01\u79cd |\r\n| \u251c\u2500 quote | string | \u8ba1\u4ef7\u5e01\u79cd |\r\n| \u251c\u2500 type | string | \u8ba2\u5355\u7c7b\u578b |\r\n| total | int32 | \u603b\u6570 |\r\n| page | int32 | \u5f53\u524d\u9875\u7801 |\r\n| pageSize | int32 | \u6bcf\u9875\u6570\u91cf |\r\n\r\n**\u793a\u4f8b\u4ee3\u7801\uff1a**\r\n\r\n```python\r\n# \u67e5\u8be2\u7279\u5b9a\u4e3b\u8ba2\u5355\u7684\u6210\u4ea4\u660e\u7ec6\r\nfills = client.get_order_fills(\r\n masterOrderId=\"your-master-order-id\",\r\n page=1,\r\n pageSize=50\r\n)\r\n\r\n# \u67e5\u8be2\u6240\u6709\u6210\u4ea4\r\nfills = client.get_order_fills(\r\n symbol=\"BTCUSDT\",\r\n startTime=\"2024-01-01T00:00:00Z\",\r\n endTime=\"2024-01-01T23:59:59Z\"\r\n)\r\n\r\n# \u7edf\u8ba1\u6210\u4ea4\u4fe1\u606f\r\ntotal_value = 0\r\ntotal_fee = 0\r\nfor fill in fills['items']:\r\n print(f\"\"\"\r\n\u6210\u4ea4\u8be6\u60c5\uff1a\r\n \u65f6\u95f4: {fill['orderCreatedTime']}\r\n \u4ea4\u6613\u5bf9: {fill['symbol']}\r\n \u65b9\u5411: {fill['side']}\r\n \u6210\u4ea4\u4ef7\u683c: ${fill['price']:.2f}\r\n \u6210\u4ea4\u6570\u91cf: {fill['filledQuantity']}\r\n \u6210\u4ea4\u91d1\u989d: ${fill['filledValue']:.2f}\r\n \u624b\u7eed\u8d39: ${fill['fee']:.4f}\r\n \u8d26\u6237: {fill['tradingAccount']}\r\n \u7c7b\u578b: {fill.get('type', 'N/A')}\r\n \"\"\")\r\n total_value += fill['filledValue']\r\n total_fee += fill['fee']\r\n\r\nprint(f\"\u603b\u6210\u4ea4\u989d: ${total_value:.2f}, \u603b\u624b\u7eed\u8d39: ${total_fee:.2f}\")\r\n```\r\n\r\n#### \u53d6\u6d88\u4e3b\u8ba2\u5355\r\n\r\n\u53d6\u6d88\u6307\u5b9a\u7684\u4e3b\u8ba2\u5355\u3002\r\n\r\n**\u8bf7\u6c42\u53c2\u6570\uff1a**\r\n\r\n| \u53c2\u6570\u540d | \u7c7b\u578b | \u662f\u5426\u5fc5\u4f20 | \u63cf\u8ff0 |\r\n|--------|------|----------|------|\r\n| masterOrderId | string | \u662f | \u8981\u53d6\u6d88\u7684\u4e3b\u8ba2\u5355 ID |\r\n| reason | string | \u5426 | \u53d6\u6d88\u539f\u56e0 |\r\n\r\n**\u54cd\u5e94\u5b57\u6bb5\uff1a**\r\n\r\n| \u5b57\u6bb5\u540d | \u7c7b\u578b | \u63cf\u8ff0 |\r\n|--------|------|------|\r\n| success | bool | \u53d6\u6d88\u662f\u5426\u6210\u529f |\r\n| message | string | \u53d6\u6d88\u7ed3\u679c\u6d88\u606f |\r\n\r\n**\u793a\u4f8b\u4ee3\u7801\uff1a**\r\n\r\n```python\r\n# \u53d6\u6d88\u8ba2\u5355\r\nresponse = client.cancel_master_order(\r\n masterOrderId=\"your-master-order-id\",\r\n reason=\"\u7528\u6237\u624b\u52a8\u53d6\u6d88\" # \u53ef\u9009\u7684\u53d6\u6d88\u539f\u56e0\r\n)\r\n\r\nif response.get('success'):\r\n print(\"\u8ba2\u5355\u53d6\u6d88\u6210\u529f\")\r\nelse:\r\n print(f\"\u8ba2\u5355\u53d6\u6d88\u5931\u8d25: {response.get('message')}\")\r\n\r\n# \u6279\u91cf\u53d6\u6d88\u793a\u4f8b\r\ndef cancel_all_active_orders(client):\r\n \"\"\"\u53d6\u6d88\u6240\u6709\u6d3b\u8dc3\u8ba2\u5355\"\"\"\r\n orders = client.get_master_orders(status=\"ACTIVE\")\r\n cancelled_count = 0\r\n \r\n for order in orders['items']:\r\n try:\r\n response = client.cancel_master_order(\r\n masterOrderId=order['masterOrderId'],\r\n reason=\"\u6279\u91cf\u53d6\u6d88\u6d3b\u8dc3\u8ba2\u5355\"\r\n )\r\n if response.get('success'):\r\n cancelled_count += 1\r\n print(f\"\u5df2\u53d6\u6d88\u8ba2\u5355: {order['masterOrderId']}\")\r\n else:\r\n print(f\"\u53d6\u6d88\u5931\u8d25: {order['masterOrderId']} - {response.get('message')}\")\r\n except Exception as e:\r\n print(f\"\u53d6\u6d88\u5f02\u5e38: {order['masterOrderId']} - {str(e)}\")\r\n \r\n print(f\"\\n\u603b\u8ba1\u53d6\u6d88 {cancelled_count} \u4e2a\u8ba2\u5355\")\r\n return cancelled_count\r\n```\r\n\r\n#### \u521b\u5efa ListenKey\r\n\r\n\u521b\u5efa\u4e00\u4e2a\u968f\u673a\u7684UUID\u4f5c\u4e3aListenKey\uff0c\u7ed1\u5b9a\u5f53\u524d\u7528\u6237\u4fe1\u606f\uff0c\u6709\u6548\u671f24\u5c0f\u65f6\u3002ListenKey\u7528\u4e8eWebSocket\u8fde\u63a5\uff0c\u53ef\u4ee5\u5b9e\u65f6\u63a5\u6536\u7528\u6237\u76f8\u5173\u7684\u4ea4\u6613\u6570\u636e\u63a8\u9001\u3002\r\n\r\n**\u8bf7\u6c42\u53c2\u6570\uff1a**\r\n\r\n| \u53c2\u6570\u540d | \u7c7b\u578b | \u662f\u5426\u5fc5\u4f20 | \u63cf\u8ff0 |\r\n|--------|------|----------|------|\r\n| \u65e0\u9700\u53c2\u6570 | - | - | - |\r\n\r\n**\u54cd\u5e94\u5b57\u6bb5\uff1a**\r\n\r\n| \u5b57\u6bb5\u540d | \u7c7b\u578b | \u63cf\u8ff0 |\r\n|--------|------|------|\r\n| listenKey | string | \u751f\u6210\u7684ListenKey |\r\n| expireAt | string | ListenKey\u8fc7\u671f\u65f6\u95f4\u6233\uff08\u79d2\uff09 |\r\n| success | bool | \u521b\u5efa\u662f\u5426\u6210\u529f |\r\n| message | string | \u521b\u5efa\u7ed3\u679c\u6d88\u606f |\r\n\r\n**\u793a\u4f8b\u4ee3\u7801\uff1a**\r\n\r\n```python\r\n# \u521b\u5efa ListenKey\r\nresult = client.create_listen_key()\r\n\r\nif result.get('success'):\r\n print(f\"ListenKey\u521b\u5efa\u6210\u529f:\")\r\n print(f\"ListenKey: {result['listenKey']}\")\r\n print(f\"\u8fc7\u671f\u65f6\u95f4: {result['expireAt']}\")\r\n \r\n # \u4f7f\u7528 ListenKey \u5efa\u7acb WebSocket \u8fde\u63a5\r\n # ws_url = f\"wss://api.quantumexecute.com/ws/{result['listenKey']}\"\r\nelse:\r\n print(f\"ListenKey\u521b\u5efa\u5931\u8d25\uff1a{result.get('message')}\")\r\n```\r\n\r\n**\u6ce8\u610f\u4e8b\u9879\uff1a**\r\n- ListenKey \u6709\u6548\u671f\u4e3a 24 \u5c0f\u65f6\uff0c\u8fc7\u671f\u540e\u9700\u8981\u91cd\u65b0\u521b\u5efa\r\n- \u6bcf\u4e2a\u7528\u6237\u540c\u65f6\u53ea\u80fd\u6709\u4e00\u4e2a\u6709\u6548\u7684 ListenKey\r\n- ListenKey \u7528\u4e8e WebSocket \u8fde\u63a5\uff0c\u53ef\u4ee5\u5b9e\u65f6\u63a5\u6536\u4ea4\u6613\u6570\u636e\u63a8\u9001\r\n- \u5efa\u8bae\u5728\u5e94\u7528\u542f\u52a8\u65f6\u521b\u5efa ListenKey\uff0c\u5e76\u5728\u63a5\u8fd1\u8fc7\u671f\u65f6\u91cd\u65b0\u521b\u5efa\r\n\r\n## \u9519\u8bef\u5904\u7406\r\n\r\nSDK \u63d0\u4f9b\u4e86\u8be6\u7ec6\u7684\u9519\u8bef\u4fe1\u606f\uff0c\u5305\u62ec API \u9519\u8bef\u548c\u7f51\u7edc\u9519\u8bef\uff1a\r\n\r\n```python\r\nfrom qe.error import ClientError, APIError\r\n\r\nresponse = client.create_master_order(\r\n # ... \u8bbe\u7f6e\u53c2\u6570\r\n)\r\n\r\nif 'error' in response:\r\n # \u68c0\u67e5\u662f\u5426\u4e3a API \u9519\u8bef\r\n error = response['error']\r\n if isinstance(error, dict) and 'code' in error:\r\n print(f\"API \u9519\u8bef - \u4ee3\u7801: {error['code']}, \u539f\u56e0: {error.get('reason')}, \u6d88\u606f: {error.get('message')}\")\r\n print(f\"TraceID: {error.get('trace_id')}\")\r\n \r\n # \u6839\u636e\u9519\u8bef\u4ee3\u7801\u5904\u7406\r\n if error['code'] == 400:\r\n print(\"\u8bf7\u6c42\u53c2\u6570\u9519\u8bef\")\r\n elif error['code'] == 401:\r\n print(\"\u8ba4\u8bc1\u5931\u8d25\")\r\n elif error['code'] == 403:\r\n print(\"\u6743\u9650\u4e0d\u8db3\")\r\n elif error['code'] == 429:\r\n print(\"\u8bf7\u6c42\u8fc7\u4e8e\u9891\u7e41\")\r\n else:\r\n print(f\"\u5176\u4ed6\u9519\u8bef: {error}\")\r\n else:\r\n print(f\"\u7f51\u7edc\u6216\u5176\u4ed6\u9519\u8bef: {error}\")\r\n```\r\n\r\n## \u9ad8\u7ea7\u914d\u7f6e\r\n\r\n### \u81ea\u5b9a\u4e49 HTTP \u5ba2\u6237\u7aef\r\n\r\n```python\r\nimport requests\r\nimport time\r\n\r\n# \u521b\u5efa\u81ea\u5b9a\u4e49 HTTP \u5ba2\u6237\u7aef\r\nsession = requests.Session()\r\nsession.timeout = 30 # 30 \u79d2\u8d85\u65f6\r\nsession.headers.update({\r\n 'User-Agent': 'QE-Python-SDK/1.0.0'\r\n})\r\n\r\nclient = Client(\"your-api-key\", \"your-api-secret\")\r\nclient.session = session\r\n```\r\n\r\n### \u4f7f\u7528\u4ee3\u7406\r\n\r\n```python\r\nimport requests\r\n\r\nproxies = {\r\n 'https': 'http://proxy.example.com:8080'\r\n}\r\n\r\nclient = Client(\"your-api-key\", \"your-api-secret\")\r\nclient.session.proxies.update(proxies)\r\n```\r\n\r\n### \u65f6\u95f4\u504f\u79fb\u8c03\u6574\r\n\r\n\u5982\u679c\u9047\u5230\u65f6\u95f4\u6233\u9519\u8bef\uff0c\u53ef\u4ee5\u8c03\u6574\u5ba2\u6237\u7aef\u7684\u65f6\u95f4\u504f\u79fb\uff1a\r\n\r\n```python\r\n# \u8bbe\u7f6e\u65f6\u95f4\u504f\u79fb\uff08\u6beb\u79d2\uff09\r\nclient.time_offset = 1000 # \u5ba2\u6237\u7aef\u65f6\u95f4\u6bd4\u670d\u52a1\u5668\u5feb 1 \u79d2\r\n```\r\n\r\n### \u8bf7\u6c42\u91cd\u8bd5\r\n\r\n```python\r\nimport time\r\nimport math\r\n\r\n# \u5b9e\u73b0\u7b80\u5355\u7684\u91cd\u8bd5\u903b\u8f91\r\ndef retry_request(func, max_retries=3):\r\n \"\"\"\u91cd\u8bd5\u8bf7\u6c42\u51fd\u6570\"\"\"\r\n for i in range(max_retries):\r\n try:\r\n return func()\r\n except Exception as e:\r\n if i == max_retries - 1:\r\n raise e\r\n \r\n # \u68c0\u67e5\u662f\u5426\u5e94\u8be5\u91cd\u8bd5\r\n if hasattr(e, 'code') and 400 <= e.code < 500:\r\n raise e # \u4e0d\u91cd\u8bd5\u5ba2\u6237\u7aef\u9519\u8bef\r\n \r\n # \u6307\u6570\u9000\u907f\r\n wait_time = math.pow(2, i)\r\n print(f\"\u8bf7\u6c42\u5931\u8d25\uff0c{wait_time}\u79d2\u540e\u91cd\u8bd5...\")\r\n time.sleep(wait_time)\r\n\r\n# \u4f7f\u7528\u91cd\u8bd5\r\ndef create_order_with_retry():\r\n return client.create_master_order(\r\n # ... \u8bbe\u7f6e\u53c2\u6570\r\n )\r\n\r\nresult = retry_request(create_order_with_retry, max_retries=3)\r\n```\r\n\r\n## \u6700\u4f73\u5b9e\u8df5\r\n\r\n### 1. API \u5bc6\u94a5\u7ba1\u7406\r\n\r\n```python\r\n# \u5b9a\u671f\u68c0\u67e5 API \u5bc6\u94a5\u72b6\u6001\r\ndef check_api_key_status(client):\r\n apis = client.list_exchange_apis()\r\n if not apis.get('items'):\r\n print(\"\u83b7\u53d6 API \u5217\u8868\u5931\u8d25\")\r\n return\r\n \r\n for api in apis['items']:\r\n if not api['isValid']:\r\n print(f\"\u8b66\u544a: API {api['id']} ({api['accountName']}) \u72b6\u6001\u5f02\u5e38\")\r\n if api['balance'] < 100:\r\n print(f\"\u8b66\u544a: \u8d26\u6237 {api['accountName']} \u4f59\u989d\u4e0d\u8db3 (${api['balance']:.2f})\")\r\n```\r\n\r\n### 2. \u8ba2\u5355\u76d1\u63a7\r\n\r\n```python\r\n# \u76d1\u63a7\u8ba2\u5355\u6267\u884c\u72b6\u6001\r\ndef monitor_order(client, master_order_id):\r\n import time\r\n \r\n while True:\r\n orders = client.get_master_orders(page=1, pageSize=1)\r\n \r\n if not orders['items']:\r\n print(\"\u8ba2\u5355\u4e0d\u5b58\u5728\")\r\n return\r\n \r\n order = orders['items'][0]\r\n print(f\"\u8ba2\u5355\u8fdb\u5ea6: {order['completionProgress']*100:.2f}%, \u72b6\u6001: {order['status']}\")\r\n \r\n if order['status'] == \"COMPLETED\":\r\n print(f\"\u8ba2\u5355\u5df2\u7ed3\u675f\uff0c\u6700\u7ec8\u72b6\u6001: {order['status']}\")\r\n return\r\n \r\n time.sleep(10) # \u6bcf 10 \u79d2\u68c0\u67e5\u4e00\u6b21\r\n```\r\n\r\n### 3. \u6279\u91cf\u5904\u7406\r\n\r\n```python\r\n# \u6279\u91cf\u83b7\u53d6\u6240\u6709\u8ba2\u5355\r\ndef get_all_orders(client):\r\n all_orders = []\r\n page = 1\r\n page_size = 100\r\n \r\n while True:\r\n result = client.get_master_orders(page=page, pageSize=page_size)\r\n all_orders.extend(result['items'])\r\n \r\n # \u68c0\u67e5\u662f\u5426\u8fd8\u6709\u66f4\u591a\u6570\u636e\r\n if len(result['items']) < page_size:\r\n break\r\n page += 1\r\n \r\n return all_orders\r\n```\r\n\r\n### 4. ListenKey \u7ba1\u7406\r\n\r\n```python\r\nimport time\r\nfrom datetime import datetime\r\n\r\n# ListenKey \u7ba1\u7406\u5668\r\nclass ListenKeyManager:\r\n def __init__(self, client):\r\n self.client = client\r\n self.listen_key = None\r\n self.expire_at = None\r\n \r\n def create_listen_key(self):\r\n \"\"\"\u521b\u5efa\u6216\u5237\u65b0 ListenKey\"\"\"\r\n result = self.client.create_listen_key()\r\n \r\n if not result.get('success'):\r\n raise Exception(f\"\u521b\u5efa ListenKey \u5931\u8d25: {result.get('message')}\")\r\n \r\n self.listen_key = result['listenKey']\r\n self.expire_at = int(result['expireAt'])\r\n \r\n print(f\"ListenKey \u521b\u5efa\u6210\u529f: {self.listen_key}, \u8fc7\u671f\u65f6\u95f4: {self.expire_at}\")\r\n return self.listen_key\r\n \r\n def is_expired(self):\r\n \"\"\"\u68c0\u67e5 ListenKey \u662f\u5426\u5373\u5c06\u8fc7\u671f\"\"\"\r\n if not self.expire_at:\r\n return True\r\n # \u63d0\u524d1\u5c0f\u65f6\u5237\u65b0\r\n return time.time() > self.expire_at - 3600\r\n \r\n def auto_refresh(self):\r\n \"\"\"\u81ea\u52a8\u5237\u65b0 ListenKey\"\"\"\r\n if self.is_expired():\r\n print(\"ListenKey \u5373\u5c06\u8fc7\u671f\uff0c\u5f00\u59cb\u5237\u65b0...\")\r\n self.create_listen_key()\r\n\r\n# \u4f7f\u7528\u793a\u4f8b\r\nmanager = ListenKeyManager(client)\r\nlisten_key = manager.create_listen_key()\r\n\r\n# \u5b9a\u671f\u68c0\u67e5\u5e76\u5237\u65b0\r\nwhile True:\r\n manager.auto_refresh()\r\n time.sleep(1800) # \u6bcf30\u5206\u949f\u68c0\u67e5\u4e00\u6b21\r\n```\r\n\r\n### 5. WebSocket \u5b9e\u65f6\u6570\u636e\u63a8\u9001\r\n\r\nSDK \u63d0\u4f9b\u4e86\u5b8c\u6574\u7684 WebSocket \u670d\u52a1\uff0c\u53ef\u4ee5\u5b9e\u65f6\u63a5\u6536\u4ea4\u6613\u6570\u636e\u63a8\u9001\uff0c\u5305\u62ec\u4e3b\u8ba2\u5355\u72b6\u6001\u66f4\u65b0\u3001\u5b50\u8ba2\u5355\u53d8\u5316\u3001\u6210\u4ea4\u660e\u7ec6\u7b49\u3002\r\n\r\n#### \u521b\u5efa WebSocket \u670d\u52a1\r\n\r\n```python\r\nimport logging\r\nimport time\r\nfrom qe import API, WebSocketService, WebSocketEventHandlers, MasterOrderMessage, OrderMessage, FillMessage\r\n\r\n# \u914d\u7f6e\u65e5\u5fd7\r\nlogging.basicConfig(level=logging.INFO)\r\nlogger = logging.getLogger(__name__)\r\n\r\ndef on_connected():\r\n \"\"\"\u8fde\u63a5\u6210\u529f\u56de\u8c03\"\"\"\r\n logger.info(\"WebSocket\u8fde\u63a5\u6210\u529f\")\r\n\r\ndef on_disconnected():\r\n \"\"\"\u65ad\u5f00\u8fde\u63a5\u56de\u8c03\"\"\"\r\n logger.info(\"WebSocket\u8fde\u63a5\u65ad\u5f00\")\r\n\r\ndef on_error(error):\r\n \"\"\"\u9519\u8bef\u56de\u8c03\"\"\"\r\n logger.error(f\"WebSocket\u9519\u8bef: {error}\")\r\n\r\ndef on_status(data):\r\n \"\"\"\u72b6\u6001\u6d88\u606f\u56de\u8c03\"\"\"\r\n logger.info(f\"\u6536\u5230\u72b6\u6001\u6d88\u606f: {data}\")\r\n\r\ndef on_master_order(message: MasterOrderMessage):\r\n \"\"\"\u4e3b\u8ba2\u5355\u6d88\u606f\u56de\u8c03\"\"\"\r\n logger.info(f\"\u6536\u5230\u4e3b\u8ba2\u5355\u6d88\u606f:\")\r\n logger.info(f\" \u4e3b\u8ba2\u5355ID: {message.master_order_id}\")\r\n logger.info(f\" \u5ba2\u6237\u7aefID: {message.client_id}\")\r\n logger.info(f\" \u7b56\u7565: {message.strategy}\")\r\n logger.info(f\" \u4ea4\u6613\u5bf9: {message.symbol}\")\r\n logger.info(f\" \u65b9\u5411: {message.side}\")\r\n logger.info(f\" \u6570\u91cf: {message.qty}\")\r\n logger.info(f\" \u72b6\u6001: {message.status}\")\r\n logger.info(f\" \u65f6\u95f4\u6233: {message.timestamp}\")\r\n\r\ndef on_order(message: OrderMessage):\r\n \"\"\"\u8ba2\u5355\u6d88\u606f\u56de\u8c03\"\"\"\r\n logger.info(f\"\u6536\u5230\u8ba2\u5355\u6d88\u606f:\")\r\n logger.info(f\" \u4e3b\u8ba2\u5355ID: {message.master_order_id}\")\r\n logger.info(f\" \u8ba2\u5355ID: {message.order_id}\")\r\n logger.info(f\" \u4ea4\u6613\u5bf9: {message.symbol}\")\r\n logger.info(f\" \u65b9\u5411: {message.side}\")\r\n logger.info(f\" \u4ef7\u683c: {message.price}\")\r\n logger.info(f\" \u6570\u91cf: {message.quantity}\")\r\n logger.info(f\" \u72b6\u6001: {message.status}\")\r\n logger.info(f\" \u5df2\u6210\u4ea4\u6570\u91cf: {message.fill_qty}\")\r\n logger.info(f\" \u5269\u4f59\u6570\u91cf: {message.quantity_remaining}\")\r\n\r\ndef on_fill(message: FillMessage):\r\n \"\"\"\u6210\u4ea4\u6d88\u606f\u56de\u8c03\"\"\"\r\n logger.info(f\"\u6536\u5230\u6210\u4ea4\u6d88\u606f:\")\r\n logger.info(f\" \u4e3b\u8ba2\u5355ID: {message.master_order_id}\")\r\n logger.info(f\" \u8ba2\u5355ID: {message.order_id}\")\r\n logger.info(f\" \u4ea4\u6613\u5bf9: {message.symbol}\")\r\n logger.info(f\" \u65b9\u5411: {message.side}\")\r\n logger.info(f\" \u6210\u4ea4\u4ef7\u683c: {message.fill_price}\")\r\n logger.info(f\" \u6210\u4ea4\u6570\u91cf: {message.filled_qty}\")\r\n logger.info(f\" \u6210\u4ea4\u65f6\u95f4: {message.fill_time}\")\r\n\r\ndef on_raw_message(message):\r\n \"\"\"\u539f\u59cb\u6d88\u606f\u56de\u8c03\"\"\"\r\n logger.debug(f\"\u6536\u5230\u539f\u59cb\u6d88\u606f: {message.type} - {message.data}\")\r\n\r\ndef main():\r\n \"\"\"\u4e3b\u51fd\u6570\"\"\"\r\n # \u521b\u5efaAPI\u5ba2\u6237\u7aef\r\n api = API(\r\n api_key=\"your_api_key\",\r\n api_secret=\"your_api_secret\",\r\n base_url=\"https://test.quantumexecute.com\"\r\n )\r\n \r\n # \u521b\u5efaWebSocket\u4e8b\u4ef6\u5904\u7406\u5668\r\n handlers = WebSocketEventHandlers(\r\n on_connected=on_connected,\r\n on_disconnected=on_disconnected,\r\n on_error=on_error,\r\n on_status=on_status,\r\n on_master_order=on_master_order,\r\n on_order=on_order,\r\n on_fill=on_fill,\r\n on_raw_message=on_raw_message\r\n )\r\n \r\n # \u521b\u5efaWebSocket\u670d\u52a1\r\n ws_service = WebSocketService(api)\r\n ws_service.set_handlers(handlers)\r\n \r\n # \u8bbe\u7f6e\u8fde\u63a5\u53c2\u6570\r\n ws_service.set_reconnect_delay(5.0) # \u91cd\u8fde\u5ef6\u8fdf5\u79d2\r\n ws_service.set_ping_interval(30.0) # \u5fc3\u8df3\u95f4\u969430\u79d2\r\n ws_service.set_pong_timeout(10.0) # Pong\u8d85\u65f610\u79d2\r\n \r\n try:\r\n # \u83b7\u53d6listen_key\r\n listen_key_result = api.create_listen_key()\r\n if not listen_key_result.get('success'):\r\n logger.error(f\"\u521b\u5efaListenKey\u5931\u8d25: {listen_key_result.get('message')}\")\r\n return\r\n \r\n listen_key = listen_key_result['listenKey']\r\n \r\n # \u8fde\u63a5WebSocket\r\n logger.info(\"\u6b63\u5728\u8fde\u63a5WebSocket...\")\r\n ws_service.connect(listen_key)\r\n \r\n # \u7b49\u5f85\u8fde\u63a5\u5efa\u7acb\r\n time.sleep(2)\r\n \r\n if ws_service.is_connected():\r\n logger.info(\"WebSocket\u8fde\u63a5\u5df2\u5efa\u7acb\uff0c\u5f00\u59cb\u63a5\u6536\u6d88\u606f...\")\r\n \r\n # \u4fdd\u6301\u8fde\u63a5\u8fd0\u884c\r\n try:\r\n while True:\r\n time.sleep(1)\r\n except KeyboardInterrupt:\r\n logger.info(\"\u6536\u5230\u4e2d\u65ad\u4fe1\u53f7\uff0c\u6b63\u5728\u5173\u95ed\u8fde\u63a5...\")\r\n else:\r\n logger.error(\"WebSocket\u8fde\u63a5\u5931\u8d25\")\r\n \r\n except Exception as e:\r\n logger.error(f\"\u53d1\u751f\u9519\u8bef: {e}\")\r\n \r\n finally:\r\n # \u5173\u95edWebSocket\u8fde\u63a5\r\n ws_service.close()\r\n logger.info(\"WebSocket\u8fde\u63a5\u5df2\u5173\u95ed\")\r\n\r\nif __name__ == \"__main__\":\r\n main()\r\n```\r\n\r\n#### \u6d88\u606f\u7c7b\u578b\u8bf4\u660e\r\n\r\n**\u5ba2\u6237\u7aef\u63a8\u9001\u6d88\u606f\u7c7b\u578b\uff1a**\r\n\r\n| \u6d88\u606f\u7c7b\u578b | \u63cf\u8ff0 |\r\n|----------|------|\r\n| data | \u6570\u636e\u6d88\u606f |\r\n| status | \u72b6\u6001\u6d88\u606f |\r\n| error | \u9519\u8bef\u6d88\u606f |\r\n| master_data | \u4e3b\u8ba2\u5355\u6570\u636e |\r\n| order_data | \u8ba2\u5355\u6570\u636e |\r\n\r\n**\u7b2c\u4e09\u65b9\u6d88\u606f\u7c7b\u578b\uff1a**\r\n\r\n| \u6d88\u606f\u7c7b\u578b | \u63cf\u8ff0 |\r\n|----------|------|\r\n| master_order | \u4e3b\u8ba2\u5355\u6d88\u606f |\r\n| order | \u5b50\u8ba2\u5355\u6d88\u606f |\r\n| fill | \u6210\u4ea4\u6d88\u606f |\r\n\r\n#### \u914d\u7f6e\u9009\u9879\r\n\r\n```python\r\n# \u8bbe\u7f6e\u91cd\u8fde\u5ef6\u8fdf\r\nws_service.set_reconnect_delay(10.0) # 10\u79d2\r\n\r\n# \u8bbe\u7f6e\u5fc3\u8df3\u95f4\u9694\r\nws_service.set_ping_interval(2.0) # 2\u79d2\r\n\r\n# \u8bbe\u7f6ePong\u8d85\u65f6\u65f6\u95f4\r\nws_service.set_pong_timeout(15.0) # 15\u79d2\r\n\r\n# \u8bbe\u7f6e\u65e5\u5fd7\u8bb0\u5f55\u5668\r\nimport logging\r\nlogger = logging.getLogger(\"websocket\")\r\nws_service.set_logger(logger)\r\n```\r\n\r\n#### \u8fde\u63a5\u72b6\u6001\u7ba1\u7406\r\n\r\n```python\r\n# \u68c0\u67e5\u8fde\u63a5\u72b6\u6001\r\nif ws_service.is_connected():\r\n print(\"WebSocket \u5df2\u8fde\u63a5\")\r\nelse:\r\n print(\"WebSocket \u672a\u8fde\u63a5\")\r\n\r\n# \u624b\u52a8\u91cd\u8fde\r\nif not ws_service.is_connected():\r\n listen_key = \"your-listen-key\"\r\n ws_service.connect(listen_key)\r\n```\r\n\r\n#### \u9519\u8bef\u5904\u7406\r\n\r\n```python\r\ndef on_error(error):\r\n \"\"\"\u9519\u8bef\u56de\u8c03\"\"\"\r\n logger.error(f\"WebSocket \u9519\u8bef: {error}\")\r\n \r\n # \u6839\u636e\u9519\u8bef\u7c7b\u578b\u8fdb\u884c\u5904\u7406\r\n if \"connection refused\" in str(error).lower():\r\n logger.error(\"\u8fde\u63a5\u88ab\u62d2\u7edd\uff0c\u53ef\u80fd\u662f\u670d\u52a1\u5668\u4e0d\u53ef\u7528\")\r\n elif \"authentication failed\" in str(error).lower():\r\n logger.error(\"\u8ba4\u8bc1\u5931\u8d25\uff0c\u8bf7\u68c0\u67e5 ListenKey \u662f\u5426\u6709\u6548\")\r\n elif \"timeout\" in str(error).lower():\r\n logger.error(\"\u8fde\u63a5\u8d85\u65f6\uff0c\u8bf7\u68c0\u67e5\u7f51\u7edc\u8fde\u63a5\")\r\n```\r\n\r\n#### \u751f\u4ea7\u73af\u5883\u4f7f\u7528\u5efa\u8bae\r\n\r\n1. **\u81ea\u52a8\u91cd\u8fde\u673a\u5236**\uff1aSDK \u5df2\u5185\u7f6e\u81ea\u52a8\u91cd\u8fde\u529f\u80fd\uff0c\u65e0\u9700\u624b\u52a8\u5b9e\u73b0\r\n2. **ListenKey \u7ba1\u7406**\uff1a\u5b9a\u671f\u68c0\u67e5 ListenKey \u6709\u6548\u6027\uff0c\u63a5\u8fd1\u8fc7\u671f\u65f6\u4e3b\u52a8\u5237\u65b0\r\n3. **\u9519\u8bef\u76d1\u63a7**\uff1a\u5b9e\u73b0\u5b8c\u5584\u7684\u9519\u8bef\u65e5\u5fd7\u8bb0\u5f55\u548c\u76d1\u63a7\r\n4. **\u8d1f\u8f7d\u5747\u8861**\uff1a\u8003\u8651\u4f7f\u7528\u591a\u4e2a WebSocket \u8fde\u63a5\u5206\u6563\u8d1f\u8f7d\r\n5. **\u6d88\u606f\u53bb\u91cd**\uff1a\u6839\u636e `messageId` \u5b9e\u73b0\u6d88\u606f\u53bb\u91cd\u5904\u7406\r\n\r\n#### \u9ad8\u7ea7\u7528\u6cd5\u793a\u4f8b\r\n\r\n```python\r\nclass TradingBot:\r\n def __init__(self, api_key, api_secret):\r\n self.api = API(api_key, api_secret)\r\n self.ws_service = None\r\n self.listen_key = None\r\n \r\n def start_websocket(self):\r\n \"\"\"\u542f\u52a8WebSocket\u8fde\u63a5\"\"\"\r\n # \u521b\u5efaListenKey\r\n result = self.api.create_listen_key()\r\n if not result.get('success'):\r\n raise Exception(f\"\u521b\u5efaListenKey\u5931\u8d25: {result.get('message')}\")\r\n \r\n self.listen_key = result['listenKey']\r\n \r\n # \u521b\u5efa\u4e8b\u4ef6\u5904\u7406\u5668\r\n handlers = WebSocketEventHandlers(\r\n on_connected=self._on_connected,\r\n on_disconnected=self._on_disconnected,\r\n on_error=self._on_error,\r\n on_master_order=self._on_master_order,\r\n on_order=self._on_order,\r\n on_fill=self._on_fill\r\n )\r\n \r\n # \u521b\u5efaWebSocket\u670d\u52a1\r\n self.ws_service = WebSocketService(self.api)\r\n self.ws_service.set_handlers(handlers)\r\n \r\n # \u8fde\u63a5\r\n self.ws_service.connect(self.listen_key)\r\n \r\n def _on_connected(self):\r\n print(\"\u4ea4\u6613\u673a\u5668\u4eba\u5df2\u8fde\u63a5\")\r\n \r\n def _on_disconnected(self):\r\n print(\"\u4ea4\u6613\u673a\u5668\u4eba\u8fde\u63a5\u65ad\u5f00\")\r\n \r\n def _on_error(self, error):\r\n print(f\"\u4ea4\u6613\u673a\u5668\u4eba\u9519\u8bef: {error}\")\r\n \r\n def _on_master_order(self, message):\r\n print(f\"\u4e3b\u8ba2\u5355\u66f4\u65b0: {message.master_order_id} - {message.status}\")\r\n \r\n def _on_order(self, message):\r\n print(f\"\u5b50\u8ba2\u5355\u66f4\u65b0: {message.order_id} - {message.status}\")\r\n \r\n def _on_fill(self, message):\r\n print(f\"\u6210\u4ea4\u901a\u77e5: {message.order_id} - {message.filled_qty} @ {message.fill_price}\")\r\n \r\n def stop(self):\r\n \"\"\"\u505c\u6b62WebSocket\u8fde\u63a5\"\"\"\r\n if self.ws_service:\r\n self.ws_service.close()\r\n\r\n# \u4f7f\u7528\u793a\u4f8b\r\nbot = TradingBot(\"your-api-key\", \"your-api-secret\")\r\nbot.start_websocket()\r\n\r\n# \u4fdd\u6301\u8fd0\u884c\r\ntry:\r\n while True:\r\n time.sleep(1)\r\nexcept KeyboardInterrupt:\r\n print(\"\u6b63\u5728\u505c\u6b62...\")\r\n bot.stop()\r\n```\r\n\r\n## \u5e38\u89c1\u95ee\u9898\r\n\r\n### 1. \u5982\u4f55\u83b7\u53d6 API \u5bc6\u94a5\uff1f\r\n\r\n\u8bf7\u767b\u5f55 Quantum Execute \u5e73\u53f0\uff0c\u5728\u7528\u6237\u8bbe\u7f6e\u4e2d\u521b\u5efa API \u5bc6\u94a5\u3002\r\n\r\n### 2. \u5982\u4f55\u5904\u7406\u65f6\u95f4\u683c\u5f0f\uff1f\r\n\r\n\u65f6\u95f4\u683c\u5f0f\u4f7f\u7528 ISO 8601 \u6807\u51c6\uff0c\u4f8b\u5982\uff1a\r\n- UTC \u65f6\u95f4\uff1a`2024-01-01T10:00:00Z`\r\n- \u5e26\u65f6\u533a\uff1a`2024-01-01T18:00:00+08:00`\r\n\r\n### 3. \u8ba2\u5355\u7c7b\u578b\u8bf4\u660e\r\n\r\n- **TWAP (Time Weighted Average Price)**\uff1a\u65f6\u95f4\u52a0\u6743\u5e73\u5747\u4ef7\u683c\u7b97\u6cd5\uff0c\u5728\u6307\u5b9a\u65f6\u95f4\u6bb5\u5185\u5e73\u5747\u5206\u914d\u8ba2\u5355\r\n- **VWAP (Volume Weighted Average Price)**\uff1a\u6210\u4ea4\u91cf\u52a0\u6743\u5e73\u5747\u4ef7\u683c\u7b97\u6cd5\uff0c\u6839\u636e\u5e02\u573a\u6210\u4ea4\u91cf\u5206\u5e03\u6267\u884c\u8ba2\u5355\r\n- **POV (Percentage of Volume)**\uff1a\u6210\u4ea4\u91cf\u767e\u5206\u6bd4\u7b97\u6cd5\uff0c\u4fdd\u6301\u5360\u5e02\u573a\u6210\u4ea4\u91cf\u7684\u56fa\u5b9a\u6bd4\u4f8b\r\n\r\n### 4. \u679a\u4e3e\u503c\u8bf4\u660e\r\n\r\n**\u7b97\u6cd5\u7c7b\u578b (Algorithm)\uff1a**\r\n\r\n| \u679a\u4e3e\u503c | \u63cf\u8ff0 |\r\n|--------|------|\r\n| TWAP | TWAP\u7b97\u6cd5 |\r\n| VWAP | VWAP\u7b97\u6cd5 |\r\n| POV | POV\u7b97\u6cd5 |\r\n\r\n**\u5e02\u573a\u7c7b\u578b (MarketType)\uff1a**\r\n\r\n| \u679a\u4e3e\u503c | \u63cf\u8ff0 |\r\n|--------|------|\r\n| SPOT | \u73b0\u8d27\u5e02\u573a |\r\n| PERP | \u5408\u7ea6\u5e02\u573a |\r\n\r\n**\u8ba2\u5355\u65b9\u5411 (OrderSide)\uff1a**\r\n\r\n| \u679a\u4e3e\u503c | \u63cf\u8ff0 |\r\n|--------|------|\r\n| buy | \u4e70\u5165 |\r\n| sell | \u5356\u51fa |\r\n\r\n**\u4ea4\u6613\u6240 (Exchange)\uff1a**\r\n\r\n| \u679a\u4e3e\u503c | \u63cf\u8ff0 |\r\n|--------|------|\r\n| Binance | \u5e01\u5b89 |\r\n\r\n**\u4fdd\u8bc1\u91d1\u7c7b\u578b (MarginType)\uff1a**\r\n\r\n| \u679a\u4e3e\u503c | \u63cf\u8ff0 |\r\n|--------|------|\r\n| U | U\u672c\u4f4d |\r\n\r\n**\u6bcd\u5355\u72b6\u6001 (MasterOrderStatus)\uff1a**\r\n\r\n| \u679a\u4e3e\u503c | \u63cf\u8ff0 |\r\n|--------|------|\r\n| NEW | \u6267\u884c\u4e2d |\r\n| COMPLETED | \u5df2\u5b8c\u6210 |\r\n\r\n**\u4ea4\u6613\u5bf9\u5e02\u573a\u7c7b\u578b (TradingPairMarketType)\uff1a**\r\n\r\n| \u679a\u4e3e\u503c | \u63cf\u8ff0 |\r\n|--------|------|\r\n| SPOT | \u73b0\u8d27\u54c1\u79cd |\r\n| FUTURES | \u671f\u8d27\u54c1\u79cd |\r\n\r\n### 5. \u516c\u5171\u63a5\u53e3\u4f7f\u7528\u8bf4\u660e\r\n\r\n**Status \u63a5\u53e3\uff08\u65e0\u9700\u8ba4\u8bc1\uff09\uff1a**\r\n- `ping()`: \u6d4b\u8bd5\u670d\u52a1\u5668\u8fde\u901a\u6027\r\n- `timestamp()`: \u83b7\u53d6\u670d\u52a1\u5668\u65f6\u95f4\u6233\r\n\r\n**Pub \u63a5\u53e3\uff08\u65e0\u9700\u8ba4\u8bc1\uff09\uff1a**\r\n- `trading_pairs()`: \u83b7\u53d6\u4ea4\u6613\u5bf9\u5217\u8868\uff0c\u652f\u6301\u5404\u79cd\u7b5b\u9009\u6761\u4ef6\r\n\r\n**User \u63a5\u53e3\uff08\u9700\u8981\u8ba4\u8bc1\uff09\uff1a**\r\n- \u6240\u6709\u4ea4\u6613\u76f8\u5173\u529f\u80fd\u90fd\u9700\u8981\u6709\u6548\u7684 API \u5bc6\u94a5\r\n\r\n### 6. \u679a\u4e3e\u7c7b\u578b\u4f7f\u7528\u5efa\u8bae\r\n\r\n\u63a8\u8350\u4f7f\u7528\u679a\u4e3e\u7c7b\u578b\u800c\u4e0d\u662f\u5b57\u7b26\u4e32\uff0c\u8fd9\u6837\u53ef\u4ee5\u83b7\u5f97\uff1a\r\n- \u7c7b\u578b\u5b89\u5168\uff1a\u7f16\u8bd1\u65f6\u68c0\u67e5\u53c2\u6570\u6b63\u786e\u6027\r\n- \u4ee3\u7801\u63d0\u793a\uff1aIDE \u53ef\u4ee5\u63d0\u4f9b\u81ea\u52a8\u8865\u5168\r\n- \u907f\u514d\u62fc\u5199\u9519\u8bef\uff1a\u51cf\u5c11\u56e0\u5b57\u7b26\u4e32\u62fc\u5199\u9519\u8bef\u5bfc\u81f4\u7684\u9519\u8bef\r\n\r\n```python\r\n# \u63a8\u8350\u4f7f\u7528\u679a\u4e3e\r\nfrom qe.lib import TradingPairMarketType\r\n\r\n# \u4f7f\u7528\u679a\u4e3e\r\npairs = pub_client.trading_pairs(marketType=TradingPairMarketType.SPOT)\r\n\r\n# \u4e0d\u63a8\u8350\u4f7f\u7528\u5b57\u7b26\u4e32\r\npairs = pub_client.trading_pairs(marketType=\"SPOT\")\r\n```\r\n\r\n### 7. WebSocket \u76f8\u5173\u8bf4\u660e\r\n\r\n**WebSocket \u8fde\u63a5\u5730\u5740\uff1a**\r\n- `wss://test.quantumexecute.com/api/ws?listen_key={listenKey}`\r\n\r\n**\u652f\u6301\u7684\u6d88\u606f\u7c7b\u578b\uff1a**\r\n- \u4e3b\u8ba2\u5355\u72b6\u6001\u66f4\u65b0\uff08`master_order`\uff09\r\n- \u5b50\u8ba2\u5355\u53d8\u5316\uff08`order`\uff09\r\n- \u6210\u4ea4\u660e\u7ec6\uff08`fill`\uff09\r\n- \u7cfb\u7edf\u72b6\u6001\u6d88\u606f\uff08`status`\uff09\r\n- \u9519\u8bef\u6d88\u606f\uff08`error`\uff09\r\n\r\n**\u8fde\u63a5\u7ba1\u7406\uff1a**\r\n- SDK \u81ea\u52a8\u5904\u7406\u5fc3\u8df3\u68c0\u6d4b\u548c\u91cd\u8fde\r\n- \u652f\u6301\u81ea\u5b9a\u4e49\u91cd\u8fde\u5ef6\u8fdf\u3001\u5fc3\u8df3\u95f4\u9694\u7b49\u53c2\u6570\r\n- \u63d0\u4f9b\u8fde\u63a5\u72b6\u6001\u67e5\u8be2\u63a5\u53e3\r\n\r\n**\u6d88\u606f\u5904\u7406\uff1a**\r\n- \u652f\u6301\u7ed3\u6784\u5316\u6d88\u606f\u89e3\u6790\r\n- \u63d0\u4f9b\u539f\u59cb\u6d88\u606f\u8bbf\u95ee\u63a5\u53e3\r\n- \u652f\u6301\u81ea\u5b9a\u4e49\u9519\u8bef\u5904\u7406\u903b\u8f91\r\n\r\n**\u6027\u80fd\u4f18\u5316\u5efa\u8bae\uff1a**\r\n- \u907f\u514d\u5728\u6d88\u606f\u5904\u7406\u5668\u4e2d\u6267\u884c\u8017\u65f6\u64cd\u4f5c\r\n- \u4f7f\u7528\u5f02\u6b65\u5904\u7406\u6d88\u606f\uff0c\u907f\u514d\u963b\u585e\u4e3b\u8fde\u63a5\r\n- \u5408\u7406\u8bbe\u7f6e\u5fc3\u8df3\u53c2\u6570\uff0c\u5e73\u8861\u5b9e\u65f6\u6027\u548c\u8d44\u6e90\u6d88\u8017\r\n\r\n**WebSocket \u4f7f\u7528\u793a\u4f8b\uff1a**\r\n\r\n```python\r\nfrom qe import API, WebSocketService, WebSocketEventHandlers\r\n\r\n# \u521b\u5efaAPI\u5ba2\u6237\u7aef\r\napi = API(\"your-api-key\", \"your-api-secret\")\r\n\r\n# \u521b\u5efaWebSocket\u670d\u52a1\r\nws_service = WebSocketService(api)\r\n\r\n# \u8bbe\u7f6e\u4e8b\u4ef6\u5904\u7406\u5668\r\nhandlers = WebSocketEventHandlers(\r\n on_connected=lambda: print(\"\u8fde\u63a5\u6210\u529f\"),\r\n on_disconnected=lambda: print(\"\u8fde\u63a5\u65ad\u5f00\"),\r\n on_error=lambda e: print(f\"\u9519\u8bef: {e}\"),\r\n on_master_order=lambda msg: print(f\"\u4e3b\u8ba2\u5355: {msg.master_order_id}\"),\r\n on_order=lambda msg: print(f\"\u5b50\u8ba2\u5355: {msg.order_id}\"),\r\n on_fill=lambda msg: print(f\"\u6210\u4ea4: {msg.filled_qty}\")\r\n)\r\n\r\nws_service.set_handlers(handlers)\r\n\r\n# \u83b7\u53d6ListenKey\u5e76\u8fde\u63a5\r\nlisten_key = api.create_listen_key()['listenKey']\r\nws_service.connect(listen_key)\r\n\r\n# \u4fdd\u6301\u8fde\u63a5\r\nimport time\r\ntry:\r\n while True:\r\n time.sleep(1)\r\nexcept KeyboardInterrupt:\r\n ws_service.close()\r\n```\r\n\r\n## \u8d21\u732e\u6307\u5357\r\n\r\n\u6b22\u8fce\u63d0\u4ea4 Issue \u548c Pull Request\uff01\r\n\r\n## \u8054\u7cfb\u6211\u4eec\r\n\r\n- \u5b98\u7f51\uff1a[https://test.quantumexecute.com](https://test.quantumexecute.com)\r\n- \u90ae\u7bb1\uff1asupport@quantumexecute.com\r\n- GitHub\uff1a[https://github.com/Quantum-Execute/qe-connector-python](https://github.com/Quantum-Execute/qe-connector-python)\r\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "This is a lightweight library that works as a connector to Quantum Execute public API.",
"version": "1.0.6",
"project_urls": {
"Homepage": "https://github.com/Quantum-Execute/qe-connector-python"
},
"split_keywords": [
"quantum-execute",
" public api"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "f5def8435540984fdb3a0c67f3c12c7257f32da7e9683dcfb74b99812ebf75d7",
"md5": "942772801b1e06fb1025441f357487db",
"sha256": "2d324166b485b525710469b6cd0f564b5fbd08b69ac69c08aa4c427f4faefd14"
},
"downloads": -1,
"filename": "qe_connector-1.0.6-py3-none-any.whl",
"has_sig": false,
"md5_digest": "942772801b1e06fb1025441f357487db",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 37784,
"upload_time": "2025-09-14T17:58:23",
"upload_time_iso_8601": "2025-09-14T17:58:23.593514Z",
"url": "https://files.pythonhosted.org/packages/f5/de/f8435540984fdb3a0c67f3c12c7257f32da7e9683dcfb74b99812ebf75d7/qe_connector-1.0.6-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "79fa3adabd3eb42aeb3f0b538c1913b72564ffdd085f52991df9f7106f4565ff",
"md5": "bd64aec36ddad62724c4f725ded4fc6f",
"sha256": "5dbf962fae11fb2535eb55525e4f41ca9ea7ebfd16e9b8a807d0d0f8279970f6"
},
"downloads": -1,
"filename": "qe-connector-1.0.6.tar.gz",
"has_sig": false,
"md5_digest": "bd64aec36ddad62724c4f725ded4fc6f",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 56723,
"upload_time": "2025-09-14T17:58:25",
"upload_time_iso_8601": "2025-09-14T17:58:25.391799Z",
"url": "https://files.pythonhosted.org/packages/79/fa/3adabd3eb42aeb3f0b538c1913b72564ffdd085f52991df9f7106f4565ff/qe-connector-1.0.6.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-09-14 17:58:25",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "Quantum-Execute",
"github_project": "qe-connector-python",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"tox": true,
"lcname": "qe-connector"
}