@@ -0,0 +1,52 @@
|
||||
# 模块入口
|
||||
|
||||
遇到不确定时:[pytsl_api.md](pytsl_api.md)、[tsbacktesting.md](tsbacktesting.md)、[wechat_message.md](wechat_message.md)、`tsl-api-reference`、项目自身文档、`scripts/*` 入口脚本、CI 配置
|
||||
|
||||
本页只负责把“现成模块、外部集成和模块 API”任务路由到正确事实页。目标页是模块 API 事实页时,智能体可以继续使用该页的签名、参数表、返回值和代码骨架;本页自身不生成代码。
|
||||
|
||||
## 智能体模块路由规则
|
||||
|
||||
- 先判断任务是否属于模块 API、业务流程、通用语法、通用函数库或项目执行上下文。
|
||||
- 命中下面“决策顺序”中的一行后,先进入对应页面,不继续向下泛化。
|
||||
- 真实账号、密码、服务地址、部署入口、脚本入口、权限模型和项目私有字段必须来自项目上下文。
|
||||
- 不要发明模块专属 API 参数、项目账号来源、部署路径、服务节点、模板字段、证券池或策略信号。
|
||||
|
||||
## 决策顺序
|
||||
|
||||
| 顺序 | 用户任务特征 | 先读哪里 | 命中后动作 |
|
||||
| ---- | ------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | ------------------------------------------------- |
|
||||
| 1 | 询问真实账号、密码、服务地址、配置文件、部署入口、脚本入口、CI、权限模型 | 项目自身文档、`scripts/*`、CI 配置 | 退出通用模块层,不从模块页猜项目事实 |
|
||||
| 2 | 用 Python 执行 TSL、调用服务器 TSL 函数、查行情、批量取数、异步取数 | [pytsl_api.md](pytsl_api.md) | 使用 pyTSL 类、函数、参数和返回结构 |
|
||||
| 3 | 发送微信通知、微信告警、微信模板消息、查询微信消息发送状态 | [wechat_message.md](wechat_message.md) | 使用微信消息接口、模板字段和展示规则 |
|
||||
| 4 | 写策略回测框架、组合回测、读取回测资产/持仓/交易/绩效结果 | [tsbacktesting.md](tsbacktesting.md) | 使用 `TSBackTesting` 对象模型、成员变量和查询接口 |
|
||||
| 5 | 查询行情、财务、板块、选股等金融函数 | 使用 `tsl-api-reference` skill 关键词查 API | 使用数据仓库函数事实 |
|
||||
| 6 | 询问 TSL 语言语法怎么写 | [../syntax/index.md](../syntax/index.md) | 回到语法主线 |
|
||||
| 7 | 查询通用函数库函数签名、参数或返回值 | 使用 `tsl-api-reference` skill:已知名走 `--name`,未知名走 `--kw` | 回到 API reference 检索 |
|
||||
|
||||
## 模块页职责
|
||||
|
||||
| 模块页 | 负责回答 | 不负责回答 |
|
||||
| -------------------------------------- | ---------------------------------------------------------------- | -------------------------------------------------- |
|
||||
| [pytsl_api.md](pytsl_api.md) | Python SDK 的类、函数、参数、返回结构、同步/异步/批量调用选择 | 真实凭证、服务地址、权限范围、业务字段口径 |
|
||||
| [wechat_message.md](wechat_message.md) | 微信发送接口、异步状态查询、模板字段、首屏/详情展示规则 | 真实 `userid`、`username`、授权关系、项目封装函数 |
|
||||
| [tsbacktesting.md](tsbacktesting.md) | `TSBackTesting` 子类骨架、组合类别、交易字段、成员变量、查询接口 | 策略信号、证券池、资金参数、费用口径、真实行情来源 |
|
||||
|
||||
## 冲突处理
|
||||
|
||||
- Python 执行一段 TSL 或调用服务器函数时,先读 [pytsl_api.md](pytsl_api.md);TSL 代码本身再按 [../syntax/index.md](../syntax/index.md) 或 `tsl-api-reference` 补充。
|
||||
- Python 调用回测脚本时,先读 [pytsl_api.md](pytsl_api.md) 确认执行方式,再读 [tsbacktesting.md](tsbacktesting.md) 确认回测框架写法。
|
||||
- 回测框架、交易字段和结果接口优先读 [tsbacktesting.md](tsbacktesting.md);策略信号、证券池、费用口径等项目事实必须来自用户需求或项目实际接口。
|
||||
- 微信通知内容来自业务结果时,先用业务页确定内容,再用 [wechat_message.md](wechat_message.md) 组织模板字段。
|
||||
- 模块页和项目文档冲突时,以项目文档的账号、部署、权限和入口为准;模块页只保留通用 API 事实。
|
||||
|
||||
## 最短跳转
|
||||
|
||||
| 任务 | 先读哪里 |
|
||||
| ------------------------------------------------- | ------------------------------------------------------------------------------ |
|
||||
| 我要用 Python 调 TSL / 查行情 / 批量取数 | [pytsl_api.md](pytsl_api.md) |
|
||||
| 我要发微信通知 / 告警 / 查询状态 | [wechat_message.md](wechat_message.md) |
|
||||
| 我要写 `TSBackTesting` 回测框架 | [tsbacktesting.md](tsbacktesting.md) |
|
||||
| 我要查行情 / 财务 / 板块 / 选股函数 | 使用 `tsl-api-reference` skill |
|
||||
| 我要确认 TSL 语法 | [../syntax/index.md](../syntax/index.md) |
|
||||
| 我要查通用函数库 | 使用 `tsl-api-reference` skill |
|
||||
| 我要确认真实账号 / 服务地址 / 部署入口 / 脚本入口 | 项目自身文档、`scripts/*`、CI 配置 |
|
||||
@@ -0,0 +1,947 @@
|
||||
# 天软 pyTSL 接口使用说明
|
||||
|
||||
文档类型:模块 API 事实页
|
||||
是否可直接用于生成代码:是,但真实账号、密码、服务地址、配置文件路径和权限范围必须来自项目上下文
|
||||
遇到不确定时:[index.md](index.md)、项目自身部署文档、官方 pyTSL 接口文档
|
||||
|
||||
本页整理 pyTSL 官方 Python SDK 的可调用接口。它负责告诉智能体“pyTSL 有哪些类、函数、参数和返回结构”,不负责提供真实凭证、项目账号来源、服务权限或业务数据口径。
|
||||
|
||||
## 智能体 pyTSL 决策规则
|
||||
|
||||
- 用户要“用 Python 调 TSL / 执行 TSL 代码 / 调天软函数 / 查行情 / 并发或异步取数”时,优先使用本页。
|
||||
- 用户只是要执行一段 TSL 并马上拿结果,默认使用 `pyTSL.Client.exec()`。
|
||||
- 用户要调用服务器上已有 TSL 函数,默认使用 `pyTSL.Client.call()`。
|
||||
- 用户要按证券、周期、开始时间、结束时间取标准行情字段,默认使用 `pyTSL.Client.query()`。
|
||||
- 用户要一次性提交很多独立任务,先考虑 `pyTSL.Batch`;不要把大量循环直接写成频繁登录、退出。
|
||||
- 用户明确要求 asyncio,才使用 `pyTSL.AsyncClient` 或 `pyTSL.async_util`。
|
||||
- 不要发明真实账号、密码、服务地址、代理、配置文件路径、服务节点、字段名或业务函数名。
|
||||
- 不要把登录脚本、临时验证脚本或私有凭证写进生成代码;示例只能使用占位值或从项目配置读取。
|
||||
|
||||
## 安装与支持范围
|
||||
|
||||
### 包与导入
|
||||
|
||||
| 项目 | 事实 |
|
||||
| ---------- | ------------------------------------------------------------------------- |
|
||||
| 安装包名 | `tspytsl` |
|
||||
| 导入模块名 | `pyTSL` |
|
||||
| 在线安装 | `pip install tspytsl` |
|
||||
| 升级 | `pip install tspytsl -U` |
|
||||
| 离线安装 | 下载对应 `.whl` 后执行 `pip install 文件名.whl` |
|
||||
| 手动安装 | 解压对应平台的 `.pyd` 或 `.so`,放入 Python 的 `site-packages` 或项目目录 |
|
||||
|
||||
### Python 与平台
|
||||
|
||||
- pyTSL 支持 Python 3.6+。
|
||||
- 官方文档截至 2025-10-13 列出 Python 3.6 到 3.14 的 Windows、Linux x86_64、Linux arm64、MacOS x86_64 支持。
|
||||
- MacOS arm64 从 Python 3.8 到 3.14 支持,Python 3.6 和 3.7 不支持。
|
||||
- Windows 需要确认已安装 VS2019 C++ 运行时库;其他系统不需要这一步。
|
||||
|
||||
## 最小同步链路
|
||||
|
||||
优先写成“一次登录,多次交互,最后退出”。`logout()` 后再次调用 `Client` 方法可能触发自动重新登录,频繁登录退出可能占用多个登录数。
|
||||
|
||||
```python
|
||||
import pyTSL
|
||||
from datetime import datetime
|
||||
|
||||
c = pyTSL.Client("user", "password", "tsl.tinysoft.com.cn", 443)
|
||||
try:
|
||||
if c.login() == 0:
|
||||
raise RuntimeError(c.last_error())
|
||||
|
||||
r = c.exec("return close();", stock="SZ000002", time=datetime(2024, 7, 30))
|
||||
if r.error():
|
||||
raise RuntimeError(r.message())
|
||||
|
||||
value = r.value()
|
||||
finally:
|
||||
c.logout()
|
||||
```
|
||||
|
||||
## `pyTSL.Client`
|
||||
|
||||
同步客户端。构造一个 `Client` 会占用一个登录数。
|
||||
|
||||
### 构造函数:账号参数方式
|
||||
|
||||
签名:
|
||||
|
||||
```python
|
||||
pyTSL.Client(user, password, ip, port, proxy_ip=None, proxy_port=None, proxy_user=None, proxy_password=None)
|
||||
```
|
||||
|
||||
| 参数位置 | 参数名 | 必填 | 接收类型 | 说明 |
|
||||
| -------- | ---------------- | ---- | -------- | -------------------------------------------------- |
|
||||
| 1 | `user` | 是 | `str` | 天软账号 |
|
||||
| 2 | `password` | 是 | `str` | 天软账号密码;支持用客户端工具生成的加密密码字符串 |
|
||||
| 3 | `ip` | 是 | `str` | 天软服务器机群地址 |
|
||||
| 4 | `port` | 是 | `int` | 天软服务器访问端口 |
|
||||
| 5 | `proxy_ip` | 否 | `str` | 代理服务器地址 |
|
||||
| 6 | `proxy_port` | 否 | `int` | 代理服务器端口 |
|
||||
| 7 | `proxy_user` | 否 | `str` | 代理服务器验证账号 |
|
||||
| 8 | `proxy_password` | 否 | `str` | 代理服务器验证密码 |
|
||||
|
||||
常见服务器:
|
||||
|
||||
| 服务器 | `ip` | `port` | 默认服务节点 |
|
||||
| ---------------- | ------------------------- | -------------- | ------------------- |
|
||||
| 深圳服务器 | `"tsl.tinysoft.com.cn"` | `443` 或 `444` | `"正式版"` |
|
||||
| 武汉服务器 | `"wh.tinysoft.com.cn"` | `443` 或 `444` | `"Default Service"` |
|
||||
| 深圳新节点服务器 | `"sznew.tinysoft.com.cn"` | `4433` | `"Default Service"` |
|
||||
|
||||
### 构造函数:ini 文件方式
|
||||
|
||||
签名:
|
||||
|
||||
```python
|
||||
pyTSL.Client(ini_file)
|
||||
```
|
||||
|
||||
| 参数位置 | 参数名 | 必填 | 接收类型 | 说明 |
|
||||
| -------- | ---------- | ---- | -------- | ------------------------------------ |
|
||||
| 1 | `ini_file` | 是 | `str` | 连接服务器信息 `.ini` 文件的绝对路径 |
|
||||
|
||||
ini 文件字段:
|
||||
|
||||
```ini
|
||||
user=
|
||||
password=
|
||||
ip=
|
||||
port=
|
||||
proxy_user=
|
||||
proxy_password=
|
||||
proxy_ip=
|
||||
proxy_port=
|
||||
```
|
||||
|
||||
路径含中文并报找不到文件时,可把路径按 GBK 编码后传入。
|
||||
|
||||
### Client 方法总表
|
||||
|
||||
| 方法 | 签名 | 返回 | 用途 |
|
||||
| ----------------- | --------------------------------------- | --------------- | ------------------------------------------- |
|
||||
| `login` | `login()` | `bool` | 登录天软服务器;成功 `1`,失败 `0` |
|
||||
| `last_error` | `last_error()` | `list` | 最近一次错误,结构为 `[错误代码, 错误信息]` |
|
||||
| `logout` | `logout()` | `int` | 断开连接;成功 `0` |
|
||||
| `exec` | `exec(code, **kwargs)` | `TSResultValue` | 执行 TSL 代码串 |
|
||||
| `call` | `call(funcname, *args, **kwargs)` | `TSResultValue` | 调用 TSL 函数 |
|
||||
| `query` | `query(**kwargs)` | `TSResultValue` | 提取行情数据 |
|
||||
| `list_bgrun` | `list_bgrun()` | `list` | 列出委托执行任务 |
|
||||
| `stop_bgrun` | `stop_bgrun(handle)` | `int` | 停止指定委托执行任务;成功 `1` |
|
||||
| `admin` | `admin(**kwargs)` | `str` | 执行天软客户端任务管理命令 |
|
||||
| `set_callback` | `set_callback(function)` | 未说明 | 设置 `rdo2` 回调函数 |
|
||||
| `default_service` | `default_service(service)` | `str` | 设置或返回默认服务节点 |
|
||||
| `server_list` | `server_list()` | `list` | 返回服务节点列表 |
|
||||
| `download_list` | `download_list(type, timeout=0)` | `list` | 下载指定类型列表 |
|
||||
| `download` | `download(type, key, ver=0, timeout=0)` | `list` | 下载指定关键字内容 |
|
||||
| `upload` | `upload(type, key, data, timeout=0)` | `list` | 上传数据至指定关键字 |
|
||||
| `remove` | `remove(type, key, timeout=0)` | `list` | 删除指定关键字内容 |
|
||||
| `is_logined` | `is_logined()` | `bool` | 已登录返回 `1`,未登录返回 `0` |
|
||||
| `is_closed` | `is_closed()` | `bool` | 已断开返回 `1`,未断开返回 `0` |
|
||||
|
||||
### `exec(code, **kwargs)`
|
||||
|
||||
执行 TSL 代码串。结果通过 `TSResultValue` 读取。
|
||||
|
||||
| 参数位置 | 参数名 | 必填 | 接收类型 | 说明 |
|
||||
| -------- | ---------- | ---- | -------- | ------------------- |
|
||||
| 1 | `code` | 是 | `str` | 要执行的 TSL 代码串 |
|
||||
| 2 | `**kwargs` | 否 | 见下表 | 执行上下文属性 |
|
||||
|
||||
### `call(funcname, *args, **kwargs)`
|
||||
|
||||
调用 TSL 函数。`*args` 会自动转换常见 Python 类型到 TSL 类型。
|
||||
|
||||
| 参数位置 | 参数名 | 必填 | 接收类型 | 说明 |
|
||||
| -------- | ---------- | ---- | ---------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------- |
|
||||
| 1 | `funcname` | 是 | `str` | 函数名 |
|
||||
| 2 | `*args` | 否 | `float` / `int` / `bool` / `str` / `bytes` / `list` / `dict` / `tuple` / `pandas.DataFrame` / `numpy.ndarray` / 日期时间类型 | 传给 TSL 函数的位置参数 |
|
||||
| 3 | `**kwargs` | 否 | 见下表 | 执行上下文属性,可通过 `code` 传入临时函数定义 |
|
||||
|
||||
Python 到 TSL 的自动转换:
|
||||
|
||||
| Python 类型 | TSL 类型 |
|
||||
| ----------------------------------------------------------------------------- | -------------------- |
|
||||
| `float` / `numpy.float32` / `numpy.float64` / `datetime` / `numpy.datetime64` | `real` / `tdatetime` |
|
||||
| `bool` / `int` / `numpy.int32` / `numpy.int64` | `int` |
|
||||
| `str` / `bytes` | `str` |
|
||||
| `list` / `dict` / `tuple` / `pandas.DataFrame` / `numpy.ndarray` | `array` |
|
||||
|
||||
### `exec` / `call` 共享 `kwargs`
|
||||
|
||||
| 参数名 | 必填 | 接收类型 | 默认值 | 说明 |
|
||||
| ------------ | ---- | ------------------------------------ | ---------------- | ------------------------------------------------------------------------------------ |
|
||||
| `stock` | 否 | `str` | `None` | 当前股票代码,如 `"SZ000002"` |
|
||||
| `cycle` | 否 | `str` | `"日线"` | 当前周期 |
|
||||
| `time` | 否 | `datetime` / `int` / `float` / `str` | 今天 | 当前时间,如 `datetime(2019, 10, 1)`、`43739.0`、`20191001`、`"2019-10-01 14:03:01"` |
|
||||
| `rate` | 否 | `int` | `0` | 复权方式:`0` 不复权,`1` 比例复权,`2` 复杂复权 |
|
||||
| `rateday` | 否 | `datetime` / `int` / `float` / `str` | `0` | 复权基准日:`0` 最后交易日,`-1` 上市日,其他值为指定基准日 |
|
||||
| `precision` | 否 | `int` | `-1` | 浮点数精度 |
|
||||
| `viewpoint` | 否 | `datetime` / `int` / `float` / `str` | `0` | 仿真时点 |
|
||||
| `code` | 否 | `str` | `None` | 临时定义函数代码段,不必先保存到服务器 |
|
||||
| `service` | 否 | `str` | 由登录服务器决定 | 指定执行服务节点 |
|
||||
| `timeout` | 否 | `int` | `None` | 超时,单位毫秒;`None` 表示无超时时限 |
|
||||
| `bgrun` | 否 | `int` | `0` | 委托执行;`1` 表示委托执行 |
|
||||
| `resultname` | 否 | `str` | `None` | 仅 `exec` 支持;`bgrun=1` 时用于指定委托保存的结果集名称 |
|
||||
| `reportmode` | 否 | `int` | `-1` | 报表数据规则 |
|
||||
| `emptymode` | 否 | `int` | `0` | 空记录模式 |
|
||||
|
||||
### `query(**kwargs)`
|
||||
|
||||
提取行情数据。适合标准证券、周期、时间区间、字段查询。
|
||||
|
||||
| 参数位置 | 参数名 | 必填 | 接收类型 | 说明 |
|
||||
| -------- | ---------- | ---- | -------- | ------------------------------------------------------------- |
|
||||
| 1 | `**kwargs` | 是 | 见下表 | 查询属性,必须包含 `stock`、`cycle`、`begin_time`、`end_time` |
|
||||
|
||||
| 参数名 | 必填 | 接收类型 | 默认值 | 说明 |
|
||||
| ------------- | ---- | ------------------------------------ | ---------------- | ------------------------------------------------ |
|
||||
| `stock` | 是 | `str` / 一维数组 | `None` | 当前股票代码;可指定多只股票 |
|
||||
| `cycle` | 是 | `str` | `"日线"` | 当前周期 |
|
||||
| `begin_time` | 是 | `datetime` / `int` / `float` / `str` | `None` | 数据开始时间 |
|
||||
| `end_time` | 是 | `datetime` / `int` / `float` / `str` | `None` | 数据结束时间 |
|
||||
| `fields` | 否 | `str` / `tuple` / `list` | 所有字段 | 查询字段;字符串用逗号分隔 |
|
||||
| `rate` | 否 | `int` | `0` | 复权方式:`0` 不复权,`1` 比例复权,`2` 复杂复权 |
|
||||
| `rateday` | 否 | `datetime` / `int` / `float` / `str` | `0` | 复权基准日 |
|
||||
| `precision` | 否 | `int` | `-1` | 浮点数精度 |
|
||||
| `viewpoint` | 否 | `datetime` / `int` / `float` / `str` | `0` | 仿真时点 |
|
||||
| `service` | 否 | `str` | 由登录服务器决定 | 指定执行服务节点 |
|
||||
| `timeout` | 否 | `int` | `None` | 超时,单位毫秒 |
|
||||
| `cyclefilter` | 否 | `int` | `0` | 周期过滤器以及集合竞价分离器 |
|
||||
|
||||
### 委托、任务管理和服务节点方法
|
||||
|
||||
#### `list_bgrun()`
|
||||
|
||||
| 参数位置 | 参数名 | 必填 | 接收类型 | 说明 |
|
||||
| -------- | ------ | ---- | -------- | ---------- |
|
||||
| 无 | 无 | 否 | 无 | 不接收参数 |
|
||||
|
||||
返回 `["+OK", [委托任务1], ...]`。委托任务结构为 `[handle, 执行的函数名, 开始执行时间, 已运行时间]`。
|
||||
|
||||
#### `stop_bgrun(handle)`
|
||||
|
||||
| 参数位置 | 参数名 | 必填 | 接收类型 | 说明 |
|
||||
| -------- | -------- | ---- | -------- | ------------ |
|
||||
| 1 | `handle` | 是 | `float` | 委托任务编号 |
|
||||
|
||||
返回整数,成功为 `1`。
|
||||
|
||||
#### `admin(**kwargs)`
|
||||
|
||||
| 参数位置 | 参数名 | 必填 | 接收类型 | 说明 |
|
||||
| -------- | ---------- | ---- | -------- | ----------------------------------------- |
|
||||
| 1 | `**kwargs` | 是 | `str` | 天软客户端任务管理命令,如 `"oa"`、`"ou"` |
|
||||
|
||||
返回对应指令的查询信息。
|
||||
|
||||
#### `set_callback(function)`
|
||||
|
||||
| 参数位置 | 参数名 | 必填 | 接收类型 | 说明 |
|
||||
| -------- | ---------- | ---- | ----------------- | -------------------- |
|
||||
| 1 | `function` | 是 | Python 可调用对象 | 设置 `rdo2` 回调函数 |
|
||||
|
||||
`rdo2 callback(...)` 调用时会回到 Python 函数;不要把已经通过 `register_proc` 注册过的函数再当作该回调。
|
||||
|
||||
#### `default_service(service)`
|
||||
|
||||
| 参数位置 | 参数名 | 必填 | 接收类型 | 说明 |
|
||||
| -------- | --------- | ---- | -------- | ---------------------------------------------- |
|
||||
| 1 | `service` | 否 | `str` | 为空时返回当前服务节点;非空时设置当前服务节点 |
|
||||
|
||||
返回字符串,内容为服务节点。
|
||||
|
||||
#### `server_list()`
|
||||
|
||||
| 参数位置 | 参数名 | 必填 | 接收类型 | 说明 |
|
||||
| -------- | ------ | ---- | -------- | ---------- |
|
||||
| 无 | 无 | 否 | 无 | 不接收参数 |
|
||||
|
||||
返回服务节点列表。
|
||||
|
||||
### 下载、上传和删除
|
||||
|
||||
#### 类型取值
|
||||
|
||||
| 类型值 | 可用于 | 说明 |
|
||||
| -------- | -------------------------------------------------- | ---------------- |
|
||||
| `0x2001` | `download_list` / `download` | 系统板块 |
|
||||
| `0x2002` | `download_list` / `download` / `upload` / `remove` | 用户板块 |
|
||||
| `0x5001` | `download_list` / `download` | 系统基本面表描述 |
|
||||
| `0x6001` | `download_list` / `download` / `upload` / `remove` | 用户函数 |
|
||||
| `0x6002` | `download_list` / `download` | 共享函数 |
|
||||
| `0x6003` | `download_list` / `download` | 系统公用函数 |
|
||||
| `0x6004` | `download_list` / `download` | 系统函数 |
|
||||
| `0x8001` | `download_list` / `download` / `upload` / `remove` | 用户数据表 |
|
||||
|
||||
#### `download_list(type, timeout=0)`
|
||||
|
||||
| 参数位置 | 参数名 | 必填 | 接收类型 | 说明 |
|
||||
| -------- | --------- | ---- | -------- | --------------------------------------- |
|
||||
| 1 | `type` | 是 | `int` | 指定类型 |
|
||||
| 2 | `timeout` | 否 | `int` | 超时,单位毫秒;默认 `0` 表示无超时限制 |
|
||||
|
||||
返回长度为 2 的列表。无错误返回 `[0, 结果列表]`,有错误返回 `[错误代码, 错误信息]`。结果列表中的单项结构为 `[关键字, 版本, 修改时间]`。
|
||||
|
||||
#### `download(type, key, ver=0, timeout=0)`
|
||||
|
||||
| 参数位置 | 参数名 | 必填 | 接收类型 | 说明 |
|
||||
| -------- | --------- | ---- | -------- | --------------------------------------- |
|
||||
| 1 | `type` | 是 | `int` | 指定类型 |
|
||||
| 2 | `key` | 是 | `str` | 关键字,如函数名、板块名 |
|
||||
| 3 | `ver` | 否 | `int` | 关键字版本;默认 `0` 表示最新版本 |
|
||||
| 4 | `timeout` | 否 | `int` | 超时,单位毫秒;默认 `0` 表示无超时限制 |
|
||||
|
||||
无错误返回 `[0, 结果]`,有错误返回 `[错误代码, 错误信息]`。结果结构包含:
|
||||
|
||||
| 键 | 说明 |
|
||||
| ---------------- | -------------------------------------------------------- |
|
||||
| `"data"` | 关键字内容,TSL 流格式,可用 `pyTSL.DecodeStream()` 转换 |
|
||||
| `"LastModified"` | 版本 |
|
||||
| `"LastTime"` | 修改时间 |
|
||||
|
||||
#### `upload(type, key, data, timeout=0)`
|
||||
|
||||
| 参数位置 | 参数名 | 必填 | 接收类型 | 说明 |
|
||||
| -------- | --------- | ---- | -------- | --------------------------------------- |
|
||||
| 1 | `type` | 是 | `int` | 只支持 `0x2002`、`0x6001`、`0x8001` |
|
||||
| 2 | `key` | 是 | `str` | 关键字,如函数名、板块名、用户数据名 |
|
||||
| 3 | `data` | 是 | `Any` | 上传至关键字的数据 |
|
||||
| 4 | `timeout` | 否 | `int` | 超时,单位毫秒;默认 `0` 表示无超时限制 |
|
||||
|
||||
无错误返回 `[0, 结果]`,有错误返回 `[错误代码, 错误信息]`。
|
||||
|
||||
#### `remove(type, key, timeout=0)`
|
||||
|
||||
| 参数位置 | 参数名 | 必填 | 接收类型 | 说明 |
|
||||
| -------- | --------- | ---- | -------- | --------------------------------------- |
|
||||
| 1 | `type` | 是 | `int` | 只支持 `0x2002`、`0x6001`、`0x8001` |
|
||||
| 2 | `key` | 是 | `str` | 关键字,如函数名、用户数据名 |
|
||||
| 3 | `timeout` | 否 | `int` | 超时,单位毫秒;默认 `0` 表示无超时限制 |
|
||||
|
||||
无错误返回 `[0, 结果]`,有错误返回 `[错误代码, 错误信息]`。
|
||||
|
||||
## `pyTSL.AsyncClient`
|
||||
|
||||
异步客户端,适用于 Python `asyncio`。与 `Client` 一样会占用登录数;异步任务数量受账号并发数限制,普通账号常见并发数为 5,应保留资源。
|
||||
|
||||
构造方式同 `Client`:
|
||||
|
||||
```python
|
||||
pyTSL.AsyncClient("user", "password", "tsl.tinysoft.com.cn", 443)
|
||||
pyTSL.AsyncClient("E:\\my.ini")
|
||||
```
|
||||
|
||||
也支持空构造后复用已有 `Client`:
|
||||
|
||||
```python
|
||||
c = pyTSL.Client("user", "password", "tsl.tinysoft.com.cn", 443)
|
||||
ac = pyTSL.AsyncClient()
|
||||
ac.c = c
|
||||
```
|
||||
|
||||
| 方法 | 签名 | 返回 | 参数来源 |
|
||||
| --------------- | --------------------------------------- | --------------- | -------------------------------- |
|
||||
| `login` | `login()` | `bool` | 无参数;成功 `1`,失败 `0` |
|
||||
| `logout` | `logout()` | `int` | 无参数;成功 `0` |
|
||||
| `exec` | `exec(code, **kwargs)` | `TSResultValue` | 同 `Client.exec` |
|
||||
| `call` | `call(funcname, *args, **kwargs)` | `TSResultValue` | 同 `Client.call` |
|
||||
| `query` | `query(**kwargs)` | `TSResultValue` | 同 `Client.query` |
|
||||
| `admin` | `admin(**kwargs)` | `str` | 同 `Client.admin` |
|
||||
| `download_list` | `download_list(type, timeout=0)` | `list` | 同 `Client.download_list` |
|
||||
| `download` | `download(type, key, ver=0, timeout=0)` | `list` | 同 `Client.download` |
|
||||
| `upload` | `upload(type, key, data, timeout=0)` | `list` | 同 `Client.upload` |
|
||||
| `remove` | `remove(type, key, timeout=0)` | `list` | 同 `Client.remove` |
|
||||
| `task_list` | `task_list()` | `list` | 返回异步任务列表 |
|
||||
| `task_cancel` | `task_cancel(task)` | `int` | 取消异步任务;成功 `1`,失败 `0` |
|
||||
|
||||
最小异步示例:
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
import pyTSL
|
||||
from datetime import datetime
|
||||
|
||||
async def main():
|
||||
c = pyTSL.AsyncClient("user", "password", "tsl.tinysoft.com.cn", 443)
|
||||
try:
|
||||
if await c.login() == 0:
|
||||
raise RuntimeError("login failed")
|
||||
r = await c.exec("return close();", stock="SZ000002", time=datetime(2024, 7, 30))
|
||||
if r.error():
|
||||
raise RuntimeError(r.message())
|
||||
return r.value()
|
||||
finally:
|
||||
await c.logout()
|
||||
|
||||
value = asyncio.run(main())
|
||||
```
|
||||
|
||||
## `pyTSL.async_util`
|
||||
|
||||
`async_util` 把普通 `Client` 的操作包装为可 `await` 的函数。所有函数第一个参数都是 `pyTSL.Client` 实例。
|
||||
|
||||
| 函数 | 签名 | 返回 | 对应同步方法 |
|
||||
| --------------------- | ------------------------------------------------ | --------------- | ---------------------- |
|
||||
| `async_login` | `async_login(c)` | `bool` | `c.login()` |
|
||||
| `async_logout` | `async_logout(c)` | `int` | `c.logout()` |
|
||||
| `async_exec` | `async_exec(c, code, **kwargs)` | `TSResultValue` | `c.exec(...)` |
|
||||
| `async_call` | `async_call(c, funcname, *args, **kwargs)` | `TSResultValue` | `c.call(...)` |
|
||||
| `async_query` | `async_query(c, **kwargs)` | `TSResultValue` | `c.query(...)` |
|
||||
| `async_admin` | `async_admin(c, **kwargs)` | `str` | `c.admin(...)` |
|
||||
| `async_download_list` | `async_download_list(c, type, timeout=0)` | `list` | `c.download_list(...)` |
|
||||
| `async_download` | `async_download(c, type, key, ver=0, timeout=0)` | `list` | `c.download(...)` |
|
||||
| `async_upload` | `async_upload(c, type, key, data, timeout=0)` | `list` | `c.upload(...)` |
|
||||
| `async_remove` | `async_remove(c, type, key, timeout=0)` | `list` | `c.remove(...)` |
|
||||
|
||||
## pyTSL 全局方法
|
||||
|
||||
### `DatetimeToDouble(datetime, timezone=8)`
|
||||
|
||||
| 参数位置 | 参数名 | 必填 | 接收类型 | 说明 |
|
||||
| -------- | ---------- | ---- | ------------------------------------- | -------------------------- |
|
||||
| 1 | `datetime` | 是 | `datetime.date` / `datetime.datetime` | Python 日期或日期时间 |
|
||||
| 2 | `timezone` | 否 | `int` | 时区,默认 `8`,即北京时间 |
|
||||
|
||||
返回 TSL 的时间类型 `TDateTime`,精度到毫秒。
|
||||
|
||||
### `DoubleToDatetime(t)`
|
||||
|
||||
| 参数位置 | 参数名 | 必填 | 接收类型 | 说明 |
|
||||
| -------- | ------ | ---- | --------------------- | ------------ |
|
||||
| 1 | `t` | 是 | `TDateTime` / `float` | TSL 时间类型 |
|
||||
|
||||
返回 Python `datetime`,精度到毫秒。
|
||||
|
||||
### `DataFrameDiff(df1, df2)`
|
||||
|
||||
| 参数位置 | 参数名 | 必填 | 接收类型 | 说明 |
|
||||
| -------- | ------ | ---- | ------------------ | ------------------------------------- |
|
||||
| 1 | `df1` | 是 | `pandas.DataFrame` | 第一个 DataFrame,结构需与 `df2` 一致 |
|
||||
| 2 | `df2` | 是 | `pandas.DataFrame` | 第二个 DataFrame,结构需与 `df1` 一致 |
|
||||
|
||||
返回两个 DataFrame 的不同数据以及行列位置。
|
||||
|
||||
### `EncodeStream(obj)`
|
||||
|
||||
| 参数位置 | 参数名 | 必填 | 接收类型 | 说明 |
|
||||
| -------- | ------ | ---- | ----------- | -------------------- |
|
||||
| 1 | `obj` | 是 | Python 变量 | 要转换的 Python 对象 |
|
||||
|
||||
返回 TSL 流格式。
|
||||
|
||||
### `DecodeStream(bytes, parse_date=False)`
|
||||
|
||||
| 参数位置 | 参数名 | 必填 | 接收类型 | 说明 |
|
||||
| -------- | ------------ | ---- | ------------------------- | ------------------------------------ |
|
||||
| 1 | `bytes` | 是 | TSL 流格式 | 要解码的 TSL 流 |
|
||||
| 2 | `parse_date` | 否 | `bool` / `list` / `tuple` | 是否把日期字段转成 Python `datetime` |
|
||||
|
||||
`parse_date` 取值:
|
||||
|
||||
| 取值 | 说明 |
|
||||
| ------------------------ | ------------------------------------------------------- |
|
||||
| `False` | 默认值,不转换,TSL `TDateTime` 保持实数 |
|
||||
| `True` | 将 TSL `TDateTime` 或日期字符串转换为 Python `datetime` |
|
||||
| `["date"]` / `("date",)` | 只转换指定字段 |
|
||||
|
||||
返回 Python 变量。
|
||||
|
||||
### `register_proc(funcname1, funcname2)`
|
||||
|
||||
| 参数位置 | 参数名 | 必填 | 接收类型 | 说明 |
|
||||
| -------- | ----------- | ---- | ----------------- | ------------------------ |
|
||||
| 1 | `funcname1` | 是 | `str` | TSL 本地调用时使用的名称 |
|
||||
| 2 | `funcname2` | 是 | Python 可调用对象 | Python 中定义的函数 |
|
||||
|
||||
将 Python 函数注册为天软函数,可在交互语句中用 `rdo2` 调用。`importfile` 和 `exportfile` 已有默认实现,不要注册同名函数。
|
||||
|
||||
### `DataFrameToTSArray(DataFrame)`
|
||||
|
||||
| 参数位置 | 参数名 | 必填 | 接收类型 | 说明 |
|
||||
| -------- | ----------- | ---- | ------------------ | ------------------ |
|
||||
| 1 | `DataFrame` | 是 | `pandas.DataFrame` | 要转换的 DataFrame |
|
||||
|
||||
返回 TSL 的 `array` 数据结构。`Client.call()` 传入 DataFrame 时也会自动转换。
|
||||
|
||||
### `start_network_threads(n)`
|
||||
|
||||
| 参数位置 | 参数名 | 必填 | 接收类型 | 说明 |
|
||||
| -------- | ------ | ---- | -------- | ---------------------------- |
|
||||
| 1 | `n` | 是 | `int` | 额外启动的网络 IO 处理线程数 |
|
||||
|
||||
返回 `None`。pyTSL 默认有 1 个线程处理网络 IO;多连接场景可以增加线程。
|
||||
|
||||
## `pyTSL.Batch`
|
||||
|
||||
用于并发执行多个天软任务,只占用一个登录数。并发数受账号资源限制,不是越大越好;普通账号常见并发数为 5,建议保守设置。
|
||||
|
||||
### 构造函数
|
||||
|
||||
签名:
|
||||
|
||||
```python
|
||||
pyTSL.Batch(parallel=5, reconnect=0)
|
||||
```
|
||||
|
||||
| 参数位置 | 参数名 | 必填 | 接收类型 | 说明 |
|
||||
| -------- | ----------- | ---- | -------- | ---------------------------------------------------- |
|
||||
| 1 | `parallel` | 否 | `int` | 并行任务数,默认 `5` |
|
||||
| 2 | `reconnect` | 否 | `int` | 是否重新连接;`0` 不重新连接,`1` 重新连接,默认 `0` |
|
||||
|
||||
### Batch 方法
|
||||
|
||||
| 方法 | 签名 | 返回 | 说明 |
|
||||
| --------- | --------------------------------------------- | ------ | ------------------------------------------------ |
|
||||
| `exec` | `exec(client, code, **kwargs)` | `list` | 并发执行 TSL 代码串 |
|
||||
| `call` | `call(client, functionname, *args, **kwargs)` | `list` | 并发调用 TSL 函数 |
|
||||
| `query` | `query(client, **kwargs)` | `list` | 并发查询行情数据 |
|
||||
| `__len__` | `__len__()` | `int` | 通过 `len(iter(batch))` 返回迭代器中剩余元素个数 |
|
||||
|
||||
`Batch.exec()` 参数:
|
||||
|
||||
| 参数位置 | 参数名 | 必填 | 接收类型 | 说明 |
|
||||
| -------- | ---------- | ---- | ---------------- | ------------------------------ |
|
||||
| 1 | `client` | 是 | `pyTSL.Client` | 已构造的客户端实例 |
|
||||
| 2 | `code` | 是 | `str` | TSL 代码串 |
|
||||
| 3 | `**kwargs` | 否 | 见 `Client.exec` | 不支持委托执行;额外支持 `key` |
|
||||
|
||||
`Batch.call()` 参数:
|
||||
|
||||
| 参数位置 | 参数名 | 必填 | 接收类型 | 说明 |
|
||||
| -------- | -------------- | ---- | ---------------- | ------------------------------ |
|
||||
| 1 | `client` | 是 | `pyTSL.Client` | 已构造的客户端实例 |
|
||||
| 2 | `functionname` | 是 | `str` | TSL 函数名 |
|
||||
| 3 | `*args` | 否 | 见 `Client.call` | 传给 TSL 函数的位置参数 |
|
||||
| 4 | `**kwargs` | 否 | 见 `Client.call` | 不支持委托执行;额外支持 `key` |
|
||||
|
||||
`Batch.query()` 参数:
|
||||
|
||||
| 参数位置 | 参数名 | 必填 | 接收类型 | 说明 |
|
||||
| -------- | ---------- | ---- | ----------------- | ------------------------------ |
|
||||
| 1 | `client` | 是 | `pyTSL.Client` | 已构造的客户端实例 |
|
||||
| 2 | `**kwargs` | 是 | 见 `Client.query` | 不支持委托执行;额外支持 `key` |
|
||||
|
||||
`key` 参数:
|
||||
|
||||
| 参数名 | 必填 | 接收类型 | 默认值 | 说明 |
|
||||
| ------ | ---- | -------- | ------ | ------------------------------------------------- |
|
||||
| `key` | 否 | `str` | `""` | 标识每个任务;也可通过返回的 `Task.key(str)` 设置 |
|
||||
|
||||
返回结构:
|
||||
|
||||
| 情况 | 返回 |
|
||||
| -------- | --------------------- |
|
||||
| 提交成功 | `[1, Task对象]` |
|
||||
| 提交失败 | `[0, 错误信息字符串]` |
|
||||
|
||||
结果读取:
|
||||
|
||||
```python
|
||||
for r in iter(batch):
|
||||
print(r.key(), r.value())
|
||||
```
|
||||
|
||||
遍历时每个 `r` 是 `TSResultValue`。
|
||||
|
||||
## `pyTSL.Task`
|
||||
|
||||
`Batch` 执行任务的标识。
|
||||
|
||||
| 方法 | 签名 | 返回 | 说明 |
|
||||
| ----- | --------------- | ----- | ------------------------------------------ |
|
||||
| `id` | `id()` | `int` | 返回任务 ID |
|
||||
| `key` | `key(str=None)` | `str` | 有参数时设置关键字;无参数时返回当前关键字 |
|
||||
|
||||
## `TSResultValue`
|
||||
|
||||
`Client.exec()`、`Client.call()`、`Client.query()`、异步方法和 `Batch` 迭代结果都会返回或产出 `TSResultValue`。
|
||||
|
||||
| 方法 | 签名 | 返回 | 说明 |
|
||||
| ----------- | ------------------------- | -------------------- | --------------------------------------- |
|
||||
| `error` | `error()` | `int` | `0` 表示无错误,非 `0` 表示出错 |
|
||||
| `message` | `message()` | `str` | 有错误时返回错误信息,无错误时为空 |
|
||||
| `value` | `value(parse_date=False)` | `list` / 标量 / 对象 | 返回结果值 |
|
||||
| `dataframe` | `dataframe()` | `pandas.DataFrame` | 输出 DataFrame;相当于把 `value()` 转表 |
|
||||
| `stream` | `stream()` | TSL 流格式 | 返回 TSL 流格式结果 |
|
||||
| `stn` | `stn()` | `str` | 返回 TSL STN 格式结果 |
|
||||
| `key` | `key()` | `str` | 返回任务关键字,配合 `Batch` 使用 |
|
||||
| `cancelled` | `cancelled()` | `bool` | 返回任务是否被取消 |
|
||||
|
||||
`value(parse_date=...)`:
|
||||
|
||||
| 取值 | 说明 |
|
||||
| ------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
|
||||
| `False` | 默认值,不转换日期,TSL `TDateTime` 保持实数 |
|
||||
| `True` | 将一维数组或单个值中的 TSL 日期时间、日期字符串转换为 Python `datetime`;`query()` 的默认行为是转换日期 |
|
||||
| `["date1", "date2"]` / `("date1", "date2")` | 对二维数组或表格中的指定日期字段做转换 |
|
||||
|
||||
推荐错误处理:
|
||||
|
||||
```python
|
||||
r = c.exec("return 1 + 1;")
|
||||
if r.error():
|
||||
raise RuntimeError(r.message())
|
||||
value = r.value()
|
||||
```
|
||||
|
||||
## `pyTSL.Const`
|
||||
|
||||
常量模块包含周期、行情字段、文件导入导出类型和文件读写类型。导入方式:
|
||||
|
||||
```python
|
||||
from pyTSL.Const import *
|
||||
```
|
||||
|
||||
### 周期常量
|
||||
|
||||
| 常量 | 对应值 |
|
||||
| ------------- | ---------------- |
|
||||
| `cy_month` | `"月线"` |
|
||||
| `cy_day` | `"日线"` |
|
||||
| `cy_week` | `"周线"` |
|
||||
| `cy_quarter` | `"季线"` |
|
||||
| `cy_halfyear` | `"半年线"` |
|
||||
| `cy_1m` | `"1分钟线"` |
|
||||
| `cy_2m` | `"2分钟线"` |
|
||||
| `cy_3m` | `"3分钟线"` |
|
||||
| `cy_5m` | `"5分钟线"` |
|
||||
| `cy_10m` | `"10分钟线"` |
|
||||
| `cy_15m` | `"15分钟线"` |
|
||||
| `cy_20m` | `"20分钟线"` |
|
||||
| `cy_30m` | `"30分钟线"` |
|
||||
| `cy_40m` | `"40分钟线"` |
|
||||
| `cy_60m` | `"60分钟线"` |
|
||||
| `cy_120m` | `"120分钟线"` |
|
||||
| `cy_detail` | `"成交明细"` |
|
||||
| `cy_halfs` | `"半秒线"` |
|
||||
| `cy_1s` | `"1秒线"` |
|
||||
| `cy_2s` | `"2秒线"` |
|
||||
| `cy_3s` | `"3秒线"` |
|
||||
| `cy_4s` | `"4秒线"` |
|
||||
| `cy_5s` | `"5秒线"` |
|
||||
| `cy_6s` | `"6秒线"` |
|
||||
| `cy_10s` | `"10秒线"` |
|
||||
| `cy_12s` | `"12秒线"` |
|
||||
| `cy_15s` | `"15秒线"` |
|
||||
| `cy_20s` | `"20秒线"` |
|
||||
| `cy_30s` | `"30秒线"` |
|
||||
| `cy_f30m` | `"期货30分钟线"` |
|
||||
| `cy_f60m` | `"期货60分钟线"` |
|
||||
|
||||
### 行情字段常量
|
||||
|
||||
| 常量 | 字段值 | 说明 |
|
||||
| ----------------------- | ------------------------- | -------------------- |
|
||||
| `STOCKID` | `"StockID"` | 股票代码 |
|
||||
| `STOCKNAME` | `"StockName"` | 股票名称 |
|
||||
| `DATE` | `"date"` | 当前时间 |
|
||||
| `PRICE` | `"price"` | 价格 |
|
||||
| `CLOSE` | `"close"` | 收盘价 |
|
||||
| `OPEN` | `"open"` | 开盘价 |
|
||||
| `HIGH` | `"high"` | 最高价 |
|
||||
| `LOW` | `"low"` | 最低价 |
|
||||
| `VOL` | `"vol"` | 成交量 |
|
||||
| `AMOUNT` | `"amount"` | 成交金额 |
|
||||
| `CJBS` | `"cjbs"` | 成交笔数 |
|
||||
| `YCLOSE` | `"yclose"` | 上次价 |
|
||||
| `SYL1` | `"syl1"` | 市盈率 1 |
|
||||
| `SYL2` | `"syl2"` | 市盈率 2 |
|
||||
| `BUY1` | `"buy1"` | 买一价 |
|
||||
| `BUY2` | `"buy2"` | 买二价 |
|
||||
| `BUY3` | `"buy3"` | 买三价 |
|
||||
| `BUY4` | `"buy4"` | 买四价 |
|
||||
| `BUY5` | `"buy5"` | 买五价 |
|
||||
| `SALE1` | `"sale1"` | 卖一价 |
|
||||
| `SALE2` | `"sale2"` | 卖二价 |
|
||||
| `SALE3` | `"sale3"` | 卖三价 |
|
||||
| `SALE4` | `"sale4"` | 卖四价 |
|
||||
| `SALE5` | `"sale5"` | 卖五价 |
|
||||
| `BC1` | `"bc1"` | 买一量 |
|
||||
| `BC2` | `"bc2"` | 买二量 |
|
||||
| `BC3` | `"bc3"` | 买三量 |
|
||||
| `BC4` | `"bc4"` | 买四量 |
|
||||
| `BC5` | `"bc5"` | 买五量 |
|
||||
| `SC1` | `"sc1"` | 卖一量 |
|
||||
| `SC2` | `"sc2"` | 卖二量 |
|
||||
| `SC3` | `"sc3"` | 卖三量 |
|
||||
| `SC4` | `"sc4"` | 卖四量 |
|
||||
| `SC5` | `"sc5"` | 卖五量 |
|
||||
| `WB` | `"wb"` | 委比 |
|
||||
| `LB` | `"lb"` | 量比 |
|
||||
| `ZMM` | `"zmm"` | 买卖标识 |
|
||||
| `BUY_VOL` | `"buy_vol"` | 主买量 |
|
||||
| `BUY_AMOUNT` | `"buy_amount"` | 主买金额 |
|
||||
| `SALE_VOL` | `"sale_vol"` | 主卖量 |
|
||||
| `SALE_AMOUNT` | `"sale_amount"` | 主卖金额 |
|
||||
| `W_BUY` | `"w_buy"` | 委买 |
|
||||
| `W_SALE` | `"w_sale"` | 委卖 |
|
||||
| `SECTIONAL_BUY_VOL` | `"sectional_buy_vol"` | 时点当日累计主买量 |
|
||||
| `SECTIONAL_BUY_AMOUNT` | `"sectional_buy_amount"` | 时点当日累计主买金额 |
|
||||
| `SECTIONAL_SALE_VOL` | `"sectional_sale_vol"` | 时点当日累计主卖量 |
|
||||
| `SECTIONAL_SALE_AMOUNT` | `"sectional_sale_amount"` | 时点当日累计主卖金额 |
|
||||
| `SECTIONAL_W_BUY` | `"sectional_w_buy"` | 时点当日累计委买 |
|
||||
| `SECTIONAL_W_SALE` | `"sectional_w_sale"` | 时点当日累计委卖 |
|
||||
| `SECTIONAL_YCLOSE` | `"sectional_yclose"` | 前日收盘 |
|
||||
| `SECTIONAL_OPEN` | `"sectional_open"` | 时点当日开盘 |
|
||||
| `SECTIONAL_HIGH` | `"sectional_high"` | 时点当日最高 |
|
||||
| `SECTIONAL_LOW` | `"sectional_low"` | 时点当日最低 |
|
||||
| `SECTIONAL_VOL` | `"sectional_vol"` | 时点当日累计成交量 |
|
||||
| `SECTIONAL_AMOUNT` | `"sectional_amount"` | 时点当日累计成交金额 |
|
||||
| `SECTIONAL_CJBS` | `"sectional_cjbs"` | 时点当日累计成交笔数 |
|
||||
| `SECTIONAL_WB` | `"sectional_wb"` | 时点当日累计委比 |
|
||||
|
||||
### 文件导入导出类型常量
|
||||
|
||||
| 常量 | 值 | 说明 |
|
||||
| ---------- | --- | --------------------------- |
|
||||
| `ftCSV` | `0` | 逗号分割文件类型 |
|
||||
| `ftXLS` | `1` | Excel 文件类型 |
|
||||
| `ftStream` | `2` | 天软对象流文件类型 |
|
||||
| `ftString` | `3` | 天软对象字符串文件类型 |
|
||||
| `ftADO` | `4` | ADO 文件类型 |
|
||||
| `ftXML` | `5` | XML 文件类型 |
|
||||
| `ftXLS2` | `6` | 支持多表头的 Excel 文件类型 |
|
||||
| `ftXLS3` | `7` | Excel 文件类型 |
|
||||
| `ftDBF` | `8` | DBF 文件类型 |
|
||||
|
||||
### 文件读写类型常量
|
||||
|
||||
| 常量 | 值 | 说明 |
|
||||
| ---------- | --- | ---------------- |
|
||||
| `rwByte` | `0` | 字节流读写类型 |
|
||||
| `rwInt` | `1` | 整数流读写类型 |
|
||||
| `rwReal` | `2` | 实数流读写类型 |
|
||||
| `rwStr` | `3` | 字符串流读写类型 |
|
||||
| `rwObj` | `4` | 对象流读写类型 |
|
||||
| `rwRaw` | `5` | 原始读写类型 |
|
||||
| `rwBinary` | `6` | 二进制读写类型 |
|
||||
|
||||
## `query` 周期与字段
|
||||
|
||||
### 周期字符串
|
||||
|
||||
| 分类 | 可用值 |
|
||||
| ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| 低频 | `"日线"`、`"周线"`、`"月线"`、`"季线"`、`"半年线"`、`"年线"` |
|
||||
| 高频 | `"1分钟线"`、`"2分钟线"`、`"3分钟线"`、`"5分钟线"`、`"10分钟线"`、`"15分钟线"`、`"20分钟线"`、`"30分钟线"`、`"40分钟线"`、`"60分钟线"`、`"120分钟线"` |
|
||||
| 超高频 | `"成交明细"`、`"半秒线"`、`"1秒线"`、`"2秒线"`、`"3秒线"`、`"4秒线"`、`"5秒线"`、`"6秒线"`、`"10秒线"`、`"12秒线"`、`"15秒线"`、`"20秒线"`、`"30秒线"` |
|
||||
| 其他 | `"任意周期"`、`"期货30分钟线"`、`"期货60分钟线"` |
|
||||
|
||||
### 低频字段
|
||||
|
||||
| 字段 | 数据类型 | 名称 | 说明 |
|
||||
| ----------- | ---------- | -------- | ------------------------------------------------------------------ |
|
||||
| `StockID` | `string` | 代码 | 股票 ID |
|
||||
| `StockName` | `string` | 名称 | 股票名称 |
|
||||
| `date` | `datetime` | 日期 | 当前时间 |
|
||||
| `price` | `real` | 最新价 | 该周期内最后一笔成交价 |
|
||||
| `open` | `real` | 开盘价 | 交易所公布的开盘价 |
|
||||
| `close` | `real` | 收盘价 | 交易所公布的收盘价 |
|
||||
| `high` | `real` | 最高价 | 周期内最高价 |
|
||||
| `low` | `real` | 最低价 | 周期内最低价 |
|
||||
| `vol` | `real` | 成交量 | 周期内成交量;股票单位为股,基金单位为份,期货和期权单位为合约数量 |
|
||||
| `amount` | `real` | 成交金额 | 周期内成交金额 |
|
||||
| `cjbs` | `real` | 成交笔数 | 股票为成交笔数;期货/期权可表示持仓变动量,日线表示当日持仓量 |
|
||||
| `yclose` | `real` | 系统昨收 | 交易所发布的考虑分红送股后的价格 |
|
||||
| `syl1` | `real` | 市盈率 1 | 期货/期权日线表示当日结算价;其他通常为 `0` |
|
||||
| `syl2` | `real` | 市盈率 2 | 期货/期权表示昨日结算价;ETF/LOF 表示时点净值;其他通常为 `0` |
|
||||
|
||||
### 高频与 Level1 字段
|
||||
|
||||
| 字段 | 数据类型 | 名称 | 说明 |
|
||||
| ----------------------- | ---------- | -------------------- | --------------------------------------------------------------------------------------------------- |
|
||||
| `StockID` | `string` | 代码 | 股票 ID |
|
||||
| `StockName` | `string` | 名称 | 股票名称 |
|
||||
| `date` | `datetime` | 时间 | 当前时间 |
|
||||
| `price` | `real` | 价格 | 交易明细为该时间点最后一笔成交价;其他为该周期最后一笔成交价 |
|
||||
| `vol` | `real` | 成交量 | 周期内成交量;分钟周期表示该分钟成交量,不是开盘累计 |
|
||||
| `amount` | `real` | 成交金额 | 周期内成交金额;分钟周期表示该分钟成交金额 |
|
||||
| `cjbs` | `real` | 成交笔数 | 股票为成交笔数;期货/期权为周期内持仓变动量 |
|
||||
| `yclose` | `real` | 上次价 | 上一周期的收盘价 |
|
||||
| `syl1` | `real` | 市盈率 1 | 期货/期权分钟线或秒线中,当日结算价存储在当日最后成交记录中;其他通常为 `0` |
|
||||
| `syl2` | `real` | 市盈率 2 | 期货/期权为昨日结算价;ETF/LOF 为时点净值;其他通常为 `0` |
|
||||
| `buy1` 至 `buy5` | `real` | 买一价至买五价 | 期货没有 `buy2` 至 `buy5` |
|
||||
| `sale1` 至 `sale5` | `real` | 卖一价至卖五价 | 期货没有 `sale2` 至 `sale5` |
|
||||
| `bc1` 至 `bc5` | `int` | 买一量至买五量 | 对应价位的委买量 |
|
||||
| `sc1` 至 `sc5` | `int` | 卖一量至卖五量 | 对应价位的委卖量 |
|
||||
| `wb` | `real` | 委比 | 公式为委买/委卖 |
|
||||
| `lb` | `int` | 量比 | 秒线取交易明细最后一笔;1 分钟线按过去 5 日均量和当日累计开市时间计算;其他分钟线取周期内最后一分钟 |
|
||||
| `zmm` | `int` | 买卖标识 | 交易明细中 `1` 主买,`2` 主卖,`3` 集合竞价/涨停/跌停等;非交易明细无意义 |
|
||||
| `buy_vol` | `real` | 主买量 | 主买成交量加买卖标识为 `3` 的成交量一半 |
|
||||
| `buy_amount` | `real` | 主买金额 | 主买成交金额加买卖标识为 `3` 的成交金额一半 |
|
||||
| `sale_vol` | `real` | 主卖量 | 主卖成交量加买卖标识为 `3` 的成交量一半 |
|
||||
| `sale_amount` | `real` | 主卖金额 | 主卖成交金额加买卖标识为 `3` 的成交金额一半 |
|
||||
| `w_buy` | `real` | 委买 | 一个周期内的委买量 |
|
||||
| `w_sale` | `real` | 委卖 | 一个周期内的委卖量 |
|
||||
| `sectional_buy_vol` | `real` | 时点当日累计主买量 | 从开盘到当前时间的主买量之和 |
|
||||
| `sectional_buy_amount` | `real` | 时点当日累计主买金额 | 从开盘到当前时间的主买金额之和 |
|
||||
| `sectional_sale_vol` | `real` | 时点当日累计主卖量 | 从开盘到当前时间的主卖量之和 |
|
||||
| `sectional_sale_amount` | `real` | 时点当日累计主卖金额 | 从开盘到当前时间的主卖金额之和 |
|
||||
| `sectional_w_buy` | `real` | 时点当日累计委买 | 从开盘到当前时间的委买量之和 |
|
||||
| `sectional_w_sale` | `real` | 时点当日累计委卖 | 从开盘到当前时间的委卖量之和 |
|
||||
| `sectional_yclose` | `real` | 前日收盘 | 上一交易日收盘价,与 `yclose` 的“上一周期收盘价”不同 |
|
||||
| `sectional_open` | `real` | 时点当日开盘 | 今天开盘价 |
|
||||
| `sectional_high` | `real` | 时点当日最高 | 从开盘到当前时间的最高价 |
|
||||
| `sectional_low` | `real` | 时点当日最低 | 从开盘到当前时间的最低价 |
|
||||
| `sectional_vol` | `real` | 时点当日累计成交量 | 从开盘到当前时间成交量之和 |
|
||||
| `sectional_amount` | `real` | 时点当日累计成交金额 | 从开盘到当前时间成交金额之和 |
|
||||
| `sectional_cjbs` | `int` | 时点当日累计成交笔数 | 股票为成交笔数;股指期货/期权可表示市场现有持仓量 |
|
||||
| `sectional_wb` | `real` | 时点当日累计委比 | 当日累计委买/当日累计委卖 |
|
||||
|
||||
## 数据类型转换规则
|
||||
|
||||
| TSL | Python | TSL 转 Python | Python 转 TSL |
|
||||
| ------------ | ------------------ | --------------------------- | ---------------------------- |
|
||||
| 数值型 | `float` / `int` | 自动转换 | 自动转换 |
|
||||
| 字符串 | `str` | 自动转换 | 自动转换 |
|
||||
| 布尔型 | `bool` / `int` | 自动转换 | 自动转换为整数语义 |
|
||||
| 日期时间实数 | `datetime` | `pyTSL.DoubleToDatetime()` | `pyTSL.DatetimeToDouble()` |
|
||||
| `array` | `pandas.DataFrame` | `TSResultValue.dataframe()` | `pyTSL.DataFrameToTSArray()` |
|
||||
| TSL 流 | Python 变量 | `pyTSL.DecodeStream()` | `pyTSL.EncodeStream()` |
|
||||
|
||||
TSL 日期时间是一个实数,例如 `20240730.145533T` 对应日期和时间;`Client.call()` 中的日期时间参数可直接传 Python `datetime`,pyTSL 会自动转换。
|
||||
|
||||
## `pyTSLPy` 兼容模块
|
||||
|
||||
`pyTSLPy` 是用 `pyTSL` 实现旧版 `TSLPy3.pyd` 功能的兼容模块。安装命令:
|
||||
|
||||
```bash
|
||||
pip install pyTSLPy
|
||||
```
|
||||
|
||||
迁移入口:
|
||||
|
||||
```python
|
||||
import pyTSLPy as ts
|
||||
```
|
||||
|
||||
支持情况:
|
||||
|
||||
| 旧接口 | 支持情况 | 说明 |
|
||||
| ----------------------------------------------- | ---------- | --------------------------------------------- |
|
||||
| `DefaultConnectAndLogin` | 支持 | 通过配置文件登录 |
|
||||
| `ConnectServer` | 支持 | 连接服务器 |
|
||||
| `LoginServer` | 支持 | 登录用户 |
|
||||
| `Disconnect` | 支持 | 断开连接 |
|
||||
| `Logined` | 支持 | 判断是否连接 |
|
||||
| `SetService` | 支持 | 设置服务器类型 |
|
||||
| `GetService` | 支持 | 获得服务器类型 |
|
||||
| `RemoteExecute` | 不完全支持 | 不支持本地交互 |
|
||||
| `RemoteCallFunc` | 不完全支持 | 不支持本地交互 |
|
||||
| `EncodeDate` / `EncodeTime` / `EncodeDateTime` | 支持 | 在 Python 中构造 TSL 日期、时间、日期时间 |
|
||||
| `DecodeDate` / `DecodeTime` / `DecodeDateTime` | 支持 | 将 TSL 日期、时间、日期时间转换到 Python 数组 |
|
||||
| `SetComputeBitsOption` / `GetComputeBitsOption` | 暂不支持 | 计算服务器位数相关 |
|
||||
| `SetSysParam` / `GetSysParam` | 暂不支持 | 系统参数相关 |
|
||||
|
||||
如果旧代码使用本地交互函数,`pyTSLPy` 只直接支持 `ExportFile` 和 `ImportFile`;其他本地交互函数应通过 `pyTSL.register_proc()` 注册。
|
||||
|
||||
## 常见风险
|
||||
|
||||
- `import pyTSL` 失败并提示找不到模块时,Windows 先确认 VC 运行库。
|
||||
- 旧版本出现字符串对象分配错误时,先升级 pyTSL。
|
||||
- MacOS 导入报签名或权限问题时,需要按系统权限策略放开对应模块。
|
||||
- `Client(ini_file)` 路径含中文时,可传入 GBK 编码后的路径。
|
||||
- `logout()` 后再次执行 `Client` 方法可能自动重新登录;生成长期任务时遵循一次登录、多次交互。
|
||||
- pyTSL 返回值编码为 UTF-8,不需要再手动从 GBK 转码。
|
||||
- 使用代理时,代理需要支持 HTTP CONNECT;只支持应用层代理的环境需要使用官方协议网关方案。
|
||||
- Linux 旧版本在子进程场景可能出现网络线程初始化问题;应使用较新 pyTSL。
|
||||
- 非中国时区下日期时间转换有偏差时,使用 `DatetimeToDouble(datetime, timezone)` 显式指定时区。
|
||||
|
||||
## 常用示例
|
||||
|
||||
### 执行 TSL 代码串
|
||||
|
||||
```python
|
||||
import pyTSL
|
||||
|
||||
c = pyTSL.Client("user", "password", "tsl.tinysoft.com.cn", 443)
|
||||
try:
|
||||
if c.login() == 0:
|
||||
raise RuntimeError(c.last_error())
|
||||
|
||||
r = c.exec("return 1 + 1;")
|
||||
if r.error():
|
||||
raise RuntimeError(r.message())
|
||||
print(r.value())
|
||||
finally:
|
||||
c.logout()
|
||||
```
|
||||
|
||||
### 查询行情并转 DataFrame
|
||||
|
||||
```python
|
||||
import pyTSL
|
||||
from datetime import datetime
|
||||
|
||||
c = pyTSL.Client("user", "password", "tsl.tinysoft.com.cn", 443)
|
||||
try:
|
||||
if c.login() == 0:
|
||||
raise RuntimeError(c.last_error())
|
||||
|
||||
r = c.query(
|
||||
stock=["SZ000001", "SZ000002"],
|
||||
cycle="日线",
|
||||
begin_time=datetime(2020, 1, 1),
|
||||
end_time=datetime(2020, 3, 20),
|
||||
fields="StockID,StockName,date,close",
|
||||
)
|
||||
if r.error():
|
||||
raise RuntimeError(r.message())
|
||||
df = r.dataframe()
|
||||
finally:
|
||||
c.logout()
|
||||
```
|
||||
|
||||
### 通过 `code` 临时定义并调用 TSL 函数
|
||||
|
||||
```python
|
||||
import pyTSL
|
||||
from datetime import date
|
||||
|
||||
tsl_code = """
|
||||
function getValue(begt, endt);
|
||||
begin
|
||||
n := tradeDays(begt, endt);
|
||||
return nday(n, "date", dateToStr(spTime()), "close", close(), "vol", vol(), "amount", amount());
|
||||
end;
|
||||
"""
|
||||
|
||||
c = pyTSL.Client("user", "password", "tsl.tinysoft.com.cn", 443)
|
||||
try:
|
||||
if c.login() == 0:
|
||||
raise RuntimeError(c.last_error())
|
||||
|
||||
r = c.call("getValue", date(2019, 4, 10), date(2019, 4, 18), code=tsl_code, stock="SH000001", cycle="日线")
|
||||
if r.error():
|
||||
raise RuntimeError(r.message())
|
||||
df = r.dataframe()
|
||||
finally:
|
||||
c.logout()
|
||||
```
|
||||
|
||||
### 并发任务
|
||||
|
||||
```python
|
||||
import pyTSL
|
||||
|
||||
c = pyTSL.Client("user", "password", "tsl.tinysoft.com.cn", 443)
|
||||
try:
|
||||
if c.login() == 0:
|
||||
raise RuntimeError(c.last_error())
|
||||
|
||||
batch = pyTSL.Batch(3, 0)
|
||||
for stock in ["SH600028", "SH600030", "SH600036"]:
|
||||
ok, task = batch.exec(c, "return stockMarketValue(20240410T);", stock=stock, key=stock)
|
||||
if ok == 0:
|
||||
print(task)
|
||||
|
||||
for r in iter(batch):
|
||||
if r.error():
|
||||
print(r.key(), r.message())
|
||||
else:
|
||||
print(r.key(), r.value())
|
||||
finally:
|
||||
c.logout()
|
||||
```
|
||||
@@ -0,0 +1,615 @@
|
||||
# 策略回测框架 TSBackTesting
|
||||
|
||||
文档类型:模块 API 事实页
|
||||
是否可直接用于生成代码:是,但策略逻辑、交易数据来源、资金参数、费用参数和实际证券池必须来自用户需求或项目上下文
|
||||
遇到不确定时:[index.md](index.md)、[pytsl_api.md](pytsl_api.md)、[../codegen/dotnet/datawarehouse/](../codegen/dotnet/datawarehouse/)、项目实际接口定义
|
||||
|
||||
本页整理 `TSBackTesting` 回测框架的对象模型、成员变量、必须重写的方法、交易数据字段和查询接口。它负责告诉智能体“回测框架怎么组织代码、哪些属性控制行为、哪些方法可调用”,不负责替用户创造策略、证券池、费用口径或交易信号。
|
||||
|
||||
## 智能体 TSBackTesting 决策规则
|
||||
|
||||
- 用户要“写回测 / 策略回测 / 回测框架 / 组合回测 / 绩效评价 / 持仓和交易结果”时,优先使用本页。
|
||||
- 用户给的是目标持仓、目标比例、调仓、选股、多因子、行业中性,默认 `FGroupType := 1`。
|
||||
- 用户给的是成交明细、成交量、成交价、动作、高频交易、真实交易回放,默认 `FGroupType := 2`。
|
||||
- 用户做期权或期权组合策略回测时,只使用数量类组合,即 `FGroupType := 2`。
|
||||
- 写代码时默认新建 `TSBackTesting` 子类并重写 `GetTradeOrder(vEndT)`;只有自定义调仓周期时才重写 `GetTimeSeries()`。
|
||||
- 初始化对象时默认使用 `new MyBackTesting()`;`CreateObject("MyBackTesting")` 只作为兼容创建方式。
|
||||
- 调用顺序固定为:声明子类 -> 设置成员变量 -> `BackTest()` -> 查询结果。
|
||||
- 不要把 `BackTest()` 当成会自动生成策略信号;策略信号必须由 `GetTradeOrder(vEndT)` 返回。
|
||||
- 不要发明股票池、费用、基准、初始资金、调仓周期、成交价来源或结果指标;这些值必须来自用户需求或项目上下文。
|
||||
|
||||
## 最小代码骨架
|
||||
|
||||
下面骨架用于生成最小可运行结构;策略信号、资金参数和查询指标按用户需求替换。
|
||||
|
||||
```tsl
|
||||
type MyBackTesting = class(TSBackTesting)
|
||||
public
|
||||
function GetTradeOrder(vEndT); override;
|
||||
end;
|
||||
|
||||
function MyBackTesting.GetTradeOrder(vEndT); override;
|
||||
begin
|
||||
return -1;
|
||||
end;
|
||||
|
||||
function RunBackTest(begT, endT);
|
||||
begin
|
||||
obj := new MyBackTesting();
|
||||
obj.FBegT := begT;
|
||||
obj.FEndT := endT;
|
||||
obj.FCycle := cy_day();
|
||||
obj.FGroupType := 1;
|
||||
obj.FIniCash := 10000000;
|
||||
obj.FIndexId := "SH000300";
|
||||
obj.BackTest();
|
||||
return array(
|
||||
"资产配置": obj.GetAssetData(begT, endT),
|
||||
"持仓": obj.GetHoldData(begT, endT),
|
||||
"区间收益": obj.GetPortfolioReturn(begT, endT)
|
||||
);
|
||||
end;
|
||||
```
|
||||
|
||||
返回规则:
|
||||
|
||||
- `GetTradeOrder(vEndT)` 返回二维数组:表示当前时点的目标持仓或交易明细。
|
||||
- `GetTradeOrder(vEndT)` 返回空数组:比例类组合表示完全清仓。
|
||||
- `GetTradeOrder(vEndT)` 返回 `-1`:表示当前时点不调仓或不交易。
|
||||
|
||||
## 回测开发流程
|
||||
|
||||
| 步骤 | 动作 | 决策点 |
|
||||
| ---- | -------------------------------------------------------------------- | -------------------------------------- |
|
||||
| 1 | 继承 `TSBackTesting` | 必须声明子类 |
|
||||
| 2 | 重写 `GetTradeOrder(vEndT)` | 必须返回比例类目标持仓或数量类交易明细 |
|
||||
| 3 | 设置 `FBegT`、`FEndT`、`FCycle`、`FGroupType`、`FIniCash` 等成员变量 | 按策略类型设置 |
|
||||
| 4 | 调用 `BackTest()` | 触发时间序列循环、交易数据获取和清算 |
|
||||
| 5 | 调用查询接口 | 读取资产、持仓、交易、收益、风险指标 |
|
||||
|
||||
## 组合类别
|
||||
|
||||
| `FGroupType` | 组合类别 | 用户提供 | 典型场景 |
|
||||
| ------------ | ---------- | ------------------------------------------ | ------------------------------------------ |
|
||||
| `1` | 比例类组合 | 目标持仓、方向、目标比例;成交量由框架计算 | 单因子、多因子、行业选股、配置类策略 |
|
||||
| `2` | 数量类组合 | 成交明细、成交价、成交量、动作 | 技术指标、高频交易、真实交易回放、期权组合 |
|
||||
|
||||
## 交易数据字段
|
||||
|
||||
### 比例类组合字段
|
||||
|
||||
`FGroupType := 1` 时,`GetTradeOrder(vEndT)` 返回目标持仓和目标比例。
|
||||
|
||||
| 字段 | 必填 | 接收类型 | 说明 |
|
||||
| --------------- | ---- | ---------- | -------------------------------------------------------- |
|
||||
| `截止日` | 是 | `DateTime` | 通常等于 `vEndT` |
|
||||
| `代码` | 是 | 字符串 | 目标持仓证券代码 |
|
||||
| `方向` | 是 | 整数 | `1` 多单;`0` 空单;缺省时按多单处理 |
|
||||
| `比例(%)` | 是 | 数值 | 目标持仓比例;`FRateType <> -1` 时可由框架按配比方式计算 |
|
||||
| `成交价` | 否 | 数值 | 比例类通常由 `FPriceType` 或 `FPriceRateTo0` 决定 |
|
||||
| `乘数` | 否 | 数值 | 默认 `1` |
|
||||
| `保证金比例(%)` | 否 | 数值 | 默认 `100` |
|
||||
| `开仓费率(%)` | 是 | 数值 | 开仓费率;股票、基金常见默认 `0.1` |
|
||||
| `平仓费率(%)` | 是 | 数值 | 平仓费率;期货常见默认 `0.01` |
|
||||
|
||||
比例类方向值:
|
||||
|
||||
| 方向 | 含义 | 常见对应 |
|
||||
| ---- | ---- | ------------------------------------------------ |
|
||||
| `1` | 多单 | 股票多头、融资买入、融资偿还、期货买开、期货卖平 |
|
||||
| `0` | 空单 | 融券卖出、融券偿还、期货卖开、期货买平 |
|
||||
|
||||
比例类规则:
|
||||
|
||||
- 动作不由用户给定,框架根据目标持仓和当前持仓差值生成交易。
|
||||
- `FRateType := -1` 时,返回数据必须包含 `比例(%)`。
|
||||
- 一期比例合计不得超过 `100`。
|
||||
- 只想配置 `80%` 仓位时,直接让比例合计为 `80`;不要额外添加现金代码。
|
||||
- 完全清仓可返回空数组。
|
||||
|
||||
### 数量类组合字段
|
||||
|
||||
`FGroupType := 2` 时,`GetTradeOrder(vEndT)` 返回交易明细。
|
||||
|
||||
| 字段 | 必填 | 接收类型 | 说明 |
|
||||
| ----------------- | -------- | ---------- | -------------------------------------------------- |
|
||||
| `截止日` | 是 | `DateTime` | 通常等于 `vEndT` |
|
||||
| `代码` | 是 | 字符串 | 交易证券代码 |
|
||||
| `方向` | 是 | 整数 | `1` 多单;`0` 空单;缺省时按多单处理 |
|
||||
| `动作` | 是 | 整数 | `0` 开仓;`1` 平仓;缺省时按开仓处理 |
|
||||
| `成交量` | 条件必填 | 数值 | `FOpenVolType := 1` 或 `FCloseVolType := 1` 时提供 |
|
||||
| `资金` | 条件必填 | 数值 | `FOpenVolType := 2` 时提供 |
|
||||
| `剩余资金占比(%)` | 条件必填 | 数值 | `FOpenVolType := 3` 时提供 |
|
||||
| `平仓数量占比(%)` | 条件必填 | 数值 | `FCloseVolType := 2` 时提供 |
|
||||
| `成交价` | 是 | 数值 | 交易成交价 |
|
||||
| `乘数` | 否 | 数值 | 默认 `1` |
|
||||
| `保证金比例(%)` | 否 | 数值 | 默认 `100` |
|
||||
| `费率(%)` | 条件必填 | 数值 | `FFeeType := 1` 时提供 |
|
||||
| `费用` | 条件必填 | 数值 | `FFeeType := 2` 时提供;只适合数量类 |
|
||||
|
||||
数量类方向和动作:
|
||||
|
||||
| 交易含义 | 方向 | 动作 |
|
||||
| ------------- | ---- | ---- |
|
||||
| 买开 / 开多单 | `1` | `0` |
|
||||
| 卖平 / 平多单 | `1` | `1` |
|
||||
| 卖开 / 开空单 | `0` | `0` |
|
||||
| 买平 / 平空单 | `0` | `1` |
|
||||
|
||||
股票常见方向和动作:
|
||||
|
||||
| 交易含义 | 方向 | 动作 |
|
||||
| -------------- | ---- | ---- |
|
||||
| 买入、融资买入 | `1` | `0` |
|
||||
| 卖出、融资偿还 | `1` | `1` |
|
||||
| 融券卖出 | `0` | `0` |
|
||||
| 融券偿还 | `0` | `1` |
|
||||
|
||||
### 期权组合策略字段
|
||||
|
||||
期权组合策略使用数量类组合。
|
||||
|
||||
| 字段 | 必填 | 接收类型 | 说明 |
|
||||
| ------------------- | -------- | ---------- | -------------------------------------------------------- |
|
||||
| `组 ID` | 是 | 字符串 | 同一组合内成分合约使用同一个组 ID |
|
||||
| `截止日` | 是 | `DateTime` | 交易时点 |
|
||||
| `代码` | 是 | 字符串 | 期权或期货合约代码 |
|
||||
| `方向` | 是 | 整数 | `1` 权利仓或多单;`0` 义务仓或空单 |
|
||||
| `动作` | 是 | 整数 | `0` 开仓;`1` 平仓;`32` 构建期权组合;`33` 解锁期权组合 |
|
||||
| `成交价` | 是 | 数值 | 构建、解锁交易中可为任意大于 `0` 的实数 |
|
||||
| `成交量` | 是 | 数值 | 合约数量 |
|
||||
| `费率(%)` 或 `费用` | 条件必填 | 数值 | 由 `FFeeType` 决定 |
|
||||
| `乘数` | 否 | 数值 | 按品种设置 |
|
||||
| `保证金比例(%)` | 否 | 数值 | 按品种设置 |
|
||||
| `组合类型` | 条件必填 | 字符串 | 组合策略标识,如 `CNSJC`、`STD` 等 |
|
||||
|
||||
期权组合动作:
|
||||
|
||||
| 动作 | 含义 |
|
||||
| ---- | -------------------- |
|
||||
| `0` | 开仓 |
|
||||
| `1` | 平仓 |
|
||||
| `32` | 申请构建期权组合策略 |
|
||||
| `33` | 期权组合策略解锁 |
|
||||
|
||||
## 成员变量
|
||||
|
||||
### 基本设置
|
||||
|
||||
| 成员变量 | 类型 | 默认值 | 说明 |
|
||||
| ------------ | -------------- | ----------------------- | ---------------------- |
|
||||
| `FBegT` | `DateTime` | 当前系统时间往前推 1 年 | 回测开始时间 |
|
||||
| `FEndT` | `DateTime` | 当前系统时间 | 回测截止时间 |
|
||||
| `FCycle` | 字符串或周期值 | 月线 | 调仓或交易周期 |
|
||||
| `FGroupType` | 整数 | `1` | `1` 比例类;`2` 数量类 |
|
||||
| `FIndexId` | 字符串 | `SH000300` | 基准代码 |
|
||||
| `FIniCash` | 实数 | `10000000` | 初始资金,单位元 |
|
||||
|
||||
### 成交和费用
|
||||
|
||||
| 成员变量 | 类型 | 默认值 | 取值 |
|
||||
| ---------------- | ---- | ------ | --------------------------------------------------------------------------- |
|
||||
| `FPriceType` | 整数 | `3` | `-1` 自定义;`1` 时点价格;`2` 收盘价;`3` 日均价;`4` 开盘价;`5` 系统昨收 |
|
||||
| `FPriceType1` | 整数 | `3` | 多头开仓价 |
|
||||
| `FPriceType2` | 整数 | `3` | 多头平仓价 |
|
||||
| `FPriceType3` | 整数 | `3` | 空头开仓价 |
|
||||
| `FPriceType4` | 整数 | `3` | 空头平仓价 |
|
||||
| `FVolModType` | 整数 | `-1` | `0` 不取整;`-1` 按证券类型自适应取整 |
|
||||
| `FFeeType` | 整数 | `1` | `1` 费率法;`2` 费用法 |
|
||||
| `FLowestFeeType` | 整数 | `0` | `0` 不考虑最低费用;`1` 启用最低费用限制 |
|
||||
| `FLowestFee` | 实数 | `5.0` | 最低费用 |
|
||||
| `FOLowestFee` | 实数 | `5.0` | 开仓最低费用 |
|
||||
| `FCLowestFee` | 实数 | `5.0` | 平仓最低费用 |
|
||||
|
||||
取整规则:
|
||||
|
||||
| `FVolModType` | 股票买入 | 股票卖出 | 期货 | 基金 | 债券 |
|
||||
| ------------- | ------------ | ---------- | ---------- | ------------ | ----------- |
|
||||
| `-1` | 100 的整数倍 | 1 的整数倍 | 1 的整数倍 | 小数点后三位 | 10 的整数倍 |
|
||||
| `0` | 不取整 | 不取整 | 不取整 | 不取整 | 不取整 |
|
||||
|
||||
### 比例类专用
|
||||
|
||||
| 成员变量 | 类型 | 默认值 | 说明 |
|
||||
| ---------------------- | ---- | ----------------- | -------------------------------------------------- |
|
||||
| `FRateType` | 整数 | `4` | 比例类组合配比方式 |
|
||||
| `FSumOfRate` | 数值 | `100` | 比例类配比之和;可用于非满仓 |
|
||||
| `FFeeType2` | 整数 | `1` | 比例类费率来源 |
|
||||
| `FPriceRateTo0` | 整数 | `3` | 自定义成交价且目标持仓没有旧持仓证券时的清仓价类别 |
|
||||
| `FIndustryMethod` | 整数 | `0` | `0` 不行业中性;`1` 行业中性 |
|
||||
| `FIndustryType` | 整数 | `1` | 行业分类 |
|
||||
| `FAdjustPositionPrice` | 整数 | 等于 `FPriceType` | 比例类调仓价 |
|
||||
| `FAdjustPriceType` | 整数 | `0` | `0` 调仓价等于成交价;`1` 用户自设调仓价 |
|
||||
|
||||
`FRateType` 取值:
|
||||
|
||||
| 值 | 含义 | 规则 |
|
||||
| ---- | ------------------ | ---------------------------------- |
|
||||
| `-1` | 用户自定义 | `GetTradeOrder` 必须返回 `比例(%)` |
|
||||
| `0` | 总市值加权 | 按总市值分配 |
|
||||
| `1` | 流通市值加权 | 按流通市值分配 |
|
||||
| `4` | 等权重 | 每只证券等比例 |
|
||||
| `5` | 等股数 | 按等股数分配 |
|
||||
| `6` | 流通市值平方根加权 | 按流通市值平方根分配 |
|
||||
| `7` | 总市值平方根加权 | 按总市值平方根分配 |
|
||||
|
||||
`FPriceRateTo0` 取值:
|
||||
|
||||
| 值 | 含义 |
|
||||
| ---- | ---------------------------- |
|
||||
| `1` | 时点价格 |
|
||||
| `2` | 收盘价 |
|
||||
| `3` | 日均价 |
|
||||
| `4` | 开盘价 |
|
||||
| `5` | 系统昨收 |
|
||||
| `-1` | 用户重写 `GetClearancePrice` |
|
||||
|
||||
### 数量类专用
|
||||
|
||||
| 成员变量 | 类型 | 默认值 | 说明 |
|
||||
| --------------- | ---- | ------ | ------------ |
|
||||
| `FOpenVolType` | 整数 | `1` | 开仓数量类别 |
|
||||
| `FCloseVolType` | 整数 | `1` | 平仓数量类别 |
|
||||
|
||||
`FOpenVolType` 取值:
|
||||
|
||||
| 值 | 含义 | `GetTradeOrder` 字段 |
|
||||
| --- | -------------- | -------------------- |
|
||||
| `1` | 固定成交量法 | `成交量` |
|
||||
| `2` | 固定金额法 | `资金` |
|
||||
| `3` | 剩余资金占比法 | `剩余资金占比(%)` |
|
||||
|
||||
`FCloseVolType` 取值:
|
||||
|
||||
| 值 | 含义 | `GetTradeOrder` 字段 |
|
||||
| --- | ---------------- | -------------------- |
|
||||
| `1` | 固定成交量法 | `成交量` |
|
||||
| `2` | 可平仓数量占比法 | `平仓数量占比(%)` |
|
||||
|
||||
### 分红、配股和止盈止损
|
||||
|
||||
| 成员变量 | 类型 | 默认值 | 说明 |
|
||||
| ------------------- | ------ | -------- | --------------------------------------------------- |
|
||||
| `FDividendType` | 整数 | `0` | `0` 分红不再投资;`1` 分红再投资;`-1` 用户重载 |
|
||||
| `FDividendType2` | 整数 | `1` | 货币基金是否分红再投资 |
|
||||
| `FAllotmentType` | 整数 | `0` | `0` 不自动参与配股;`1` 自动参与配股;`-1` 用户重载 |
|
||||
| `FGLType` | 整数 | `-1` | `-1` 不止盈止损;`0` 低频止盈止损;`1` 日内止盈止损 |
|
||||
| `FMaxGainRatio` | 整数 | `10^8` | 止盈率,`FGLType` 为 `0` 或 `1` 时有效 |
|
||||
| `FMaxLossRatio` | 整数 | `-100` | 止损率,`FGLType` 为 `0` 或 `1` 时有效 |
|
||||
| `FMaxGainCondition` | 字符串 | `"CBJ"` | 止盈基准价表达式 |
|
||||
| `FMaxLossCondition` | 字符串 | `"CBJ"` | 止损基准价表达式 |
|
||||
| `FGainName` | 字符串 | `"止盈"` | 止盈交易备注 |
|
||||
| `FLossName` | 字符串 | `"止损"` | 止损交易备注 |
|
||||
|
||||
止盈止损规则:
|
||||
|
||||
- `FGLType := 0`:低频止盈止损,按交易日判断。
|
||||
- `FGLType := 1`:日内止盈止损,按当前时点价格判断。
|
||||
- 期权及期权组合策略不参与止盈止损。
|
||||
|
||||
### 交易约束
|
||||
|
||||
| 成员变量 | 类型 | 默认值 | 说明 |
|
||||
| ------------------- | ---- | ------ | ---------------------------------------- |
|
||||
| `FTradeOption` | 整数 | `0` | `0` 非交易日可交易;`1` 非交易日不可交易 |
|
||||
| `FNoZT` | 整数 | `0` | `0` 涨停可买入;`1` 涨停不可买入 |
|
||||
| `FNoDT` | 整数 | `0` | `0` 跌停可卖出;`1` 跌停不可卖出 |
|
||||
| `FNoOverSold` | 整数 | `0` | `0` 允许超卖;`1` 不允许超卖 |
|
||||
| `FPartialjy` | 整数 | `0` | `0` 超卖时可部分成交;`1` 超卖时不可卖出 |
|
||||
| `FMinVol` | 实数 | `-1` | 最小成交量 |
|
||||
| `FMinAmount` | 实数 | `-1` | 最小成交金额 |
|
||||
| `FMaxVolPercent` | 实数 | `-1` | 最大成交量占比 |
|
||||
| `FMaxAmountPercent` | 实数 | `-1` | 最大成交金额占比 |
|
||||
| `FMinBuyVol` | 实数 | `-1` | 最小买入数量 |
|
||||
| `FMinSellVol` | 实数 | `-1` | 最小卖出数量 |
|
||||
| `FMinBuyCash` | 实数 | `-1` | 最小买入金额 |
|
||||
| `FMinSellCash` | 实数 | `-1` | 最小卖出金额 |
|
||||
| `FMinBuyRatio` | 实数 | `-1` | 最小买入占比 |
|
||||
| `FMinSellRatio` | 实数 | `-1` | 最小卖出占比 |
|
||||
|
||||
被交易约束剔除的交易,通过 `GetDelTradeData(vBegT, vEndT)` 查询。
|
||||
|
||||
### 期权、衍生品和主力合约
|
||||
|
||||
| 成员变量 | 类型 | 默认值 | 说明 |
|
||||
| -------------------- | ---- | ------ | ---------------------------------------------------- |
|
||||
| `FOptionRs` | 整数 | `0` | `0` 盘后不自动构成备兑组合;`1` 盘后自动构成备兑组合 |
|
||||
| `FAMType` | 整数 | `0` | `0` 盘中不追加资金;`1` 盘中追加资金 |
|
||||
| `FAMType2` | 整数 | `0` | `0` 盘后不追加资金;`1` 盘后追加资金 |
|
||||
| `FWithdrawableRatio` | 数值 | `100` | 衍生品可提资金比例 |
|
||||
| `FTradeOfDelist` | 整数 | `1` | `0` 到期不自动平仓;`1` 到期自动平仓 |
|
||||
| `FMainFutureMap` | 整数 | `0` | `0` 主力连续合约不映射;`1` 映射到实际合约交易 |
|
||||
|
||||
### 输出和基准
|
||||
|
||||
| 成员变量 | 类型 | 默认值 | 说明 |
|
||||
| ----------------- | ------ | --------------------------- | ------------------------------------------------------ |
|
||||
| `FHisFlag` | 整数 | `1` | `0` 不输出历史持仓;`1` 输出历史持仓 |
|
||||
| `FVersionID` | 整数 | `1` | `1` 不输出本地;`2` 每日一个文件;`3` 所有数据一个文件 |
|
||||
| `FDestDir` | 字符串 | `"C:\\Test\\MyPortfolio\\"` | 本地输出目录 |
|
||||
| `FDateToStr` | 整数 | `0` | `0` 日期型;`1` 查询结果日期转字符串 |
|
||||
| `FHFDataOutPut` | 整数 | `0` | `0` 不输出高频每周期清算数据;`1` 输出 |
|
||||
| `FisCashToAdjust` | 整数 | `0` | `0` 不调整;`1` 现金小于 0 时调整买入量 |
|
||||
| `FOrdertype` | 整数 | `3` | 买入量调整顺序 |
|
||||
| `FBMType` | 整数 | `0` | `0` 单一基准;`1` 复合基准 |
|
||||
| `FBMDetail` | 数组 | `array()` | 复合基准成分,字段为 `代码`、`比例(%)` |
|
||||
| `FBMOption` | 整数 | `0` | `0` 累乘;`1` 累加 |
|
||||
|
||||
`FOrdertype` 取值:
|
||||
|
||||
| 值 | 资金分配顺序 |
|
||||
| --- | -------------------------------------------------- |
|
||||
| `0` | 资金先分配给符合交易约束的买入交易 |
|
||||
| `1` | 按交易约束后的交易顺序分配 |
|
||||
| `2` | 比例类按目标比例从小到大;数量类按成交金额从小到大 |
|
||||
| `3` | 比例类按目标比例从大到小;数量类按成交金额从大到小 |
|
||||
|
||||
复合基准示例:
|
||||
|
||||
```tsl
|
||||
obj.FBMType := 1;
|
||||
obj.FBMDetail := array(
|
||||
("代码": "SH000001", "比例(%)": 40),
|
||||
("代码": "SH000300", "比例(%)": 60)
|
||||
);
|
||||
obj.FBMOption := 0;
|
||||
```
|
||||
|
||||
## 成员方法
|
||||
|
||||
### `BackTest()`
|
||||
|
||||
用途:回测主函数。
|
||||
|
||||
参数个数:0
|
||||
返回值:数组;结果读取通常通过查询接口完成。
|
||||
|
||||
| 参数位置 | 参数名 | 必填 | 接收类型 | 说明 |
|
||||
| -------- | ------ | ---- | -------- | ---- |
|
||||
|
||||
执行行为:
|
||||
|
||||
1. 调用 `GetTimeSeries()` 获取回测时间序列。
|
||||
2. 对每个时间点调用 `GetTradeOrder(vEndT)`。
|
||||
3. 根据交易数据、当前持仓、资产、费用和约束清算。
|
||||
4. 生成最新持仓、资产配置和绩效数据。
|
||||
|
||||
### `GetTimeSeries()`
|
||||
|
||||
用途:获取调仓或交易时间序列。
|
||||
|
||||
参数个数:0
|
||||
返回值:一维时间序列数组。
|
||||
|
||||
| 参数位置 | 参数名 | 必填 | 接收类型 | 说明 |
|
||||
| -------- | ------ | ---- | -------- | ---- |
|
||||
|
||||
重写规则:
|
||||
|
||||
- 基类默认按 `FBegT`、`FEndT`、`FCycle` 生成市场交易日序列。
|
||||
- 自定义调仓日、事件驱动调仓、非固定周期交易时重写。
|
||||
- 比例类组合返回需要发生调仓的时点。
|
||||
- 数量类组合返回需要发生交易的时点。
|
||||
|
||||
### `GetTradeOrder(vEndT)`
|
||||
|
||||
用途:获取当前时点目标持仓或交易明细。
|
||||
|
||||
参数个数:1
|
||||
返回值:二维数组、空数组或 `-1`。
|
||||
|
||||
| 参数位置 | 参数名 | 必填 | 接收类型 | 说明 |
|
||||
| -------- | ------- | ---- | ---------- | ----------------------------------------------------------------- |
|
||||
| 1 | `vEndT` | 是 | `DateTime` | 当前调仓或交易时点,由 `BackTest()` 从 `GetTimeSeries()` 结果传入 |
|
||||
|
||||
重写规则:
|
||||
|
||||
- 必须在子类中重写。
|
||||
- 不要在 `GetTradeOrder(vEndT)` 中修改 `vEndT`。
|
||||
- 如果要使用历史区间,从 `vEndT` 推导,例如 `stockzf(incMonth(vEndT, -1), vEndT)`。
|
||||
|
||||
### 可重写方法
|
||||
|
||||
| 方法 | 参数个数 | 返回值 | 用途 |
|
||||
| ---------------------------------------------- | -------- | -------- | ------------------------------------------------ |
|
||||
| `GetTA(vEndT)` | 1 | 二维数组 | 获取申购赎回、资金转入转出数据 |
|
||||
| `StockFee(stockId, vEndT, actionId, position)` | 4 | 实数 | 获取证券交易费率 |
|
||||
| `GetPercent(t, vEndT)` | 2 | 二维数组 | 比例类组合中计算目标持仓比例 |
|
||||
| `ReturnBenchmark(vBegT, vEndT, t)` | 3 | 二维数组 | 获取区间基准收益率序列;复合基准或高频基准可重写 |
|
||||
| `GetOtherData(vEndT)` | 1 | 二维数组 | 自定义分红、送股、配股数据 |
|
||||
| `GetClearancePrice(t, vEndT, ptype)` | 3 | 实数 | 比例类自定义清仓价 |
|
||||
| `GetIntVol(stype, actionId, modType, vJYSL)` | 4 | 实数 | 自定义成交量取整 |
|
||||
|
||||
### 当前状态读取方法
|
||||
|
||||
| 方法 | 参数个数 | 返回值 | 用途 |
|
||||
| ------------------------- | -------- | -------- | -------------------------------------------------- |
|
||||
| `GetSurplusFund()` | 0 | 实数 | 最新剩余资金 |
|
||||
| `GetNetAssetValue()` | 0 | 实数 | 最新资产净值 |
|
||||
| `GetAssetData()` | 0 | 二维数组 | 最新资产配置 |
|
||||
| `GetAssetJZValue()` | 0 | 实数 | 最新单位净值 |
|
||||
| `GetHoldData()` | 0 | 二维数组 | 最新持仓 |
|
||||
| `GetSellpool()` | 0 | 二维数组 | 当前可卖品种和数量 |
|
||||
| `CalcashByTradeData(tjy)` | 1 | 一维数组 | 根据指定日交易数据计算交易资金变动和交易后剩余资金 |
|
||||
|
||||
`GetTA(vEndT)` 返回字段:
|
||||
|
||||
| 字段 | 必填 | 接收类型 | 说明 |
|
||||
| ---------- | ---- | ---------- | ------------------ |
|
||||
| `截止日` | 是 | `DateTime` | 资金发生日期 |
|
||||
| `业务类型` | 是 | 整数 | `2` 出金;`3` 入金 |
|
||||
| `成交金额` | 是 | 数值 | 出入金额 |
|
||||
| `备注` | 是 | 字符串 | 出金或入金说明 |
|
||||
|
||||
`GetOtherData(vEndT)` 返回字段:
|
||||
|
||||
| 字段 | 必填 | 接收类型 | 说明 |
|
||||
| --------------- | ---- | ---------- | ---------------------------- |
|
||||
| `截止日` | 是 | `DateTime` | 事件日期 |
|
||||
| `代码` | 是 | 字符串 | 证券代码 |
|
||||
| `方向` | 是 | 整数 | `1` 多单;`0` 空单 |
|
||||
| `动作` | 是 | 整数 | `2` 分红;`3` 送股;`4` 配股 |
|
||||
| `成交量` | 是 | 数值 | 动作为 `2` 时为 `0` |
|
||||
| `成交价` | 是 | 数值 | 动作为 `2`、`3` 时为 `0` |
|
||||
| `成交金额` | 是 | 数值 | 分红金额或配股金额 |
|
||||
| `乘数` | 否 | 数值 | 默认 `1` |
|
||||
| `保证金比例(%)` | 否 | 数值 | 默认 `100` |
|
||||
| `费率(%)` | 否 | 数值 | 默认 `0` |
|
||||
| `备注` | 否 | 字符串 | 分红、配股等说明 |
|
||||
|
||||
## 查询接口
|
||||
|
||||
### 资产和持仓
|
||||
|
||||
| 方法 | 参数个数 | 返回值 | 用途 |
|
||||
| ---------------------------------- | -------- | -------- | ------------------ |
|
||||
| `GetAssetData(vEndT)` | 1 | 二维数组 | 指定日资产配置 |
|
||||
| `GetAssetData(vBegT, vEndT)` | 2 | 二维数组 | 区间资产配置 |
|
||||
| `GetAssetJZData(vEndT)` | 1 | 实数 | 指定日单位净值 |
|
||||
| `GetAssetJZData(vBegT, vEndT)` | 2 | 二维数组 | 区间单位净值 |
|
||||
| `GetHoldData(vEndT)` | 1 | 二维数组 | 指定日持仓 |
|
||||
| `GetHoldData(vBegT, vEndT)` | 2 | 二维数组 | 区间持仓 |
|
||||
| `GetOptionGroupData()` | 0 | 二维数组 | 当前期权组合持仓 |
|
||||
| `GetOptionGroupData(vEndT)` | 1 | 二维数组 | 指定日期权组合持仓 |
|
||||
| `GetOptionGroupData(vBegT, vEndT)` | 2 | 二维数组 | 区间期权组合持仓 |
|
||||
|
||||
### 交易和剔除数据
|
||||
|
||||
| 方法 | 参数个数 | 返回值 | 用途 |
|
||||
| -------------------------------------- | -------- | -------- | -------------------------------------------------------- |
|
||||
| `GetTradeData(vBegT, vEndT)` | 2 | 二维数组 | 区间交易数据 |
|
||||
| `GetDelTradeData(vBegT, vEndT)` | 2 | 二维数组 | 被成交量约束、交易约束、期权组合构建或解锁失败剔除的交易 |
|
||||
| `GetTAData(vBegT, vEndT)` | 2 | 二维数组 | 区间资金进出数据 |
|
||||
| `GetPortfolioPercent(vBegT, vEndT)` | 2 | 二维数组 | 区间组合配比;比例类专用 |
|
||||
| `GetJyByPercent(pfInfoData, tPercent)` | 2 | 二维数组 | 根据 T-1 调整后持仓和 T 日目标比例生成 T 日交易 |
|
||||
|
||||
### 盈亏和收益
|
||||
|
||||
| 方法 | 参数个数 | 返回值 | 用途 |
|
||||
| ------------------------------------------ | -------- | -------- | ------------------------------------ |
|
||||
| `GetGainandLoss(vBegT, vEndT)` | 2 | 二维数组 | 区间组合、分类资产每日盈亏和累计盈亏 |
|
||||
| `GetTradingAmount(vBegT, vEndT)` | 2 | 二维数组 | 区间每日买入、卖出、分红、净买卖金额 |
|
||||
| `GetGainandLossBySecurity(vBegT, vEndT)` | 2 | 二维数组 | 区间按个券汇总盈亏 |
|
||||
| `GetTradingAmountBySecurity(vBegT, vEndT)` | 2 | 二维数组 | 区间按个券汇总交易金额 |
|
||||
| `GetPortfolioReturn()` | 0 | 实数 | 最新组合收益率 |
|
||||
| `GetPortfolioReturn(vBegT, vEndT)` | 2 | 实数 | 区间组合收益率 |
|
||||
| `GetPortfolioAccumulativeReturn()` | 0 | 实数 | 组合成立以来收益率 |
|
||||
| `GetPortfolioReturn2(vBegT, vEndT)` | 2 | 二维数组 | 区间组合和基准每日收益率序列 |
|
||||
| `GetTrailingReturn(vEndT)` | 1 | 二维数组 | 指定日阶段收益率 |
|
||||
| `GetRollingReturn(vBegT, vEndT, cy)` | 3 | 二维数组 | 区间滚动收益率 |
|
||||
| `GetStockBuyandHoldReturn(vBegT, vEndT)` | 2 | 二维数组 | 区间持仓不动收益和交易贡献 |
|
||||
| `GetIRRReturn(vBegT, vEndT, vAnnual)` | 3 | 实数 | 区间现金流内部收益率 |
|
||||
|
||||
### 风险评价和行业配置
|
||||
|
||||
| 方法 | 参数个数 | 返回值 | 用途 |
|
||||
| -------------------------------------- | -------- | -------- | --------------------------------------------- |
|
||||
| `GetSectorAllocation(vEndT)` | 1 | 二维数组 | 指定日行业配置 |
|
||||
| `GetReturnandRisk(vBegT, vEndT)` | 2 | 二维数组 | 区间累计收益、标准差、夏普等风险回报 |
|
||||
| `GetRelativePerformance(vBegT, vEndT)` | 2 | 二维数组 | 区间超额收益、alpha、beta、跟踪误差等相对表现 |
|
||||
|
||||
通用日期参数:
|
||||
|
||||
| 参数位置 | 参数名 | 必填 | 接收类型 | 说明 |
|
||||
| -------- | ------- | ---------- | ---------- | ------ |
|
||||
| 1 | `vBegT` | 视签名而定 | `DateTime` | 开始日 |
|
||||
| 2 | `vEndT` | 视签名而定 | `DateTime` | 截止日 |
|
||||
|
||||
## 查询结果关键字段
|
||||
|
||||
### `GetAssetData`
|
||||
|
||||
| 字段 | 说明 |
|
||||
| ------------------- | -------------------------- |
|
||||
| `截止日` | 资产配置日期 |
|
||||
| `现金市值` | 当前现金 |
|
||||
| `股票市值` | 股票资产市值 |
|
||||
| `基金市值` | 基金资产市值 |
|
||||
| `债券市值` | 债券资产市值 |
|
||||
| `金融衍生品市值` | 金融衍生品保证金市值 |
|
||||
| `资产净值` | 组合资产净值 |
|
||||
| `股票占净值比例(%)` | 股票市值 / 资产净值 \* 100 |
|
||||
| `现金占净值比例(%)` | 现金市值 / 资产净值 \* 100 |
|
||||
|
||||
### `GetHoldData`
|
||||
|
||||
| 字段 | 说明 |
|
||||
| --------------- | -------------------------------------- |
|
||||
| `组 ID` | 期权组合或组合持仓标识;全为空时不返回 |
|
||||
| `截止日` | 持仓日期 |
|
||||
| `代码` | 证券代码 |
|
||||
| `方向` | 多单或空单 |
|
||||
| `数量` | 持仓数量 |
|
||||
| `收盘` | 收盘价格 |
|
||||
| `市值` | `收盘 * 数量` |
|
||||
| `保证金占用` | `收盘 * 数量 * 保证金比例` |
|
||||
| `占净值比例(%)` | 保证金占用 / 资产净值 \* 100 |
|
||||
| `总成本` | 持仓总成本 |
|
||||
| `成本价` | 持仓成本价 |
|
||||
| `浮动盈亏` | 市值 - 总成本 |
|
||||
| `浮盈率(%)` | 浮动盈亏 / 总成本 |
|
||||
| `证券类别` | 证券类型 |
|
||||
| `行业名称` | 行业分类名称 |
|
||||
| `组合类型` | 期权组合策略类型;全为空时不返回 |
|
||||
|
||||
### `GetTradeData`
|
||||
|
||||
| 字段 | 说明 |
|
||||
| ------------------ | ------------------------ |
|
||||
| `组 ID` | 期权组合或组合交易标识 |
|
||||
| `截止日` | 交易日期 |
|
||||
| `代码` | 证券代码 |
|
||||
| `名称` | 证券名称 |
|
||||
| `方向` | 多单或空单 |
|
||||
| `动作` | 开仓、平仓、构建、解锁等 |
|
||||
| `成交价` | 成交价格 |
|
||||
| `成交量` | 成交数量 |
|
||||
| `费率(%)` | 交易费率 |
|
||||
| `成交金额(税前)` | 成交价 \* 成交量 |
|
||||
| `费用` | 手续费 |
|
||||
| `成交金额` | 税后成交金额 |
|
||||
| `组合类型` | 期权组合策略类型 |
|
||||
| `备注` | 交易备注 |
|
||||
| `止盈止损基准价` | 有止盈止损交易时可能返回 |
|
||||
| `止盈止损成交价` | 有止盈止损交易时可能返回 |
|
||||
|
||||
## 常见专项规则
|
||||
|
||||
### 高频回测
|
||||
|
||||
- 高频策略通常设置 `FCycle` 为分钟线或秒线周期。
|
||||
- 高频策略若要以当前时点价格成交,设置 `FPriceType := 1`。
|
||||
- 高频回测需要返回每个周期清算数据时,设置 `FHFDataOutPut := 1`。
|
||||
- 高频并且重写 `ReturnBenchmark` 时,基准收益率也要按每个时点计算。
|
||||
|
||||
### 现金不足调整
|
||||
|
||||
- 全股票组合经过涨停、跌停、停牌、超卖、最大最小成交量和成交金额约束后,如果可用资金小于 `0`,可设置 `FisCashToAdjust := 1`。
|
||||
- `FOrdertype` 决定买入量调整顺序。
|
||||
- 调整后仍应通过 `GetAssetData()` 检查现金市值。
|
||||
|
||||
### 主力连续合约
|
||||
|
||||
- `FMainFutureMap := 0` 时,不对期货主力连续合约做映射。
|
||||
- `FMainFutureMap := 1` 时,将主力连续合约映射到当时实际合约。
|
||||
- 比例类组合中,主力变更日若是调仓日,以当日调仓数据为准。
|
||||
- 数量类组合中,主力变更日无论是否为交易时点,都需要处理主力换仓交易。
|
||||
|
||||
### 自定义成交价
|
||||
|
||||
- 比例类目标持仓使用自定义成交价时,设置 `FPriceType := -1`。
|
||||
- `GetTradeOrder(vEndT)` 返回目标持仓中可提供 `成交价`。
|
||||
- 原持仓证券在本期目标持仓中不存在时,清仓价由 `FPriceRateTo0` 决定。
|
||||
- `FPriceRateTo0 := -1` 时,重写 `GetClearancePrice(t, vEndT, ptype)`。
|
||||
|
||||
## 缺失输入处理
|
||||
|
||||
| 情况 | 生成处理 |
|
||||
| ------------------------------ | ----------------------------------------------------------------- |
|
||||
| 只有“写回测框架”,没有策略逻辑 | 生成 `TSBackTesting` 子类骨架,`GetTradeOrder(vEndT)` 先返回 `-1` |
|
||||
| 没有证券池、调仓规则或交易明细 | 只生成框架和参数入口,不生成具体交易信号 |
|
||||
| 没有期权需求 | 使用比例类或数量类普通字段,不加入期权组合字段 |
|
||||
| `FGroupType := 1` | `GetTradeOrder(vEndT)` 返回目标持仓和目标比例字段 |
|
||||
| `FGroupType := 2` | `GetTradeOrder(vEndT)` 返回成交明细、成交价、成交量和动作字段 |
|
||||
| 高频且要求当前时点价格成交 | 设置 `FPriceType := 1` |
|
||||
| `FDateToStr := 1` | 查询结果里的日期按字符串处理;后续日期计算先转换回日期值 |
|
||||
@@ -0,0 +1,246 @@
|
||||
# 发送微信消息使用说明
|
||||
|
||||
文档类型:模块 API 事实页
|
||||
是否可直接用于生成代码:是,但 `userid`、`username`、模板标题、模板关键字含义和真实通知内容必须来自用户需求或项目上下文
|
||||
遇到不确定时:[index.md](index.md)、调用侧账户体系文档、项目实际接口说明、天软科技服务号模板列表
|
||||
|
||||
本页整理通过“天软科技服务号”发送微信模板消息的接口事实。它负责告诉智能体“该调用哪个函数、参数顺序是什么、同步和异步怎么选择、状态如何查询”,不负责替用户创造账户、授权关系、模板映射或通知内容。
|
||||
|
||||
## 智能体微信消息决策规则
|
||||
|
||||
- 用户要“发送微信通知 / 微信消息 / 微信告警 / 微信模板消息 / 查询微信发送状态”时,优先使用本页。
|
||||
- 紧急通知、需要立刻知道发送结果时,默认使用 `send_wechat_message(...)`。
|
||||
- 非紧急通知、批量通知、发送后可稍后查询状态时,默认使用 `send_wechat_message_async(...)`。
|
||||
- 用户要求查询异步状态时,生成 `get_wechat_message_status(userid, username, wechat_message_id)`;三个实参必须来自参数、已知变量或项目上下文。
|
||||
- 参数必须严格按接口顺序传入;所有参数按字符串处理。
|
||||
- `url` 是固定位置参数;无详情地址时传空字符串 `""`。
|
||||
- `k1` 到 `k6` 的含义由模板标题决定;只按模板映射或用户输入填充,不要发明关键字含义。
|
||||
- 用户要求“通知第一眼看到”的内容时,放入带字段名的 `kN` 参数;`first` 和 `remark` 只作为点入通知后的详情文本。
|
||||
- 给他人发消息时,必须使用接收者授权给发送者的 `userid`,不要把发送者自己的 `userid` 当成接收者标识。
|
||||
- 不要发明 `userid`、`username`、项目封装函数、模板标题、模板关键字、授权关系或账号映射。
|
||||
|
||||
## 前置条件
|
||||
|
||||
| 条件 | 说明 |
|
||||
| ------------------------------- | -------------------------------------------------------------------------------------- |
|
||||
| 已绑定服务号 | 首次使用需要关注并绑定“天软科技服务号”,绑定后取得 `userid` |
|
||||
| 已取得 `userid` | `userid` 与用户账户和微信绑定关系相关,应由调用侧提供 |
|
||||
| 给他人发送时已授权 | 接收者绑定后在服务号 `userid` 页面授权发送者账号,发送者使用接收者提供的 `userid` 发送 |
|
||||
| 查询异步状态时已取得 `username` | `username` 是账号名,脚本查询发送状态时需要;来源以项目账户体系为准 |
|
||||
|
||||
## 接口总览
|
||||
|
||||
| 函数 | 用途 | 返回值 |
|
||||
| ---------------------------------------------------------------------------------------- | ---------------- | ------------------------------------------------- |
|
||||
| `send_wechat_message(userid, url, title, first, remark[, k1, k2, k3, k4, k5, k6])` | 同步发送模板消息 | 成功返回字符串 `success`;失败返回错误信息 |
|
||||
| `send_wechat_message_async(userid, url, title, first, remark[, k1, k2, k3, k4, k5, k6])` | 异步发送模板消息 | 返回 16 位字符串消息 ID |
|
||||
| `get_wechat_message_status(userid, username, wechat_message_id)` | 查询异步发送结果 | 成功返回字符串 `成功`;否则返回状态信息或错误信息 |
|
||||
|
||||
## 同步发送
|
||||
|
||||
签名:
|
||||
|
||||
```text
|
||||
send_wechat_message(userid, url, title, first, remark[, k1, k2, k3, k4, k5, k6])
|
||||
```
|
||||
|
||||
参数表:
|
||||
|
||||
| 参数位置 | 参数名 | 必填 | 接收类型 | 说明 |
|
||||
| -------- | -------- | -------- | -------- | ----------------------------------------------------------------- |
|
||||
| 1 | `userid` | 是 | 字符串 | 绑定账户后取得的用户标识;给他人发送时使用接收者授权后的 `userid` |
|
||||
| 2 | `url` | 是 | 字符串 | 详情地址;没有详情地址时传 `""` |
|
||||
| 3 | `title` | 是 | 字符串 | 模板消息标题,例如 `监控报告通知` |
|
||||
| 4 | `first` | 是 | 字符串 | 详情页开头文本;不作为通知列表首屏字段 |
|
||||
| 5 | `remark` | 是 | 字符串 | 详情页结尾备注;不作为通知列表首屏字段 |
|
||||
| 6 | `k1` | 条件必填 | 字符串 | 模板关键字 1;带字段名的 `kN` 行属于首屏展示字段 |
|
||||
| 7 | `k2` | 条件必填 | 字符串 | 模板关键字 2;带字段名的 `kN` 行属于首屏展示字段 |
|
||||
| 8 | `k3` | 否 | 字符串 | 模板关键字 3;部分模板需要 |
|
||||
| 9 | `k4` | 否 | 字符串 | 模板关键字 4;部分模板需要 |
|
||||
| 10 | `k5` | 否 | 字符串 | 模板关键字 5;部分模板需要 |
|
||||
| 11 | `k6` | 否 | 字符串 | 模板关键字 6;部分模板需要 |
|
||||
|
||||
返回值:
|
||||
|
||||
| 返回值 | 含义 |
|
||||
| ---------- | ------------ |
|
||||
| `success` | 同步发送成功 |
|
||||
| 其他字符串 | 错误信息 |
|
||||
|
||||
使用规则:
|
||||
|
||||
- 同步发送会阻塞当前程序,必须等待发送函数执行完毕后才进入下一步。
|
||||
- 紧急通知优先使用同步发送。
|
||||
- 返回值不是 `success` 时,按错误信息处理。
|
||||
|
||||
## 异步发送
|
||||
|
||||
签名:
|
||||
|
||||
```text
|
||||
send_wechat_message_async(userid, url, title, first, remark[, k1, k2, k3, k4, k5, k6])
|
||||
```
|
||||
|
||||
参数表:
|
||||
|
||||
| 参数位置 | 参数名 | 必填 | 接收类型 | 说明 |
|
||||
| -------- | -------- | -------- | -------- | ----------------------------------------------------------------- |
|
||||
| 1 | `userid` | 是 | 字符串 | 绑定账户后取得的用户标识;给他人发送时使用接收者授权后的 `userid` |
|
||||
| 2 | `url` | 是 | 字符串 | 详情地址;没有详情地址时传 `""` |
|
||||
| 3 | `title` | 是 | 字符串 | 模板消息标题 |
|
||||
| 4 | `first` | 是 | 字符串 | 详情页开头文本;不作为通知列表首屏字段 |
|
||||
| 5 | `remark` | 是 | 字符串 | 详情页结尾备注;不作为通知列表首屏字段 |
|
||||
| 6 | `k1` | 条件必填 | 字符串 | 模板关键字 1;带字段名的 `kN` 行属于首屏展示字段 |
|
||||
| 7 | `k2` | 条件必填 | 字符串 | 模板关键字 2;带字段名的 `kN` 行属于首屏展示字段 |
|
||||
| 8 | `k3` | 否 | 字符串 | 模板关键字 3;部分模板需要 |
|
||||
| 9 | `k4` | 否 | 字符串 | 模板关键字 4;部分模板需要 |
|
||||
| 10 | `k5` | 否 | 字符串 | 模板关键字 5;部分模板需要 |
|
||||
| 11 | `k6` | 否 | 字符串 | 模板关键字 6;部分模板需要 |
|
||||
|
||||
返回值:
|
||||
|
||||
| 返回值 | 含义 |
|
||||
| ----------- | ---------------------------------------------------------- |
|
||||
| 16 位字符串 | 异步消息 ID;前 10 位为 1900 年以来的秒数,后 6 位为随机数 |
|
||||
|
||||
使用规则:
|
||||
|
||||
- 异步发送把命令提交给服务器后立即返回,不等待最终发送结果。
|
||||
- 非紧急通知优先使用异步发送。
|
||||
- 需要最终结果时,保存返回的 `wechat_message_id`,再调用 `get_wechat_message_status(...)` 查询。
|
||||
|
||||
## 查询异步发送状态
|
||||
|
||||
签名:
|
||||
|
||||
```text
|
||||
get_wechat_message_status(userid, username, wechat_message_id)
|
||||
```
|
||||
|
||||
参数表:
|
||||
|
||||
| 参数位置 | 参数名 | 必填 | 接收类型 | 说明 |
|
||||
| -------- | ------------------- | ---- | -------- | ---------------------------------------------------- |
|
||||
| 1 | `userid` | 是 | 字符串 | 发送时使用的用户标识 |
|
||||
| 2 | `username` | 是 | 字符串 | 账号名;脚本执行查询时需要,来源以项目账户体系为准 |
|
||||
| 3 | `wechat_message_id` | 是 | 字符串 | `send_wechat_message_async(...)` 返回的 16 位消息 ID |
|
||||
|
||||
返回值:
|
||||
|
||||
| 返回值 | 含义 |
|
||||
| ---------- | ------------------ |
|
||||
| `成功` | 异步消息发送成功 |
|
||||
| 其他字符串 | 状态信息或错误信息 |
|
||||
|
||||
调用规则:
|
||||
|
||||
- 状态查询用于异步发送后的结果确认。
|
||||
- `username` 按账号名参数、已知变量或项目上下文传入,不写字面量 `"username"`。
|
||||
- `wechat_message_id` 使用 `send_wechat_message_async(...)` 的返回值。
|
||||
|
||||
## 模板展示规则
|
||||
|
||||
| 模板片段 | 展示位置 | 生成规则 |
|
||||
| ----------------------------------- | ---------------------- | ------------------------------------------------ |
|
||||
| `字段名:{{kN}}` | 通知列表首屏可见 | 用户要求“第一眼看到”的信息放到对应 `kN` |
|
||||
| `{{first}}` | 点入通知后的详情页开头 | 放说明、背景、摘要引导;不承载首屏必须展示的信息 |
|
||||
| `{{remark}}` | 点入通知后的详情页结尾 | 放补充说明、处理建议、联系人等尾部信息 |
|
||||
| 字面标题行,例如 `监控报告通知` | 模板固定内容 | 不作为接口参数;接口参数 `title` 仍使用模板标题 |
|
||||
| 动态标签行,例如 `{{k5}}幅:{{k6}}` | 通知列表首屏可见 | `k5` 填字段标签的一部分,`k6` 填对应数值 |
|
||||
|
||||
生成规则:
|
||||
|
||||
- `title` 决定模板,`k1` 到 `k6` 按模板字段名依次填入。
|
||||
- 有名称的 `kN` 行是首屏展示字段;需要首屏展示的信息优先放入 `kN`。
|
||||
- `first` 和 `remark` 是详情页内容;不要把“第一眼必须看到”的核心字段放入 `first` 或 `remark`。
|
||||
- 模板未列出的 `kN` 不主动传入;需要扩展字段时先换模板或由用户提供模板映射。
|
||||
|
||||
## 模板关键字映射
|
||||
|
||||
### 系统监控类
|
||||
|
||||
| 模板标题 | `k1` | `k2` | `k3` | `k4` | `k5` | `k6` |
|
||||
| -------------------- | ------------ | ------------ | ------------ | ---- | ---- | ---- |
|
||||
| `系统运行简报` | 系统名称 | 简报内容 | 发布时间 | | | |
|
||||
| `监控报告通知` | 运行状态 | 时间 | | | | |
|
||||
| `监控结果通知` | 监控项目 | 内容 | 时间 | | | |
|
||||
| `告警通知` | 告警内容 | 告警发生时间 | | | | |
|
||||
| `故障恢复通知` | 故障信息 | 恢复时间 | | | | |
|
||||
| `服务器异常监控通知` | 监控通知 | 监控通知类型 | 监控通知内容 | | | |
|
||||
| `服务器宕机通知` | 故障时间 | 故障原因 | | | | |
|
||||
| `服务器恢复通知` | 故障停止时间 | 故障持续时间 | | | | |
|
||||
|
||||
### 交易通知类
|
||||
|
||||
| 模板标题 | `k1` | `k2` | `k3` | `k4` | `k5` | `k6` |
|
||||
| -------------- | -------- | -------- | -------- | -------- | -------- | -------- |
|
||||
| `交易成功通知` | 交易金额 | 交易类型 | 交易时间 | 交易单号 | | |
|
||||
| `交易完成通知` | 股票简称 | 股票代码 | 股票价格 | 交易状态 | 股票数量 | |
|
||||
| `交易下单通知` | 交易品种 | 下单方向 | 下单价格 | 止损价格 | 下单时间 | |
|
||||
| `成交回报提示` | 证券名称 | 证券代码 | 买卖标识 | 成交价格 | 成交数量 | 成交时间 |
|
||||
| `委托成交提醒` | 数量 | 价格 | 时间 | | | |
|
||||
|
||||
### 策略通知类
|
||||
|
||||
| 模板标题 | `k1` | `k2` | `k3` | `k4` | `k5` | `k6` |
|
||||
| ------------------ | -------- | ---------- | ------------ | ---------- | ------------------------- | ------ |
|
||||
| `投资策略更新提醒` | 策略名称 | 操作风格 | 目前策略收益 | | | |
|
||||
| `股票调仓通知` | 股票名称 | 操作类型 | 调仓时间 | 调仓价格 | 调仓仓位 | |
|
||||
| `实时建仓提醒` | 品种 | 方向 | 仓位 | 价格 | 止盈止损 | |
|
||||
| `个股到价通知` | 股票名 | 当前成交价 | 预警价 | | | |
|
||||
| `个股涨跌幅通知` | 股票名 | 当前成交价 | 对比日期 | 对比收盘价 | 动态标签,组成 `{{k5}}幅` | 动态值 |
|
||||
|
||||
### 其他通知类
|
||||
|
||||
| 模板标题 | `k1` | `k2` | `k3` | `k4` | `k5` | `k6` |
|
||||
| ------------------ | -------- | -------- | ---- | ---- | ---- | ---- |
|
||||
| `账号绑定成功通知` | 账号名称 | 绑定时间 | | | | |
|
||||
| `服务开启通知` | | | | | | |
|
||||
| `授权请求通知` | 申请人 | 请求权限 | | | | |
|
||||
|
||||
`服务开启通知` 当前只记录模板标题,未固定 `k1` 到 `k6` 的字段映射。
|
||||
|
||||
## 发送示例
|
||||
|
||||
同步发送系统运行简报:
|
||||
|
||||
```tsl
|
||||
function SendSystemBrief(user_id);
|
||||
begin
|
||||
url := "";
|
||||
title := "系统运行简报";
|
||||
first := "系统运行情况如下。";
|
||||
k1 := "风控服务";
|
||||
k2 := "运行正常";
|
||||
dateTimeToString(k3, "YYYY-MM-DD HH:NN:SS", now());
|
||||
remark := "如有疑问请联系值班人员。";
|
||||
|
||||
return send_wechat_message(user_id, url, title, first, remark, k1, k2, k3);
|
||||
end;
|
||||
```
|
||||
|
||||
异步发送并保留消息 ID:
|
||||
|
||||
```tsl
|
||||
function SendSystemBriefAsync(user_id);
|
||||
begin
|
||||
url := "";
|
||||
title := "系统运行简报";
|
||||
first := "系统运行情况如下。";
|
||||
k1 := "风控服务";
|
||||
k2 := "运行正常";
|
||||
dateTimeToString(k3, "YYYY-MM-DD HH:NN:SS", now());
|
||||
remark := "如有疑问请联系值班人员。";
|
||||
|
||||
return send_wechat_message_async(user_id, url, title, first, remark, k1, k2, k3);
|
||||
end;
|
||||
```
|
||||
|
||||
查询异步发送结果:
|
||||
|
||||
```tsl
|
||||
function QueryWechatMessageStatus(user_id, username, wechat_message_id);
|
||||
begin
|
||||
return get_wechat_message_status(user_id, username, wechat_message_id);
|
||||
end;
|
||||
```
|
||||
Reference in New Issue
Block a user