指南

LPSignal 能做什么

LPSignal 监控 Ethereum、BNB Chain、Base、Arbitrum、Optimism 和 Polygon 上的集中流动性池(Uniswap v3 与 v4、PancakeSwap v3、Aerodrome 与 Velodrome Slipstream)。它每小时针对一组价格区间,计算在每个池中做 LP 扣除无常损失 (IL) 后本可获得的收益。当某个区间过去一周收益良好、今天仍在持续产生收益时,你会收到一条信号,其中给出应开立的精确仓位。

池中的两种代币都必须在我们的蓝筹列表中,因此你不会看到新币或流动性差的代币的信号。Uniswap v4 池仅在无 hook 且费率固定时才会纳入。

净 APR 如何计算

净 APR = 手续费 APR − 无常损失 (IL),由基于该池自身逐小时历史数据的回测年化得出。(API 中该损失以负值 ilApr 表示,因此 netApr = feeApr + ilApr。)

  • 手续费来自池合约的手续费增长(fee growth)计数器,在每小时结束时读取。这是每单位区间内流动性实际赚取的精确金额,包含动态费率。我们从不用交易量估算的手续费来触发信号。
  • 无常损失是仓位价值相对于直接持有你所存入的两种代币的差额,两者都按窗口最后一个小时的收盘价计价。
  • 区间内时间占比是价格处于区间内的小时数占比。区间外的小时没有收益,但仍计入平均值。

每个池按其类型测试相应的区间宽度。±5% 的区间表示仓位覆盖从入场价格下方 5% 到上方 5% 的价格,并按该池的 tick spacing 向外取整。

池类型示例测试区间
稳定型USDT/USDC±0.05% · ±0.1% · ±0.5%
相关型wstETH/WETH, cbBTC/WETH±0.5% · ±1% · ±3%
波动型WETH/USDC, WBNB/USDT±5% · ±10% · ±20% · full range

统计窗口为最近 24 小时、7 天和 30 天。Aerodrome 和 Velodrome 的数据针对未质押的流动性。若在 gauge 中质押可获得排放奖励,我们会在池旁显示该收益率供参考,但它不会触发信号,也不参与回测。

信号何时触发

在整点时,若某个池的某一区间同时满足以下全部条件,该池即触发机会信号:

条件稳定型相关型波动型
最近 7 天净 APR≥ 8%≥ 10%≥ 30%
最近 24 小时净 APR≥ 8%≥ 10%≥ 30%
7 天区间内时间占比≥ 80%
  • 只计入精确的手续费数据。若某个窗口缺少手续费增长读数,该池不会触发。
  • 若有多个区间符合条件,你只会收到 7 天净 APR 最高的那个。
  • 触发信号后,同一个池会静默 72 小时,除非其 7 天净 APR 升至上次信号时的 1.5 倍。
  • 落后超过 2 小时的链在追上进度前不会触发任何信号,因此你不会收到基于过时数据的信号。
信号描述的是已经发生的事。上周收益 40% 的区间,一旦价格突破,下周就可能亏损。请据此控制仓位。

短时机会

有些区间会在一两个小时内收益很高——一段剧烈行情、新的激励、一波集中的交易——远早于 7 天平均值反映出来。短时机会信号(kind: "burst")在整点时,某个区间同时满足以下全部条件时触发:

条件稳定型相关型波动型
最近 1 小时净 APR≥ 30%≥ 45%≥ 110%
这 1 小时内在区间内的时间≥ 67%
这 1 小时的成交笔数(单笔大额成交不算高峰)≥ 3
  • 和所有机会信号一样,只计入精确的手续费数据。
  • 同一小时已触发 7 天信号的池子不会再触发短时机会。短时机会触发后,该池 12 小时内保持静默,除非其 1 小时净 APR 再提高一半。
  • 每条短时机会在触发后的 24 小时评分(7 天信号为触发后 7 天),有单独的历史表现:GET /v1/signals/stats?kind=burst。
  • 信号在其描述的整点之后 30–90 分钟到达(归档只包含已最终确认的区块)。1 小时的高峰可能在你操作前就已结束。数据按小时汇总,因此最短窗口是 1 小时。
短时机会默认不推送。如需推送请订阅(见下文);它始终会显示在信号页面和 API 中。

高收益 · 高风险

