Type/to search
2
Follow
541
Followers
发明者量化 DEX 模块补全:一级市场的买币、做市、跨链比价,都能写成策略
Original
Created 2026-10-16 13:04:24  Updated 2026-10-21 13:22:55
 0
 5

一、Robinhood 链带来的这一波

Robinhood 链上线以后,链上交易明显热了起来。新币持续上线,池子一个接一个建起来,股票代币、meme 币、稳定币池同时活跃。热度也没有停留在一条链上:资金和用户在 Robinhood、Solana、BSC 之间来回流动,Solana 和 BSC 上的新币和流动性池也跟着活跃起来,有点鲶鱼效应的意思。

这一波行情的主战场是一级市场:币刚上线、池子刚建好,中心化交易所还没上,机会都在链上。用户的需求很具体:

  • 在链上第一时间买到新币,卖出时不被滑点吃掉;
  • 给新池子提供流动性,赚交易手续费;
  • 在几条链、几个池子之间比较,哪里价格更好、手续费更高;
  • 而且最好都能写成策略,自动执行、统一记账。

发明者很早就支持 Web3,方式是一个统一的接口:通过 exchange.IO 连接节点、调用合约。这个接口很灵活,理论上什么都能做,但对大多数用户来说门槛太高。想在 Uniswap 上换一次币,要自己查合约地址、编码 ABI、处理代币授权、算滑点、估 Gas、等交易确认;想提供一次集中流动性,还要换算 tick、计算两种代币的配比、管理仓位 NFT。更麻烦的是每条链、每家 DEX 都不一样:Uniswap 有 V2、V3、V4,PancakeSwap 有自己的 Infinity,Aerodrome 有 basic 池和 Slipstream,Solana 上又是 Meteora、Raydium、Orca 另一套体系。真正写策略的时间,大部分花在了和合约打交道上。

二、这次补全了什么

这次我们把 DEX 模块整体补全了。思路是:不再让用户直接面对合约,而是把每家 DEX 做成一个交易所对象,像接入中心化交易所一样接入,再为链上特有的操作提供专门的函数。

添加交易所时选好链和钱包,之后在策略里就是熟悉的写法:GetTicker 取价格,GetAssets 查余额,Buy / Sell / CreateOrder 下单。授权、路由、滑点、Gas、交易确认由平台处理。需要精细控制时,可以通过参数指定路由版本(v2 / v3 / v4)、费率档位和具体池子。新上线几小时的币,平台币种表里还没有,用一行 exchange.IO("token", 名称, 合约地址) 登记进来,就能像普通交易对一样交易。

类型交易所说明文档
Swap / 聚合路由(新)Uniswap(含 PancakeSwap、Aerodrome、Velodrome 等)、KyberSwap、1inch、OKX DEX、Jupiter链上买卖、指定路由与池子;Uniswap 系与 Jupiter 支持集中流动性 LPUniswap、KyberSwap、1inch、OKX DEX、Jupiter
链上永续 / 现货订单簿(更新)Hyperliquid、Lighter、edgeX、Aster、Aevo、WOOFi Pro用法接近中心化交易所,持仓、保证金、成交均价、条件单等字段口径对齐Hyperliquid、Lighter、edgeX、Aster、Aevo、WOOFi Pro
收益率 / 利率交易Pendle、Boros(Futures_Boros)Pendle 交易 PT / YT,按收益率定价;Boros 在链上订单簿交易永续合约的资金费率Pendle 与 Boros

各交易所支持哪些函数,可以在能力矩阵里对照查看。

对一级市场用户来说,补全之后最直接的变化是三点:

  1. 一套写法跨链跨 DEX。同一份策略,交易所换成 Robinhood 上的 Uniswap、BNB Chain 上的 PancakeSwap 或 Solana 上的 Jupiter,函数和字段都一样,只是链和池子不同。
  2. 新币即登记即交易。不用等平台收录,拿到合约地址(Solana 上是 mint 地址)就能报价、下单、做市。
  3. 流动性做市(LP)有了专门的函数。找池子、定区间、建仓、领手续费、撤出,各有一个 lp.* 函数,原来要自己换算的 tick、配比、授权都收进了函数里。

下面用一个 LP 示范策略,把这些能力串起来看一遍。先花两分钟说说 LP 是怎么回事。

三、先花两分钟理解 LP

DEX 上没有传统的买卖挂单,交易是和“池子”完成的。池子里放着两种币,比如 CASHCAT 和 WETH,谁想买 CASHCAT,就把 WETH 放进池子、把 CASHCAT 拿走,同时付一笔手续费(这个池子是 1%)。池子里的币来自 LP,手续费也按份额分给 LP。

