编程总算有些入门了
最近在学编程,这是一个很好玩的地方,当专注在这上面时候,我发现我所有中年人的焦虑都不见了,没有时间去焦虑;同时我还得很专注地思考,去想如何解决问题。当我专注很长时间,而我编程的目的又达到了的话,这种成就感,不足为外人道也。
起始
22年初时候,人有些无聊,每天就在刷apple store的MBP 16寸,看何时可以入店买到。第一次刷到之后,我的理智制止了我,说已经有一部13年的MBP了,不需要再多一台冗余。错过第一台。错过后就疯狂想要再入,得给自己找个理由。说我需要做编程吧,一个当时自己都不大信的理由,就剁手了。
编程前后
编程其实入手很难,没有人指导,没有明确目标,完全就不知道该做什么。我尝试看廖雪峰的python教程,一开始还成,稍微复杂点就做不下去了,没有短期正反馈的情况,在现在这个信息快餐时代,我是没啥耐心的。
这个时候,我其实维护了一份google sheet,用来评估我的crypto portfolio。它通过一些特定的api,能够抓取我的LP的数据,集合在一起,可以给我直观的感受,哪些需要对冲了,哪些表现如何如何。每一日的心情和portfolio的表现直接相关,赚时候很开心,亏时候就不舒服。但是每天刷时候,有些小问题:
- 开启之前要先刷debank
- 对冲要手动执行
尤其是第二点,当市场巨大波动时候,我的LP平滑向不利仓位变化,而我对冲的仓位不变,短期impermanent loss就会过大,影响挖矿收益。
也入手了MBP,也有了编程目标就直接在干中学吧。我整理了一下,差不多有下面几点是学到的:
- 如何通过request抓取数据
- 抓取数据后,如何整理成dataframe,输出json,符合需要
- 如何从区块链数据中获取我的LP信息
- 如何将数据整理成api链接输出到google sheet
- 数据的储存、更新
- 如何设立自动对冲交易机器人
- 如何后台持续运行python程序,并实时监控
- 如何发送通知
看下来每一步都是环环紧扣的,没有对计算机的热情,任何地方都会让人抓脑袋,直到最终放弃。
起步
抓取数据最开始就是google搜索到一个google sheet上的importjson插件,没有啥了解运行的原理的情况,直接就拿起来用,有了插件,就得有api抓取,刚好需要一直用debank,它们也很巧地提供了api,一边有api,一边有插件就试出来了。但是debank的数据其实是很复杂的嵌套式dict+list,importjson没法做处理,结果就只能简单处理,每次LP变动都会影响到数据的输出,都需要手动调整。
抓取数据最开始就是google搜索到一个google sheet上的importjson插件,没有啥了解运行的原理的情况,直接就拿起来用,有了插件,就得有api抓取,刚好需要一直用debank,它们也很巧地提供了api,一边有api,一边有插件就试出来了。但是debank的数据其实是很复杂的嵌套式dict+list,importjson没法做处理,结果就只能简单处理,每次LP变动都会影响到数据的输出,都需要手动调整。
数据抓取的第二个成功尝试就是前几篇博文中都提到的google frameworks. 我通过这个配合ccxt的ftx, binance api 居然真的可以抓到交易所的数据,用很简单的python条件类型语句,我成功地建立起一个网址,当我访问网址时候,网址就会转为简单的ccxt函数,将抓取的交易所数据返回给输入端,importjson就可以把数据导出到google sheet。
都是很小心的几步,但是我能够建立起编程的信心,也小小地达到编程的成就感。
尝试和试错
交易所数据搞定了,我就希望可以抓取LP池子的数据,说实话,这个很困难,不知道改如何着手。我甚至都忘记了是如何开始的。spooky的池子应该是最早抓取成功的吧。展开之前,要先介绍一下区块和合约的背景。区块链,顾名思义,所有的历史都能在区块上看见。我做流动性挖矿,就是把两个token组队提供到池子里,池子就产生了可以提供swap交换的功能,而我因为提供了流动性可以在swap上获得手续费和池子本身的token奖励。池子运营的好坏,将决定到tvl的总量,total locked value,而这又反过来影响到token的价值。三五人的团队开发一个池子,如果tvl有个10亿美元,他们的token轻而易举可以值数千万美元,除去要分给流动性提供者,他们自己作为团队也是可以留10-20%,这里就有一个好或者坏螺旋的潜力。
话再说回来,所有的数据都可以在链上看到。所以我提供LP的行为可以在区块看到,我需要做的就是以我的钱包地址为基础,去抓取从钱包设立开始所有交易的区块数据。每个有我钱包地址的交易区块,都能看见我在这地址上做了什么,所以如果要计算我提供的LP,只需要把过往所有区块的存款和过往所有区块的提款互相加减得到的净金额就是我需要的数字。
存储区块的历史涉及到啥呢?
- 得会抓取
- 抓取了得会存
- 存好了得能读取
- 不能手动抓吧,python程序是不是得设置一个定时工作类似cron的程序
抓取不难,按照fantomscan给出的api文档,依其要求就可以拉回来。拉回来的数据要如何储存呢?我选择postgresql的docker。postgresql有自己的语法,得,又要开始摸索学习,我有个好处,学会了,比较容易举一反三,融会贯通;但是记性不行,所有东西都会即时记到我私人的笔记软件中。python和postgresql之间的通讯也得学会。这样存取,读取也都搞定了。配合python的schedule的库,这些也都解决了。
LP数据也是一个token,所以还需要对LP进行分析解读,了解这个token在任何时候指向的资产内容是什么。于是就得开始学习分析合约地址区块啥的,得找到LP vault的地址,要知道这个地址hold的资产,要找到发行LP token的总数,这样依照比例我就能知道资产的数据,最后这些数据要导入到google sheet中。
am3CRV的链上数据分析
上面的fantom LP还是比较容易的。夸张的是am3CRV的计算。polygon curve的tricrypto v3的池子当提供LP并stake进去后,curve是会将所有的资产打到对应的vault,amUSDC, amUSDT, amDAI, amWETH, amWBTC. 最搞的是这个vault不是就curve这个池子单独使用,而是和整个aave 池子共享的。资产一进去,你就不知道你的比例,数字了。
最有效的方式就是分析区块交易,找一个sample的交易,拷贝出所有的交易内容。因为链上地址太复杂,有代入的方法缩写成简单的字母,更容易理解。比如,当test地址向a01发出19.88 crvUSD token时,a01收到就提交给genesis地址进行销毁,销毁成功后,b02地址就会向a01地址颁发11079的am3CRV token。a01又把这个token提交给genesis销毁。此时,链上的amUSDT,amUSDC,amDAI就会给a01颁发USDT,USDC和DAI token;而这些合约地址因为vault中的美元资产减少了,他们就要给genesis打入对应的wrapped token进行销毁,保证他们wrapped的token和vault里真正的资产是1:1对应。amWETH和amWBTC也是类似的分析。至此,第一步分析就算完毕。我能知道在一个am3CRV的withdraw交易中,提交存取凭证的token,是如何最终获得真实资产,以及背后的vault以何种机制来销毁凭证,做到资产1:1对应的。是不是很漂亮,在区块链,大家不信任,大家确认。we don't need to trust it, we verify it.
在前述的交易中,很容易找到合约地址持有wbtc vault的资产,将自己地址上的LP除以地址颁发的所有的LP得到的比例ratio去乘以vault下面持有的eth和btc个数,就可以得出你自己地址上持有的币数,而这个数值和网站上的数值是一致到小数点后面8位的,也可以这么说,网站的计算方法我理解是和我使用的方法一致的。
而在找地址对应的稳定币资产时,就困难很多。最后的方式居然是,先计算自己和LP池子的比例;LP池子收到资产自己不拿的,全部放入aave的vault中,所以还要多考虑一个LP池子持有的token占aave池子总token数量的比例,两个比例乘好的结果才可以用来计算vault对应自己的资产。比例算出来,刚刚不是找到三个稳定币合约地址,他们vault下的持仓就是稳定币个数了。
python上的尝试
直到这两日我才知道python有个web3的库,可以通过rpc获得区块数据。这之前,我的做法是通过blockscan的api拉取数据,要计算我的LP个数,很简单,计算我和合约交易中自开始存入多少LP,取出多少LP,相加减得到。觉得很麻烦,但是挡不住数学的美丽。哈哈,而且我通过程序来自动拉取数据,通过postgresql整理,还是不麻烦的。
此外写了一个自动对冲交易的程序,通过我前面的数据积累,每隔60秒跟进我做LP的仓位。比如我持有的FTM-USDC,我不想要FTM的exposure,我就会在交易所对这个仓位进行对冲。以往的对冲都是手动的,一来对冲不及时,人不会一直看市场;二来对冲不全面,impermanent loss问题比较严重;三来对冲时候的价格总是成本更高的价格,为了成交也总是以市场价格进行交易,被迫支付taker的手续费。通过这个程序,我能把上面几点问题都解决,首先只以limit order下单,maker的fee是返点的,相当于交易越多收入越多;每60秒刷新的间隔,可以紧紧跟进价格波动,睡觉也不用管。用了这个,我基本感觉是portfolio的波动变小很多,几个币种的exposure都从原来几千刀缩小成几百刀。portfolio涨不涨另说,但我感觉不必要的成本就省下来不少。
系统的选择
我选择了微软的visual code。编好推送到debian的vps服务器。python的可持续化运行通过supervisor来进行,本来systemdctl也可以,但是supervisor提供了一个网页端直接看当前运行的情况,这个大赞。
小结
在买入MBP之前从未完整意义上看完python的书,但是这次因为有操作目的,向着这个目的推进,然后一路上解决可能碰到的各种问题,当所有问题的解决了,我发现我编程的目的也实现了。干中学真是非常好的学习方式。
下一步,我希望使用react,flask,web3.js来做一个小工具,可以一键收割的那种。