tqx

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

TQX Quant — Factor Analysis & Strategy Backtest

TQX 量化工具 — 因子分析与策略回测

TQX (https://www.tqx.trade) is a HK/US stock quant platform. This skill drives it through the official
tqx-cli
pip package.

Official TQX skills (source of truth — read these first)

官方TQX Skill(权威来源 — 请先阅读)

TQX publishes two official skills. Fetch the raw URLs directly (the repo UI is a JS SPA; only
/-/git/raw/
URLs return content):
1. tqx-research — factor analysis, strategy backtest, workflow management (Python
tqx-cli
, email/password login):
  • Main:
    https://cnb.cool/liangyunzhijing/clis/-/git/raw/main/skills/tqx-research/SKILL.md
  • References (read before generating code — do NOT guess APIs):
    • commands:
      .../skills/tqx-research/references/commands.md
    • strategy templates:
      .../skills/tqx-research/references/strategy_templates.md
    • US API:
      .../skills/tqx-research/references/stock_us_api.md
    • HK API:
      .../skills/tqx-research/references/stock_hk_api.md
    • tqx_data:
      .../skills/tqx-research/references/tqx_data_usage.md
      (replace
      ...
      with
      https://cnb.cool/liangyunzhijing/clis/-/git/raw/main
      )
2. tqx-trading — account/positions/orders/trades queries + authorized order placement (TypeScript
@tqx-ai/cli@0.1.3
, API-key auth, pin the version):
  • Main:
    https://cnb.cool/liangyunzhijing/clis/-/git/raw/main/skills/tqx-trading/SKILL.md
  • OpenAPI:
    https://www.tqx.trade/openapi/v1/openapi.json
    (interactive:
    /openapi/v1/scalar
    )
Routing rule: research/backtest/factor work → tqx-research (
tqx-cli
, Python). Live account state & order execution → tqx-trading (
tqx
, TS CLI). They use DIFFERENT CLIs and DIFFERENT auth (email login vs
TQX_API_KEY
) — don't mix them. This skill below adds what the official docs don't cover: verified onboarding, failure-mode table, and agent-automation patterns.
TQX发布了两款官方Skill。请直接获取原始URL(仓库UI是JS单页应用;只有
/-/git/raw/
开头的URL会返回内容):
1. tqx-research — 因子分析、策略回测、工作流管理(基于Python的
tqx-cli
,邮箱/密码登录):
  • 主文档:
    https://cnb.cool/liangyunzhijing/clis/-/git/raw/main/skills/tqx-research/SKILL.md
  • 参考文档(生成代码前请阅读 — 请勿猜测API):
    • 命令说明:
      .../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
2. tqx-trading — 账户/持仓/订单/交易查询 + 授权下单(基于TypeScript的
@tqx-ai/cli@0.1.3
,API密钥认证,请固定版本):
  • 主文档:
    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自动化模式。

User onboarding (first-time setup, ~3 minutes)

用户入门(首次设置,约3分钟)

  1. Register at https://www.tqx.trade (email signup). A PAPER (simulation) account is provisioned automatically — all workflows below are safe to run on it. Paper and live are the SAME API:
    tqx trading account
    reports
    "mode": "PAPER"
    or
    "mode": "LIVE"
    , and every command (
    positions
    ,
    orders place|modify|cancel
    ,
    trades
    ) is identical on both. Switching to real money is an account-level change on TQX, not a different code path — which is exactly why order-size caps and the human-approval rule below matter.
    Trading competition: TQX runs an agent trading competition — entry and rules at https://luma.com/dawwrdxk?tk=adzfZA. Competition accounts are created from the same dashboard (https://www.tqx.trade/hk/competition-manage?catalog=2), which is also where the
    TQX_API_KEY
    for the trading CLI is issued.
  2. Collect credentials securely: agents must use
    request_env_input
    for
    TQX_EMAIL
    and
    TQX_PASSWORD
    — never ask for credentials in chat.
  3. Install + login + verify:
bash
pip install tqx-cli
tqx-cli login --email "$TQX_EMAIL" --password "$TQX_PASSWORD"
tqx-cli --json balance        # non-error response = onboarding complete
Token is cached in
~/.tqx/config.yaml
.
  1. First quick win (recommended demo): run the "5d momentum" factor analysis from §1 below — completes in ~1–2 min and produces IC/IR/Sharpe numbers you can show immediately.
⚠️ Token expiry gotcha: both accessToken AND refresh_token can expire together. Do NOT only match one specific error string — re-login on ANY response containing
LOGIN_REQUIRED
,
均已失效
, or
Please log in to continue
. A strict matcher silently fails and every later call returns auth errors.
  1. 注册:访问https://www.tqx.trade(邮箱注册)。系统会自动为你创建一个PAPER(模拟)账户 — 以下所有工作流在该账户上运行都是安全的。模拟账户与实盘账户使用相同的API:
    tqx trading account
    命令会返回
    "mode": "PAPER"
    "mode": "LIVE"
    ,且所有命令(
    positions
    orders place|modify|cancel
    trades
    )在两种账户上的用法完全一致。切换到实盘交易是在TQX平台上的账户级别设置变更,无需修改代码 — 这也正是下文提到的订单限额和人工审核规则至关重要的原因。
  2. 安全收集凭证:Agent必须使用
    request_env_input
    来获取
    TQX_EMAIL
    TQX_PASSWORD
    — 绝不能在聊天中直接索要凭证。
  3. 安装 + 登录 + 验证
bash
pip install tqx-cli
tqx-cli login --email "$TQX_EMAIL" --password "$TQX_PASSWORD"
tqx-cli --json balance        # 返回无错误响应即表示入门设置完成
Token会缓存到
~/.tqx/config.yaml
中。
  1. 快速上手演示(推荐):运行下文§1中的“5日动量”因子分析 — 约1-2分钟即可完成,并生成可即时展示的IC/IR/Sharpe指标。
⚠️ Token过期陷阱:accessToken和refresh_token可能同时过期。请勿仅匹配某一特定错误字符串 — 只要响应中包含
LOGIN_REQUIRED
均已失效
Please log in to continue
,就需要重新登录。严格匹配单一错误字符串会导致静默失败,后续所有调用都会返回认证错误。

CLI command map

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
Add
--json
for machine-readable output.
factor_create / factor_run / factor_result / factor_list / factor_delete
strategy_create / strategy_run / strategy_result / strategy_list / strategy_delete
backtest_result   # 单回测详情:包含summary/account/position/profit/trade/log等板块
workflow_list / workflow_stop / balance
添加
--json
参数可获取机器可读格式的输出。

1. Factor analysis (cross-sectional IC/IR)

1. 因子分析(横截面IC/IR)

bash
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
Result parsing gotcha: the result JSON has TWO formats depending on backend version — legacy
nodes[].result_json
and current root-level
factor_analysis
. Handle both. Key metrics: IC mean, IR, t-stat, annualized group returns, Sharpe.
bash
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>          # 等待并返回结果
结果解析陷阱:返回的结果JSON有两种格式,取决于后端版本 — 旧版为
nodes[].result_json
,新版为根层级的
factor_analysis
。需要兼容两种格式。关键指标:IC均值、IR、t统计量、年化分组收益、Sharpe比率。

2. Strategy backtest (panda_backtest engine)

2. 策略回测(panda_backtest引擎)

bash
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>
bash
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>

Strategy code contract

策略代码约定

python
from panda_backtest.api.api import *            # common trading API — MANDATORY
from panda_backtest.api.stock_us_api import *   # US market data API — MANDATORY
python
from panda_backtest.api.api import *            # 通用交易API — 必须导入
from panda_backtest.api.stock_us_api import *   # 美股数据API — 必须导入

HK market: from panda_backtest.api.stock_hk_api import *

港股市场: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}")

