HTTP 接口(战术信号)
以下为 /api/signal-records 及相关路径的调用说明。各策略的 strategy_key、规则正文见左侧对应子页。
GET分页查询
/api/signal-records
列表数据公开,无需鉴权即可读取行数据。若请求携带有效身份(见下),每行会额外合并当前用户的 user_note。
可选身份(用于 user_note):与写入接口相同,支持 Authorization: Bearer <JWT 或 个人中心 API Key>(JWT 亦可来自 Cookie 登录态)。未携带或校验失败时 user_note 恒为 null。
| 参数 | 类型 | 说明 |
|---|---|---|
limit | number | 每页条数,默认 50,最大 200 |
offset | number | 偏移,默认 0 |
strategy_key | string | 按策略标识精确筛选 |
code | string | 模糊匹配:code 或 stock_name 含该子串(最多 64 字符) |
review_status | string | 复盘状态精确匹配,如 pending、completed、calculating |
date_from / date_to | string | 信号日范围,格式 YYYY-MM-DD,可只传其一 |
include_deleted | string | 传 1 时包含已软删(deleted_at 非空)的记录 |
sort_key | string | 排序字段:signal_date、return_percent、signal_strength、strategy_key、code、created_at、review_status、review_end_date;非法值回退为 signal_date |
sort_dir | string | asc 或 desc(默认 desc) |
成功响应:success: true,data 含 rows、total、limit、offset。rows[] 字段如下(与库表及 mapRow 一致;金额为数值或 null)。
| 字段 | 说明 |
|---|---|
id | 主键字符串 |
strategy_key / strategy_version | 策略标识与版本 |
signal_date | 信号日 YYYY-MM-DD |
code / stock_name | 股票代码与简称 |
signal_timestamp | ISO 时间或 null |
trade_direction | 如 buy、sell 等 |
signal_strength / volume_ratio | 信号强度、信号相关量比(与日线快照量比含义不同) |
signal_price | 次一交易日开盘价(万元单位不适用);无行情时可能为 null |
ref_open_price / ref_close_price | 信号日开盘、收盘(来自日线) |
daily_pre_close_price、daily_change_percent、daily_total_market_value | 信号日日线快照 |
daily_ma5~daily_ma60、daily_volume_ratio | 信号日均线与量比快照 |
signal_day_mf_lg_elg_net_wan | 信号日大单+特大单净流入(万元),来自资金流合并;无则 null |
signal_day_net_mf_5d_wan | 5 日主力净额(万元)等;无则 null |
review_end_date / review_end_price | 复盘结束日、结束价 |
return_percent、max_favorable_return、max_adverse_return | 收益率与最大有利/不利波动(%) |
holding_days、exit_reason、signal_direction_correct | 持仓天数、平仓原因、方向是否正确(0/1/null) |
review_status | 如 pending、completed、calculating |
forced_exit_trading_days、stop_loss_percent | 强平下标(2~30,默认 5)、止损%(0~100 或 null);与 lib/cyq-signal-review-rule 一致 |
strategy_params_json / signal_detail_json | JSON |
deleted_at | 软删时间 ISO 或 null |
created_at / updated_at | ISO 时间 |
same_code_prior_signal_count_2y | 近两年同代码更早信号条数(整数,≥0) |
same_code_prior_avg_return_pct_2y | 上述样本平均收益率%,无则 null |
user_note | 当前登录用户或 API Key 对应用户对该条的备注文本;无身份或未写备注时为 null |
GET策略键列表
/api/signal-records/strategy-keys
公开,无需鉴权。返回表中 strategy_key 去重升序列表。
成功:success: true,data.keys: string[]。
GET策略月度统计
/api/signal-records/monthly-stats
需鉴权:Authorization: Bearer <JWT 或 API Key> 或 ?api_key=(与 POST 相同)。
Query:month_from、month_to(均必填,YYYY-MM),可选 strategy_key(≤64 字符)。按 signal_date 自然月聚合。仅统计 review_status 为 completed、calculating 且未软删的记录。胜率 = 有 return_percent 的条目中 return_percent > 0 的比例。avg_drawdown_pct 为组内 max_adverse_return 的算术平均(复盘写入后才有)。market_month_pct 为上证指数 000001.SH 当月自然月涨跌幅;vs_market_pct 为 avg_return − market_month_pct。data.benchmark 含指数说明。
行字段:strategy_key、ym、n_all、n_with_return、n_win、win_rate、avg_return、max_return、min_return、avg_drawdown_pct、market_month_pct、vs_market_pct。
POST回补 signal_price
/api/signal-records/backfill-signal-price
需鉴权(同 POST 主接口)。为 signal_price 为空且未软删的记录,按更新时间倒序尝试写入次一交易日开盘价。
Query:limit,默认 20,范围 1~20。
成功:data.scanned(本批候选条数)、data.updated(实际写入条数)。
POST批量战术复盘任务
/api/signal-records/review
当前实现未校验 HTTP 鉴权——任意能访问该 URL 的客户端均可触发复盘逻辑。若部署在公网,请务必通过网络策略、网关或内网限制保护;生产环境建议仅服务端或可信任务调度调用。
请求体 JSON(均可选):signal_date(只处理该信号日)、end_date(复盘日历截止,默认当天)、after_id(上一批最后一条 id,下一批只取 id > after_id 以分页)。 单批最多处理 8 条(lib/review-batch REVIEW_BATCH_SIZE);若可能仍有待处理记录,响应 data.has_more === true,可携带返回的 data.next_after_id 再次 POST。
规则与 lib/cyq-signal-review-rule 一致,仅更新 stock_signal_record。响应含 reviewed_count、skipped_count、error_count、deferred_count、deferred_breakdown、errors 等。
POST用户备注
/api/signal-records/note
需身份:getUserIdFromRequest——支持 Cookie 登录 JWT、Authorization: Bearer (JWT 或 API Key)。空字符串 note 表示删除该条备注。备注最长 4000 字。
请求体:id(信号记录主键字符串)、note(字符串)。成功返回 data.note(字符串或 null)。未解析到用户时 HTTP 401(文案可能为「请先登录」,但 API Key 与 JWT 等价有效)。
POST新增或覆盖写入
/api/signal-records
需鉴权:优先 Authorization: Bearer(JWT 或 API Key,与 lib/auth 校验一致);否则查询参数 ?api_key=。
Query:upsert=1 或 upsert=true — 当唯一键(strategy_key + signal_date + code)已存在则更新,否则插入;不传时仅插入,冲突返回 409。成功时 data.upsert 为布尔,表示本次是否走 upsert;走 upsert 时另含 data.prior_existed(写入前是否已有同键行)、data.prior_review_status(有则为其当时的 review_status)。若已有行且 review_status === 'completed',仅更新附属 JSON/名称等同码 prior 统计,不覆盖复盘终局与收益率。
请求体(JSON)
| 字段 | 必填 | 说明 |
|---|---|---|
strategy_key | 是 | 策略标识,最长 64 字符 |
signal_date | 是 | 信号所属交易日 T(YYYY-MM-DD):策略在哪一天触发,由调用方在提交时给出;不是次日,也无需等复盘结束才填 |
code | 是 | 股票代码,1~20,仅字母数字及 ._- |
strategy_version | 否 | 字符串,最长 10 字符(与库列 VARCHAR(10) 一致);也可传整数(将转为字符串)。未传时默认 "1" |
trade_direction | 否 | 如 buy、sell、neutral、both,最长 16,默认 buy |
signal_timestamp | 否 | ISO 时间字符串或 null。不传时服务端自动填为与 signal_date 对应的 UTC 日初;显式传 null 表示不存时间戳 |
signal_strength | 否 | 信号强度(统一刻度,如 0~100);数字 |
volume_ratio | 否 | 数字或 null(信号相关量比,与下方日线快照字段含义不同) |
review_end_price | 否 | 复盘平仓/结束时的结算价(元);数字 |
return_percent | 否 | 复盘终局收益率(%),与筹码等战术 pnl% 同字段名;数字 |
max_favorable_return | 否 | 持有期内相对信号过程的最大有利变动(%);数字 |
max_adverse_return | 否 | 持有期内最大不利波动(%,多为负值表示回撤);数字 |
review_end_date | 否 | 复盘平仓/结束日(YYYY-MM-DD);与 signal_date 同为日历日 |
forced_exit_trading_days | 否 | 整数 2~30,默认 5。与复盘库 lib/cyq-signal-review-rule 中 fullPath 下标一致:强平发生在该下标 K 线当日开盘(历史默认即「原第 5 根非信号 K」)。战术复盘会按此拉取足够日线并计算。 |
stop_loss_percent | 否 | 数字或 null:相对 T+1 入场价的止损比例(%),如 5 表示跌破约 −5%(按当日最低价与入场价比较);下一交易日开盘平仓。null 或省略表示不按百分比止损(仍保留收阴离场与到期强平)。须在 0~100。 |
strategy_params_json | 否 | 策略参数快照(JSON 对象/数组,或 JSON 字符串);用于复现、版本对比等;null 表示清空 |
signal_detail_json | 否 | 策略扩展明细(JSON 对象/数组,或 JSON 字符串);存放不便拆成列的结构化信息;null 表示清空 |
deleted_at | 否 | 软删时间:合法 ISO 字符串或 null。一般应由服务端或管理流程维护;对外调用若需软删可显式传入。 |
服务端自动补全的名称(勿在请求体中填写)
stock_name 由服务端根据 code 查询证券基础信息并写入;调用方无需填写,请求体中的同名键将被忽略。若无对应基础信息,则该字段可能为空。
服务端自动补全的「信号基准价」signal_price(勿在请求体中填写)
为次一交易日开盘价(signal_date 之后 stock_daily_data 中最近一条交易日的 open_price)。T 日提交时通常尚无 T+1 行情,故不接受调用方传入;若当时无下一日行情或尚未入库,该字段可能为空。站内打开 /signal-records 约 4 秒后、同一会话仅一次请求 POST /api/signal-records/backfill-signal-price(每次最多 20 条)尝试回补;亦可在 T+1 行情就绪后自行 ?upsert=1 再写。与信号日 ref_open_price / ref_close_price 含义不同。
服务端自动补全的日线快照(勿在请求体中填写)
以下字段与信号日当日行情一致,由服务端在写入/更新时根据 code 与 signal_date 从行情日线数据补全;调用方无需、也不应依赖请求体传入(传入将被忽略)。若该日无行情记录,则这些字段可能为空。
daily_pre_close_pricedaily_change_percentdaily_total_market_valuedaily_ma5、daily_ma10、daily_ma20、daily_ma60daily_volume_ratioref_open_price:信号日open_priceref_close_price:信号日收盘价,取当日current_price
复盘结果字段(POST 不接受写入,与列表返回一致)
holding_days、signal_direction_correct、exit_reason、review_status 等主要由复盘任务写入;创建时库默认 review_status 多为 pending。POST 解析层不接受调用方传入上述复盘独占字段来覆盖(与路由内注释一致)。?upsert=1 的 update 侧也会剥离上述复盘独占字段,避免误覆盖;已完成复盘(completed)时仅允许刷新 signal_detail_json、strategy_params_json、stock_name 及同码 prior 统计字段。
HTTP 状态
200:成功,响应含success: true与data.row(写入后的记录,字段同列表行)、data.upsert,以及 upsert 时的prior_existed/prior_review_status400:参数或 JSON 不合法401:未鉴权409:唯一键冲突(未使用 upsert 时)500:服务端错误
DELETE按主键物理删除
/api/signal-records/<id>
需鉴权:与 POST 相同(Bearer 或 ?api_key=)。
从数据库永久删除该行(非软删)。id 为列表返回中的主键字符串。
200:success: true,data.id为已删除记录 id400:id 非法401:未鉴权404:记录不存在500:服务端错误