# 完整接口参考

适用于 exsdk 1.1.2。`Literal` 表示允许值集合，`Mapping` 表示只读映射，`pd.DataFrame` 指 pandas DataFrame。示例片段里的 `token`、`symbol`、`limit_price`、`order_id` 由调用方提供，片段放在正确的 ExApi 生命周期内运行。完整可独立执行程序见 [示例下载](./examples.md)。

## 通用调用约定

所有实例方法在创建实例的线程使用；不可在运行中的 asyncio 事件循环内调用同步方法。观察类接口先创建句柄、再调用 wait_update 推进。交易类读取需配置 CtpAccount。上下文方式 `with ExApi(token, account) as api:` 退出会关闭资源，但不会撤销委托。

## ExApi

```text
ExApi(token: str, account: CtpAccount | None=None)
```

创建同步 SDK 实例。请使用 with 管理生命周期。

### 参数

| 参数 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `token` | `str` | `必填` | 用户中心签发的非空 SDK Token；不能只包含空白。 |
| `account` | `CtpAccount \| None` | `None` | CTP 账户配置，不传时仅使用行情。 |

### 返回与行为

ExApi 实例。无需交易时不传 account。

无效 Token 抛 TypeError；处于运行中的 asyncio 循环或不正确线程上下文会报错。网络故障以 ExError 报告。

### 示例

```python
with ExApi(token) as api:
    print(api.query_symbols("FUTURE"))
```

## ExApi.trading_status

```text
ExApi.trading_status() -> Literal['SYNCING', 'READY', 'DISCONNECTED', 'ERROR']
```

读取最近发布的交易状态，不主动查询。

### 参数

无。

### 返回与行为

SYNCING、READY、DISCONNECTED、ERROR 四种字符串之一。

需要配置 CTP；READY 不代表资金和行情即时。

### 示例

```python
if api.trading_status() == "READY":
    print("可以提交委托")
```

## ExApi.watch_account

```text
ExApi.watch_account() -> Watch[Account]
```

创建资金观察句柄。

### 参数

无。

### 返回与行为

Watch[Account]；data() 返回独立资金快照。

需要 CTP。未知字段为 None，资金来自完整柜台查询，默认每 5 秒安排刷新。

### 示例

```python
funds = api.watch_account()
# 在 wait_update 后读取
print(funds.data().available)
```

## ExApi.watch_position

```text
ExApi.watch_position(symbol: str | None=None) -> Watch[Mapping[str, Position]]
```

观察全部或某合约的持仓。

### 参数

| 参数 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `symbol` | `str \| None` | `None` | 交易所.合约格式；查询结果中的有效代码。可选时 None 表示不过滤合约。 |

### 返回与行为

Watch[Mapping[str, Position]]；键为 symbol。

指定 symbol 仍返回 Mapping；无效合约格式抛 ValueError。归零对象继续保留。

### 示例

```python
positions = api.watch_position(symbol)
position = positions.data().get(symbol)
```

## ExApi.watch_order

```text
ExApi.watch_order(symbol: str | None=None) -> Watch[Mapping[str, Order]]
```

观察当前交易日全部或某合约订单。

### 参数

| 参数 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `symbol` | `str \| None` | `None` | 交易所.合约格式；查询结果中的有效代码。可选时 None 表示不过滤合约。 |

### 返回与行为

Watch[Mapping[str, Order]]；键为本地 order_id。

需要 CTP；包括同一账户其他客户端的普通投机订单。

### 示例

```python
orders = api.watch_order()
order = orders.data().get(order_id)
```

## ExApi.watch_trade

```text
ExApi.watch_trade(symbol: str | None=None) -> Watch[Mapping[str, Trade]]
```

观察当前交易日全部或某合约真实成交。

### 参数

| 参数 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `symbol` | `str \| None` | `None` | 交易所.合约格式；查询结果中的有效代码。可选时 None 表示不过滤合约。 |

### 返回与行为

Watch[Mapping[str, Trade]]；键为原始 CTP TradeID。

需要 CTP；不包含估算成交，不以订单提交推断成交。

### 示例

```python
trades = api.watch_trade()
for trade_id, trade in trades.data().items():
    print(trade_id, trade.volume)
```

## ExApi.insert_order

```text
ExApi.insert_order(symbol: str, direction: Literal['BUY', 'SELL'], offset: Literal['OPEN', 'CLOSE'], volume: int, limit_price: float) -> list[TradingResult]
```

提交普通投机限价委托；可能按平仓规则拆成多个子单。

