LP 的全称是 Liquidity Provider,也就是流动性提供者。我们平时说“做 LP”,就是把资产放进去中心化交易所的流动性池,供其他人兑换,并从交易中分得手续费。这次做的是集中流动性 LP,可以自己选择提供流动性的价格区间,把资金集中在一段价格附近。价格在区间内运行,就有机会持续收取手续费;价格走出区间,这部分流动性便不再参与当前价格上的交易。对于代币与计价币组成的池子,如果代币一路下跌,仓位里的代币会越来越多,跌穿下限时,可能已经全部变成了代币。LP 其实很早就有了,不过随着链上交易的爆发,这段时间确实热闹,我也有机会下场做了几把。九月份 Robinhood 链比较火爆的时候,随便进一个池子,瞬间都有一笔莫名高额的手续费收益。俗话说,站在风口上,猪都能起飞。不过赚得多,亏得也不少(管不住手啊)。
后来链上的热度逐渐冷却,整体金融市场也比较低迷,正好有机会把之前的操作整理一下。手动挑选标的、建池子、领取收益、止盈止损,这些事情随着发明者新版 DEX 函数的开发,都可以交给程序完成。于是,耗费了大量 token,一版自动选币、自适应管理仓位的 LP 策略就开始折腾起来了。
从排行榜选币开始踩坑
中间当然也走了弯路。我还是按照以前的思路,找最热门的币种,也就是排行榜前几名,让程序去开仓。谁知道碰上的不少都是骗子,刚进去,分钟级别就来个大跳水,跑都来不及,直接跌穿池子下限,喜提上百万枚分文不值的代币。
这件事对 LP 尤其难受。直接买币,跌下来至少还是原来那么多币;做集中流动性,价格下跌的过程中,池子还在不断把计价币换成代币。原本想着一边收手续费,一边等价格波动,结果手续费收了一点,仓位倒是接得满满当当。热门榜上那些漂亮的成交数字,放到自己的钱包里,就完全是另一回事了。
以前写量化策略,通常是选定标的、选定指标,满足条件进场,达到条件出场,已经算一个小型系统化的实现。但这次连标的都需要程序自己选择,入场以后还涉及区间、资金分配、手续费变化和链上执行,单独改一个选币指标,解决不了整个过程的问题。于是,我想到了控制论。
用反馈组织整个 LP 过程
控制论研究的是如何通过反馈调节系统。比如空调设定一个温度,传感器持续读取室温,控制器根据温差调整制冷功率。实际环境会变,控制动作也跟着变。常见的 PID 控制器,就是把这种调节拆成三个部分:
u(t) = Kp·e(t) + Ki·∫e(t)dt + Kd·de(t)/dt
其中,e(t) 是目标值与当前值的偏差,u(t) 是控制器输出的动作。P 是比例项,根据当前偏差调整;I 是积分项,处理一段时间累计下来的偏差;D 是微分项,根据偏差变化的速度作出反应。三个系数决定各部分对控制动作的影响程度。
当然,交易没有空调那么听话,设定一个收益率,市场也不会按照要求把钱送过来。这套策略采用的是反馈控制的思路:把 LP 的资产变化和手续费收入放进模型,模拟不同操作可能带来的结果,再用实际运行数据修正模型。PID 用来理解反馈很直观,程序里的区间和仓位则由收益与风险模型计算。
这里先要统一收益目标。做 LP 收到的手续费,只是整笔交易收入的一部分;仓位里的资产涨跌、换币损耗和 Gas,都要一起计入。系统围绕计入这些影响后的净收益作判断,并给资金使用和亏损设置边界。这样,选币时觉得值得做的机会,到了建仓环节还要经得起实际成本的检验,持仓以后也要接受真实结果的检验。
按这个思路,我把整个过程分成了五层:选币、选池子、建仓、监控、撤离。
第一层:选币
选币先解决哪些币值得拿来做 LP。
热门排行榜仍然有用,它能提供一个不断更新的候选范围。但经过前面那几次大跳水,我已经不想让排名直接决定开仓了。成交活跃只是起点,还要结合代币安全、交易历史和价格稳定性,判断眼前的成交有没有参与的价值。对于 LP 来说,一个币短时间涨得很猛,未必比一个交易持续、波动相对平稳的币更合适。
这一层会把预期手续费和价格波动造成的库存损耗放在一起比较。手续费高,意味着有收入来源;波动太剧烈,又可能在很短时间内吃掉这些收入。选币就是先从大量候选里缩小范围,把资金更适合参与的对象交给后面计算。扫描结果和否决原因也会留下来,状态栏里能看到程序这一轮在研究什么,哪些币被筛掉了。