DEX 网站按池子整体 APR 给池子排名:最近 24 小时的交易手续费除以池子的流动性,再年化。高收益信号(kind: "hot_pool")在大池子的这个数字暴涨时触发,条件是整点时以下全部满足:

条件阈值
最近 24 小时池子整体手续费 APR≥ 50%
相对该池自己的 7 天平均≥ 2×
池子 TVL(3 小时内刷新过)≥ $500k
  • 手续费按成交量 × 池子费率估算,用最新价格折算。Uniswap v4 池子不参与:它的 TVL 是价格附近的深度,会把这个数字算高。
  • 这是池子整体的数据,不是推荐仓位(tickLower 和 tickUpper 为 0),也不参与评分。旁边的 bestNet24h 是同一天里我们最好的区间扣除无常损失后的实际净 APR(bestRangeBp 说明是哪个区间),没有 24 小时回测时为 null。
  • 同一个池子 24 小时内只触发一次。付费套餐实时收到,免费套餐 24 小时后,与其他机会信号相同。
手续费暴涨通常伴随剧烈的价格波动:无常损失可能超过手续费,暴涨也可能几小时内就结束。这类信号默认不推送;如需推送请订阅(见下文)。

历史表现

机会信号触发 7 天后,我们会用这 7 天的数据回测它推荐的精确 tick,并将结果公布在该信号上。每个信号都会如此,包括亏损的信号。

  • 结果:实际实现的净 APR,以及其中的手续费和无常损失 (IL) 部分。
  • 待定:尚未满 7 天。
  • 未评分:该周的精确手续费数据始终没有到位。这类信号仍会显示,但不计入平均值,因此历史表现绝不会用估算值充数。

风险提醒

所有套餐的风险提醒均免费且实时推送。

提醒触发条件
流动性流出池的流动性在 3 小时内下降 30% 或以上,且链上实时状态连续两次读数(间隔至少一分钟)都如此(撤出后下一个区块又加回的不算)。按当前价格计价,因此代币价格下跌本身不会触发。仅适用于规模高于最低门槛的池。
脱锚在稳定型或相关型交易对上,链上实时价格连续两次读数(间隔至少一分钟)均偏离 7 天中位数至少 0.5% 且方向相同(或最近两个小时收盘价均如此)。偏离达 2% 时标记为严重。

聪明 LP 评分

我们在 Uniswap v3、PancakeSwap v3 和 Slipstream 上追踪仓位 NFT,从存入一直到最终提取。仓位关闭时,其得分为所有者收回的金额减去继续持有所存代币的价值,均按该次提取时刻的池价格计价。

  • 钱包需至少有 3 次已评分的平仓、资金达 $10,000,才会进入排名。
  • 由多个钱包出资、中途转给新所有者、在 gauge 中质押,或开仓后才首次被发现的仓位不参与评分。
  • 机器人和金库不参与排名:合约地址、每天平仓超过 10 次的钱包,以及仓位持有时间中位数不到 1 小时的钱包。信号在开仓后几分钟到一小时才能到达,来不及跟随它们。你关注的钱包仍会照常提醒。
  • 当排名前 20 的钱包或你关注的钱包开立 $10,000 及以上的仓位时,Pro 会员会收到提醒。

套餐与延迟

免费版BasicPro
机会信号触发 24 小时后实时实时
短时机会触发 24 小时后实时(需订阅)实时(需订阅)
高收益 · 高风险触发 24 小时后实时(需订阅)实时(需订阅)
风险提醒实时实时实时
聪明 LP 提醒与完整排行榜––支持
Telegram支持(延迟)支持支持
Webhook、WebSocket、API 密钥–支持支持
自定义规则–320

每条消息发送时都会重新检查套餐权限,因此套餐到期前排队的信号不会在到期后送达。

自定义规则

Basic(3 条规则)和 Pro(20 条规则)可以设置你自己的阈值。每条规则每小时都会用与默认信号相同的精确数据检查一次。命中只发送给你,通过你连接的所有渠道推送;它带有 rule 字段(规则的 id 和名称),不参与评分,也不显示在公开的历史表现中。

kind阈值默认信号(作为参考)
net_aprminNet7d、minNet24h(默认等于 minNet7d)、minInRange7d(默认 0.8)按池子类型分别为 8% / 10% / 30%,区间内时间 80%
depegminDeviation(0.001–0.5),仅限稳定型和相关型交易对0.5%
tvl_outflowminDrop(0.05–0.95)、windowHours(1–24,默认 3)3 小时内下降 30%

