关于 tqx
tqx 是通过 TQX 官方命令行工具使用量化平台的 Agent 技能,面向量化研究和交易工作流。它指导使用 tqx-cli 进行因子分析与策略回测,并区分这些研究任务和由独立 tqx 交易命令行处理的账户查询及下单操作。
主要功能
- 01因子分析
- 02策略回测
- 03工作流与运行结果查询
- 04命令行安装和认证指引
- 05研究与交易命令分流
适用场景
- 01用 IC 和 IR 指标评估股票因子
- 02回测单只股票策略
- 03查看回测交易和表现
- 04将账户查询与下单操作交给 tqx
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ starchild-ai-agent/ official-skills --skill tqx安装后在 Claude Code 中输入/tqx确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
templates/studio/agent.pybacktests.pyindex.htmljournal.pyserver.pystrategies.py详细介绍
TQX Quant — 因子分析与策略回测
TQX(https://www.tqx.trade)是一个港/美股量化平台。本 skill 通过官方 tqx-cli pip 包驱动它。
官方 TQX skills(唯一可信来源 — 请先阅读这些内容)
TQX 发布两个官方 skill。直接抓取 raw URL(仓库 UI 是 JS SPA;只有 /-/git/raw/ URL 会返回内容):
1. tqx-research — 因子分析、策略回测、工作流管理(Python tqx-cli,邮箱/密码登录):
- 主文档:
https://cnb.cool/liangyunzhijing/clis/-/git/raw/main/skills/tqx-research/SKILL.md - 参考文档(生成代码前先阅读 — 不要猜测 API):
- commands:
.../skills/tqx-research/references/commands.md - 策略模板:
.../skills/tqx-research/references/strategy_templates.md - 美股 API:
.../skills/tqx-research/references/stock_us_api.md - 港股 API:
.../skills/tqx-research/references/stock_hk_api.md - tqx_data:
.../skills/tqx-research/references/tqx_data_usage.md(将...替换为https://cnb.cool/liangyunzhijing/clis/-/git/raw/main)
- commands:
2. tqx-trading — 账户/持仓/订单/成交查询 + 授权下单(TypeScript @tqx-ai/[email protected],API-key 认证,需锁定版本):
- 主文档:
https://cnb.cool/liangyunzhijing/clis/-/git/raw/main/skills/tqx-trading/SKILL.md - OpenAPI:
https://www.tqx.trade/openapi/v1/openapi.json(交互式:/openapi/v1/scalar)
路由规则: 研究/回测/因子相关工作 → tqx-research(tqx-cli,Python)。实盘账户状态与订单执行 → tqx-trading(tqx,TS CLI)。二者使用不同的 CLI 和不同的认证方式(邮箱登录 vs TQX_API_KEY)— 不要混用。下面的这个 skill 补充了官方文档未覆盖的内容:经验证的入门流程、故障模式表,以及 Agent 自动化模式。
用户入门(首次设置,约 3 分钟)
-
注册:在 https://www.tqx.trade 注册(邮箱注册)。系统会自动开通一个 PAPER(模拟)账户 — 下面所有工作流都可以安全地在其上运行。模拟盘和实盘使用相同的 API:
tqx trading account会报告"mode": "PAPER"或"mode": "LIVE",且每条命令(positions、orders place|modify|cancel、trades)在两者上完全一致。切换到真实资金是 TQX 账户级别的变更,而不是不同的代码路径 — 这正是下面订单规模上限和人工审批规则如此重要的原因。交易大赛: TQX 举办 Agent 交易大赛 — 报名和规则见 https://luma.com/dawwrdxk?tk=adzfZA。大赛账户从同一个仪表盘创建(https://www.tqx.trade/hk/competition-manage?catalog=2),交易 CLI 的
TQX_API_KEY也在此处签发。 -
安全收集凭据:Agent 必须使用
request_env_input获取TQX_EMAIL和TQX_PASSWORD— 切勿在聊天中索要凭据。 -
安装 + 登录 + 验证:
pip install tqx-cli
tqx-cli login --email "$TQX_EMAIL" --password "$TQX_PASSWORD"
tqx-cli --json balance # non-error response = onboarding complete
Token 缓存在 ~/.tqx/config.yaml。
- 首个快速成果(推荐演示):运行下面 §1 中的 "5d momentum" 因子分析 — 约 1–2 分钟即可完成,并产出一组可以立即展示的 IC/IR/Sharpe 数值。
⚠️ Token 过期陷阱: accessToken 和 refresh_token 可能同时过期。不要只匹配某一个特定的错误字符串 — 只要响应中包含 LOGIN_REQUIRED、均已失效 或 Please log in to continue,就应重新登录。严格的匹配器会静默失败,导致后续每次调用都返回认证错误。
CLI 命令地图
factor_create / factor_run / factor_result / factor_list / factor_delete
strategy_create / strategy_run / strategy_result / strategy_list / strategy_delete
backtest_result # per-backtest detail: summary/account/position/profit/trade/log sections
workflow_list / workflow_stop / balance
添加 --json 可获得机器可读的输出。
1. 因子分析(横截面 IC/IR)
tqx-cli --json factor_create --market us --name "5d momentum" \
--formula "close/ref(close,5)-1" \
--start-date 20250101 --end-date 20250701 --group-number 2
tqx-cli --json factor_run <factor_id> # waits and returns results
结果解析陷阱: 结果 JSON 有两种格式,取决于后端版本 — 旧版为 nodes[].result_json,当前版为根级 factor_analysis。两种都要处理。关键指标:IC 均值、IR、t 统计量、分组年化收益、Sharpe。
2. 策略回测(panda_backtest 引擎)
tqx-cli --json strategy_create --market us --name "AAPL SMA cross" \
--code "$(cat strategy.py)" \
--start-date 20250101 --end-date 20250701 \
--start-capital 1000000 --commission-rate 0.0003 --slippage 0.001 --frequency 1d
tqx-cli --json strategy_run <strategy_id>
策略代码约定
from panda_backtest.api.api import * # common trading API — MANDATORY
from panda_backtest.api.stock_us_api import * # US market data API — MANDATORY
# HK market: from panda_backtest.api.stock_hk_api import *
import tqx_data
def initialize(context):
# Account ID is per-user — discover it once, do NOT hardcode.
# The '8888' from CN-market docs does NOT exist for HK/US backtests.
context.account = list(context.stock_account_dict.keys())[0]
context.symbol = 'AAPL.NB' # symbol format: US = TICKER.NB (NOT .US!), HK = 00700.HK
context.closes = []
def handle_data(context, data):
account = context.stock_account_dict.get(context.account)
if account is None:
return
bar = data.get(context.symbol)
# bar CAN be None — with a WRONG suffix it is None EVERY day (silent 0-trade run)
if bar is None or getattr(bar, 'close', None) is None or float(bar.close) <= 0:
return
price = float(bar.close)
context.closes.append(price)
if len(context.closes) < 20:
return
fast = sum(context.closes[-5:]) / 5
slow = sum(context.closes[-20:]) / 20
position = account.positions.get(context.symbol)
quantity = 0 if position is None else position.quantity
sellable = 0 if position is None else position.sellable
if fast > slow and quantity == 0:
buy_qty = int(account.cash * 0.9 // price)
if buy_qty > 0:
order_shares(context.account, context.symbol, buy_qty, style=MarketOrderStyle)
print(f"BUY {buy_qty} @ {price:.2f}") # print() = strategy log; SRLog is FORBIDDEN
elif fast < slow and quantity > 0 and sellable > 0:
order_shares(context.account, context.symbol, -sellable, style=MarketOrderStyle)
print(f"SELL {sellable} @ {price:.2f}")
参考运行:这段确切的代码在 AAPL.NB、20250101–20251231 上会产生 18 笔真实成交(用 backtest_result <backtest_id> --section trade --all-pages 检查)。
从真实失败中学到的硬性规则:
| 现象 | 根本原因 | 修复 |
|---|---|---|
禁止使用危险函数 dir() | 安全过滤器阻止内省 | 绝不使用 dir()/eval()/exec;要检查上下文,用 raise Exception(str(...)) 并读取运行日志中的 error_detail |
下单时 访问了不存在的键 | 账户 ID 错误(例如 '8888') | 使用 list(context.stock_account_dict.keys())[0] |
order_shares() missing 1 required positional argument | 用 2 个参数调用 | 签名为 order_shares(account, symbol, quantity) |
股票X不属于当前股票回测市场 | 股票代码后缀错误 | 美股 = TICKER.NB(不是 .US!),港股 = XXXXX.HK;.O/.N/裸代码会被拒绝 |
| 回测 SUCCESS 但 0 笔交易、0 行日志、profit = 0.0 | 代码后缀 .US(或任何错误后缀)→ 每根 bar 都返回 None → 防御性守卫静默跳过所有日期 | 美股用 TICKER.NB。务必通过 backtest_result <id> --section trade 验证——SUCCESS ≠ 已执行交易 |
| 运行立即 FAILED(约 0.3s,节点失败) | SRLog 不是策略代码中的有效 API | 策略日志用普通 print()(可在 --section log 中看到) |
| 运行状态 FAILED 但没有失败节点(所有节点 success/pending) | 临时的 TQX 队列/调度器错误,不是你的代码问题 | 重新提交同一个工作流一次——通常约 30s 内成功。只有节点确实失败时才调试策略代码 |
回测 SUCCESS 但 0 笔交易,标的不在当前回测数据集内 | 日期范围超出已摄入的市场数据(即使基准序列存在,最近几个月也可能未加载) | 把窗口往前移(例如用去年的范围);在信任指标前先确认 trade 部分的 trades>0 |
frequency 被拒绝 | 只有 1d 和 1M 是有效的 | — |
读取结果
strategy_run/strategy_result 返回运行状态 + 节点输出。要获取完整细节,从运行日志(BacktestNodeIdentifier: 行)或节点输出中提取回测 id,然后:
tqx-cli --json backtest_result <backtest_id> --section summary # profit, alpha, beta, sharpe, IR
tqx-cli --json backtest_result <backtest_id> --section trade # ⚠️ always check trades executed
tqx-cli --json backtest_result <backtest_id> --section log # per-order rejection reasons
一次运行可能报告 SUCCESS 却零交易(订单被逐日静默拒绝)。在报告业绩数字前,务必确认 trade 部分非空。
每日净值曲线(--section profit)
profit 部分是逐日 NAV 序列——每个交易日一行,包含 gmt_create(YYYYMMDD)、strategy_profit(策略累计收益,小数)和 csi_stock(基准累计收益,小数)。
# ⚠️ --all-pages does NOT work for the profit section: it silently returns only page 1 (100 rows).
tqx-cli --json backtest_result <backtest_id> --section profit --page-size 1000
# -> pagination {total: 252, page: 1, page_size: 1000, total_pages: 1} ✅ full year in one call
还有两个行为需要处理(参考:AAPL.NB,2025 全年 = 252 行):
- 返回的行未排序——绘图前务必按
gmt_create升序排序;不要假设 API 顺序。 - 值是小数,不是百分比(
-0.1174= −11.74%),且已是累计值,所以直接绘图;不要再复利计算。 - 最后一行必须与
summary部分的总收益一致——用它作为正确性检查。
把序列缓存在本地(每次运行一个文件)而不是重新获取:该调用耗时约 2–4 s,且运行完成后数据不可变。
调试失败的运行
错误细节不在顶层状态中——获取运行日志并读取 error_detail,其中包含确切的策略行号和异常消息:
from tqx_cli.config import load_config
from tqx_cli.auth import require_login
from tqx_cli.workflow import get_run_logs
cfg = load_config(); token, uid, _ = require_login(cfg, cfg.get("_config_path"))
for l in get_run_logs(cfg, token, uid, run_id).get("logs") or []:
if l.get("error_detail"): print(l["error_detail"])
成本与节奏
回测按 TQX 计算积分计费(tqx-cli balance)。一次 6 个月日频单只股票回测约需 2 分钟实际时间。每 3s 轮询一次 strategy_result;不要并发触发同一工作流的多次运行。
3. 模板(可复制粘贴的起点)
T1 — 动量因子(横截面,全市场)
tqx-cli --json factor_create --market us --name "5d momentum" \
--formula "close/ref(close,5)-1" \
--start-date 20250101 --end-date 20250701 --group-number 5
其他已验证的公式:均值回归 -(close/ref(close,5)-1),成交量激增 volume/mean(volume,20)。
因子模式仅支持全市场横截面(--market hk|us)——它无法针对单只股票;对于单只股票的问题,请使用策略回测(T2)。
T2 — 单股回测(AAPL 上的 SMA 交叉)
逐字使用 §2 中的策略代码契约——它就是模板。只修改 context.symbol 和信号逻辑。保留 None-bar 防护和动态账户发现。
T3 — Agent 驱动的自动交易循环
该模式已经过 10 轮实盘运行验证(端到端约 21 分钟):
loop every N minutes:
1. fetch live positions + account state
2. compute signal (factor value or strategy rule)
3. decide: buy / sell / hold ← agent reasoning step
4. place order (paper account, small fixed qty during development)
5. journal the decision: {ts, reasoning, tool_calls, params, result, position_delta}
自动化硬性规则:
- 默认使用 PAPER 账户。 实盘交易使用完全相同的命令接口,因此代码中没有任何东西会阻止实盘订单——只有你的门控会。在将循环指向实盘账户前,必须获得用户明确批准,保持硬性订单规模上限,并始终传递
--idempotencyKey,这样重试永远不会重复成交。 - 记录每个决策(JSONL 即可)——用户必须能够审计每笔交易发生的原因。
- 遇到任何类似认证的错误字符串时重新登录(见上文 token 陷阱);循环中途 token 过期必须能自愈,而不是终止循环。
- 在每次回测类调用前检查计算余额,以避免静默透支。
T4 — Studio:开箱即用的配套 UI(templates/studio/)
本技能附带一个完整、经过测试的 Web 工作台——不要从零构建仪表盘。将 templates/studio/ 复制到用户的工作区,启动它,然后按需调整。
文件:
| 文件 | 作用 |
|---|---|
server.py | 标准库 HTTP 后端(端口 8090,无 pip 依赖)。代理 tqx-cli,token 过期时自动重新登录,提供所有 /api/* 路由 |
index.html | 单文件前端:因子分析、回测提交/历史、持仓、Agent 决策时间线 |
agent.py | Agent 交易循环(通过 proxied_post + 工具调用接入大模型),JSONL 决策日志 |
backtests.py / strategies.py / journal.py | 磁盘持久化模块(见下方数据规范) |
UI 语言: 模板仅提供英文。运行时你看到的任何中文都来自 TQX API 本身(指标键名、错误字符串)——不要翻译这些内容,它们会被用于匹配。
运行: 在 studio 目录下执行 python3 server.py(后台运行),然后对其调用 preview(action="serve")。凭据来自 TQX_EMAIL / TQX_PASSWORD 环境变量(通过安全输入收集——切勿硬编码)。
设计规范(重新设计样式时保留):
- 极简量化科技美学:深色优先、等宽数字、密集表格,无装饰性图形。避免明亮或赛博朋克主题。
- 历史记录行必须可加载:点击任意历史记录上的 Load 后,其完整结果会重新显示在顶部结果区域(因子运行 → 通过
loadBt显示因子指标/图表;策略运行 → 通过loadStgBt显示专用策略结果卡片:收益对比基准、年化、Sharpe、最大回撤、交易次数、参数 + 代码链接)。只列出记录行而不支持重新加载的历史表是不完整的。 - UI 只暴露高频参数(公式、市场、日期范围、分组、再平衡、方向)+ 账户切换器 + 净值曲线 + 决策时间线。所有复杂内容(自定义策略代码、股票池、手续费/滑点)都留在对话层——Agent 拥有完整的命令行接口,UI 不得重复提供。
- 金额:使用单一专用格式化器格式化金币/现金值,两个相互竞争的格式化器会产生不一致的输出。检查每张卡片的深色模式对比度。
持久化与路径(为什么需要两个目录):
tqx-cli 会将其登录配置写入 /root/.tqx/config.yaml,该文件位于容器的临时层上,每次机器重启都会被清除——Agent 会静默丢失其会话。只有 /data/workspace 能在重启后保留,因此 studio 会将配置镜像到 /data/workspace/.tqx/,并在启动时双向同步(server.py 中的 sync_tqx_config()、agent.py 中的 _sync_tqx_config())。
这些路径是刻意固定的,并非可移植性方面的疏忽:每个 Agent 的布局都完全相同——/data/workspace = 持久卷,/root = 临时目录。扩展 studio 时请保持这条规则:任何必须在重启后存活的内容都写入 workspace 下,绝不写入 /root 或 /tmp。 studio 内部状态(data/backtests、data/journal、data/strategies)已经相对于 __file__,因此只要 studio 本身被复制到 workspace 中,它们就能继承持久性。如果你在 Starchild 机器之外运行它,请覆盖持久根目录——代码中没有任何其他地方假定绝对路径。
数据存储规范:
data/backtests/index.json+ 每次运行一个 JSON 文件——必须持久化完整的策略代码字符串(而非截断的预览),以便任何运行都能被重新加载并再次编辑。data/journal/*.jsonl——每个 Agent 决策一行,标记为source: manual | agent,仅追加,绝不重写。data/strategies/——具名保存的策略。所有状态都是磁盘上的纯 JSON;无数据库。
测试规范(在宣布 studio“可用”之前):
curl localhost:8090/api/health(或任意 GET 路由)返回 JSON——后端存活。- 通过 UI 提交一次真实回测,并确认它出现在历史面板中,包含完整代码 + 指标。仅页面渲染出来不算验证。
- 通过
backtest_result <id> --section trade验证成交存在——SUCCESS 状态但 0 笔成交意味着符号后缀 bug(参见失败表)。 - 终止/重启
server.py并确认历史记录仍然存在(来自磁盘,而非内存)。