### 参数

| 参数 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `symbol` | `str` | `必填` | 交易所.合约格式；查询结果中的有效代码。可选时 None 表示不过滤合约。 |
| `direction` | `Literal['BUY', 'SELL']` | `必填` | BUY 买入或 SELL 卖出。 |
| `offset` | `Literal['OPEN', 'CLOSE']` | `必填` | OPEN 开仓或 CLOSE 平仓。 |
| `volume` | `int` | `必填` | 正整数手数。 |
| `limit_price` | `float` | `必填` | 有效限价，须符合合约最小变动价位。 |

### 返回与行为

list[TradingResult]，每个子单一个即时提交结果。

SUBMITTED 不等于成交；UNKNOWN 不自动重发。未配置账户或非 READY 等业务拒绝返回 REJECTED。调用上下文错误仍可抛异常。

### 示例

```python
results = api.insert_order(symbol, "BUY", "OPEN", 1, limit_price)
for result in results:
    print(result.status, result.order_id, result.message)
```

## ExApi.cancel_order

```text
ExApi.cancel_order(order_id: str) -> list[TradingResult]
```

按本地订单号发起撤单。

### 参数

| 参数 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `order_id` | `str` | `必填` | 本地订单标识 FrontID:SessionID:OrderRef，不是交易所系统订单号。 |

### 返回与行为

list[TradingResult]；不存在、结束或已有撤单在处理时返回 []。

未确认或无系统编号立即拒绝，不缓存撤单意图。最终看订单 status/cancel_pending/cancel_error。

### 示例

```python
for result in api.cancel_order(order_id):
    print(result.status, result.message)
```

## ExApi.query_symbols

```text
ExApi.query_symbols(ins_class: Literal['FUTURE', 'OPTION'], exchange_id: str | None=None, product_id: str | None=None, is_main: bool | None=None) -> list[str]
```

一次性查询合约列表，不是持续观察对象。

### 参数

| 参数 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `ins_class` | `Literal['FUTURE', 'OPTION']` | `必填` | FUTURE 或 OPTION，区分期货和期权，必填。 |
| `exchange_id` | `str \| None` | `None` | 交易所代码，如 SHFE；None 不筛选。 |
| `product_id` | `str \| None` | `None` | 品种代码，如 rb；None 不筛选。 |
| `is_main` | `bool \| None` | `None` | True 仅主力，False 仅非主力，None 不限；期权均为非主力。 |

### 返回与行为

list[str]，可能为空。

无效 ins_class、筛选值抛 ValueError；响应格式或运行故障抛 ExError。

### 示例

```python
symbols = api.query_symbols("FUTURE", exchange_id="SHFE", is_main=True)
```

## ExApi.query_symbol_info

```text
ExApi.query_symbol_info(symbol: str) -> dict
```

一次性查询单个合约详细信息。

### 参数

| 参数 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `symbol` | `str` | `必填` | 交易所.合约格式；查询结果中的有效代码。可选时 None 表示不过滤合约。 |

### 返回与行为

dict，顶层字段为 symbol、exchange_id、product_id、ins_class、is_main、data。data 的详细键由服务提供。

无效代码抛 ValueError，响应无效或请求失败抛 ExError。

### 示例

```python
info = api.query_symbol_info(symbol)
print(info["ins_class"], info["data"])
```

## ExApi.watch_quote

```text
ExApi.watch_quote(symbol: str) -> Watch[Quote]
```

创建期货或期权实时行情观察句柄，相同合约复用。

### 参数

| 参数 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `symbol` | `str` | `必填` | 交易所.合约格式；查询结果中的有效代码。可选时 None 表示不过滤合约。 |

### 返回与行为

Watch[Quote]，data() 返回独立行情快照。

初始 timestamp=0，数值可能 NaN，盘口可空；检查时效。无效代码抛 ValueError。

### 示例

```python
quote = api.watch_quote(symbol)
while api.wait_update():
    if quote.is_changing("last_price"):
        print(quote.data().last_price)
```

## ExApi.watch_kline

```text
ExApi.watch_kline(symbol: str, period: Literal['1m', '5m', '10m', '15m', '30m', '1h', '4h', '1d'], data_length: int=200) -> Watch[pd.DataFrame]
```

初始化并订阅期货固定长度 K 线窗口。

### 参数