任何规则都可以用 chains、pairClasses、pools("chain:address",最多 50 个)和 minTvlUsd(至少 100,000,默认 1,000,000)缩小范围。cooldownHours(24–720,默认 24)让规则触发后在同一池子上保持静默。每个账户每 24 小时最多 50 次命中。

无论订阅了哪些类型,规则命中都会推送(只想通过规则接收的类型可以退订)。如果某次命中与你已收到的同一池子、同一小时的信号重复,会被跳过。降级后规则会保留,但只有套餐允许数量内的规则会运行(active)。

推送给你的信号

Telegram、webhook 和 WebSocket 信号流推送你订阅的信号类型。核心事件默认开启:net_apr、tvl_outflow、depeg 和 smart_lp。短时机会 burst 和高收益 hot_pool 需要你添加后才会推送。能收到哪些仍由套餐决定,自定义规则的命中总会推送。

可在账户页面修改,或调用 PUT /v1/me/subscriptions 并传入 {"kinds": ["net_apr", "burst", "depeg"]}。WebSocket 连接可以用 ?kinds=net_apr,burst 单独指定类型,REST 也接受同样的 kinds 参数;source=subscribed 返回的正是你的推送渠道收到的内容。

API

SDK

官方 SDK 支持 Node.js (20+) 和 Python (3.10+),封装了完整的 API、信号流和 webhook 验证,以 MIT 许可证开源:LPSignals/lpsignal-node 与 LPSignals/lpsignal-python。

npm install lpsignal
  • REST 客户端:响应带类型,API 错误码以异常抛出,触发频率限制后自动重试。
  • 不漏任何信号的信号流。每次连接前,SDK 会先通过 REST 拉取比你上一条信号更新的全部信号,再从其后续接信号流。任意时长的中断都会被补齐,进程运行期间每条信号只送达一次。进程崩溃后最后一条可能重复送达,因此请按 id 幂等处理信号。
  • 重启后续接。用内置的文件存储保存最后一条信号的 id;Node 与 Python 使用相同的文件格式。
  • Webhook 验证:一次调用完成,返回解析后的投递内容。

认证

REST API 地址为 https://api.lpsignal.app/v1。公开接口无需密钥。以 bearer token 方式发送密钥,即可按你的套餐查看信号并使用账户接口。密钥以 lps_ 开头,可在账户页面创建或替换密钥。

import { LPSignal } from 'lpsignal';

const lps = new LPSignal({ apiKey: process.env.LPSIGNAL_API_KEY });
const { signals, next } = await lps.signals({ kind: 'net_apr', limit: 20 });
// next page: lps.signals({ kind: 'net_apr', before: next })

匿名及免费版调用方只能看到触发已满 24 小时的机会信号。风险提醒始终包含在内。

频率限制与错误

限制项请求数 / 分钟
每个 API 密钥300
无密钥时,每个 IP120
全部流量,每个 IP600
区间回测(/backtest)30

超出限制时返回 429,并附带 Retry-After 响应头。错误以 JSON 返回,带有稳定的 error 错误码:

状态码error含义
400invalid_request参数校验失败。issues 列出每个出错字段。
401invalid_api_key密钥错误或已被替换。
403pro_required该接口需要 Pro 套餐。
404pool_not_found该链上没有这个被追踪的池。
429rate_limited请等待 retryAfterSec 秒。
500internal_error服务端出错。联系支持时请附上 requestId。

接口