Uniswap V3 之后有了集中流动性:LP 可以只在自己选定的价格区间里提供流动性。一个仓位在不同价格下装的东西不一样:

img

  • 价格在区间内:仓位里两种币都有,每笔经过这个区间的交易都会付给你手续费。
  • 价格往下跌:别人不断把代币卖给池子,你的仓位在一路买入代币;跌破下沿时,仓位里全部是代币。
  • 价格往上涨:反过来,你的仓位在一路卖出代币;涨破上沿时,全部变成计价币。

所以一个 LP 仓位可以理解为一张自动执行的“低买高卖”挂单,成交时还能收手续费:

  • 收入是手续费。价格在区间里来回波动越多,收的手续费越多;区间越窄,资金越集中,分到的比例越高。
  • 风险是单边行情。一路跌穿区间,手里全是代币;一路涨穿区间,早早把代币卖光了。相对“一直拿着不动”的差额,就是常说的无常损失。

做 LP 赚不赚钱,本质上是一道算术题:手续费收入能不能超过价格波动带来的损失。

3.1 平台提供的 LP 函数

lp.* 函数对应一个 LP 仓位从找池子到撤出的完整过程,统一通过 exchange.IO("lp.xxx", ...) 调用。Uniswap 系(含 PancakeSwap、Aerodrome 等)和 Jupiter(Solana 上的 Meteora DLMM、Raydium CLMM、Orca)用的是同一组函数名和返回字段:

函数作用主要返回
lp.pools(代币[, 计价币])列出该币的池子;不传计价币时列出全部计价币的池子协议、费率档、TVL、24h 成交额与手续费、现价、是否空池
lp.select(代币, 预算[, 选项])按规则自动挑一个池子一个池子 + 选择理由
lp.pool(池子 ID) / lp.ticks(...)池子实时状态 / 各价格段的流动性分布tick(或 bin)、价格、流动性
lp.plan(参数)按预算、区间、形状生成建仓计划(只读,不发交易)每档上下沿与数量、是否需换币、占池比例、预估日手续费
lp.simulate(计划)不签名,模拟执行建仓交易模拟得到的仓位
lp.add(计划)换币、授权、添加流动性交易哈希、各仓位 ID 与区间
lp.increase / lp.decrease给仓位加仓 / 按比例减仓交易哈希、收到的币
lp.collect(仓位 ID 列表[, 卖出])领取手续费,可直接卖成计价币领到的手续费
lp.remove(仓位 ID 列表[, 比例[, 卖出]])撤出流动性并领取手续费,可直接卖成计价币撤回的本金与手续费
lp.positions([过滤[, 钱包]])查询钱包里的仓位区间、是否在区间内、两币数量、价值、未领手续费
lp.track(仓位 ID 列表)登记 V4 等仓位,便于查询已登记的 ID

Aerodrome / Velodrome 还额外提供 lp.stake、lp.unstake、lp.claim,用于质押仓位领取奖励。完整参数见文档 Uniswap · 集中流动性(LP) 和 Jupiter。

四、示范策略:web3 流动性做市

我们用这些函数写了一个示范策略「web3 流动性做市示范策略」。它不是全自动的黑盒,而是把一轮 LP 拆成几个清楚的步骤:选池 → 配置头寸 → 看规划和情景分析 → 建仓 → 领取手续费 / 减仓 / 撤池子。建仓、领取、撤出都由状态栏按钮手动触发,策略负责计算、展示、换币、记账,并把每一步写进日志。

参数只有三个:币种(已收录的填名称,新币填“名称,合约地址”)、每次投入的金额、是否实盘。不勾实盘就是模拟:只读链上数据,仓位在本地按 Uniswap 公式记账,不发任何交易。

整体流程和每一步用到的函数:

img

4.1 识别链、登记新币

启动时先识别当前交易所在哪条链,据此确定资金币和 Gas 币:Robinhood 用 USDG,BNB Chain 用 USDT,其余链和 Solana 用 USDC。Uniswap 系通过 contracts 读链信息,Jupiter 按交易所名识别为 Solana。然后登记新币、读现价和钱包:

javascript
var ct = exchange.IO("contracts") // chainId、链名、常用合约 exchange.IO("token", "CASHCAT", "0x020bfc650a365f8bb26819deaabf3e21291018b4") // 名称 + 合约地址 var ticker = exchange.GetTicker() // 链上现价 var assets = exchange.GetAssets() // 钱包余额

启动日志把这些逐条写清楚:哪条链、资金币和 Gas 币、新币是否登记成功、现价、钱包余额、当前是模拟还是实盘;实盘时余额不够或 Gas 偏少会直接提示。

img

4.2 选池:一个币的全部池子