选币扫描实截图:成交活跃的币,仍可能因手续费不足以覆盖模型估计的损耗、交易历史不足或短时回撤过大而被筛掉。
第二层:选池子
同一个币,往往有不同交易对、不同费率的池子,选中了币还没有解决资金放在哪里的问题。
最容易产生误判的地方,是直接拿币种总成交量估算自己能赚多少手续费。交易可能主要发生在另一个池子里;即使选中了成交最大的池子,也可能有大量流动性在共同分账。费率高低、池子成交和竞争资金,需要放在一起看。
发明者的 DEX 接口可以直接列出候选池:
javascript
var pools = exchange.IO("lp.pools", BASE, QUOTE);
程序拿到这些池子后,再逐个比较。对于集中流动性,还要关注当前价格附近真正参与交易的活跃流动性,因为池子里总共有多少钱,与当前这一笔交易由多少资金共同承接,并不是同一个数。这个区别会影响我方手续费份额的估计,也会影响后面应该投入多少资金。
所以,选池这一层是在给模型确定具体的交易环境。前面筛出来的币,到了这里如果找不到合适的池子,同样不会继续开仓。币和池子的判断分开以后,策略就不用把“这个币很热”和“这个池子值得投钱”混为一谈。
第三层:建仓
建仓是模拟 LP 过程最集中的地方。手动做的时候,区间很容易凭感觉来定。挂窄一点,资金集中,可能分到更多手续费,但价格稍微一动就跑出去了;挂宽一点,可以容纳更大的波动,资金利用效率又会下降。投入金额也会影响结果,小仓位容易被固定 Gas 吃掉,大仓位则可能增加换币冲击,手续费份额也不会始终随着本金等比例增长。
我把这些取舍放进同一个模型里计算。程序根据近期价格数据生成多条可能的价格路径,模拟在不同区间、不同投入金额下,仓位里的资产会如何变化、能够收取多少手续费,最后退出需要付出多少成本。这样得到的是一组可能结果,可以据此比较收益和风险,再选择区间与仓位。
这里模拟的是 LP 的实际运作过程。价格走到哪里,两种资产各剩多少,资金还有多少时间处在有效区间内,都与最终收益有关。如果只模拟币价涨跌,再额外加一个固定手续费收益,很多集中流动性的特征就丢掉了。
模型选出方案后,再由 DEX 函数生成建仓计划并执行:
javascript
var plan = exchange.IO("lp.plan", {
symbol: SYMBOL,
budget: budget,
range: {pct: rg.pct},
shape: "spot",
layers: LAYERS,
pool: pool.id,
slippage: LP_SLIPPAGE
});
var opened = exchange.IO("lp.add", plan);
lp.plan 把资金预算、区间和池子转成建仓计划,lp.add 负责执行。策略模型与链上操作在这里接上:前面计算的结果,要能变成实际仓位,后续反馈才有对象。
对于缺少实测记录的币,程序会先以较小的资金试探,再根据积累的数据调整后续投入。缩小仓位以后,成本也要重新计算,避免理论方案看着不错,实际只投了一点钱,手续费还没有覆盖进出场费用。这些计算结果会呈现在建仓判断中,方便检查区间和金额的依据。
第四层:监控
仓位建好以后,反馈控制开始持续发挥作用。入场前使用的手续费数据,多少带有外推的成分。过去一段时间成交热闹,不代表接下来同样热闹;其他人的资金进入池子,也会改变自己的分成。程序需要不断读取实际仓位,将已经收到的手续费与原来的预测进行比较。
javascript
var positions = exchange.IO("lp.positions", SYMBOL);
如果实际手续费持续低于预期,模型就下调后续估计。随着本币实测记录增加,建仓时借用的经验估计也会逐渐让位于实际表现。这些记录会保留下来,供后续决策继续使用,同一个币再次进入候选时,程序已经有了之前参与过的经验。
监控还包括重新评估当前区间。价格移动以后,原区间是否仍然合适,继续持有能否覆盖风险,换一个区间是否值得付出重新交易的成本,都需要结合最新状态计算。程序会比较继续持有、换区间和退出几种处理方式,但不会看到一次短暂变化就立即执行。链上调整有成本,控制频率太高,很容易把本来能留下的手续费消耗掉。
第五层:撤离
撤离负责把这一轮 LP 真正结束掉。正常撤离来自收益判断的变化,例如交易热度下降以后,继续持有已经没有足够吸引力,或者价格离开区间,重新建仓也不划算。这类退出可以留出一定确认时间,减少反复进出的消耗。涉及合约异常、池子流动性骤降、亏损触线时,外层风控则直接介入,不再等待收益判断慢慢确认。
执行上,撤出流动性和卖掉代币要连起来处理:
javascript
var closed = exchange.IO("lp.remove", ids, 1, true);
这里要求撤出全部流动性,并卖回计价币。不过链上操作可能分成多笔交易,撤池成功之后还要核对钱包,确认代币是否已经卖出。仍有残留就继续处理,卖不掉则报警。前面已经体验过拿着上百万枚代币的感觉,这一步自然得认真做。
退出结果也会回到系统里。每轮实际赚了多少手续费、资产变化带来多少盈亏、交易花了多少成本,都会形成记录。历史轮次和币种记录因此有了用处:可以检查某类机会是否长期被高估,也能发现频繁换区间是否值得。下一轮选币和建仓,继续参考这些已经发生的结果。
五层接起来以后,程序便能从候选发现一直处理到资金退出。市场变化进入模型,模型生成操作,链上执行产生新的仓位和收益数据,再回到下一轮计算。发明者新版 DEX 函数省下了不少基础操作的开发工作,让精力可以更多放在这套决策和反馈过程上。
这两天的使用感受
用下来比较直观的感受,是原来需要自己来回翻榜单、查池子、算收益的过程,现在可以集中在状态栏和日志栏里观察。状态栏看当前处在哪个阶段、资金和仓位是什么情况,日志栏则把具体判断按时间留下来。从选币、选池、建仓,到持仓期间的调整和最后撤离,整个策略过程都有记录可查。
比如这次日志里,CRCL 通过了选币筛选,程序也比较了它的池子,但按实际仓位重新计算以后,风险调整收益没有达到入场要求,最后没有建仓。把前后几条日志连起来看,就能明白它停在哪一步。以后调整模型,也能沿着这些记录查找原因。
经过这两天测试,这版程序已经能从候选里挑选出相对稳健的币种,并根据池子和行情进行合理建仓。趁着现在链上没那么热,把这套流程慢慢打磨好,希望下一个链上火热的时候,手里已经准备好了一个好用的工具。
- 1