路径密钥返回
GET/v1/chains–各链的扫描进度与池数量
GET/v1/pools?chain&class&window&minTvlUsd&minPoolApr&limit&offset&sort&order–各池及其最佳区间。window = 1、24、168 或 720 小时。sort = netApr(默认)、feeApr、ilApr、inRange、emissionApr、tvl、fee、volume24h、fees24h 或 poolApr;order = desc(默认)或 asc。每个池带 volume24hUsd 与 fees24hUsd(过去 24 小时交易手续费的估算:成交量 × 当前费率,未扣协议分成;动态费率池为近似值)以及 best.net24h(同一区间的 24 小时净 APR),还有 poolApr24h:DEX 网站上常见的池子 24h APR(估算 24h 手续费 ÷ TVL × 365,不计无常损失;Uniswap v4 为 null);minPoolApr 只保留不低于该值的池子(0.3 = 30%)。返回 total,用 offset 翻页。TVL 低于 $10k 的池默认不列出,除非 minTvlUsd = 0(几乎没有流动性的池,其按流动性折算的 APR 没有意义)
GET/v1/pools/:chain/:address–单个池的全部区间 × 窗口指标。v4 池使用其 32 字节的 pool id
GET/v1/pools/:chain/:address/hours?hours–逐小时手续费、交易量和价格,最多 720 小时
GET/v1/pools/:chain/:address/backtest?rangePct&days–回测任意区间(0 = 全区间),最长 30 天
GET/v1/signals?kind&kinds&source&limit&before&sort&order&offset可选kinds = 多个类型,例如 net_apr,burst。默认按时间倒序,用上一次响应中的 next 值作为 before 翻页,或用 offset 翻页(此时返回 total);或 sort = return(信号发出时的 APR)或 outcome(7 天实际结果),order = desc(默认)或 asc,用 offset 翻页(返回 total;没有该数值的信号排在最后)。source = default(全局信号)、rules(你的规则命中)或 subscribed(与推送渠道收到的完全一致)
GET/v1/signals/stats?days&kind–kind 为 net_apr(默认)或 burst 的历史表现
GET/v1/signals/:id可选单条信号
GET/v1/smart-lps?windowDays&chain&limit&offset&sort&order可选排行榜。sort = rank(默认,即盈亏排名)、pnl、return、capital、closes、wins、apr 或 winRate;无论怎么排,rank 始终是盈亏排名。每个钱包带 aprVsHold(相对持有的年化超额收益,按资金 × 占用时间计)、winRate 与 avgHoldH。返回 total。非 Pro:仅前 10 名,隐藏地址
GET/v1/smart-lps/:owner/positions?limit&openOffset&openSort&openOrder&closedOffset&closedSort&closedOrderPro某个钱包的未平仓与已平仓仓位,两个列表各自分页、排序:openSort = lastEvent、openedAt 或 entryUsd;closedSort = closedAt、openedAt、capitalUsd 或 pnlUsd;总数见 openTotal / closedTotal;未平仓仓位带 poolTick(所在池当前的 tick)
GET/v1/me需要你的套餐与已连接的通知渠道
PUT/v1/me/webhook需要设置 webhook URL。签名密钥仅返回一次
DELETE/v1/me/webhook需要删除 webhook
POST/v1/me/telegram-link需要用于 Telegram 机器人的一次性代码
GET/v1/me/followsPro你关注的钱包
PUT/v1/me/follows/:ownerPro关注钱包(最多 50 个)
DELETE/v1/me/follows/:ownerPro取消关注
GET/v1/me/rules需要你的规则、套餐上限和最近 24 小时的命中次数
POST/v1/me/rules付费版创建规则(Basic:3 条,Pro:20 条)
PUT/v1/me/rules/:id需要替换一条规则
DELETE/v1/me/rules/:id需要删除一条规则
PUT/v1/me/subscriptions需要推送给你的信号类型
WS/v1/stream?since&kinds付费版实时信号,见下文

所有 APR 与比率字段均为小数:0.345 表示 34.5%。fee 的单位是百分之一基点,因此 500 表示 0.05% 费率档。时间戳为 UTC 的 ISO 8601 格式。id 均为字符串。

信号对象

REST、webhook 和信号流都以如下结构发送信号。

{
  "id": "4821",
  "kind": "net_apr",
  "firedAt": "2026-09-30T09:00:00.000Z",
  "chain": "base",
  "dex": "uniswap_v3",
  "pool": "0xd0b53d9277642d899df5c87a3966a349a798f224",
  "pair": "WETH/USDC",
  "fee": 500,
  "pairClass": "volatile",
  "tvlUsd": 38200000,
  "rangeBp": 500,
  "entryTick": -200720,
  "tickLower": -201210,
  "tickUpper": -200230,
  "net24h": 0.41,
  "net7d": 0.345,
  "net30d": 0.298,
  "fee7d": 0.518,
  "il7d": -0.173,
  "inRange7d": 0.94,
  "rule": null,
  "outcome": null
}
字段含义
kindnet_apr 机会信号,burst 短时机会,hot_pool 高收益(高风险),tvl_outflow 或 depeg 风险提醒,smart_lp 钱包入场
rule当信号由你的某条自定义规则产生时存在:{ id, name }。其他信号为 null。
tickLower, tickUpper推荐的仓位。可直接使用这些 tick,它们已按该池的 tick spacing 对齐。
rangeBp所测试的区间档位,以价格的基点表示(500 = ±5%,0 = 全区间)
fee7d, il7d7 天净 APR 的两个组成部分。il7d 是相对于持有两种代币的损失,因此为零或负值:net7d = fee7d + il7d。API 中所有的 feeApr、ilApr 和 netApr 均同理。
net24h, net7d, net30d该仓位在各窗口内的净 APR。net30d 在该池积累满 30 天历史前为 null。
stakedEmissionApr仅限 Slipstream:若改为质押,按当前速率可获得的 gauge 排放收益。仅供参考。
outcome评分前为 null,之后为 { status, netApr, feeApr, ilApr, evaluatedAt }。status 为 done 或 inexact。