一级市场的新币,往往同时有好几个池子:不同计价币(USDG、WETH、原生 ETH)、不同协议版本、不同费率档。lp.pools 不传计价币时,会把该币所有计价币的池子都列出来:

javascript
var pools = exchange.IO("lp.pools", "CASHCAT") // 不限计价币 pools.forEach(function (p) { if (p.empty) return // 现价附近没有流动性的空池 p.dailyYield = p.fees24hUsd / p.tvlUsd * 100 // 日费率:每 1 美元一天分到多少手续费 })

LP 赚的是手续费,所以比的不是成交量,而是日费率 = 24 小时手续费 / TVL。策略把有效池子按计价币分页列表:费率档、现价(非资金币计价的同时折算成资金币)、TVL、24h 成交与手续费、日费率、年化、日周转,以及按默认头寸估算的“本次投入预估日收益”。空池单独排除。

实盘里 CASHCAT 扫出多个有效池子(USDG、WETH、ETH)。WETH 计价的 1% 池子 TVL 最深,约 250 万美元。

img

池子的计价币不是资金币(比如 CASHCAT/WETH)也可以直接选:建仓时策略先用钱包里已有的 WETH,不够的部分用 USDG 自动兑换;撤出后再把 WETH 换回 USDG,盈亏统一按资金币记账。这类跨计价币的操作,在原来需要自己串好几笔合约调用,现在就是一次 Buy / Sell。

4.3 配置头寸,看规划和情景分析

在池子上点“配置头寸”,设置三样东西:

  • 流动性分布:均匀 Spot、中心集中 Curve、两端集中 Bid-Ask;
  • 区间:相对现价的下沿和上沿,上沿填负数表示只在现价下方分批挂“买单”;
  • 档数:均匀分布时把区间按对数价格等分成几档。

确认后策略立即调用 lp.plan 规划(不发交易),出现两张表:

javascript
var plan = exchange.IO("lp.plan", { symbol: "CASHCAT_WETH", budget: 0.0041, // 投入的计价币(按资金币金额换算) range: {lower: a, upper: b}, // 这一档的价格上下沿 shape: "spot", pool: pool.id, slippage: 0.01 }) // plan.positions:价格上下沿、两种币数量;plan.swap:要先换多少币;plan.estDailyFeesUsd:预估日手续费
  • 头寸规划:每一档的价格区间、两种币各多少、折合多少资金币;
  • 收益与情景分析:预估日手续费和年化、占池比例、资金准备、建仓换币、钱包余额是否够用,以及价格跌到下沿 / 涨到上沿时的盈亏和无常损失、跌到下沿需要几天手续费才能补回。

多档规划有一个细节:池子的价格只能落在 tick 间距的整数倍上(1% 费率的池子一格约 2%),lp.plan 会把每档上下沿向外对齐。如果各档独立规划,相邻两档就会重叠。策略的做法是下一档的下沿取上一档对齐后的实际上沿,保证首尾相接;某档窄到被并进上一档,就跳过并提示减少档数。

img

收益合适,就在情景分析表里点“建仓”;不合适,直接在别的池子上重新配置。

4.4 建仓

lp.add 按规划执行:需要换币就先换,处理授权,然后逐档添加流动性。实际 Gas 通过回执读出(Solana 上取交易费和不可退的账户租金),计入这一轮的成本:

javascript
var r = exchange.IO("lp.add", part) // 每一档一笔 var rc = exchange.IO("receipt", r.txHash) // rc.fee:实际 Gas

链上交易偶尔会超时没被打包(Solana 上比较常见)。平台在报错里会明确说明交易是否已经上链:确认没上链的,策略按最新价格重新规划这一档并自动补发,最多 2 次;状态不确定的不重试,避免重复建仓。

建仓日志按“规划 → 换币 → 逐档上链 → 完成”四步输出,每一档的仓位 ID 和交易哈希都能在日志里查到。

4.5 持仓管理

建仓后,“头寸规划”表变成实际持仓,每 10 秒用 lp.positions 刷新一次:

javascript
var ps = exchange.IO("lp.positions", "CASHCAT_WETH") ps.forEach(function (p) { // p.priceLower / p.priceUpper / p.amountBase / p.amountQuote / p.value / p.feesValue })

每一档显示价格区间、状态、两种币数量、投入、价值、未收手续费和盈亏(扣除分摊的 Gas,各档相加正好等于本组盈亏)。状态一栏直接说明这一档在干什么:

  • 🟢 区间内:距下沿、上沿各多少;
  • ⏳ 未触及,价格需跌 x% 进入:当前全是计价币,等着买入代币;
  • ⏳ 未触及,价格需涨 x% 进入:当前全是代币,等着卖出。

img

每一档和合计行都有三个按钮:

按钮函数作用
领取手续费lp.collect(ids, true)领取后卖回计价币,再换回资金币
减仓lp.remove(ids, 比例, true)按输入的比例撤出
撤池子并卖出lp.remove(ids, 1, true) + Sell全部撤出、领取手续费,代币和计价币全部卖回资金币

撤池子时,平台逐个仓位发交易,中途某笔超时会在报错里带上已完成的仓位。策略先把已完成的记账,剩下的确认没上链就自动补;撤之前也会先核对链上还在哪些仓位,不会重复撤。

上方的指标卡、价格与区间图、手续费覆盖率、区间位置、资金与收益明细、收益归因(价格变动 / 无常损失 / 手续费 / Gas / 计价币汇率),把“手续费能不能补上波动损失”这道算术题实时摆在眼前。

img

4.6 一份代码,多条链

因为 DEX 都做成了交易所对象,这份策略不改代码就能在几条链上运行,只需要换交易所:

链交易所配置资金币示例币种参数
RobinhoodUniswapUSDGCASHCAT,0x020b…18b4
BNB ChainUniswap(DEX 选 PancakeSwap,含 Infinity)USDTCAKE,0x0E09…cE82
Base / Arbitrum / EthereumUniswap(或 Aerodrome)USDCWETH
SolanaJupiter(Meteora / Raydium / Orca)USDCSOL,或 ORCA,orcaEKTd…ktZE

Solana 上有两点不同,策略已经处理:币名和 mint 地址区分大小写;仓位 ID 带协议前缀,比如 orca:地址、meteora:地址。

五、实盘情况

我们在 Robinhood 链上用 10 USDG 跑了一轮实盘,选的是 CASHCAT/WETH 1% 池子,均匀 3 档、区间 ±6%:

步骤实际情况
选池4 个有效池子、9 个空池被排除;选 WETH 计价、TVL 约 250 万美元的 1% 池子
换币钱包没有 WETH,用 10.15 USDG 自动兑换
建仓3 笔 lp.add 依次上链,投入约 9.97 USDG,Gas 约 0.056 USDG
管理进场后 2 档在区间内,最下面一档等待价格回落;试了一次 50% 减仓,收回的 WETH 自动换回 USDG

Solana 上用 ORCA 也跑了一轮,Orca 池子建仓、撤池子都正常;期间遇到交易超时,就是 4.4、4.5 节里自动补发和部分完成记账的来源。

img

小资金跑一轮说明不了长期收益。比较稳妥的做法是先用模拟模式跑几天,看手续费覆盖率、区间内时间、和同期“买入持有”的对比,再用小资金上实盘,确认真实的 Gas 和滑点。Solana 上建议给 Jupiter 交易所配置私有 RPC,公共节点限频严重,容易交易超时。

六、顺带一提:新版状态栏

上面这些截图用的是平台新版的状态栏。LogStatus 现在可以直接传对象渲染组件:指标卡、仪表盘、进度条、各类图表、日历热力图、标签页等,原有的表格和按钮也照样能用。比如持仓页顶部的指标卡:

javascript
LogStatus("流动性做市 · CASHCAT", {type: "badge", items: [{text: "持仓中", color: "up"}, {text: "实盘", color: "down"}]}, "\n", [ {type: "alert", level: "success", title: "在区间内,正在赚手续费", text: "2/3 档在区间内"}, {type: "grid", cols: 3, items: [ {type: "kpi", title: "策略权益", value: 9.998, unit: "USDG"}, {type: "kpi", title: "手续费收入", value: 0, unit: "USDG", color: "up"}, {type: "progress", title: "区间位置", value: 0.62} ]} ])
组件本策略中的用途
badge / alert阶段、模式标签,区间状态提示
kpi / grid策略权益、本组盈亏、手续费、年化、现价
chart价格与区间图、收益归因、每日盈亏
gauge / progress手续费覆盖率、区间位置、区间内时间
stat资金与收益明细
calendar每日收益率日历
tabs / table每日收益、历史轮次;选池表、规划表、持仓表(带按钮)

各组件的完整写法见文档 LogStatus。

七、接下来

DEX 模块补全以后,一级市场的几类玩法:抢新币、做市赚手续费、跨链跨池比价、链上永续和收益率交易,都可以在同一套 API 下写进策略。这个 LP 示范策略只是其中一个例子,我们会继续开发更多链上策略,陆续和大家分享。如果你有想在链上实现的玩法,或者在使用中遇到问题,欢迎在社区留言。


参考文档

Related Recommendations
Comment
All comments (0)
No data
No data
  • 1
Forums
PINE Language
Get the app
iPhone Download
© 2015 - ∞ INVENTOR PTE LTD (SG)