金融科技后端前端【免费下载链接】binance-trading-botAutomated Binance trading bot with pluggable strategies, historical backtesting, and a live dashboard项目地址https://gitcode.com/gh_mirrors/bi/binance-trading-bot点击查看免费下载本文基于仓库docs/operations/目录下的六份运营手册Runbook编写是 binance-trading-bot 上生产之后的“Day-two 参考”涵盖生产 Compose 覆盖层与密钥管理、数据库迁移与 TimescaleDB 升级、三级应急停机kill switch、登录与安全含单点登录与锁定恢复、环境变量与 Prometheus 告警指标以及常见故障排查路径。读完本文你将掌握这套自托管量化交易机器人在真实服务器上部署、监控、快速止血与恢复故障的完整操作能力。阅读前提本文假设你已完成首次部署克隆、配置.env、启动、创建操作员、连接 Binance该流程见 安装与部署本文的六个主题分别对应 deploy、kill-switch、sign-in-and-security、env-vars、metrics、troubleshooting 六份手册。一、生产部署覆盖层、密钥与启动流程生产环境在基础栈之上叠加了三个密钥文件和一份生产 Compose 覆盖层。内置的 Postgres 与 Redis 直接读取deploy/secrets/*中的密码而不是从.env读取——这是三层处理方式各不相同的关键设计。1. 生成密钥文件mkdir -p deploy/secrets openssl rand -hex 32 deploy/secrets/session_secret openssl rand -hex 32 deploy/secrets/postgres_password openssl rand -hex 32 deploy/secrets/redis_password chmod 600 deploy/secrets/*三个密钥的接线方式完全不同从 docker-compose.prod.yml 可以看到postgres容器通过原生 Docker Secret 的_FILE间接引用POSTGRES_PASSWORD_FILE/run/secrets/postgres_passwordredis容器在 entrypoint 中用$(cat /run/secrets/redis_password)把密码内联进redis-server --requirepass而api 不支持_FILE间接引用需要手动注入.env。2. 把 AUTH_SECRET 与 REDIS_URL 镜像进.envapi 从环境变量读取AUTH_SECRET和带认证的REDIS_URL因此这两项必须从密钥文件同步出来用sed而非保证重复执行幂等REDIS_PW$(cat deploy/secrets/redis_password) sed -i.bak \ -e s|^AUTH_SECRET.*|AUTH_SECRET$(cat deploy/secrets/session_secret)| \ -e s|^REDIS_URL.*|REDIS_URLredis://:${REDIS_PW}redis:6379| \ .env rm .env.bak chmod 600 .env注意生产环境的redis服务强制--requirepass缺少带密码的REDIS_URL会导致 api/worker 无法连接。3. 拉取镜像并启动镜像由 CI 发布到公共 Docker Hub 仓库不可变标签vX.Y.Zlatest跟随 main 移动可用.env中的IMAGE_TAG固定版本。匿名拉取一般即可命中匿名限流时先docker logindocker compose -f deploy/compose/docker-compose.yml \ -f deploy/compose/docker-compose.prod.yml \ --env-file .env pull docker compose -f deploy/compose/docker-compose.yml \ -f deploy/compose/docker-compose.prod.yml \ --env-file .env up -d启动链中depends_on: { condition: service_healthy }会阻塞app服务直到 Postgres 与 Redis 就绪因此全新启动无需重试循环即可干净完成。4. TLS 与端口边界栈只在APP_HTTP_PORT上提供明文 HTTP不内置反向代理。请在app服务前面加 TLS——Cloudflare Tunnel、nginx/Traefik 主机代理或托管边缘均可三个参考配置在deploy/README.md的 TLS at the edge 一节。同时记住/healthz、/readyz、/metrics都是未认证的且/metrics携带逐 profile 的操作细节因此9100/9101 端口绝不加入ports:详见下文告警章节。5. 升级 TimescaleDB扩展版本不会自动跟随镜像新的 TimescaleDB 镜像不会升级既有数据库里的扩展镜像保留旧版扩展库数据库继续运行它已有的版本直到你手动更新。迁移也不负责这件事create extension if not exists从不升级。因此每次 TimescaleDB 镜像升级后都需要手动执行dc() { docker compose -f deploy/compose/docker-compose.yml -f deploy/compose/docker-compose.prod.yml --env-file .env $; } dc stop app # 更新期间不要有 app 会话使用旧版本 dc exec postgres sh -c psql -X -U $POSTGRES_USER -d $POSTGRES_DB -c ALTER EXTENSION timescaledb UPDATE; dc exec postgres sh -c psql -X -U $POSTGRES_USER -d $POSTGRES_DB -tAc select extversion from pg_extension where extname timescaledb; dc start app最后一条查询应打印镜像标签中的版本。ALTER EXTENSION必须是新会话的第一条命令所以psql带-X跳过.psqlrc否则 TimescaleDB 会拒绝并报 “cannot be updated after the old version has already been loaded”。6. 数据库迁移启动时自动执行手动路径仅限离线迁移在启动时自动运行——容器入口 apps/server/docker-entrypoint.sh 在应用启动前运行幂等的迁移执行器除非SKIP_MIGRATIONS设置为1/true等真值这留给离线维护命令使用。拆分拓扑中的每个api、worker、study容器都会在启动前迁移。这是安全的因为 packages/db/src/migrate.ts 为会话持有 Postgres 咨询锁固定的锁键MIGRATION_LOCK_KEY并发启动被串行化后到的调用者观察迁移台账而非竞争 DDL这也防止新部署的 worker 在另一个角色应用加列之前引用它。迁移执行器是自定义实现非 drizzle-kit migrate因为需要 drizzle-kit 无法表达的扩展、角色与 TimescaleDB hypertable/保留策略 DDL每个*.sql文件按字典序应用一次已应用的校验和记录在_app_migrations表中。一个失败的迁移会让容器非零退出、readiness 永不应答编排器会退避而非提供过时 schema。手动离线路径仅当应用不启动时docker compose -f deploy/compose/docker-compose.yml \ -f deploy/compose/docker-compose.prod.yml \ --env-file .env exec app bun /app/dist/migrate.js附加提醒TimescaleDB 升级后刷新已打开的浏览器标签页再依赖净盈亏Net P/L。旧版缓存的 SPA 代码会忽略增量完整性标记——页面仍可用但展示的是旧逻辑。二、环境变量进程级配置全集进程级配置全部位于仓库根目录的.env复制.env.example后编辑并重启。逐 profile 的交易设置——网格层级、指标、通知器、技术门槛——不是环境变量它们存在数据库里、在应用内编辑见 配置指南。任何变量都是“加一行KEYvalue到.env然后重启”生效启动时会校验值无效或缺失的必需值会以精确错误阻止启动而不是带病运行。下表为 生成的 env 目录 的精选该页默认值由进程实际解析的 schema 断言生成不会声称应用未应用的默认值分组变量含义 / 默认值 / 注意事项必需AUTH_SECRET签署登录会话 Cookie64 位十六进制必填无默认openssl rand -hex 32生成实例间不可复用短于 32 字符启动失败变更会使所有会话失效必需WEB_ORIGIN允许的浏览器源列表逗号分隔不含通配符必填无默认与登录 CSRF、CORS、WebSocket 升级相关含*启动失败必需DATABASE_URL/REDIS_URLPostgres / Redis 连接串Compose 部署由 compose 文件提供网内默认REDIS_URL需带密码redis://:pwhost:6379运行时ROLEall单进程跑 apiworkerstudy默认、api、worker、study拆分拓扑见docker-compose.scale.yml只有api角色运行数据库迁移运行时LIVE_DEMO公共无登录沙箱模式默认关闭为每个匿名请求注入演示操作员并封锁凭证/通知器等路由拒绝在存在真实 Binance 账户时启动运行时MCP_ENABLED/MCP_RESOURCE_URL挂载经 OAuth 2.1 授权的 MCP 控制平面默认关闭不挂载/api/mcp开启时MCP_RESOURCE_URL必须为https回环主机除外登录PASSWORD_SIGN_IN_ENABLED默认开启关掉后表单隐藏且密码登录/注册端点返回 404与SINGLE_SIGN_ON_ENABLED至少一个开启登录SINGLE_SIGN_ON_*PUBLIC_BASE_URL开启 OIDC 单点登录所需issuer URL需与 provider 发布值逐字符一致含尾斜杠、client id/secret、按钮文案、回调基础 URL端口PORT/ADMIN_PORT/ADMIN_HOST/WORKER_ADMIN_PORT/WORKER_ADMIN_HOST公共端口默认 3000api 管理端口默认 9100、worker 默认 9101默认绑定127.0.0.1Kubernetes 下改为0.0.0.0供 kubelet 探针APP_HTTP_PORT是 Compose 专用发布端口生产文件默认 80数据库POSTGRES_DB/POSTGRES_USER/PGSSLMODE/API_DB_POOL_MAX(10) /WORKER_DB_POOL_MAX(25) /ADMIN_DB_POOL_MAX(2)池上限硬编码于 packages/db/src/pool.ts只接受纯数字连接池耗尽不再挂起——超过 5s 超时的 checkout 失败并返回 503db_pool_checkout_timeoutwarn 行调大对应池是对该日志名的回应保留期DISCOVERY_SNAPSHOT_RETENTION_DAYS(180) /EQUITY_SNAPSHOT_RETENTION_DAYS(365)自动发现宇宙快照与逐 profile 权益序列的保留天数Worker 调优BACKTEST_CONCURRENCY(1) /TICK_CONCURRENCY(25) /KLINE_CONCURRENCY(8) /TICK_PERSIST_TIMEOUT_MS(100) /STUDY_CPU_SHARE回测是 CPU 密集的共享核心时保持 1–2TICK_CONCURRENCY降低只会减吞吐、不影响正确性(profile, symbol) 顺序始终保证持久化超时会回退到降级缓存路径可观测性OTEL_*/DEPLOY_ENV设置OTEL_EXPORTER_OTLP_ENDPOINT才启用 OTLP 追踪导出DEPLOY_ENVproduction启用采样追踪构建部署IMAGE_TAG/BACKUP_DIR(/backups) /GIT_SHA/WEB_DIST_DIRIMAGE_TAG用于固定发布版本GIT_SHA由 Docker 构建注入用于状态栏的 api/worker 版本偏差检测VITE_*为构建期变量改后必须重新构建三、应急停机三级 Kill SwitchKill switch 是紧急停止装置它让机器人停止下达新订单让你可以冷静排查。它在三个层级生效——单币、单 profile、或整个账户。它做什么、不做什么停止新买入与卖出订单的下达不会卖出你已持有的仓位不会取消 Binance 上已挂的订单——它们保持有效直到成交或你手动取消。要同时清掉挂单请在币种页面取消或 删除 profile删除会主动取消该 profile 的活动订单。层级在哪里操作持续多久单币币种页面——Pause控件到你设置的定时器到期最长 7 天或你手动解除单 profileprofile 的Settings页——Stop开关直到你重新关闭无定时器整个账户Account设置页——一个按钮同时停止所有 profile直到你逐个重新打开无定时器单币暂停某个币异常而 profile 其余部分正常时在币页面使用Pause可设置时长——冻结时间上限7 天。这个上限是刻意的你忘记设置的暂停不会默默比你的记忆存活更久。定时器结束后币自动恢复。原因——写入审计日志的短备注便于日后回溯。暂停期间币页面横幅显示暂停生效可随时提前解除。单 profile 停止profile 的Settings页Stop开关冻结整个 profile——它交易的所有币。与单币暂停不同它没有定时器保持开启直到你手动关闭。适合在检查某套策略配置时先按住它。整个账户停止Account设置页的账户级 kill switch 一键停止账户上的每个 profile。注意这是客户端扇出逐一调用各 profile 的 disable-all并非单一原子操作——部分失败可能让某些 profile 仍在交易。账户级停止后每个 profile 保持停止直到你逐个重新开启。自动入场熔断器——每日亏损上限、连亏守卫、回撤守卫——会自行暂停新入场是独立于 kill switch 的机制。生效位置的可见性与解除已停止 profile 的仪表盘卡片显示kill-switch徽章profile 切换器与侧边导航标记已停止的 profile经 MCP 读取 profile 仪表盘的 Agent 会看到killSwitch字段——能设置开关的工具也能读回它每次开/关都会写入该 profile 的审计日志相关 API 路由集中在 apps/api/src/routes/kill-switch.ts例如POST /profiles/{profileId}/symbols/{symbol}/disable。解除方式关闭同一控件——profile 的Stop开关、账户按钮、或暂停币横幅的 release 动作暂停的币在定时器结束时也会自动解除。kill switch 与禁用 profile 的区别禁用 profileenable/disable 状态与 kill switch 都会停止新订单、都保留挂单。kill switch 是快速紧急停止禁用是“暂时做完这套设置”的常规开关。见 Go live → 暂停与删除 profile。四、登录与安全SSO、限额、锁定恢复与入侵响应系统只有一个操作员你。第一个完成 onboard 的人成为操作员服务器在每一层包括数据库都拒绝创建第二个。1. 登录方式与会话密码邮箱 至少 12 字符密码密码仅以 scrypt 哈希存储PASSWORD_SIGN_IN_ENABLED控制默认开。单点登录SSO在 Auth0、Okta、Microsoft Entra 等身份提供商处登录用 OpenID Connect 告知机器人身份由SINGLE_SIGN_ON_ENABLED与SINGLE_SIGN_ON_*变量控制。成功登录给浏览器一个会话Cookie。会话在 8 小时未使用后结束或登录后 24 小时无论多活跃结束两个上限都可在Settings Security修改。2. 配置单点登录以 Auth0 为例在 Auth0 创建Regular Web Application把PUBLIC_BASE_URL/api/auth/callback/oidc加入允许的回调 URLPUBLIC_BASE_URL是你浏览器访问机器人的地址如https://bot.example.com在连接上关闭公开注册防止他人创建身份在提供商处开启多因素认证如手机验证码策略设为Always——机器人不检查登录是否用了第二因子提供商设置是唯一强制手段。登录一次确认提供商要求第二因子。然后设置变量并重启SINGLE_SIGN_ON_ENABLED1 SINGLE_SIGN_ON_ISSUER_URLhttps://your-tenant.auth0.com/ SINGLE_SIGN_ON_CLIENT_ID... SINGLE_SIGN_ON_CLIENT_SECRET... SINGLE_SIGN_ON_BUTTON_LABELSign in with Auth0 PUBLIC_BASE_URLhttps://bot.example.comissuer URL 必须与提供商issuer完全一致含尾斜杠。重要细节已有密码时SSO 登录不会自动关联到你的账户即使邮箱匹配。用密码登录后在Settings Security → Sign-in methods选择Link single sign-on防止任何控制了某提供商中你的邮箱身份的人接管操作员。你的身份 提供商 你在那里的用户 id更换提供商/租户后旧链接失效。SSO 验证成功后可考虑PASSWORD_SIGN_IN_ENABLED0让带第二因子的提供商成为唯一入口——关闭期间已存密码不再可登录、不可修改、不可用于确认变更用密码登录过的会话仍工作到过期。提供商宕机时启动时提供商不可达机器人仍启动——SSO 按钮显示不可用、发送告警、每 5 分钟重试提供商恢复应答后 api 进程自停并重启注册默认ROLEall下 worker 也随容器重启策略unless-stopped重启。若密码登录也关着且无可用方式该次运行会重新开启密码登录并单独发一条告警。3. 限额与锁定密码尝试受以下限额约束全部可在Settings Security修改服务器强制取值范围被盗会话只能收紧保护、不能关掉检查默认含义每地址尝试每 5 分钟 3 次一个 IP 5 分钟内试 3 次密码超限封禁 15 分钟一天内每次重复使封禁翻倍上限 1 天每邮箱尝试每 5 分钟 5 次针对同一邮箱的尝试无论来自哪个地址账户锁定1 小时内 5 次失败锁定 1 小时某邮箱错误密码过多则锁定其密码登录全站退避每小时 20 次失败失败跨地址累积时所有地址减速到每周期一次其他登录请求每地址每分钟 20 次SSO 回调、Agent 授权等AI Agent 按 Agent 分配此额度同地址所有 Agent 共享其四倍已知设备30 天内成功登录过的浏览器每次成功登录重置 30 天。它跳过账户锁定与全站退避并有自己的每邮箱尝试额度——陌生人狂试你的邮箱不会把你锁在自己的浏览器外它不跳过每地址限额。所有限额对不存在的邮箱行为一致无法用限额探测哪个邮箱是你的。4. 被锁定了按顺序尝试命令在服务器仓库根目录执行需指定与启动相同的 compose 文件与.env根目录没有 compose 文件用以前登录过的浏览器——它跳过锁定。用单点登录若已配置。在服务器上解除锁定仅解除你邮箱的锁定、全站减速与每个地址的封禁——服务器无法区分哪个地址是你的所以全部清除仍猜密码的人会被同一限额再次封禁密码保持不变docker compose -f deploy/compose/docker-compose.yml -f deploy/compose/docker-compose.prod.yml --env-file .env \ run --rm app bun /app/dist/reset-password.js --email email --clear-lockout重置密码打印新密码、解除第 3 步解除的一切、注销每个浏览器与每个 AI Agent若提供商身份本身丢失或被入侵加--unlink-single-sign-on该命令从不联系身份提供商提供商宕机也能用docker compose -f deploy/compose/docker-compose.yml -f deploy/compose/docker-compose.prod.yml --env-file .env \ run --rm app bun /app/dist/reset-password.js --email email密码登录被关掉了设PASSWORD_SIGN_IN_ENABLED1并重启再按第 4 步重置密码。该 CLI 的实现见 apps/api/scripts/reset-password.ts默认设置新随机密码若操作员只有 SSO 则创建密码登录、全站注销会话与 Agent 并解除锁定退出码 0/1/2/3/4 区分成功、未捕获错误、参数错误、无此邮箱、Redis 不可达无法删锁。5. 怀疑有人入侵在Settings Security选择Sign out everywhere结束所有会话含你的、遗忘所有已知设备、关闭所有活动连接、吊销所有 AI Agent。然后按第 4 步重置密码、轮换 Binance API key。若怀疑服务器本身被入侵同时更换AUTH_SECRET并重启——所有会话 Cookie、已知设备、已链接 SSO 身份都不可读MCP 控制平面开启时 Agent 签名密钥也随之不可读Better Auth 用AUTH_SECRET加密该密钥需删除旧密钥新 Agent 登录时重新生成docker compose -f deploy/compose/docker-compose.yml -f deploy/compose/docker-compose.prod.yml --env-file .env \ exec -T postgres sh -c psql -U $POSTGRES_USER -d $POSTGRES_DB -c DELETE FROM jwks;6. 记录与通知、防洪每次登录、失败、锁定、限额触发、凭证变更、会话变更与 Agent 授权都记为安全事件Settings Security → Security activity。任何人均可触发的事件如对非你邮箱的失败尝试按每 5 分钟一行聚合计数针对你邮箱的失败尝试始终单独一行。重要事件作为安全告警发送到你的通知器auth-alert类别不可静音无法送达时如通知器被删光worker 计数并触发AuthAlertUndelivered告警。完整事件清单与通知策略见SECURITY_EVENT_CATALOGpackages/contracts/src/security-events.ts。安全事件保留 365 天最长 5 年比常规审计历史更长。防洪是分层、最廉价拒绝优先的边缘层Cloudflare 等并在那里限制/api/auth/来源最重要拆分进程docker-compose.scale.yml让 api 与 worker 分离防止 API 被洪泛耗尽后延误交易决策机器人内部每地址无会话 60 次/分钟、有会话 600 次/分钟Agent 合计 120 次/分钟密码校验故意慢同时 2 个运行、最多 10 个等待再往上拒绝并给重试时间每会话 5 个活动连接、每地址 20 个。机器人从最右侧X-Forwarded-For读取客户端地址——仅当前面恰好只有一个代理时才是正确的见 Auth 威胁模型。五、指标与 Prometheus 告警1. 指标出口与抓取拓扑worker 在自有管理监听器上暴露/metricsWORKER_ADMIN_PORT默认 9101api 在ADMIN_PORT默认 9100。两者默认绑定127.0.0.1且未认证——容器内这等于该容器自己的回环因此默认情况下其他容器包括internal网络上的 Prometheus连不上发布端口也无效Docker 把发布端口转发到容器 IP而非其回环。要抓取需放宽绑定并走 compose 网络# .env —— Prometheus 要够到任一管理监听器都必须 ADMIN_HOST0.0.0.0 WORKER_ADMIN_HOST0.0.0.0scrape_configs: - job_name: worker # WorkerDown 精确匹配此名称 static_configs: - targets: [app:9101] # WORKER_ADMIN_PORT - job_name: api static_configs: - targets: [app:9100] # ADMIN_PORT让 Prometheus 跑在internal网络上以便这些主机名解析。默认单容器ROLEall部署中两个监听器都在同一个app容器内所以两个 target 共享同一主机名拆分拓扑docker-compose.scale.yml中让每个 job 指向各自服务。⚠️不要把 9100/9101 加进ports:。/healthz、/readyz、/metrics未认证/metrics携带逐 profile 操作细节。放宽绑定到0.0.0.0暴露给 compose 网络是目的发布端口则是放到你的 LAN。必须暴露到主机之外如 Kubernetes时用 NetworkPolicy 限制端口——Service 不是防火墙。2. 指标目录与读取注意事项指标参考 说明worker 通过只接受固定名称的 sink 记录因此拼写错误无法生成新序列临时指标也无法在没有目录项的情况下出现表格由该目录生成“What it measures”列就是 scrape 携带的HELP文本页面与/metrics不会分歧。基数受你的部署规模约束tick 指标每 (profile, symbol) 一个序列、审计指标每 Redis 审计流一个、Binance user-data 流指标每账户一个、BullMQ 深度 gauge 每队列一个Postgres 池 gauge 完全无标签——每个进程各一个。读取陷阱计数器只增不减worker 重启归零要用rate()/increase()窗口读取绝不当裸值读多个序列在首次触碰时以零播种。gauge 是 last-value-wins是相反的陷阱——停止写入的 gauge 会持续导出最后采样audit_consumer_lag对停止探测的流就是这样。worker 还导出 prom-client 默认收集器提供的process_*、nodejs_*以及 Prometheus 自身合成的up每抓取目标一个——WorkerDown读up仓库内没有任何代码写它。3. 二十五条内置告警规则deploy/observability/alerts.yml 随仓库附带二十五条 Prometheus 告警规则分三组binance-trading-bot.workers交易与审计路径、binance-trading-bot.infra底层进程压力、binance-trading-bot.auth登录与安全读api导出的序列需同时抓取 api 与 worker。加载到你的 Prometheus 栈即可获得默认告警姿态Alertmanager / PagerDuty / Slack 接收器接线由你负责。关键规则选读告警级别触发条件WorkerDowncriticaljobworker的/metrics抓取失败 2 分钟。v1.0 单副本worker 离线即交易停止BinanceWeightExhaustedcriticalbinance_api_weight持续高于 1000 达 2 分钟。Binance 在 1200 以上封禁此值留出干预空间。刻意不聚合——权重头覆盖整个 API keysum 会按活跃 profile 数倍增AuditDrainerBacklogwarning审计流读而未持久化的积压持续增长或超 1 万条滞留未投递或最近有 pass 因修剪以外原因无法度量积压。Postgres 不可达移动的是audit_consumer_pending而非 lag按“增长”而非“水平”告警因为恢复中的正常回放不该持续触发HighTickFailureRatecritical10 分钟内超过 5% 的 tick 抛错tick_failures_total/tick_total。比率而非计数因为 tick 量随活跃 profile 与币数伸缩tick_total计入完成、节流与抛错分母不缩水QueueBacklogcriticalBullMQ 队列等待任务超 1000 达 5 分钟。v1.0 单副本无法横向吸收积压——这是消费者落后而非突发DBPoolStarvedcritical有人等待 Postgres 连接整整 5 分钟pg_pool_waiting 0。只覆盖 worker 池api 池饥饿请看http_requests_total{status503}WSDisconnectsHighwarning15 分钟内超过 5 次 Binance websocket 关闭仅统计 worker 未主动请求的关闭。池自行重连因此是 warningAuthSignInFailureSpikewarning15 分钟内超过 20 次失败登录密码与 SSO 合计保持 5 分钟AuthAlertUndeliveredcritical安全通知无法送达no-notifier/failed。入侵者删除通知器看起来完全一样——因此它打 pageAgentTokenRejectedSpikewarning15 分钟内超过 30 次被拒的 AI Agent token告警表达式与指标名的配套由 CI 守门scripts/ci/promtool-lint.sh在每次 push 时用promtool test rules重放合成序列deploy/observability/tests/alerts.test.ymlscripts/ci/no-phantom-alert-metric.sh校验规则命名的每个指标确有发射防止“语法合法但永不触发”的静默规则。注意metric 名与标签键被检查标签值不被检查如外部抓取值jobworker阈值与for:窗口也不被检查。编辑规则后仍应在 Prometheus 表达式浏览器中对照真实数据确认并保证非空结果。4. 尚未覆盖的失效模式有两类失效模式暂无规则皆因缺序列而非缺阈值只能通过 UI 或docker compose logs -f app感知技术指标陈旧Technicals staleness旧扫描器导出的technicals_breaker_state等序列被进程内计算取代fetch 状态改为写入 Redis key一旦有指标导出它规则才能读它。活跃 worker 内审计排干循环卡死循环死掉或挂起不写任何序列审计规则没有“陈旧变空”机制暴露缺席WorkerDown只覆盖整个进程退出。两者都在alerts.yml底部注释中连同缺失序列命名no-phantom-alert-metric.sh守门禁止规则读取从不发射的序列。六、故障排查速查故障排查手册 的前半是症状式急救后半是分步 playbook。以下是最常用的几条路径。1. “机器人不交易”依次排查profile 是否启用禁用的 profile 不做新决策API key 是否绿色Account 的 API-keys 页否则是 key、权限或 IP 白名单问题买入条件是否真正满足“不作为”是合法且常见的决策——打开 profile 的 History → Logs它记录每个 tick 的决定与依据数字行太稀疏时打开Capture every tick等待复现预算与余额是否充足。2. API key 报错 / 订单被 Binance 拒绝API key 报错几乎总是权限不足需同时开启Enable Reading与Enable Spot Margin Trading见 API key 页、IP 白名单不匹配把服务器出口 IP 加进 Binance API Management、或 key 被吊销/过期。订单被拒时History → Logs 显示 Binance 的精确原因展开行的Context看完整拒绝载荷再调整 profile 预算或步长。3. 保存成功但警告“order sizing was not verified”你的变更已保存——该警告关于服务器没能完成的校验而非你刚做的事不回滚、无需重做。保存前服务器想用两个实时事实确认下单可行性该币的交易所交易规则最小订单额与价格/数量步长和当前价格都存在短时缓存。任一缺失则跳过尺寸校验并明示。三种消息的处置规则未加载→等后台刷新通常应用启动后几分钟内价格未缓存→新币正常价格只为运行中 profile 盯的币保留启用 profile 后才有“策略读不懂设置”→多半是切换策略后配置与预期不符打开 Strategy 重新保存。若校验发现真问题如买入预算低于币的最小订单额保存会直接报错拒绝而非警告。4. 仪表盘打不开在服务器上确认容器docker compose -f deploy/compose/docker-compose.yml -f deploy/compose/docker-compose.prod.yml --env-file .env ps看日志... logs -f确认访问地址与安装时设置的WEB_ORIGIN一致。5. 构建版本 / api-worker 偏差GET /status是公开未认证端点返回 api 与 worker 的运行构建 SHA、启动时间与最近应用的 DB 迁移时间戳只泄露 SHA 与时间戳无账户数据。桌面状态栏轮询它并提示两个警告api 与 worker SHA 不同半途而废的部署重启 worker 同步与worker 启动早于最新迁移worker 跑在比它加载的 schema 更新的 schema 上重启 worker。worker: null表示 worker 心跳 key 缺失——worker 宕机或重启后未写状态。SHA 由GIT_SHA构建参数在镜像构建时注入GIT_SHA$(git rev-parse --short HEAD) docker compose build app无GIT_SHA的构建回退到本地 git SHA再到生产 alpine 镜像无 git 二进制回退unknown。6. 告诉机器人你已持有币的入场价两种方式添加 symbol 时填“Average entry price”字段一步完成之后——Symbol 页 → Logs 标签 → “Show advanced” → “Set average entry price”。任一方式都会写入成本基准台账并入队 worker 任务apply-avg-entry-price强制设置运行中策略的入场价下一 tick 即生效无需重启。它权威地既作用于新持有币也用于修正机器人已在管理的仓位成本基准普通 tick 或重配不会覆盖已定价仓位。价格而非数量是操作员输入的原因机器人每个 tick 从钱包读取持有数量并钉住钱包真相你记录的数量是对它的上限约束而非替代——机器人从不写入超过钱包持有的数量加减一个可交易增量。无法判断钱包时会整体拒绝建仓日志pipeline_apply_avg_entry_price_no_sellable_positionsymbol 页显示“Not held — nothing sellable backs this cost basis”补足到交易所最小额以上后每 15 分钟的仓位对账 pass 会自动清除该提示。组合的添加 symbol 路径没有台账行可回退需要profile 处于启用状态才能读余额。7. 孤儿订单孤儿是 Binance 挂单簿上无 profile 跟踪的订单。静置的孤儿锁定其基础资产并可能让真实仓位失保因此是操作员任务按 Orphan orders playbook 认领机器人识别的订单、按该页指示取消或保留其余。删除 profile 是唯一会为你取消孤儿的路径而一个无法解析的 profile 配置会丢失其订单所有权证明的“指纹”一半——删 profile 前务必确认。8. 存储配置超出 schema 最大值某个策略配置 schema 可能在新版本中收紧上限trailing-trade 首购candleLimit从 1000 收到 999momentum 慢 EMA 周期加了 998 上限。上限在配置解析时生效因此绝不会改写已存储的超限行——profile 继续交易实时 tick 路径读存储配置不解析但所有解析路径认领孤儿、删除时证明挂单所有权、live gate 的回测匹配、保存 profile都会劣化。用jsonb_path_exists而非WHERE中 cast防止单行非数值中止整个查询排查两处存储——profiles.config与profile_symbols.override_config两查询都空才没事第一个空证明不了什么因为合法的profiles.config正是非法 override 藏身之处-- 存储的策略配置超出 schema 上限、已无法解析的 profile SELECT id, name, strategy_name, config # {buy,candleLimit} AS candle_limit, config # {ema,slow} AS ema_slow FROM profiles WHERE jsonb_path_exists(config, $.buy.candleLimit ? ( 999)) OR jsonb_path_exists(config, $.ema.slow ? ( 998)); -- 超出同一上限的逐 symbol 覆盖。被解析的是合并后的配置一条就足以单独破坏该 symbol SELECT ps.profile_id, p.name, p.strategy_name, ps.symbol, ps.override_config # {buy,candleLimit} AS candle_limit, ps.override_config # {ema,slow} AS ema_slow FROM profile_symbols ps JOIN profiles p ON p.id ps.profile_id WHERE jsonb_path_exists(ps.override_config, $.buy.candleLimit ? ( 999)) OR jsonb_path_exists(ps.override_config, $.ema.slow ? ( 998));每条返回行都需要在下次编辑或删除该 profile之前把被标记的值降回合法范围candle 窗口 ≤999、慢 EMA 周期 ≤998并保存——保存本身即修复。特别在下次删除 profile 之前处理解析不了的配置会让未被本地记录的订单簿记故障遗留类失去指纹认领资格成为留在 Binance 上的孤儿且可能没有任何日志行宣布。七、常用操作员命令在仓库根目录运行每个命令都要点名与第 4 步相同的 compose 文件与.env因为根目录没有 compose 文件备份从 Settings Backup restore 进行而非 compose 服务dc() { docker compose -f deploy/compose/docker-compose.yml -f deploy/compose/docker-compose.prod.yml --env-file .env $; } dc logs -f app # 跟随 app 日志 dc run --rm app bun /app/dist/reset-password.js --email email # 重置主密码 dc down # 停止卷保留修改配置所有进程级设置都在.env中、重启后生效完整清单见 环境变量逐 profile 交易设置不在环境变量里存在数据库中、在应用内编辑。遇到手册未覆盖的深层问题贡献指南 介绍内部实现适合能读日志与代码的你继续深挖。赞分享金融科技后端前端【免费下载链接】binance-trading-botAutomated Binance trading bot with pluggable strategies, historical backtesting, and a live dashboard项目地址https://gitcode.com/gh_mirrors/bi/binance-trading-bot点击查看免费下载相关推荐ROMA-DSPy 生产环境部署指南Docker Compose 全栈部署、可观测性与安全加固实战ROMA DSPy 生产环境部署指南Docker Compose 全栈部署、可观测性与安全加固实战 本指南以 ROMA DSPyRecursive OpenAI AgentAgent 框架多智能体后端MCP 服务jquery-smooth-scroll完全指南让页面内导航滚动如丝般顺滑jquery smooth scroll完全指南让页面内导航滚动如丝般顺滑 jquery smooth scroll是一款轻量级jQuery插件能够让网页内binance-trading-bot 安装部署指南30 分钟从零起步并接入 Binancebinance trading bot 安装部署指南30 分钟从零起步并接入 Binance 本指南是 binance trading bot 的完整首次部署金融科技后端前端上一篇easy-vibe 实战指南JavaScript 原理速通读懂并指挥 AI 生成的前端代码下一篇Spark Connect Protobuf 定义协议文件与 Python 桩代码生成全指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考