| 参数 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `symbol` | `str` | `必填` | 交易所.合约格式；查询结果中的有效代码。可选时 None 表示不过滤合约。 |
| `period` | `Literal['1m', '5m', '10m', '15m', '30m', '1h', '4h', '1d']` | `必填` | 1m / 5m / 10m / 15m / 30m / 1h / 4h / 1d。 |
| `data_length` | `int` | `200` | 固定窗口长度，1–10000 的整数，默认 200。 |

### 返回与行为

Watch[pandas.DataFrame]，列见数据字典，attrs 包含 symbol、period。

期权不支持；无效周期、长度抛 ValueError。初始化整体上限 180 秒，故障抛 ExError。相同三元参数复用句柄。

### 示例

```python
bars = api.watch_kline(symbol, "1m", data_length=200)
frame = bars.data()
if not frame.empty:
    print(frame.iloc[-1])
```

## ExApi.wait_update

```text
ExApi.wait_update(deadline: float | None=None) -> bool
```

推进 I/O 并等待下一批可见数据更新。

### 参数

| 参数 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `deadline` | `float \| None` | `None` | Unix 秒绝对时间；None 表示不设置本次等待期限。 |

### 返回与行为

bool，提交更新返回 True；本次等待期限到达而无更新返回 False。

False 不表示故障，不重置恢复额度。运行故障抛 ExError；deadline 不是相对秒数。

### 示例

```python
import time
if api.wait_update(deadline=time.time() + 5):
    print(quote.data())
```

## ExApi.close

```text
ExApi.close() -> None
```

主动关闭实例并释放行情、交易资源。

### 参数

无。

### 返回与行为

None。

关闭不撤销已提交订单。优先使用 with，异常退出时会清理资源。

### 示例

```python
try:
    print(api.query_symbols("FUTURE"))
finally:
    api.close()
```

## Watch.data

```text
Watch.data() -> T
```

读取最近提交数据的独立快照；不触发查询。

### 参数

无。

### 返回与行为

由句柄决定：Quote、DataFrame、Account 或只读 Mapping[str, Position/Order/Trade]。

旧快照不再变化；断线时保留旧数据。交易未知字段为 None；DataFrame 指标列不带入下一次快照。

### 示例

```python
snapshot = quote.data()
print(snapshot.last_price)
```

## Watch.is_changing

```text
Watch.is_changing(key: str | list[str] | None=None) -> bool
```

检查最近一次 wait_update 提交中对象或指定字段是否变化。

### 参数

| 参数 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `key` | `str \| list[str] \| None` | `None` | None 检查整体；字符串检查单字段；字符串列表检查任意指定字段。 |

### 返回与行为

bool。字段列表按任意一个变化判断。

使用字段名，不把快照本身传入。集合成员增减也构成集合变化。

### 示例

```python
if quote.is_changing(["last_price", "volume"]):
    print(quote.data())
```

## api.tools.download_kline_data

```text
api.tools.download_kline_data(symbol: str, period: Literal['1m', '5m', '10m', '15m', '30m', '1h', '4h', '1d'], start: str, end: str, csv_file_name: str | os.PathLike) -> int
```

同步按交易日分页下载期货 K 线到 CSV。

### 参数

| 参数 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `symbol` | `str` | `必填` | 交易所.合约格式；查询结果中的有效代码。可选时 None 表示不过滤合约。 |
| `period` | `Literal['1m', '5m', '10m', '15m', '30m', '1h', '4h', '1d']` | `必填` | 1m / 5m / 10m / 15m / 30m / 1h / 4h / 1d。 |
| `start` | `str` | `必填` | 起始交易日，YYYYMMDD，包含当天。 |
| `end` | `str` | `必填` | 结束交易日，YYYYMMDD，包含当天，不能早于 start。 |
| `csv_file_name` | `str \| os.PathLike` | `必填` | 输出 CSV 文件路径，字符串或 PathLike；父目录必须存在。 |

### 返回与行为

int，写入数据行数；无数据写出表头并返回 0。

只支持期货；无效日期/周期/路径类型抛 TypeError 或 ValueError；查询、保存故障抛 ExError。成功覆盖文件，失败保留原文件。

### 示例

```python
rows = api.tools.download_kline_data(
    symbol, "1m", "20260901", "20260909", "history.csv"
)
print(rows)
```

## 上下文管理与 Watch 类型

`ExApi.__enter__()` 返回当前实例，`ExApi.__exit__(...)` 关闭实例并清理资源。业务程序优先使用 with。

`Watch[T]` 由 SDK 的 watch 方法创建，不应由调用方直接构造；只使用 data() 与 is_changing() 公开方法。辅助对象 api.tools 由 ExApi 自动创建，不自行实例化 ExTools。
