ReplayEdge Algorithm API

ReplayEdge Algorithm API

用脚本交易匿名历史行情

REST API 与网页交易台使用同一套撮合、手续费、滑点、杠杆和排行榜系统。算法只能读取已经揭示的 Tick;下单统一在下一根 Tick 的开盘价成交;股票代码和历史日期会在结算报告中公布。

本地 Base URLhttp://localhost:5178/api/v1

认证

API 文档可以在未登录时访问;真实交易接口必须使用 API Key。请先登录网页账户,点击顶部 API 生成 Key。带 Key 创建的回放会绑定账户,并在结算后进入最近 10 局和排行榜。

Authorization: Bearer redge_live_your_key
安全提醒不要把 Key 写入 Git、前端 JavaScript 或公开日志。推荐通过环境变量 REPLAYEDGE_API_KEY 注入。重新生成或撤销后,旧 Key 立即失效。

速率限制

每个 API Key 在一分钟窗口内最多请求 500 次,其中创建新回放最多 2 次。公开文档、API 概览和排行榜不计入 Key 额度;创建失败不会消耗开局额度,但仍计为一次 API 请求。

限制响应头额度
全部认证请求X-RateLimit-Limit / Remaining / Reset500 次 / 分钟 / Key
创建回放X-ReplayLimit-Limit / Remaining / Reset2 局 / 分钟 / Key

超过额度返回 429 rate_limited。脚本应读取 Retry-After 等待对应秒数,避免立即循环重试;Reset 是 Unix 秒级时间戳。

30 秒快速开始

export REPLAYEDGE_API_KEY="redge_live_..."

curl -X POST http://localhost:5178/api/v1/replays \
  -H "Authorization: Bearer $REPLAYEDGE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"universe":"mega","volatility":"any","trend":"any","timeOfDay":"any","totalTicks":180,"startAtOpen":false}'

保存响应中的 data.replayId。创建成功时返回最初 60 根 K 线,之后调用 advance 才会揭示新行情。

回放生命周期

创建回放
60 / N
读取行情
计算信号
提交订单
下一 Tick 成交
主动或自动结算
生成报告
  • 初始资金固定为 $100,000,最大总杠杆为 2x
  • 订单提交后不会立刻成交;市价、限价和止损触发单统一按下一根 Tick 的 open 价格计算成交,市价/止损会加滑点。
  • 每个回放绑定创建它的 API Key 用户,其他用户无法读取或操作。
  • 回放闲置 3 小时后可能失效。完成后成绩自动进入该用户排行榜。
POST/replays

创建匿名回放

字段允许值默认
universeall, mega, tech, etfall
volatilityany, low, medium, highany
trendany, up, down, rangeany
timeOfDayany, open, midday, closeany
totalTicks90-390 的整数,常用 120/180/240/390180
startAtOpentrue 时样本从美东 09:30 开始false
{
  "data": {
    "replayId": "6d90...",
    "status": "active",
    "tick": 60,
    "totalTicks": 180,
    "currentBar": { "o": 189.2, "h": 189.4, "l": 189.1, "c": 189.3, "v": 48210, "vw": 189.27, "time": "10:29" },
    "revealedBars": ["60 bar objects"],
    "account": { "equity": 100000, "buyingPower": 200000, "position": 0, "currentPrice": 189.3 }
  }
}
GET/replays/{replayId}

查询账户与订单状态

返回当前 Tick、账户、持仓、全部订单和成交记录,不重复返回 K 线数组。回放结束后还会包含 data.report

GET/replays/{replayId}/market?from_tick=61

读取已揭示行情

from_tick 是从 1 开始的 Tick 编号。接口最多返回当前 Tick,无法通过参数获取未来数据。

{ "data": { "replayId": "...", "fromTick": 61, "toTick": 65, "totalTicks": 180, "bars": [] } }
POST/replays/{replayId}/advance

推进行情

一次推进 1-30 个 Tick。revealedBars 只包含本次新揭示的数据。

{ "steps": 1 }
POST/replays/{replayId}/orders

提交订单

字段类型说明
sidestringbuysell
typestringmarket, limit, stop
quantityinteger至少 1 股;小数会向下取整
triggerPricenumber限价单和止损触发单必填
stopLossnumber可选;成交后创建保护单
takeProfitnumber可选;与止损组成 OCO
{
  "side": "buy",
  "type": "market",
  "quantity": 100,
  "stopLoss": 187.50,
  "takeProfit": 193.00
}
避免重复订单当前 v1 不提供幂等键。网络超时后不要直接重试 POST;先调用状态接口检查订单是否已经创建。
DELETE/replays/{replayId}/orders/{orderId}

撤销挂单

pendingpartial 状态的订单可以撤销,已成交和已拒绝订单不可撤销。

POST/replays/{replayId}/settle

结算并获取报告

未平仓持仓会按当前行情平仓,所有挂单撤销。响应的 data.report 会公布股票代码、交易日期和完整复盘统计。

GET/leaderboard?mode=score

读取排行榜

无需认证。mode 可为 scorepnl,只返回公开昵称、选填大学和训练统计。评分、收益和胜率按每位用户最近 10 局计算。

行情与账户字段

字段含义
o/h/l/c当前分钟开、高、低、收价格
v成交量
vw该分钟成交量加权平均价;成交额可按 vw × v 计算
time美东时间 HH:mm
position正数为多仓,负数为空仓
buyingPower考虑 2x 杠杆和当前敞口后的剩余买力
liquidationPrice维持保证金强平参考价;空仓时为 null

错误处理

{ "error": { "code": "invalid_request", "message": "quantity 必须至少为 1 股整数。" } }
HTTPcode处理建议
400invalid_request修正参数,不要原样重试
401unauthorized检查 API Key 是否撤销或复制不完整
403forbidden回放不属于当前账户
404not_found检查 ID,回放也可能已过期
429rate_limitedRetry-After 等待后重试
502market_data_unavailable稍后重新创建回放

完整 Python 策略骨架

示例使用 10/20 均线交叉,按 25% 可用买力下单。它仅演示 API 生命周期,不代表投资建议。

import math
import os
import requests

BASE = "http://localhost:5178/api/v1"
HEADERS = {
    "Authorization": f"Bearer {os.environ['REPLAYEDGE_API_KEY']}",
    "Content-Type": "application/json",
}

def api(method, path, **kwargs):
    response = requests.request(method, BASE + path, headers=HEADERS, timeout=30, **kwargs)
    response.raise_for_status()
    return response.json()["data"]

replay = api("POST", "/replays", json={"universe": "mega", "totalTicks": 180, "startAtOpen": False})
replay_id = replay["replayId"]
bars = replay["revealedBars"]

while replay["status"] == "active":
    closes = [bar["c"] for bar in bars]
    fast = sum(closes[-10:]) / 10
    slow = sum(closes[-20:]) / 20
    position = replay["account"]["position"]

    if fast > slow and position == 0:
        price = replay["account"]["currentPrice"]
        qty = math.floor(replay["account"]["buyingPower"] * 0.25 / price)
        if qty >= 1:
            replay = api("POST", f"/replays/{replay_id}/orders", json={
                "side": "buy", "type": "market", "quantity": qty
            })
    elif fast < slow and position > 0:
        replay = api("POST", f"/replays/{replay_id}/orders", json={
            "side": "sell", "type": "market", "quantity": position
        })

    replay = api("POST", f"/replays/{replay_id}/advance", json={"steps": 1})
    bars.extend(replay.get("revealedBars") or [])

report = replay["report"]
print(report["symbol"], report["timeRange"], report["pnl"], report["score"])