风险提醒包含 drop、tvlBeforeUsd、tvlNowUsd 和 windowHours(流动性流出)或 deviation 和 severe(脱锚)。聪明 LP 提醒包含 owner、rank、top、entryUsd 和 wallet30d。高收益信号包含 poolApr24h、poolApr7d、volume24hUsd、fees24hUsd、bestNet24h、bestRangeBp 和 risk。

Webhook

每条信号以 {"type": "signal", "deliveryId": "…", "signal": {…}} 的形式 POST 到你的 URL,并附带以下请求头:

x-lpsignal-delivery每次投递唯一。同一信号可能到达不止一次,请跳过已处理过的 id。
x-lpsignal-timestamp签名该请求时的 Unix 时间戳(秒)
x-lpsignal-signaturesha256= 前缀加上用你的签名密钥对 "<timestamp>.<raw body>" 计算的 HMAC-SHA256
import express from 'express';
import { verifyWebhook, WebhookVerificationError } from 'lpsignal';

app.post('/lpsignal', express.raw({ type: 'application/json' }), (req, res) => {
  try {
    const event = verifyWebhook(req.body, req.headers, process.env.LPSIGNAL_WEBHOOK_SECRET);
    // at-least-once: skip event.deliveryId if you have already handled it
    res.sendStatus(200);
  } catch (e) {
    if (e instanceof WebhookVerificationError) return res.status(400).send(e.reason);
    throw e;
  }
});
  • 请在 15 秒内返回任意 2xx 响应。不会跟随重定向。
  • 投递失败后会在 1 分钟、5 分钟、30 分钟和 2 小时后依次重试,之后放弃。
  • URL 必须为 HTTPS 且解析到公网地址,每次投递时都会重新检查。

WebSocket 信号流

SDK 会替你处理以下全部细节,包括中断超过 24 小时后的补齐。连接 wss://api.lpsignal.app/v1/stream,并在 Authorization 请求头中携带密钥,浏览器中则以 ?key= 传入。信号按 id 升序到达,同一连接上不会重复。保存你处理过的最后一个 id,并用 ?since=<id> 重连,即可补齐最近 24 小时内的全部信号。加上 ?kinds=net_apr,burst 可为单个连接指定类型;不加则按你订阅的类型推送。

import { LPSignal, SignalStream, FileLastIdStore } from 'lpsignal';

const stream = new SignalStream({
  client: new LPSignal({ apiKey: process.env.LPSIGNAL_API_KEY }),
  store: new FileLastIdStore('./lpsignal-state.json'),   // resume point survives restarts
  onSignal: async (signal, { source }) => {
    // once per signal, in id order; source = 'rest' | 'replay' | 'live'
  },
  onEvent: (e) => { if (e.type === 'fatal') console.error(e.error.message); },
});
await stream.start();
消息或关闭码含义
{"type":"signal"}一条信号。replay: true 表示这是 ?since= 之后的补齐消息。
{"type":"ready"}补齐完成,此后均为实时消息。
{"type":"replay_truncated"}待补齐的信号超过 1,000 条。请将 since 设为返回的 lastId 后重连。
close 4409补齐未能完成。请用你收到的最后一个 id 重连。
close 4402你的套餐已不再包含信号流。
close 1001服务器重启。请带上 since 重连。

服务器每 30 秒发送一次 ping,标准客户端会自动响应。

Telegram

  1. 在账户页面点击连接 Telegram,获取一次性代码。
  2. 打开 @LPsignals_bot 并发送 /start <code>。
  3. 此后你的套餐所包含的信号都会发送到该聊天。免费版在机会信号触发 24 小时后收到。