把想法,变成可验证的策略。
从数字资产研究到跨市场观察,都在同一个工作台完成。结论都带来源与时间。
一条完整的研究路径
01 → 04- 定义策略选取规则,明确入场、出场与成本。
- 检验历史运行回测,对照成交记录与资金曲线。
- 持续观察设置价格或涨跌幅预警,记录触发证据。
- 及时知晓站内查看;验证邮箱后可启用邮件提醒。
服务连接
真实状态AI 和邮件需要管理员配置服务。没有配置时不会模拟调用或投递成功。
市场快照
查看全球风险 →策略实验室
编辑规则、运行回测,让每笔模拟成交都有依据。
策略编辑
先调整常用参数,也可以展开完整规则编辑。首版不执行任意 Python 代码。
完整策略 JSON · 高级编辑
time,open,high,low,close,volume
time 为 UTC 毫秒,周期需连续且与策略一致。
信号收盘确认,下一根开盘成交。短于 30 天的区间不显示年化和夏普。
AI 辅助编辑
未配置回测结果
完成首次回测后,这里会显示资金曲线和成交记录。
| UTC 成交时间 | 方向 | 价格 | 数量 | 手续费 |
|---|
结果仅来自所选数据上的模拟;期末持仓按收盘估值。
任务记录
全球风险观察
数字资产、股票、黄金和原油。按来源时间判断有效性。
预警如何判断
设置我的预警 →核验新鲜度
保留原始来源时间,数据过期时显示待核验,不发出新市场信号。
匹配你的规则
检查价格阈值或 5 分钟涨跌。缺少历史参照时,等待足够样本。
保存触发证据
首次越线生成通知,恢复后重新布防;持续越线不会重复刷屏。
预警与通知
行情与资讯在服务器端持续采集,规则判断和投递都不依赖浏览器是否打开。
数据源健康
正在读取采集心跳…保持服务运行,第一轮采集后显示各数据源状态。
行情每分钟采集一次,资讯每两分钟一次。连续失败 3 次标红:那是限流或网络异常,不是休市。
实时资讯
正在加载资讯…
创建预警
服务器端判断我的规则
命中即记录证据通知中心
页面可见时每 10 秒更新邮件投递记录
同批告警合并寄送同一账户的多条告警会合并成一封风险简报;每日上限 40 封,超出顺延不丢弃。“SMTP 已接受”不等于已到达收件箱。
策略进化
在参数空间里搜索,用前向验证判断它是不是只在拟合噪声。
搜索设置
基准来自实验室基准参数取自「策略实验室」当前编辑器。搜索只改动下面声明的参数,其余字段保持不变。
寻优在独立进程运行,超过 120 秒自动停止;同一账户同时只能有 1 个寻优任务,最多使用 8,000 根 K 线。
稳健性结论
完成首次寻优后,这里会显示评分、过拟合概率与成本压力结果。
参数排名
按综合评分降序 · 前 20 组| # | 参数 | 评分 | 样本外收益 | 样本外夏普 | 回撤 | 交易 |
|---|
样本外指标来自前向验证段;评分为 0 表示该参数在验证段没有产生交易。
参数热力图
越亮评分越高至少需要两个参数存在多个取值。
寻优记录
回测平台
多标的组合、目标仓位、次日开盘成交;成本、滑点与止损都写进撮合层,结果可复算。
配置参数
登录后可创建与管理数据集。
新建数据集
time,open,high,low,close,volume;time 为 UTC 毫秒。
币安按 1,000 根分页拉取,最多 20,000 根;相同内容自动去重。
运行历史
策略库
| 名称 | 最后修改 | 创建日期 | 回测 | 操作项 |
|---|
读当前代码、按你的一句话改。先给预览,点「应用到编辑器」才写回去,不会偷偷覆盖。
发送当前代码与本段指令给所配置的 AI 服务,不包含账户、邮箱等身份信息。助手会消耗少量调用额度。
代码里用 Params.fast 读取,这里的值会覆盖代码中的默认值。提交回测时按快照保存,同一份代码配不同参数可以分别回测。
0 / 200 · 显示在策略库列表的悬停提示里,方便几个月后还记得当初怎么想的。
笔记保存在这台设备的浏览器里(localStorage),不随账号同步,也不参与回测。
行情变量
- Open / High / Low / Close
- 当前 K 线的四个价格
- Volume
- 当前 K 线成交量
- BarIndex
- 已处理 K 线序号,从 0 开始
- Equity / Cash
- 当前权益与可用现金
- Position
- 持仓快照:
qty/avgPrice/weight(0–1) - BarTime
- 当前 K 线开盘时间(UTC 毫秒)
指标函数
- MA(n) / EMA(n)
- 简单与指数移动平均
- RSI(n)
- 相对强弱,0–100
- HHV(n) / LLV(n)
- 最近 n 根的最高 / 最低
- ATR(n)
- 平均真实波幅
- STD(n)
- 收盘价标准差
下单与输出
- Target(w)
- 把目标仓位设为权益的 w 倍,下一根开盘成交
- Buy() / Sell()
- 满仓 / 清仓的快捷写法
- Log(...)
- 写一条策略日志,随结果一起返回
- Plot(name, value)
- 在结果页画一条自绘指标线
- Params
- 参数对象,如
Params.fast
执行约定
- onBar()
- 每根已收盘 K 线调用一次
- onInit()
- 可选,回测开始时调用一次
- WARMUP
- 声明预热根数;不写则按指标最长周期推断。只用于校验数据量,不会跳过 K 线
- 撮合
- 信号收盘确认、下一根开盘成交,手续费与滑点由引擎统一计入
改动代码后先点「检查语法」,语法错误会在提交前拦下,不消耗当天的回测额度。查看完整 API 参考(含边界与报错对照)→
配置参数
策略 API
策略文件是一段跑在沙箱里的 JavaScript。这一页写清它能读什么、能返回什么、以及哪些事它做不到。
速查表
24 项策略能碰到的全部名字都在这张表里——表外的东西一律不存在。按名称过滤,点任意一行跳到对应章节。
| 名称 | 类型 | 说明 |
|---|---|---|
onInit() | 生命周期 | 可选,回测开始时调用一次 |
onBar() | 生命周期 | 必须定义,每根已收盘 K 线调用一次,返回下一根的目标仓位 |
WARMUP | 生命周期 | 声明预热根数(1–500),用于数据量校验与结果标注 |
Open High Low Close | 变量 | 当前 K 线的四个价格,USDT 计价 |
Volume | 变量 | 当前 K 线成交量,单位为基础资产 |
BarIndex | 变量 | 已处理 K 线序号,从 0 开始 |
BarTime | 变量 | 当前 K 线开盘时间(UTC 毫秒) |
Equity | 变量 | 当前权益:现金 + 持仓按当前收盘价估值 |
Cash | 变量 | 可用现金 |
Position | 变量 | 持仓对象:qty / avgPrice / weight |
Params | 变量 | 只读的运行参数对象,如 Params.fast |
MA(n) | 指标 | 收盘价简单移动平均 |
EMA(n) | 指标 | 指数移动平均,α = 2/(n+1) |
RSI(n) | 指标 | Wilder 相对强弱,取值 0–100 |
HHV(n) | 指标 | 最近 n 根收盘价的最高值 |
LLV(n) | 指标 | 最近 n 根收盘价的最低值 |
ATR(n) | 指标 | Wilder 平均真实波幅 |
STD(n) | 指标 | 收盘价样本标准差(分母 n−1) |
Target(w) | 仓位 | 把目标仓位设为权益的 w 倍(0–1),下一根开盘执行 |
Buy() | 仓位 | Target(1) 的快捷写法,满仓 |
Sell() | 仓位 | Target(0) 的快捷写法,清仓 |
Hold() | 仓位 | 维持当前权重,不做任何调仓 |
Log(...) | 输出 | 写一条策略日志,最多 400 条 |
Plot(name, value) | 输出 | 在结果页画一条自绘曲线,最多 8 条 |
没有匹配的 API。试试 target、rsi 或 position。
快速开始
01一个策略文件只需要一个 onBar()。它在每根 K 线收盘时被调用一次,返回值就是下一根 K 线要持有的目标仓位:0 空仓,1 满仓,中间值按比例持有。
var WARMUP = 30;
function onBar() {
var fast = MA(10);
var slow = MA(30);
// 预热期数据不足,指标返回 NaN,先空仓等指标就绪
if (!isFinite(fast) || !isFinite(slow)) return Target(0);
return fast > slow ? Target(1) : Target(0);
}
一次回测里发生什么
- 文件执行一次声明函数、初始化状态变量,限时 2 秒。这一步拿不到任何行情。
- 调用 onInit()可选。此时数据已就绪,适合读
Params、写第一条日志。 - 逐根调用 onBar()从第 0 根到倒数第二根,每根限时 250 毫秒。指标只到当前根,看不到未来。
- 按收盘价收尾最后一根不调用 onBar(没有下一根可以成交),期末持仓按最后收盘价计入权益。
生命周期
02引擎只认三个钩子。写错名字不会报错,只会安静地什么都不发生——所以先确认函数名。
| 名称 | 调用时机 | 说明 |
|---|---|---|
onInit() | 数据就绪后、第一根 K 线之前 | 可选,只调用一次。适合读参数、初始化状态、写启动日志。 |
onBar() | 每根已收盘 K 线 | 必须定义。返回值是下一根的目标仓位;不返回就沿用 Target() 的设定。 |
WARMUP | 数据加载时读取 | 文件级变量,取值 1–500。决定这次回测「至少需要多少根 K 线」,并标注在结果里。 |
onBar 的返回值怎么算
三种情况按顺序判断,先命中先用:
- 返回了有限数字直接当目标仓位,并夹到 0–1。可以直接
return 0.5,也可以return Target(0.5)。 - 返回 undefined 或 NaN用本根内最后一次
Target()的值;一次都没调用就退到第 3 条。 - 什么都没说维持当前持仓权重,等同于
Hold()。
文件级变量会保留
整个文件只执行一次,所以 var 声明的变量在整次回测里一直活着。记录入场价、上一根信号、连续亏损次数都靠它——不需要把它们塞进 Params。
var entryPrice = 0; // 整次回测内一直保留
function onBar() {
if (Position.weight <= 0) {
entryPrice = 0; // 空仓时清掉,避免拿着上一笔的旧价
return Target(1);
}
if (entryPrice === 0) entryPrice = Position.avgPrice;
// 收盘价比持仓均价高出 5% 就止盈离场
if (Close > entryPrice * 1.05) return Target(0);
return Hold();
}
WARMUP + 3 根就报错),以及在结果里标注预热根数。引擎仍然从第 0 根开始调用 onBar,那时指标还是 NaN,必须自己判断——写法见上面的 isFinite 守卫。行情变量
03这些名字每根 K 线覆盖写一次,永远是「当前这根」的值。
| 名称 | 类型 | 含义 |
|---|---|---|
Open High Low Close | 数字 | 当前 K 线的开盘、最高、最低、收盘价,USDT 计价。 |
Volume | 数字 | 当前 K 线成交量,单位是基础资产(BTC / ETH / SOL),不是 USDT。 |
BarIndex | 整数 | 已处理 K 线序号,从 0 开始。第 1 根 K 线时它是 0。 |
BarTime | 数字 | 当前 K 线开盘时间,UTC 毫秒时间戳。换成本地时间用 new Date(BarTime)。 |
Equity | 数字 | 当前权益 = 可用现金 + 持仓按当前收盘价估值。回测开始时等于初始资金。 |
Cash | 数字 | 可用现金。尚未成交的买单不会预先扣减,所以它是上一根收盘时点的余额;真正下单时再受它约束。 |
Position | 对象 | 持仓快照,三个字段见下表。只读:改它不会影响账户。 |
Position 的三个字段
| 字段 | 含义 |
|---|---|
Position.qty | 持仓数量,单位为基础资产。空仓为 0。 |
Position.avgPrice | 持仓加权成交均价(按成交金额摊,不含手续费)。空仓为 0。 |
Position.weight | 持仓市值 ÷ 权益,0–1。这是「你现在几成仓」,不是上一根的目标值。 |
Close[1]、Close[i - 1] 拿到的都是 undefined——这些是标量,不是序列。要看历史窗口用 HHV / LLV / MA,要看上一根就把值自己存进状态变量。这不是限制性能,而是从结构上杜绝未来函数。指标函数
04七个指标,全部返回「当前这根」的数值。数据不足时返回 NaN,不会返回 0,也不会抛错——用 isFinite() 判断。
| 函数 | 口径 | 首个有效位置 |
|---|---|---|
MA(n) | 收盘价 n 根简单移动平均:ΣClose / n | BarIndex ≥ n − 1 |
EMA(n) | 指数移动平均,α = 2 / (n + 1),首个值取前 n 根均值 | BarIndex ≥ n − 1 |
RSI(n) | Wilder 平滑的相对强弱,0–100。要求 n ≥ 2 | BarIndex ≥ n |
HHV(n) | 最近 n 根收盘价的最高值,窗口包含当前根 | BarIndex ≥ n − 1 |
LLV(n) | 最近 n 根收盘价的最低值,窗口包含当前根 | BarIndex ≥ n − 1 |
ATR(n) | Wilder 平均真实波幅,TR = max(H−L, |H−C₋₁|, |L−C₋₁|) | BarIndex ≥ n − 1 |
STD(n) | 收盘价样本标准差,分母为 n − 1 | BarIndex ≥ n − 1 |
三条使用规则
- 周期必须是 1–500 的整数。传小数、
NaN或超范围的值会直接中止整次回测,报「指标周期必须是 1–500 的整数」。周期来自Params时先取整。 - 只有收盘价,别指望它替你看最高最低。
HHV/LLV/STD都基于Close。要做「突破当根最高价」得自己用High比较,或者用ATR之类带高低价的指标。 - 同名同周期只算一次。指标按整段数据预先算好,每根只取第 i 个值;重复调用
MA(20)不会重复计算,可以放心写在循环里。
function onBar() {
var rsi = RSI(14);
// 前 14 根是 NaN,先空仓等指标就绪
if (!isFinite(rsi)) return Target(0);
if (rsi < 30) return Target(1); // 超卖,满仓
if (rsi > 70) return Target(0); // 超买,清仓
return Hold(); // 中间区间不动
}
仓位与输出
05Target(w) 是唯一的下单入口。它只表达「下一根开盘,我想持有多少仓位」,具体买多少、够不够钱、要不要扣手续费,全由引擎算。
| 名称 | 行为 | 边界 |
|---|---|---|
Target(w) | 把目标仓位设为权益的 w 倍,返回夹取后的值 | w 夹到 0–1;NaN 当 0 处理 |
Buy() | 等同 Target(1),满仓 | 仍受现金约束,可能被缩减 |
Sell() | 等同 Target(0),清仓 | 只卖已持有的数量,不会开空 |
Hold() | 等同 Target(Position.weight),不动 | — |
Log(...args) | 写一条日志,随回测结果一起返回 | 最多 400 条,每条 300 字符;非字符串用 JSON 序列化 |
Plot(name, value) | 在结果页画一条自绘曲线 | 最多 8 条;name 超过 24 字符会被忽略 |
分批建仓是合法的
目标是「权益的几成」,所以 0.34 → 0.68 → 1 就是分三批进场。注意引擎有 2% 调仓阈值:目标与当前市值的差小于权益的 2% 时不会下单,所以别用 0.001 这种量级去试探。
function onBar() {
var ma = MA(60);
if (!isFinite(ma)) return Target(0);
Plot('MA60', ma); // 结果显示页会画出这条线
var premium = Close / ma - 1;
if (premium > 0.02) {
var next = Math.min(1, Position.weight + 0.34); // 每根加一档
if (next > Position.weight) Log('加仓到', next.toFixed(2));
return Target(next);
}
if (premium < -0.02) {
if (Position.weight > 0) Log('跌回均线下方,清仓');
return Target(0);
}
return Hold();
}
Log 不是 console.log:沙箱里没有 console,写了会抛 ReferenceError。运行参数
06「参数设置」里填的 JSON 会变成 Params,一份代码可以配不同参数分别回测。对象是冻结的,写它不生效,也不会报错。
| 规则 | 说明 |
|---|---|
| 形状 | 必须是一层 JSON 对象,最多 20 个键,序列化后不超过 4 KB。 |
| 缺省 | 没填就是空对象 {},所以代码里一定要给默认值。 |
| 只读 | Object.freeze;写 Params.fast = 5 在非严格模式下静默失败。 |
| 快照 | 提交回测时参数与代码一起存进那次运行记录,之后改策略不影响历史结果。 |
// 参数面板填:{"fast": 12, "slow": 48, "risk": 0.02}
function onBar() {
var fast = Number(Params.fast) || 12;
var slow = Number(Params.slow) || 48;
var risk = Number(Params.risk) || 0.02;
fast = Math.max(1, Math.min(500, Math.floor(fast))); // 周期必须取整且在 1–500
slow = Math.max(fast + 1, Math.min(500, Math.floor(slow)));
if (MA(fast) > MA(slow)) return Target(1 - risk);
return Target(0);
}
撮合与成本
07策略只产生目标仓位,成交由引擎按同一套规则处理。这些规则对内置策略和代码策略完全一致,所以两者的结果可比。
- 收盘生成信号第 i 根收盘后调用
onBar,拿到目标权重。 - 换算成金额目标市值 = 权重 × 当时权益;差额小于权益的 2% 直接忽略,避免小额度反复交易。
- 下一根开盘成交按第 i+1 根开盘价成交,先卖后买,永远不用当根收盘价成交。
- 扣成本手续费按成交金额双边收取,滑点按不利方向计入成交价。
| 配置项 | 默认值 | 说明 |
|---|---|---|
| 初始资金 | 10,000 USDT | capital。在「更多参数」里可改。 |
| 手续费 | 10 bps | feeBps。万分之一,买卖各收一次。 |
| 滑点 | 5 bps | slippageBps。按不利方向固定基点计入成交价。 |
| 调仓阈值 | 2% | rebalanceThresholdPct。差额小于权益的 2% 不下单,这是「几乎不交易」最常见的原因。 |
| 总仓位上限 | 100% | maxGrossExposure。单标的、只做多,实际用不到。 |
| 引擎止损 / 止盈 / 移动止损 | 0(关闭) | stopLossPct / takeProfitPct / trailingStopPct。按盘中最高最低价判断;代码策略的回测面板不提交这三项,因此默认关闭。 |
| 冷却 | 1 根 | cooldownBars。止损或止盈后暂停买入的根数;上述三项关闭时不生效。 |
Position.avgPrice 算浮动盈亏,或用 Equity 相对峰值回撤,示例见「完整示例」第二段。另外两点也会影响结果:买单受现金约束,可能被缩减(完全买不起时才记为「被拒成交」);期末持仓按最后收盘价估值,不会强制平仓,也不计入已平仓交易统计。
沙箱与限制
08策略跑在独立的虚拟机上下文里,只拿到数字和纯函数。下面这些上限是硬的,超了会被直接终止,不会「慢一点也跑完」。
| 项目 | 上限 | 超限表现 |
|---|---|---|
| 代码体积 | 64 KB | 保存与回测时都拒绝提交。 |
| 文件执行 | 2 秒 | 报「策略初始化失败」。 |
onInit | 2 秒 | 同上。 |
单根 onBar | 250 毫秒 | 报「第 N 根 K 线执行超时」并终止整次回测。 |
| 日志 | 400 条 × 300 字符 | 超出部分静默丢弃。 |
| 自绘曲线 | 8 条 | 第 9 条起静默忽略。 |
| 指标周期 | 1–500 的整数 | 抛错,整次回测失败。 |
| 数据集 | 1 个 | 代码策略不支持多标的,请用内置组合策略。 |
| 单次运行 | 60 秒 | worker 强制终止,额度按已耗时扣减。 |
沙箱里没有这些
require、import / export、process、fetch、console、eval、new Function、定时器、文件读写——一律不存在。代码生成能力被关闭,也没有 window 或 document。要用什么就先在文件里自己写,或者用平台给的指标函数。
onBar 里,则会在跑到那一根 K 线时才失败,报错会指名是第几根。先在本地写个 node -e 试算,比在浏览器里反复提交快得多。常见错误
09报错信息都指名到根,先看它说的是哪一根,再去对那一根的数据。
| 现象 | 原因 | 处理 |
|---|---|---|
| 第 N 根 K 线执行超时 | 单根里做了重活:嵌套循环、大数组、递归、字符串拼接日志 | 改用指标函数;把重活挪到 onInit;日志只在关键节点写。 |
| 策略初始化失败 | 文件顶层引用了不存在的变量,或 onInit 抛错 | 注释掉可疑行二分定位;初始化逻辑放进 onInit 并先判断数据。 |
| 指标周期必须是 1–500 的整数 | 周期来自 Params 且是小数或 NaN | 用 Math.floor 取整,并给默认值兜底。 |
| 策略必须至少定义一个 onBar() 函数 | 函数名拼错,或只写了 onInit | 用函数声明 function onBar() {},注意大小写。 |
| 数据不足:该策略至少需要 N 根 K 线 | 区间太短,或 WARMUP 写得比数据还长 | 拉长区间,或降低指标周期与 WARMUP。 |
| 代码策略一次只回测一个数据集 | 选了多个标的 | 拆成多个策略分别回测,或改用内置组合策略。 |
| 一直空仓、几乎不交易 | 预热期没判断 NaN;或目标变动小于 2% 阈值 | 加 isFinite 守卫;仓位用 0 / 0.5 / 1 这类明显不同的档位。 |
| 反复满仓清仓 | 没有滞回区间,价格在阈值附近抖动 | 进场和出场用两个不同阈值,或加一根确认 K 线。 |
完整示例
10第二段是一个能直接跑的完整策略:ATR 通道突破 + 分三批建仓 + 权益回撤保护。把它贴进编辑器,参数留空也能跑。
var WARMUP = 30;
var FAST = 10;
var SLOW = 30;
function onInit() {
Log('策略启动', JSON.stringify(Params || {}));
}
function onBar() {
var fast = MA(FAST);
var slow = MA(SLOW);
if (!isFinite(fast) || !isFinite(slow)) return Target(0);
Plot('快线', fast);
Plot('慢线', slow);
if (fast > slow) return Target(1);
return Target(0);
}
// 突破最近 N 根高点时分三批建仓,跌破 M 根低点时清仓;
// 权益从峰值回撤超过 maxDD 也清仓,并冷却 5 根 K 线再考虑进场。
// 参数(可留空):{"entry": 20, "exit": 10, "maxDD": 0.15}
var WARMUP = 60;
var peakEquity = 0;
var cooldown = 0;
function onInit() {
Log('启动', JSON.stringify(Params || {}));
}
function onBar() {
var entry = Math.max(2, Math.min(500, Math.floor(Number(Params.entry) || 20)));
var exitN = Math.max(2, Math.min(500, Math.floor(Number(Params.exit) || 10)));
var maxDD = Math.max(0.02, Math.min(0.9, Number(Params.maxDD) || 0.15));
peakEquity = Math.max(peakEquity, Equity);
if (cooldown > 0) {
cooldown--;
return Target(0);
}
// 回撤保护:从权益峰值回撤超过 maxDD 就清仓,先离场再说
if (peakEquity > 0 && Equity / peakEquity - 1 < -maxDD) {
cooldown = 5;
Log('回撤保护触发', ((Equity / peakEquity - 1) * 100).toFixed(1) + '%');
return Target(0);
}
var upper = HHV(entry);
var lower = LLV(exitN);
var atr = ATR(14);
if (!isFinite(upper) || !isFinite(lower) || !isFinite(atr)) return Target(0);
Plot('上轨', upper);
Plot('下轨', lower);
// 用 0.25 倍 ATR 做缓冲,避免价格贴着轨线反复进出
if (Close > upper - atr * 0.25) {
var next = Math.min(1, Position.weight + 0.34); // 0 → 0.34 → 0.68 → 1
if (next > Position.weight + 0.001) Log('加仓到', next.toFixed(2));
return Target(next);
}
if (Close < lower + atr * 0.25) {
if (Position.weight > 0) Log('跌破下轨,清仓');
return Target(0);
}
return Hold();
}
这段代码在 400 根 K 线的样本上可以正常跑完:预热 60 根,之后分三批建仓、画两条轨线、日志记录每次加减仓。它不保证赚钱——参数没调过、也没做样本外验证,那属于「策略进化」该做的事。
源码对照
11这一页不是承诺,是对实现的描述。任何一条都可以在下面这些文件里核对;如果哪天代码改了而文档没跟上,以代码为准,也请顺手提一句。
| 文件 | 管什么 |
|---|---|
src/bt/code.mjs | 沙箱创建、全局变量与函数清单、超时、日志与曲线的限额 |
src/bt/indicators.mjs | 七个指标的公式与首个有效位置 |
src/bt/engine.mjs | 执行时序、2% 调仓阈值、止损止盈、收盘估值 |
src/bt/index.mjs | 配置默认值与取值范围、参数校验、结果字段 |
src/ai-code.mjs | AI 助手看到的同一份 API 卡片 |
spectrum-bt/1.0,每次回测结果里都会带上它。口径变更会同时在结果里升级版本号,便于区分「策略变了」和「引擎变了」。SPECTRUM · 策略研究工作台
欢迎回来
公网注册和登录需要 HTTPS,请先完成服务器证书配置。
还没有账户?
策略、回测与预警数据按账户隔离,仅你本人可见。
账号恢复
重置密码
用注册时的用户名,通过邮箱验证码设置新密码。
账户设置
基本信息
- 用户名
- —
- 账号 ID
- —
- 注册时间
- —
- 上次登录
- —
账号安全
- 邮箱验证
- —
- 登录方式
- 用户名 + 密码
- 并发会话
- 最多 4 个,超出时最早的失效
- 二次验证
- 暂未提供
通知方式
站内通知始终开启;邮件与即时推送按渠道分别开关。
联系方式
未验证即时通知
未添加邮件之外,预警还能推到微信或浏览器。可以同时添加多个渠道,规则命中时每个渠道各发一条。
公众号方案:打开微信公众平台的「接口测试号」页面扫码,即得 AppID 与 AppSecret,免费且无需认证。在测试号页面「模板消息 → 新增测试模板」把正文写成 标题:{{title.DATA}} 和 内容:{{content.DATA}},再把关注者的 openid 从「用户列表」复制过来。务必先把服务器 IP 加进测试号的 IP 白名单,否则取 token 会报 40164。
Server酱:sct.ftqq.com 微信扫码登录后复制 SendKey。PushPlus:pushplus.plus 微信登录后复制 token。密钥只存服务端,页面上只显示首尾几位。
浏览器推送需要授权通知权限;iPhone 要 16.4 以上并先把本站「添加到主屏幕」。同一台设备卸载或清理浏览器数据后,需要重新开启。
修改密码
修改成功后所有设备立即退出,需要用新密码重新登录。
登录与会话
- 登录方式
- 用户名 + 密码
- 会话时长
- 8 小时,空闲 30 分钟自动退出
- 并发会话
- 最多 4 个,超出时最早的失效
- Cookie
- __Host-crp_session · HttpOnly · SameSite=Lax
- 二次验证
- 暂未提供,建议使用 20 位以上长口令
密码只保存 scrypt 摘要,服务端无法还原明文;忘记密码只能走邮箱验证码重置。