openapi: 3.0.3 info: title: Veyra API version: 0.15.0 description: 开发身份、账户、供应商配置、候选、计划、成交账本、站内通知、研究策略、Python 回测与公开 A 股开发行情。模拟工作流仅限 local/test;正式行情授权、完整交易规则及远程推送未完成。 servers: - url: http://127.0.0.1:8080 paths: /healthz: get: operationId: getLiveness responses: "200": description: API 进程存活,与依赖是否就绪无关 content: application/json: schema: type: object required: - status properties: status: type: string enum: - alive /readyz: get: operationId: getReadiness responses: "200": $ref: "#/components/responses/Health" "503": $ref: "#/components/responses/Health" /api/v1/system/health: get: operationId: getSystemHealth responses: "200": $ref: "#/components/responses/Health" "503": $ref: "#/components/responses/Health" /api/admin/v1/auth/login: post: operationId: adminLogin description: 开发环境登录,要求同源 Origin;会话只在 HttpOnly Cookie 中返回。 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/LoginRequest" responses: "200": description: 已创建管理端会话 headers: Set-Cookie: schema: type: string description: veyra_admin_session; HttpOnly; SameSite=Strict; Path=/api/admin content: application/json: schema: allOf: - $ref: "#/components/schemas/Envelope" - properties: data: $ref: "#/components/schemas/AdminLogin" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "429": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" /api/v1/auth/login: post: operationId: developmentAppLogin description: local/test 开发登录,返回 App 专用会话。正式短信登录与刷新流程待接入。 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/LoginRequest" responses: "200": description: 已创建 App 会话 content: application/json: schema: allOf: - $ref: "#/components/schemas/Envelope" - properties: data: $ref: "#/components/schemas/AppLogin" "401": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "429": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" /api/admin/v1/me: get: operationId: getAdminIdentity security: - adminCookie: [] responses: "200": $ref: "#/components/responses/Identity" "401": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" /api/v1/me: get: operationId: getAppIdentity security: - appBearer: [] responses: "200": $ref: "#/components/responses/Identity" "401": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" /api/admin/v1/auth/logout: post: operationId: adminLogout description: 同源 Origin 请求,撤销会话并清除管理端 Cookie。 security: - adminCookie: [] responses: "200": $ref: "#/components/responses/Logout" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" /api/v1/auth/logout: post: operationId: appLogout security: - appBearer: [] responses: "200": $ref: "#/components/responses/Logout" "401": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" /api/admin/v1/users: get: operationId: listAppUsers description: 最近创建的 100 位 App 用户,不包含密码、登录名或后台权限。 security: - adminCookie: [] responses: "200": description: App 用户列表 content: application/json: schema: allOf: - $ref: "#/components/schemas/Envelope" - properties: data: type: array items: $ref: "#/components/schemas/User" "401": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" /api/v1/accounts: get: operationId: listOwnAccounts security: - appBearer: [] responses: "200": description: 当前用户账户列表 content: application/json: schema: allOf: - $ref: "#/components/schemas/Envelope" - properties: data: type: array items: $ref: "#/components/schemas/AccountSummary" "401": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" post: operationId: createOwnAccount description: simulation 要求 initial_cash,manual_real 必须省略;每种模式仅一个账户。 security: - appBearer: [] requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreateAccount" responses: "201": $ref: "#/components/responses/AccountSummary" "401": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" /api/v1/accounts/{id}/summary: get: operationId: getOwnAccountSummary security: - appBearer: [] parameters: - name: id in: path required: true schema: type: string format: uuid responses: "200": $ref: "#/components/responses/AccountSummary" "401": $ref: "#/components/responses/Error" "404": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" /api/admin/v1/providers: get: operationId: listProviderConfigurations security: - adminCookie: [] description: 列出已保存配置,初始为空数组;不返回密钥或密文。 responses: "200": description: 已保存的供应商配置 content: application/json: schema: allOf: - $ref: "#/components/schemas/Envelope" - properties: data: type: array items: $ref: "#/components/schemas/ProviderConfig" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" /api/admin/v1/providers/{key}: put: operationId: saveProviderConfiguration security: - adminCookie: [] description: 同源 Origin 写入;首次 expected_version 为 0,后续使用当前版本。省略 api_key 保留密钥,clear_api_key 清除。修改接口地址须重新填写或清除已有密钥。配置保存不代表连接已验证。 parameters: - name: key in: path required: true schema: type: string enum: - model_primary - model_backup - model_review - market_primary requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/ProviderInput" responses: "200": description: 配置、历史与审计已原子保存 content: application/json: schema: allOf: - $ref: "#/components/schemas/Envelope" - properties: data: $ref: "#/components/schemas/ProviderConfig" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" /api/admin/v1/audit-events: get: operationId: listAuditEvents security: - adminCookie: [] description: 最近 100 条后台操作审计,详情不含密钥。 responses: "200": description: 审计事件 content: application/json: schema: allOf: - $ref: "#/components/schemas/Envelope" - properties: data: type: array items: $ref: "#/components/schemas/AuditEvent" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" /api/admin/v1/candidates: get: operationId: adminCandidates description: 最近 100 条候选;管理端列出最新修订及当前发布版本,App 仅显示当前有效发布。仅模拟数据。 security: - adminCookie: [] parameters: - in: query name: limit schema: type: integer minimum: 1 maximum: 100 default: 100 - in: query name: status schema: type: string enum: - DRAFT - PENDING_REVIEW - PUBLISHED - RETURNED - WITHDRAWN responses: "200": description: 操作成功,data 包含记录或列表 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "404": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" post: operationId: createCandidate description: 保存独立模拟草稿,要求同源 Origin。 security: - adminCookie: [] requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CandidateDraft" responses: "201": description: 操作成功,data 包含记录或列表 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "404": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" /api/admin/v1/candidates/{id}: get: operationId: adminCandidateDetail description: 读取修订详情;App 不能读取未发布内容,历史发布可查看失效状态及撤回原因。 security: - adminCookie: [] parameters: - in: path name: id required: true schema: type: string format: uuid responses: "200": description: 操作成功,data 包含记录或列表 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "404": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" /api/v1/candidates: get: operationId: appCandidates description: 最近 100 条候选;管理端列出最新修订及当前发布版本,App 仅显示当前有效发布。仅模拟数据。 security: - appBearer: [] parameters: - in: query name: limit schema: type: integer minimum: 1 maximum: 100 default: 100 responses: "200": description: 操作成功,data 包含记录或列表 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "404": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" /api/v1/candidates/{id}: get: operationId: appCandidateDetail description: 读取修订详情;App 不能读取未发布内容,历史发布可查看失效状态及撤回原因。 security: - appBearer: [] parameters: - in: path name: id required: true schema: type: string format: uuid responses: "200": description: 操作成功,data 包含记录或列表 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "404": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" /api/admin/v1/candidates/{id}/revisions: post: operationId: reviseCandidate description: 创建下一份独立修订,保留原文;待审版本需先退回;要求同源 Origin。 security: - adminCookie: [] parameters: - in: path name: id required: true schema: type: string format: uuid requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CandidateRevisionInput" responses: "201": description: 操作成功,data 包含记录或列表 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "404": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" /api/admin/v1/candidates/{id}/submit: post: operationId: submitCandidate description: 提交审核;要求具体意见、版本匹配和同源 Origin。审核、审计、事件同事务。 security: - adminCookie: [] parameters: - in: path name: id required: true schema: type: string format: uuid requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CandidateAction" responses: "200": description: 操作成功,data 包含记录或列表 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "404": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" /api/admin/v1/candidates/{id}/publish: post: operationId: publishCandidate description: 审核发布并替代旧发布;要求具体意见、版本匹配和同源 Origin。审核、审计、事件同事务。 security: - adminCookie: [] parameters: - in: path name: id required: true schema: type: string format: uuid requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CandidateAction" responses: "200": description: 操作成功,data 包含记录或列表 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "404": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" /api/admin/v1/candidates/{id}/return: post: operationId: returnCandidate description: 退回,等待创建新修订;要求具体意见、版本匹配和同源 Origin。审核、审计、事件同事务。 security: - adminCookie: [] parameters: - in: path name: id required: true schema: type: string format: uuid requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CandidateAction" responses: "200": description: 操作成功,data 包含记录或列表 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "404": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" /api/admin/v1/candidates/{id}/withdraw: post: operationId: withdrawCandidate description: 撤回当前有效发布;要求具体意见、版本匹配和同源 Origin。审核、审计、事件同事务。 security: - adminCookie: [] parameters: - in: path name: id required: true schema: type: string format: uuid requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CandidateAction" responses: "200": description: 操作成功,data 包含记录或列表 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "404": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" /api/v1/plan-previews: post: operationId: previewPlan description: 模拟买入预算预览,不保留现金。数量为字符串且须为 100 股整数倍;预计费用由用户输入。 security: - appBearer: [] requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/PlanPreviewInput" responses: "201": description: 操作成功,data 包含记录或列表 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "404": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" /api/v1/plan-previews/{id}/confirm: post: operationId: confirmPlan description: 确认时重检所有权、候选版本、时效与可用现金。确认同一预览幂等,保留预算但不扣现金。 security: - appBearer: [] parameters: - in: path name: id required: true schema: type: string format: uuid requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/EmptyObject" responses: "200": description: 操作成功,data 包含记录或列表 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "404": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" /api/v1/plans: get: operationId: listPlans description: 读取本人最近 100 条计划,候选撤回或过期后失效并释放预算。 security: - appBearer: [] responses: "200": description: 操作成功,data 包含记录或列表 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "404": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" /api/v1/plans/{id}/cancel: post: operationId: cancelPlan description: 版本保护的取消,释放保留预算,已记录成交保留。 security: - appBearer: [] parameters: - in: path name: id required: true schema: type: string format: uuid requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/ExpectedVersion" responses: "200": description: 操作成功,data 包含记录或列表 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "404": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" /api/v1/accounts/{id}/budget: get: operationId: getBudget description: 模拟账本现金、有效计划保留及可用金额,均为十进制字符串。 security: - appBearer: [] parameters: - in: path name: id required: true schema: type: string format: uuid responses: "200": description: 操作成功,data 包含记录或列表 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "404": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" /api/v1/fills: post: operationId: recordFill description: 录入已发生的模拟成交;同账户 idempotency_key 重试幂等,不同内容拒绝。按发生时间顺序录入;模拟可卖时间须手工指定,不推断真实交易日。 security: - appBearer: [] requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/FillInput" responses: "201": description: 操作成功,data 包含记录或列表 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "404": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" /api/v1/fills/{id}/reverse: post: operationId: reverseFill description: 只冲正账户最新未冲正成交;原成交和费用记录不可覆盖。反向现金、批次恢复、审计、事件同事务,原计划不自动重开。 security: - appBearer: [] parameters: - in: path name: id required: true schema: type: string format: uuid requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/ReversalInput" responses: "200": description: 操作成功,data 包含记录或列表 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "404": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" /api/v1/accounts/{id}/fills: get: operationId: listFills description: 本人模拟账户最近 100 条成交,包括已冲正原记录;金额与数量为字符串。 security: - appBearer: [] parameters: - in: path name: id required: true schema: type: string format: uuid responses: "200": description: 操作成功,data 包含记录或列表 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "404": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" /api/v1/accounts/{id}/portfolio: get: operationId: getPortfolio description: 真实读取模拟账本现金、FIFO 剩余成本和含费用已实现盈亏;市值与浮盈亏为 null。 security: - appBearer: [] parameters: - in: path name: id required: true schema: type: string format: uuid responses: "200": description: 操作成功,data 包含记录或列表 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "404": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" /api/v1/notifications: get: operationId: listNotifications description: 本人最近 100 条站内通知,不代表远程推送已发送。 security: - appBearer: [] responses: "200": description: 操作成功,data 包含记录或列表 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "404": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" /api/v1/notifications/{id}/read: post: operationId: markNotificationRead description: 本人通知标记已读,可重复。 security: - appBearer: [] parameters: - in: path name: id required: true schema: type: string format: uuid requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/EmptyObject" responses: "200": description: 操作成功,data 包含记录或列表 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "404": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" /api/admin/v1/notification-tasks: get: operationId: listNotificationTasks description: 最近 100 条持久化事件及站内通知数量;已处理不一定有通知收件人。 security: - adminCookie: [] responses: "200": description: 操作成功,data 包含记录或列表 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "404": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" /api/admin/v1/simulation-quotes: get: operationId: listSimulationQuotes description: 最新 100 个手工模拟价格快照,不代表在线行情。 security: - adminCookie: [] responses: "200": description: 操作成功,data 包含记录或列表 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "404": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" post: operationId: recordSimulationQuote description: 录入手工模拟价格,要求同源 Origin;当前版本、有效计划与候选均重新核验,触发仅产生站内提醒。 security: - adminCookie: [] requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/SimulationQuoteInput" responses: "201": description: 操作成功,data 包含记录或列表 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "404": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" /api/admin/v1/strategies: get: operationId: listStrategies security: - adminCookie: [] responses: "200": description: 成功 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" post: operationId: createStrategy security: - adminCookie: [] responses: "201": description: 成功 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/StrategyInput" /api/admin/v1/strategies/{id}: get: operationId: getStrategy security: - adminCookie: [] responses: "200": description: 成功 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" parameters: - name: id in: path required: true schema: &a1 type: string format: uuid /api/admin/v1/strategies/{id}/versions: post: operationId: reviseStrategy security: - adminCookie: [] responses: "201": description: 成功 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" parameters: - name: id in: path required: true schema: *a1 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/StrategyInput" /api/admin/v1/strategies/{id}/deploy: post: operationId: selectResearchVersion security: - adminCookie: [] responses: "200": description: 成功 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" parameters: - name: id in: path required: true schema: *a1 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/StrategyDeployment" /api/admin/v1/backtests: get: operationId: listBacktests security: - adminCookie: [] responses: "200": description: 成功 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" post: operationId: queueManualBacktest security: - adminCookie: [] responses: "202": description: 成功 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/BacktestInput" /api/admin/v1/backtests/{id}: get: operationId: getBacktest security: - adminCookie: [] responses: "200": description: 成功 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" parameters: - name: id in: path required: true schema: *a1 /api/admin/v1/backtests/from-market: post: operationId: queueMarketBacktest security: - adminCookie: [] responses: "202": description: 成功 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/MarketBacktestInput" /api/v1/instruments: get: operationId: searchInstrumentsApp security: - appBearer: [] responses: "200": description: 成功 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" parameters: - name: q in: query schema: &a2 type: string /api/v1/market/history: get: operationId: getMarketHistoryApp security: - appBearer: [] responses: "200": description: 成功 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" parameters: - name: symbol in: query required: true schema: *a2 - name: exchange in: query required: true schema: *a2 - name: start in: query required: true schema: *a2 - name: end in: query required: true schema: *a2 /api/admin/v1/instruments: get: operationId: searchInstrumentsAdmin security: - adminCookie: [] responses: "200": description: 成功 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" parameters: - name: q in: query schema: *a2 /api/admin/v1/market/history: get: operationId: getMarketHistoryAdmin security: - adminCookie: [] responses: "200": description: 成功 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" parameters: - name: symbol in: query required: true schema: *a2 - name: exchange in: query required: true schema: *a2 - name: start in: query required: true schema: *a2 - name: end in: query required: true schema: *a2 /api/admin/v1/market/syncs: get: operationId: listMarketSyncs security: - adminCookie: [] responses: "200": description: 成功 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "409": $ref: "#/components/responses/Error" "422": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" /api/admin/v1/strategy-screenings: get: tags: - Admin summary: 最近自动日线筛选记录 description: 管理员专用。只记录已完成筛选;不满足数据时效或来源失败时不生成候选。SIGNAL 提交到待审核,不自动发布。 security: - adminCookie: [] responses: "200": &a3 description: 成功 content: application/json: schema: $ref: "#/components/schemas/Envelope" "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" /api/admin/v1/strategy-screenings/{id}: get: tags: - Admin summary: 查看自动筛选不可覆盖的参数与日线输入快照 description: 管理员专用。只记录已完成筛选;不满足数据时效或来源失败时不生成候选。SIGNAL 提交到待审核,不自动发布。 security: - adminCookie: [] parameters: - name: id in: path required: true schema: type: string format: uuid responses: "200": *a3 "401": $ref: "#/components/responses/Error" "403": $ref: "#/components/responses/Error" "404": $ref: "#/components/responses/Error" "503": $ref: "#/components/responses/Error" /api/admin/v1/strategy-screening-status: get: operationId: getScreeningWorkerState summary: 当前进程的最近一批筛选状态 description: 状态与数量仅对应当前进程最近一批;持久化结果使用 strategy-screenings。 security: - adminCookie: [] responses: "200": description: 成功 content: &a5 application/json: schema: $ref: "#/components/schemas/Envelope" "401": &a4 $ref: "#/components/responses/Error" "403": *a4 "503": *a4 /api/admin/v1/strategy-screenings/run: post: operationId: requestStrategyScreening summary: 请求立即自动筛选 description: 同源管理员请求,异步执行。运行中或已排队时复用现有请求,不另起 Worker。每批最多 20 只,固定范围最大 100 只;不自动发布候选。 security: - adminCookie: [] requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/EmptyObject" responses: "202": description: 已排队或已有正在执行的任务 content: *a5 "401": *a4 "403": *a4 "422": *a4 "503": *a4 components: securitySchemes: adminCookie: type: apiKey in: cookie name: veyra_admin_session appBearer: type: http scheme: bearer responses: Error: description: 标准业务错误 content: application/json: schema: type: object required: - error - meta properties: error: type: object required: - code - message - retryable properties: code: type: string message: type: string retryable: type: boolean meta: $ref: "#/components/schemas/Meta" Identity: description: 当前身份 content: application/json: schema: allOf: - $ref: "#/components/schemas/Envelope" - properties: data: $ref: "#/components/schemas/User" Logout: description: 会话已撤销 content: application/json: schema: allOf: - $ref: "#/components/schemas/Envelope" - properties: data: type: object required: - revoked properties: revoked: type: boolean AccountSummary: description: 账户与账本估算现金 content: application/json: schema: allOf: - $ref: "#/components/schemas/Envelope" - properties: data: $ref: "#/components/schemas/AccountSummary" Health: description: PostgreSQL 和 Redis 都正常时为 200,任一不可用或未配置时为 503 content: application/json: schema: $ref: "#/components/schemas/Health" schemas: Meta: type: object required: - request_id properties: request_id: type: string format: uuid server_time: type: string format: date-time Envelope: type: object required: - data - meta properties: data: {} meta: $ref: "#/components/schemas/Meta" User: type: object required: - id - display_name - status - created_at - updated_at properties: id: type: string format: uuid display_name: type: string status: type: string enum: - ACTIVE - DISABLED created_at: type: string format: date-time updated_at: type: string format: date-time LoginRequest: type: object additionalProperties: false required: - login_name - password properties: login_name: type: string minLength: 3 maxLength: 64 password: type: string minLength: 1 maxLength: 72 writeOnly: true AdminLogin: type: object required: - user - expires_at properties: user: $ref: "#/components/schemas/User" expires_at: type: string format: date-time AppLogin: allOf: - $ref: "#/components/schemas/AdminLogin" - type: object required: - access_token properties: access_token: type: string CreateAccount: type: object additionalProperties: false required: - mode - name properties: mode: type: string enum: - simulation - manual_real name: type: string minLength: 1 maxLength: 80 initial_cash: type: string description: CNY 十进制字符串,最多两位小数,范围 0 至 1000000000.00 AccountSummary: type: object required: - id - user_id - mode - name - currency - ledger_status - created_at - cash_balance properties: id: type: string format: uuid user_id: type: string format: uuid mode: type: string enum: - simulation - manual_real name: type: string currency: type: string enum: - CNY ledger_status: type: string enum: - COMPLETE - INCOMPLETE created_at: type: string format: date-time cash_balance: type: string nullable: true description: CNY 十进制字符串,现金历史不完整时为 null Health: type: object required: - status - checked_at - components properties: status: type: string enum: - ready - not_ready checked_at: type: string format: date-time components: type: object required: - postgresql - redis properties: postgresql: $ref: "#/components/schemas/Component" redis: $ref: "#/components/schemas/Component" Component: type: object required: - status properties: status: type: string enum: - ready - unavailable - not_configured ProviderInput: type: object additionalProperties: false required: - name - base_url - model_name - enabled - timeout_seconds - clear_api_key - expected_version properties: name: type: string maxLength: 80 base_url: type: string maxLength: 2048 description: 留空或无用户信息、query、fragment 的 HTTPS 地址 model_name: type: string maxLength: 120 wire_api: type: string enum: - responses - chat_completions default: responses model_catalog_url: type: string maxLength: 2048 disable_response_storage: type: boolean description: Omitted values preserve existing settings; defaults to true on create requires_openai_auth: type: boolean description: Omitted values preserve existing settings; defaults to true on create enabled: type: boolean timeout_seconds: type: integer minimum: 1 maximum: 30 api_key: type: string minLength: 1 maxLength: 4096 writeOnly: true clear_api_key: type: boolean expected_version: type: integer format: int64 minimum: 0 market_adapter: type: string enum: - "" - eastmoney_public - sina_public history_base_url: *a2 quote_base_url: *a2 ProviderConfig: type: object properties: id: type: string format: uuid config_key: type: string enum: - model_primary - model_backup - model_review - market_primary name: type: string base_url: type: string model_name: type: string wire_api: type: string enum: - responses - chat_completions model_catalog_url: type: string disable_response_storage: type: boolean requires_openai_auth: type: boolean enabled: type: boolean timeout_seconds: type: integer has_api_key: type: boolean version: type: integer format: int64 last_test_status: type: string enum: - NOT_CONFIGURED - NOT_TESTED - READY - FAILED last_tested_at: type: string format: date-time nullable: true last_test_message: type: string updated_by: type: string format: uuid created_at: type: string format: date-time updated_at: type: string format: date-time market_adapter: type: string enum: - "" - eastmoney_public - sina_public history_base_url: *a2 quote_base_url: *a2 AuditEvent: type: object properties: id: type: string format: uuid actor_id: type: string format: uuid action: type: string object_type: type: string object_id: type: string format: uuid request_id: type: string format: uuid details: type: object additionalProperties: true created_at: type: string format: date-time EmptyObject: type: object additionalProperties: false ExpectedVersion: type: object required: - expected_version additionalProperties: false properties: expected_version: type: integer format: int64 minimum: 1 CandidateAction: type: object additionalProperties: false required: - expected_version - reason properties: expected_version: type: integer format: int64 minimum: 1 reason: type: string minLength: 1 maxLength: 1000 CandidateContent: type: object required: - symbol - exchange - name - strategy_code - title - thesis - evidence - counter_evidence - invalidation - reference_plan properties: symbol: type: string pattern: ^[0-9]{6}$ exchange: type: string enum: - SSE - SZSE name: type: string maxLength: 80 strategy_code: type: string enum: - trend_following - pullback - event_driven title: type: string maxLength: 120 thesis: type: string maxLength: 2000 counter_evidence: type: string maxLength: 1000 invalidation: type: string maxLength: 1000 evidence: type: array minItems: 1 maxItems: 8 items: type: object required: - source_url - locator - summary properties: source_url: type: string format: uri description: HTTPS 来源链接,系统当前不自动获取或验证来源内容 locator: type: string maxLength: 200 summary: type: string maxLength: 1000 reference_plan: type: object required: - entry_low - entry_high - stop_loss - target_price properties: entry_low: type: string description: 精确元,最多两位小数 entry_high: type: string stop_loss: type: string target_price: type: string CandidateDraft: type: object required: - content - observed_at - valid_until properties: content: $ref: "#/components/schemas/CandidateContent" observed_at: type: string format: date-time description: 最近 24 小时,不能超过允许的时钟误差 valid_until: type: string format: date-time description: 未来最长 7 天 CandidateRevisionInput: allOf: - $ref: "#/components/schemas/CandidateDraft" - type: object required: - expected_version properties: expected_version: type: integer format: int64 minimum: 1 PlanPreviewInput: type: object additionalProperties: false required: - account_id - candidate_revision_id - expected_candidate_version - quantity - fee_budget properties: account_id: type: string format: uuid candidate_revision_id: type: string format: uuid expected_candidate_version: type: integer format: int64 minimum: 1 quantity: type: string pattern: ^[1-9][0-9]{0,6}$ description: 模拟规则为 100 股整数倍,上限 1000000 fee_budget: type: string description: 用户输入的预计费用,允许 0 FillInput: type: object additionalProperties: false required: - account_id - idempotency_key - side - symbol - exchange - name - quantity - price - fee - occurred_at properties: account_id: type: string format: uuid plan_id: type: string format: uuid nullable: true description: 仅买入,属于相同账户;候选失效不阻止记录已发生事实,需填写偏离说明 idempotency_key: type: string format: uuid side: type: string enum: - BUY - SELL symbol: type: string pattern: ^[0-9]{6}$ exchange: type: string enum: - SSE - SZSE name: type: string maxLength: 80 quantity: type: string description: 正整数字符串,上限 1000000;模拟买入须为 100 的整数倍 price: type: string description: 正数元,最多两位小数 fee: type: string description: 实际录入费用,允许 0 occurred_at: type: string format: date-time sellable_at: type: string format: date-time nullable: true description: 买入必填的模拟可卖时间,不早于成交;卖出须为空 note: type: string maxLength: 1000 ReversalInput: type: object additionalProperties: false required: - reason properties: reason: type: string minLength: 1 maxLength: 1000 SimulationQuoteInput: type: object additionalProperties: false required: - symbol - exchange - price - observed_at properties: symbol: type: string pattern: ^[0-9]{6}$ exchange: type: string enum: - SSE - SZSE price: type: string description: 精确正数元,最多两位小数 observed_at: type: string format: date-time description: 最近 1 分钟,不接受倒序快照 StrategyInput: type: object required: - code - name - description - parameters properties: code: *a2 name: *a2 description: *a2 expected_version: &a6 type: integer parameters: type: object required: - short_window - long_window - fee_bps - slippage_bps - lot_size properties: short_window: *a6 long_window: *a6 fee_bps: *a6 slippage_bps: *a6 lot_size: *a6 screening: $ref: "#/components/schemas/ScreeningParameters" StrategyDeployment: type: object required: - status - expected_version - reason properties: version_id: *a1 status: type: string enum: - ACTIVE - PAUSED expected_version: *a6 reason: *a2 HistoricalBar: type: object required: - date - open - high - low - close properties: date: type: string format: date open: *a2 high: *a2 low: *a2 close: *a2 BacktestInput: type: object required: - strategy_version_id - dataset_name - symbol - initial_cash - bars properties: strategy_version_id: *a1 dataset_name: *a2 symbol: *a2 initial_cash: *a2 bars: type: array minItems: 4 maxItems: 1000 items: $ref: "#/components/schemas/HistoricalBar" MarketBacktestInput: type: object required: - strategy_version_id - symbol - exchange - start - end - initial_cash properties: strategy_version_id: *a1 symbol: *a2 exchange: type: string enum: - SSE - SZSE start: type: string format: date end: type: string format: date initial_cash: *a2 ErrorEnvelope: type: object properties: error: type: object properties: code: *a2 message: *a2 request_id: *a2 ScreeningParameters: type: object additionalProperties: false required: - securities - entry_band_bps - stop_loss_bps - target_bps - valid_hours properties: securities: type: array minItems: 1 maxItems: 100 uniqueItems: true items: type: object additionalProperties: false required: - symbol - exchange properties: symbol: type: string pattern: ^[0-9]{6}$ exchange: type: string enum: - SSE - SZSE entry_band_bps: type: integer minimum: 0 maximum: 1000 stop_loss_bps: type: integer minimum: 1 maximum: 5000 description: 必须大于 entry_band_bps target_bps: type: integer minimum: 1 maximum: 10000 description: 必须大于 entry_band_bps valid_hours: type: integer minimum: 1 maximum: 168