Reference run: this exact code on AAPL.NB, 20250101–20251231, produces 18 real fills (check with `backtest_result <backtest_id> --section trade --all-pages`).

Hard rules learned from real failures:

| Symptom | Root cause | Fix |
|---|---|---|
| `禁止使用危险函数 dir()` | Security filter blocks introspection | Never use `dir()`/`eval()`/`exec`; to inspect context, `raise Exception(str(...))` and read the error_detail in run logs |
| `访问了不存在的键` on order | Wrong account ID (e.g. `'8888'`) | Use `list(context.stock_account_dict.keys())[0]` |
| `order_shares() missing 1 required positional argument` | Called with 2 args | Signature is `order_shares(account, symbol, quantity)` |
| `股票X不属于当前股票回测市场` | Wrong symbol suffix | US = `TICKER.NB` (NOT `.US`!), HK = `XXXXX.HK`; `.O`/`.N`/bare tickers are rejected |
| Backtest SUCCESS but 0 trades, 0 log lines, profit = 0.0 | Symbol suffix `.US` (or any wrong suffix) → every bar returns None → defensive guard skips all days silently | Use `TICKER.NB` for US stocks. ALWAYS verify via `backtest_result <id> --section trade` — SUCCESS ≠ trades executed |
| Run FAILED immediately (~0.3s, node failed) | `SRLog` is not a valid API in strategy code | Use plain `print()` for strategy logging (visible in `--section log`) |
| Run status FAILED but NO failed node (all nodes success/pending) | Transient TQX queue/scheduler error, not your code | Resubmit the same workflow once — typically succeeds in ~30s. Only debug strategy code if a node actually failed |
| Backtest SUCCESS but 0 trades, `标的不在当前回测数据集内` | Date range beyond ingested market data (recent months may not be loaded even though the benchmark series exists) | Shift the window earlier (e.g. use last year's range); verify trades>0 in the `trade` section before trusting metrics |
| `frequency` rejected | Only `1d` and `1M` are valid | — |
import tqx_data
def initialize(context): # 账户ID为用户专属 — 需动态获取,请勿硬编码。 # 国内市场文档中的'8888'在港美股回测中不存在。 context.account = list(context.stock_account_dict.keys())[0] context.symbol = 'AAPL.NB' # 代码格式:美股 = TICKER.NB(不是.US!),港股 = 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可能为None — 如果后缀错误,每天的bar都会是None(导致无交易的静默回测) 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()用于记录策略日志;禁止使用SRLog 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`;如需检查context,可`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日志行、收益=0.0 | 代码后缀为`.US`(或其他错误后缀)→ 每天的bar都返回None → 防御性检查跳过了所有交易日 | 美股使用`TICKER.NB`。务必通过`backtest_result <id> --section trade`验证 — SUCCESS不代表有交易执行 |
| 运行立即失败(约0.3秒,节点失败) | 策略代码中使用了无效API `SRLog` | 使用普通`print()`记录策略日志(可在`--section log`中查看) |
| 运行状态显示FAILED但无失败节点(所有节点为success/pending) | TQX队列/调度器的临时错误,与代码无关 | 重新提交同一工作流一次 — 通常约30秒后会成功。只有当确实有节点失败时才需要调试策略代码 |
| 回测显示SUCCESS但0交易,提示`标的不在当前回测数据集内` | 时间范围超出了已加载的市场数据(即使基准序列存在,最近几个月的数据可能未加载) | 将时间窗口提前(例如使用去年的范围);在信任指标前务必验证`trade`板块的交易数>0 |
| `frequency`参数被拒绝 | 仅支持`1d`和`1M` | — |

Reading results

结果解读

strategy_run
/
strategy_result
returns run status + node outputs. For full detail, extract the backtest id from run logs (
BacktestNodeIdentifier:
line) or node output, then:
bash
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
A run can report SUCCESS with zero trades (orders silently rejected day by day). Always confirm the
trade
section is non-empty before reporting performance numbers.
strategy_run
/
strategy_result
返回运行状态 + 节点输出。如需完整详情,可从运行日志(
BacktestNodeIdentifier:
行)或节点输出中提取回测ID,然后执行:
bash
tqx-cli --json backtest_result <backtest_id> --section summary   # 收益、alpha、beta、Sharpe比率、IR
tqx-cli --json backtest_result <backtest_id> --section trade     # ⚠️ 务必检查是否有交易执行
tqx-cli --json backtest_result <backtest_id> --section log       # 每笔订单的拒绝原因
回测可能显示SUCCESS但实际无交易(订单每天被静默拒绝)。在报告业绩指标前,务必确认
trade
板块非空。

Daily equity curve (
--section profit
)

每日权益曲线(
--section profit

The
profit
section is the day-by-day NAV series — one row per trading day with
gmt_create
(YYYYMMDD),
strategy_profit
(cumulative strategy return, decimal) and
csi_stock
(cumulative benchmark return, decimal).
bash
undefined
profit
板块包含每日净值序列 — 每个交易日一行,包含
gmt_create
(YYYYMMDD)、
strategy_profit
(策略累计收益,小数)和
csi_stock
(基准累计收益,小数)。
bash
undefined

⚠️ --all-pages does NOT work for the profit section: it silently returns only page 1 (100 rows).

⚠️ --all-pages参数对profit板块无效:会静默返回仅第1页(100行)的数据。

tqx-cli --json backtest_result <backtest_id> --section profit --page-size 1000
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

-> 分页信息 {total: 252, page: 1, page_size: 1000, total_pages: 1} ✅ 一次调用获取全年数据


Two more behaviours to handle (reference: AAPL.NB, full-year 2025 = 252 rows):
- Rows come back **unsorted** — always sort by `gmt_create` ascending before plotting; do not assume the API order.
- Values are **decimals, not percent** (`-0.1174` = −11.74%) and are already cumulative, so plot them directly; don't compound them again.
- The last row must match the `summary` section's total return — use that as your correctness check.

Cache the series locally (one file per run) instead of re-fetching: the call costs ~2–4 s and the data is immutable once the run is done.

需要处理的两种特殊情况(参考:AAPL.NB,2025全年=252行):
- 返回的行是**未排序**的 — 绘图前务必按`gmt_create`升序排序;不要假设API返回的顺序是正确的。
- 值为**小数而非百分比**(`-0.1174` = −11.74%),且已为累计值,可直接绘图;无需再次计算复利。
- 最后一行的值必须与`summary`板块的总收益一致 — 以此作为正确性校验。

将序列本地缓存(每个运行对应一个文件),避免重复获取:该调用耗时约2-4秒,且数据一旦生成即为不可变。

Debugging failed runs

失败运行的调试

Error details are NOT in the top-level status — fetch run logs and read
error_detail
, which includes the exact strategy line number and exception message:
python
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"])
错误详情不在顶层状态中 — 获取运行日志并查看
error_detail
,其中包含策略代码的具体行号和异常信息:
python
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"])

Cost & pacing

成本与 pacing

Backtests are billed in TQX compute credits (
tqx-cli balance
). A 6-month daily-frequency single-stock backtest takes ~2 minutes wall time. Poll
strategy_result
every 3s; don't fire concurrent runs of the same workflow.
回测按TQX计算积分计费(可通过
tqx-cli balance
查询)。一次6个月日频单股票回测耗时约2分钟。每3秒轮询一次
strategy_result
;不要并发运行同一工作流的多个实例。

3. Templates (copy-paste starting points)

3. 模板(可直接复制粘贴的起点)

T1 — Momentum factor (cross-sectional, whole market)

T1 — 动量因子(横截面,全市场)

bash
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
Other verified formulas: mean reversion
-(close/ref(close,5)-1)
, volume surge
volume/mean(volume,20)
. Factor mode is whole-market cross-sectional only (
--market hk|us
) — it CANNOT target one stock; for single-stock questions use a strategy backtest (T2).
bash
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 — Single-stock backtest (SMA cross on AAPL)

T2 — 单股票回测(AAPL均线交叉策略)

Use the strategy code contract in §2 verbatim — it IS the template. Change
context.symbol
and the signal logic only. Keep the None-bar guard and dynamic account discovery.
直接使用§2中的策略代码约定 — 这就是模板。仅修改
context.symbol
和信号逻辑即可。保留bar为None的防御性检查和动态账户发现逻辑。

T3 — Agent-driven automated trading loop

T3 — Agent驱动的自动化交易循环

Pattern verified over a 10-round live run (~21 min, end-to-end):
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}
Hard rules for automation:
  • PAPER account by default. Live trading uses the identical command surface, so nothing in the code stops a live order — only your gating does. Require an explicit user approval before pointing the loop at a live account, keep a hard order-size cap, and always pass
    --idempotencyKey
    so a retry can never double-fill.
  • Journal every decision (JSONL is enough) — users must be able to audit why each trade happened.
  • Re-login on ANY auth-ish error string (see token gotcha above); a mid-loop token expiry must self-heal, not kill the loop.
  • Check compute balance before each backtest-class call to avoid silent overdraft.
经10轮实盘运行验证的模式(约21分钟,端到端):
每N分钟循环一次:
  1. 获取实时持仓 + 账户状态
  2. 计算信号(因子值或策略规则)
  3. 决策:买入 / 卖出 / 持有  ← Agent推理步骤
  4. 下单(开发阶段使用模拟账户,固定小订单量)
  5. 记录决策日志:{ts, reasoning, tool_calls, params, result, position_delta}
自动化严格规则:
  • 默认使用模拟账户。实盘交易使用完全相同的命令接口,因此代码本身无法阻止实盘订单 — 只有你的管控可以。在将循环指向实盘账户前,必须获得用户明确批准,设置严格的订单限额,且始终传递
    --idempotencyKey
    ,避免重试导致重复下单。
  • 记录每一次决策(JSONL格式即可)— 用户必须能够审计每笔交易的决策原因。
  • 任何类似认证错误的响应都要重新登录(见上文Token陷阱);循环中的Token过期必须自动恢复,不能终止循环。
  • 每次调用回测类命令前检查计算积分余额,避免静默透支。

T4 — Studio: ready-to-run companion UI (
templates/studio/
)

T4 — Studio:可直接运行的配套UI(
templates/studio/

A complete, tested web workbench ships with this skill — do NOT build a dashboard from scratch. Copy
templates/studio/
into the user's workspace, start it, and adapt.
Files:
FileRole
server.py
Stdlib HTTP backend (port 8090, no pip deps). Proxies
tqx-cli
, auto re-login on token expiry, serves all
/api/*
routes
index.html
Single-file frontend: factor analysis, backtest submit/history, positions, agent decision timeline
agent.py
Agent trading loop (LLM via
proxied_post
+ tool calls), JSONL decision journal
backtests.py
/
strategies.py
/
journal.py
Disk persistence modules (see data spec below)
UI language: the template ships English-only. Any Chinese you see at runtime comes from the TQX API itself (metric key names, error strings) — do not translate those, they are matched against.
Run:
python3 server.py
from the studio dir (background), then
preview(action="serve")
on it. Credentials come from
TQX_EMAIL
/
TQX_PASSWORD
env vars (collect via secure input — never hardcode).
Design spec (keep when restyling):
  • Minimalist quant-tech aesthetic: dark-first, monospace numerals, dense tables, no decorative graphics. Avoid bright or cyberpunk themes.
  • History rows must be loadable: clicking Load on any history record re-displays its full result in the top result area (factor runs → factor metrics/charts via
    loadBt
    ; strategy runs → dedicated strategy-result card via
    loadStgBt
    : return vs benchmark, annualized, Sharpe, max drawdown, trade count, params + code link). A history table that only lists rows without load-back is incomplete.
  • UI exposes only high-frequency params (formula, market, date range, groups, rebalance, direction) + account switcher + NAV curve + decision timeline. Everything complex (custom strategy code, stock pools, commission/slippage) stays in the conversation layer — the agent has the full CLI surface, the UI must not duplicate it.
  • Amounts: format gold/cash values with a single dedicated formatter two competing formatters produce inconsistent output. Check dark-mode contrast on every card.
Persistence & paths (why the two directories):
tqx-cli
writes its login config to
/root/.tqx/config.yaml
, which lives on the container's ephemeral layer and is wiped on every machine restart — the agent would silently lose its session. Only
/data/workspace
survives restarts, so the studio mirrors the config into
/data/workspace/.tqx/
and syncs both ways on startup (
sync_tqx_config()
in
server.py
,
_sync_tqx_config()
in
agent.py
).
These paths are intentionally fixed, not a portability oversight: every agent has the identical layout —
/data/workspace
= persistent volume,
/root
= ephemeral. Keep the rule when extending the studio: anything that must survive a restart is written under the workspace, never under
/root
or
/tmp
.
In-studio state (
data/backtests
,
data/journal
,
data/strategies
) is already
__file__
-relative, so it inherits persistence as long as the studio itself is copied into the workspace. If you ever run this outside a Starchild machine, override the persistent root — nothing else in the code assumes an absolute path.
Data storage spec:
  • data/backtests/index.json
    + one JSON per run — MUST persist the full strategy code string (not a truncated preview) so any run can be reloaded and re-edited.
  • data/journal/*.jsonl
    — one line per agent decision, tagged
    source: manual | agent
    , append-only, never rewritten.
  • data/strategies/
    — named saved strategies. All state is plain JSON on disk; no DB.
Testing spec (before declaring the studio 'working'):
  1. curl localhost:8090/api/health
    (or any GET route) returns JSON — backend alive.
  2. Submit one REAL backtest through the UI and confirm it appears in the history panel with full code + metrics. A rendered page alone is NOT verification.
  3. Verify fills exist via
    backtest_result <id> --section trade
    — SUCCESS status with 0 trades means a symbol-suffix bug (see failure table).
  4. Kill/restart
    server.py
    and confirm history persists (disk, not memory).
本Skill附带一个完整的、经过测试的Web工作台 — 无需从零构建仪表板。将
templates/studio/
复制到用户工作区,启动后即可按需调整。
文件说明:
文件作用
server.py
标准库HTTP后端(端口8090,无需额外pip依赖)。代理
tqx-cli
,Token过期时自动重新登录,提供所有
/api/*
路由
index.html
单页前端:因子分析、回测提交/历史记录、持仓、Agent决策时间线
agent.py
Agent交易循环(通过
proxied_post
调用LLM + 工具调用),JSONL决策日志
backtests.py
/
strategies.py
/
journal.py
磁盘持久化模块(详见下文数据规范)
UI语言:模板默认仅支持英文。运行时出现的中文内容来自TQX API本身(指标键名、错误字符串)—— 请勿翻译这些内容,它们用于匹配校验。
运行方式:在studio目录下执行
python3 server.py
(后台运行),然后对其执行
preview(action="serve")
。凭证来自
TQX_EMAIL
/
TQX_PASSWORD
环境变量(通过安全输入收集 — 请勿硬编码)。
设计规范(调整样式时需遵守):
  • 极简量化科技风格:优先深色模式等宽数字、密集表格,无装饰性图形。避免亮色或赛博朋克主题。
  • 历史记录行必须可加载:点击任何历史记录的Load按钮,需在顶部结果区域重新展示其完整结果(因子运行 → 通过
    loadBt
    展示因子指标/图表;策略运行 → 通过
    loadStgBt
    展示专属策略结果卡片:收益 vs 基准、年化收益、Sharpe比率、最大回撤、交易次数、参数 + 代码链接)。仅列出行而无法加载详情的历史表格是不完整的。
  • UI仅暴露高频参数(公式、市场、时间范围、分组、调仓、方向)+ 账户切换器 + 净值曲线 + 决策时间线。所有复杂配置(自定义策略代码、股票池、佣金/滑点)保留在对话层 — Agent拥有完整的CLI接口,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可正常运行前需完成):
  1. curl localhost:8090/api/health
    (或任何GET路由)返回JSON — 后端正常运行。
  2. 通过UI提交一次真实回测,并确认其出现在历史面板中,包含完整代码 + 指标。仅渲染页面不足以验证功能正常。
  3. 通过
    backtest_result <id> --section trade
    确认存在成交记录 — SUCCESS状态但0交易意味着代码后缀错误(见故障表)。
  4. 终止并重启
    server.py
    ,确认历史记录仍存在(存储在磁盘而非内存中)。