From ed50381d9818b293ef61490c377008ff585ac803 Mon Sep 17 00:00:00 2001 From: sklbancor <109073706+sklbancor@users.noreply.github.com> Date: Fri, 3 May 2024 23:17:16 +0100 Subject: [PATCH] NBTest 102 --- resources/NBTest/NBTest_102_APIBasics.ipynb | 1403 +++++++++++++++++++ resources/NBTest/NBTest_102_APIBasics.py | 102 +- 2 files changed, 1499 insertions(+), 6 deletions(-) create mode 100644 resources/NBTest/NBTest_102_APIBasics.ipynb diff --git a/resources/NBTest/NBTest_102_APIBasics.ipynb b/resources/NBTest/NBTest_102_APIBasics.ipynb new file mode 100644 index 000000000..92864ef97 --- /dev/null +++ b/resources/NBTest/NBTest_102_APIBasics.ipynb @@ -0,0 +1,1403 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "cc40bc23-abde-4094-abec-419f0a7fa81e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "imported m, np, pd, plt, os, sys, decimal; defined iseq, raises, require, Timer\n", + "CurveBase v1.0 (23/Jan/2024)\n", + "ConstantProductCurve v4.0-alpha02 (04/May/2024)\n", + "CurveContainer v4.0-alpha02 (04/May/2024)\n", + "MargPOptimizer v6.0-alpha02 (04/May/2024)\n" + ] + } + ], + "source": [ + "try:\n", + " from fastlane_bot.tools.cpc import CurveBase, ConstantProductCurve as CPC, CurveContainer\n", + " from fastlane_bot.tools.optimizer import MargPOptimizer\n", + " from fastlane_bot.testing import *\n", + "\n", + "except:\n", + " from tools.cpc import CurveBase, ConstantProductCurve as CPC, CurveContainer\n", + " from tools.optimizer import MargPOptimizer\n", + " from tools.testing import *\n", + "\n", + "ConstantProductCurve = CPC\n", + "\n", + "#from io import StringIO\n", + "import types\n", + "import math as m\n", + "\n", + "print(\"{0.__name__} v{0.__VERSION__} ({0.__DATE__})\".format(CurveBase))\n", + "print(\"{0.__name__} v{0.__VERSION__} ({0.__DATE__})\".format(CPC))\n", + "print(\"{0.__name__} v{0.__VERSION__} ({0.__DATE__})\".format(CurveContainer))\n", + "print(\"{0.__name__} v{0.__VERSION__} ({0.__DATE__})\".format(MargPOptimizer))\n", + "\n", + "#plt.style.use('seaborn-dark')\n", + "#plt.rcParams['figure.figsize'] = [12,6]\n", + "# from fastlane_bot import __VERSION__\n", + "# require(\"3.0\", __VERSION__)" + ] + }, + { + "cell_type": "markdown", + "id": "b3f59f14-b91b-4dba-94b0-3d513aaf41c7", + "metadata": {}, + "source": [ + "# API Basics [NBTest102]\n", + "\n", + "This notebook describes API features of the Optimizer library. Everything contained in this notebook's tests here should be considered stable, and breaking changes will only ever happen a major version number increases" + ] + }, + { + "cell_type": "markdown", + "id": "3971ba2d-7ba3-4bff-a54e-82a94152232d", + "metadata": {}, + "source": [ + "## CurveBase ConstantProductCurve CPC CurveContainer\n", + "\n", + "The `CurveBase` object is the base class of all curve objects fed into the optimizer. Currently only the `ConstantProductCurve` object -- typically imported as `CPC` -- is providing an actual implementation for that class, and it can only describe (or approximate) constant product curves." + ] + }, + { + "cell_type": "markdown", + "id": "e56487dc-5dd5-451a-9e4b-268b60f44d85", + "metadata": {}, + "source": [ + "### CurveBase" + ] + }, + { + "cell_type": "markdown", + "id": "22493f6c-e961-4d3d-99c5-a37a410ec897", + "metadata": {}, + "source": [ + "assert that certain functions exist on `CurveBase`" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "51ac566e-7e52-4ce4-a889-e7885558f044", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "assert isinstance(CurveBase.dxvecfrompvec_f, types.FunctionType)\n", + "assert isinstance(CurveBase.xvecfrompvec_f, types.FunctionType)\n", + "assert isinstance(CurveBase.invariant, types.FunctionType)" + ] + }, + { + "cell_type": "markdown", + "id": "8b7a58c8-711b-48ea-9f67-4c11f4f283ca", + "metadata": {}, + "source": [ + "assert that CurveBase cannot be instantiated with one of the functions missing" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "260e9ab0-9fa1-481f-948c-cf7ab21db31e", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "assert raises(CurveBase)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "03c4a6d1-265f-4b87-b426-c5f9a3b6033c", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "class Curve(CurveBase):\n", + " def dxvecfrompvec_f(self, pvec, *, ignorebounds=False):\n", + " ...\n", + " def xvecfrompvec_f(self, pvec, *, ignorebounds=False):\n", + " ...\n", + " # def invariant(self, include_target=False): \n", + " # ...\n", + "assert raises(Curve)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "dedf5019-6797-458f-b34a-418d4fb78490", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "class Curve(CurveBase):\n", + " def dxvecfrompvec_f(self, pvec, *, ignorebounds=False):\n", + " ...\n", + " # def xvecfrompvec_f(self, pvec, *, ignorebounds=False):\n", + " # ...\n", + " def invariant(self, include_target=False): \n", + " ...\n", + "assert raises(Curve)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "f57dc72c-1ea4-441c-93b5-a011b53e0431", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "class Curve(CurveBase):\n", + " # def dxvecfrompvec_f(self, pvec, *, ignorebounds=False):\n", + " # ...\n", + " def xvecfrompvec_f(self, pvec, *, ignorebounds=False):\n", + " ...\n", + " def invariant(self, include_target=False): \n", + " ...\n", + "assert raises(Curve)" + ] + }, + { + "cell_type": "markdown", + "id": "51e22e2a-68cb-460e-9fb2-01ac5cb280dc", + "metadata": {}, + "source": [ + "### ConstantProductCurve" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "70d2d955-0a8f-4d2e-bb54-1bfb39f378bd", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "p = dict(foo=1, bar=2, baz=3)\n", + "kwargs = dict(pair=\"TKNB/TKNQ\", cid=\"c_cid\", descr=\"des\", fee=0.005, params=p)" + ] + }, + { + "cell_type": "markdown", + "id": "70a9e00f-6475-427b-ba55-c734f690cc35", + "metadata": {}, + "source": [ + "#### unlevered generic constructors" + ] + }, + { + "cell_type": "markdown", + "id": "a49272ce-ebe2-478d-9d74-85cf45fa8b0a", + "metadata": { + "tags": [] + }, + "source": [ + "the `from_pk` constructor takes a price `p` and a constant `k`" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "41200a28-3176-4aa8-9c00-1a0b6e37320d", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "c = CPC.from_pk(10, 10*1*25**2, **kwargs)\n", + "assert raises(CPC.from_pk, 10, 10*1*10**2, 10)\n", + "assert iseq(c.p, 10)\n", + "assert iseq(c.x, 25)\n", + "assert iseq(c.x, c.x_act)\n", + "assert iseq(c.y, 250)\n", + "assert iseq(c.y, c.y_act)\n", + "assert iseq(c.k, 6250)\n", + "assert c.pair == \"TKNB/TKNQ\"\n", + "assert c.cid == \"c_cid\"\n", + "assert c.descr == \"des\"\n", + "assert c.fee == 0.005\n", + "assert c.params == p" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "92452ee0-38a9-4bc5-9f09-580914637481", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'ConstantProductCurve.from_pk() takes 3 positional arguments but 4 were given'" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "raises(CPC.from_pk, 10, 10*1*10**2, 10)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "477b3601-4b16-47f3-bffe-0c094cd8579b", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "c1 = CPC.from_kx(c.k, c.x, **kwargs)\n", + "assert CPC.from_kx(k=c.k, x=c.x, **kwargs) == c1\n", + "assert raises(CPC.from_kx, 10, 10*1*10**2, 10)\n", + "assert iseq(c1.p, c.p)\n", + "assert iseq(c1.x, c.x)\n", + "assert iseq(c1.x_act, c.x_act)\n", + "assert iseq(c1.y, c.y)\n", + "assert iseq(c1.y_act, c.y_act)\n", + "assert iseq(c1.k, c.k)\n", + "assert c1.pair == c1.pair\n", + "assert c1.cid == c1.cid\n", + "assert c1.descr == c1.descr\n", + "assert c.fee == c1.fee\n", + "assert c1.params == c1.params" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "1fe29598-0cd0-46bb-a8bf-6e568001a653", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "c1 = CPC.from_ky(c.k, c.y, **kwargs)\n", + "assert CPC.from_ky(k=c.k, y=c.y, **kwargs) == c1\n", + "assert raises(CPC.from_ky, 10, 10*1*10**2, 10)\n", + "assert iseq(c1.p, c.p)\n", + "assert iseq(c1.x, c.x)\n", + "assert iseq(c1.x_act, c.x_act)\n", + "assert iseq(c1.y, c.y)\n", + "assert iseq(c1.y_act, c.y_act)\n", + "assert iseq(c1.k, c.k)\n", + "assert c1.pair == c1.pair\n", + "assert c1.cid == c1.cid\n", + "assert c1.descr == c1.descr\n", + "assert c.fee == c1.fee\n", + "assert c1.params == c1.params" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "cc1a3920-6b6d-4c30-a034-175f3f977b79", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "c1 = CPC.from_xy(c.x, c.y, **kwargs)\n", + "assert CPC.from_xy(x=c.x, y=c.y, **kwargs) == c1\n", + "assert raises(CPC.from_xy, 10, 10*1*10**2, 10)\n", + "assert iseq(c1.p, c.p)\n", + "assert iseq(c1.x, c.x)\n", + "assert iseq(c1.x_act, c.x_act)\n", + "assert iseq(c1.y, c.y)\n", + "assert iseq(c1.y_act, c.y_act)\n", + "assert iseq(c1.k, c.k)\n", + "assert c1.pair == c1.pair\n", + "assert c1.cid == c1.cid\n", + "assert c1.descr == c1.descr\n", + "assert c.fee == c1.fee\n", + "assert c1.params == c1.params" + ] + }, + { + "cell_type": "markdown", + "id": "38c3130c-3e93-4c9d-b568-652c52abc232", + "metadata": { + "tags": [] + }, + "source": [ + "#### levered generic constructors" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "424fdcc2-d764-4d3e-9d8a-5870af35cd64", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "c = CPC.from_pkpp(10, 10*1*25**2, 8, 12, **kwargs)\n", + "assert raises(CPC.from_pkpp, 10, 10*1*10**2, 8, 12, 10)\n", + "assert iseq(c.p, 10)\n", + "assert iseq(c.p_min, 8)\n", + "assert iseq(c.p_max, 12)\n", + "assert iseq(c.x, 25)\n", + "assert iseq(c.x_act, 2.1782267706180782)\n", + "assert iseq(c.y, 250)\n", + "assert iseq(c.y_act, 26.393202250021034)\n", + "assert iseq(c.k, 6250)\n", + "assert c.pair == \"TKNB/TKNQ\"\n", + "assert c.cid == \"c_cid\"\n", + "assert c.descr == \"des\"\n", + "assert c.fee == c1.fee\n", + "assert c.params == p" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "ab6f7df7-f8f8-422a-9664-5ca57617ff2c", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "c1 = CPC.from_kx(c.k, c.x, x_act=c.x_act, y_act = c.y_act, **kwargs)\n", + "assert iseq(c1.p, c.p)\n", + "assert iseq(c1.x, c.x)\n", + "assert iseq(c1.x_act, c.x_act)\n", + "assert iseq(c1.y, c.y)\n", + "assert iseq(c1.y_act, c.y_act)\n", + "assert iseq(c1.k, c.k)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "5c773ae9-c968-4f1b-9816-935a1ba55883", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "c1 = CPC.from_ky(c.k, c.y, x_act=c.x_act, y_act = c.y_act, **kwargs)\n", + "assert iseq(c1.p, c.p)\n", + "assert iseq(c1.x, c.x)\n", + "assert iseq(c1.x_act, c.x_act)\n", + "assert iseq(c1.y, c.y)\n", + "assert iseq(c1.y_act, c.y_act)\n", + "assert iseq(c1.k, c.k)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "a289614e-5f97-4bd4-8609-f9e069c89e1e", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "c1 = CPC.from_xy(c.x, c.y, x_act=c.x_act, y_act = c.y_act, **kwargs)\n", + "assert iseq(c1.p, c.p)\n", + "assert iseq(c1.x, c.x)\n", + "assert iseq(c1.x_act, c.x_act)\n", + "assert iseq(c1.y, c.y)\n", + "assert iseq(c1.y_act, c.y_act)\n", + "assert iseq(c1.k, c.k)" + ] + }, + { + "cell_type": "markdown", + "id": "4fcfaef5-66ee-4e66-8bd1-f53e0a5bd6a5", + "metadata": {}, + "source": [ + "#### Carbon constructor\n", + "\n", + "note: the Carbon constructor takes _only_ keyword arguments" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "971e0f98-03b0-4fb9-9ca7-9f329d1df81f", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "assert raises(CPC.from_carbon, 1)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "6170a94f-a0ad-4292-b8ce-eb7941cdbafc", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "pa, pb = 12, 8 # USDC per LINK\n", + "yint = y = 25 # LINK" + ] + }, + { + "cell_type": "markdown", + "id": "7b3071cb-cd87-403d-a4ba-c927e651710e", + "metadata": {}, + "source": [ + "with prices, `tkny` is the quote token (USDC)\n", + "\n", + "_note: isdydx does not matter because dy per dx is same as tknq per tknb_" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "ae8a9711-0988-477d-91fa-c6f912ba3f39", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "c = CPC.from_carbon(pair=\"LINK/USDC\", tkny=\"USDC\", yint=yint, y=y, pa=pa, pb=pb, isdydx=False)\n", + "c2 = CPC.from_carbon(pair=\"LINK/USDC\", tkny=\"USDC\", yint=yint, y=y, pa=pa, pb=pb, isdydx=True)\n", + "assert c.pair == \"LINK/USDC\"\n", + "assert c2 == c\n", + "assert iseq(c.p_max, pa)\n", + "assert iseq(c.p_min, pb)\n", + "assert iseq(c.p, c.p_max)\n", + "assert iseq(c.x_act, 0)\n", + "assert iseq(c.y_act, yint)\n", + "assert iseq(c.x, 11.353103630798294)\n", + "assert iseq(c.y, 136.23724356957953)\n", + "assert iseq(c.y/c.x, pa)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "44ebc661-00ca-4e31-af33-532d36bf8685", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "dx, dy, p_ = c.dxdyfromp_f(p=c.p_min)\n", + "dxvec = c.dxvecfrompvec_f(pvec=dict(LINK=p_, USDC=1))\n", + "assert iseq(dx, yint/m.sqrt(pa*pb))\n", + "assert iseq(dy, -yint)\n", + "assert iseq(p_, c.p_min)\n", + "assert iseq(dxvec[\"USDC\"], dy)\n", + "assert iseq(dxvec[\"LINK\"], dx)" + ] + }, + { + "cell_type": "markdown", + "id": "39f30da0-8182-43ba-a88f-4f970afabe18", + "metadata": { + "tags": [] + }, + "source": [ + "same, but with A,B (A = sqrt(pa)-sqrt(pb), B = sqrt(pb), pa > pb in dy/dx)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "46b265c3-d9d3-4185-ba95-48279e6a3ac3", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "A = m.sqrt(pa)-m.sqrt(pb)\n", + "B = m.sqrt(pb)\n", + "c1 = CPC.from_carbon(pair=\"LINK/USDC\", tkny=\"LINK\", yint=yint, y=y, A=A, B=B)\n", + "assert iseq(c1.p_max, c.p_max)\n", + "assert iseq(c1.p_min, c.p_min)\n", + "assert iseq(c1.p, c.p)" + ] + }, + { + "cell_type": "markdown", + "id": "dfe32f7b-1097-46f0-9b8a-d93bfef8c685", + "metadata": {}, + "source": [ + "with prices, `tkny` is the base token (LINK)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "7d906756-caf5-47bb-b2b3-2e94e2f0a1fb", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(0.125, 0.08333333333333333, 200.0)" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pa_ = 1/pb\n", + "pb_ = 1/pa\n", + "yint_ = y_ = yint / pa_\n", + "pa_, pb_, yint_" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "abec0ce8-601a-4958-9c05-11e441a9c956", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "c = CPC.from_carbon(pair=\"LINK/USDC\", tkny=\"LINK\", yint=yint_, y=y_, pa=pa_, pb=pb_, isdydx=True)\n", + "c2 = CPC.from_carbon(pair=\"LINK/USDC\", tkny=\"LINK\", yint=yint_, y=y_, pa=pb, pb=pa, isdydx=False)\n", + "assert c.pair == \"USDC/LINK\"\n", + "assert c2.pair == c.pair \n", + "assert iseq(c.p_max, pa_)\n", + "assert iseq(c2.p_max, c.p_max)\n", + "assert iseq(c.p_min, pb_)\n", + "assert iseq(c2.p_min, c.p_min)\n", + "assert iseq(c.p, c.p_max)\n", + "assert iseq(c2.p, c2.p_max)\n", + "assert iseq(c.x_act, 0)\n", + "assert iseq(c2.x_act, c.x_act)\n", + "assert iseq(c.y_act, yint_)\n", + "assert iseq(c2.y_act, c.y_act)\n", + "assert iseq(c.x, 8719.18358845308)\n", + "assert iseq(c2.x, c.x)\n", + "assert iseq(c.y, 1089.897948556635)\n", + "assert iseq(c2.y, c.y)\n", + "assert iseq(c.y/c.x, pa_)\n", + "assert iseq(c2.y/c2.x, pa_)" + ] + }, + { + "cell_type": "markdown", + "id": "a28239aa-b503-4e0a-bfcb-3180738e92d6", + "metadata": {}, + "source": [ + "#### Uniswap v2 constructor" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "f53cc512-f528-42d0-99d4-c7cede82c785", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "kwargs = dict(pair=\"LINK/USDC\", descr=\"des\", cid=\"cid\", fee=0.005, params=p)" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "b45b2201-ab52-4f5e-b484-1a9fd32e262e", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "c = CPC.from_univ2(x=10, y=20, **kwargs)\n", + "assert iseq(c.x, 10)\n", + "assert iseq(c.y, 20)\n", + "assert iseq(c.k, c.x*c.y)\n", + "assert c.pair == kwargs[\"pair\"]\n", + "assert c.descr == kwargs[\"descr\"]\n", + "assert c.cid == kwargs[\"cid\"]\n", + "assert c.fee == kwargs[\"fee\"]\n", + "assert c.params == kwargs[\"params\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "33f9d7f4-e50e-4be2-90fb-181aaa9d43cf", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "c1 = CPC.from_univ2(x=c.x, k=c.k, **kwargs)\n", + "assert iseq(c1.x, c.x)\n", + "assert iseq(c1.y, c.y)\n", + "assert iseq(c1.k, c.k)" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "303d06fc-d9ee-438e-8e22-0aa13d450c76", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "c2 = CPC.from_univ2(y=c.y, k=c.k, **kwargs)\n", + "assert iseq(c2.x, c.x)\n", + "assert iseq(c2.y, c.y)\n", + "assert iseq(c2.k, c.k)" + ] + }, + { + "cell_type": "markdown", + "id": "c40daefb-9348-4fe7-9708-85188d05a33b", + "metadata": {}, + "source": [ + "#### Uniswap v3 constructor" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "5595ed0d-c56d-47af-bebe-b68180365ddd", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# TODO" + ] + }, + { + "cell_type": "markdown", + "id": "966de7fd-130a-4c35-b665-833f4a833173", + "metadata": {}, + "source": [ + "### CurveContainer\n", + "\n", + "A `CurveContainer` (legacy name: `CPCContainer`) is a container object for curve objects (`CurveBase` derivatives)" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "b1d38195-171c-4363-9477-b9ed8735b6e5", + "metadata": {}, + "outputs": [], + "source": [ + "# TODO" + ] + }, + { + "cell_type": "markdown", + "id": "61c1f220-2d54-4141-9de7-edf75ba94d7e", + "metadata": {}, + "source": [ + "## MargPOptimizer" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "03765e57-a600-4dfe-9b5a-bdffa9693f41", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "CC = CurveContainer([\n", + " CPC.from_pk(pair=\"LINK/USDC\", p=10, k = 10*250_000**2, cid=\"c10\"),\n", + " CPC.from_pk(pair=\"LINK/USDC\", p=12, k = 10*250_000**2, cid=\"c12\"),\n", + "])\n", + "pstart = dict(LINK=10.3, USDC=1)" + ] + }, + { + "cell_type": "markdown", + "id": "9403f6d4-01fe-4f9f-b82e-80fecd6c628b", + "metadata": {}, + "source": [ + "### Running the optimizer" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "76bc7020-7552-49e1-bcd1-8487c8114557", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "CPCArbOptimizer.MargpOptimizerResult(result=-10868.538042440545, time=0.0003840923309326172, method='margp', targettkn='USDC', p_optimal_t=(10.931723975202656,), dtokens_t=(-2.9103830456733704e-11,), tokens_t=('LINK',), errormsg=None)" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "O = MargPOptimizer(CC)\n", + "r = O.optimize(\"USDC\")\n", + "assert not r.is_error\n", + "assert r.errormsg is None\n", + "assert iseq(r.result, -10868.538042440545)\n", + "assert iseq(r.p_optimal_t[0], 10.931723975214778)\n", + "assert r.method == 'margp'\n", + "assert r.targettkn == \"USDC\"\n", + "assert r.time > 0\n", + "r" + ] + }, + { + "cell_type": "markdown", + "id": "c7c74040-e8ef-4401-80d7-9cfea30a99e2", + "metadata": {}, + "source": [ + "#### pstart" + ] + }, + { + "cell_type": "markdown", + "id": "93a5fa01-e5bc-43e2-9b97-a658ecf5fa5c", + "metadata": {}, + "source": [ + "pstart must be a kwarg if provided" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "0defc16c-8434-4e53-93ce-e13d4d01567e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'MargPOptimizer.optimize() takes from 1 to 2 positional arguments but 3 were given'" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "assert raises(O.optimize, \"USDC\", pstart)\n", + "assert not raises(O.optimize, \"USDC\")\n", + "assert not raises(O.optimize, \"USDC\", pstart=pstart)\n", + "raises(O.optimize, \"USDC\", pstart)" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "e9c30b78-c170-4a44-9dab-8bb1b464f3bf", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "CPCArbOptimizer.MargpOptimizerResult(result=-10868.538042440545, time=0.0003368854522705078, method='margp', targettkn='USDC', p_optimal_t=(10.931723975202656,), dtokens_t=(-2.9103830456733704e-11,), tokens_t=('LINK',), errormsg=None)" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "r1 = O.optimize(\"USDC\", pstart=pstart)\n", + "assert iseq(r.result, r1.result, eps=1e-3)\n", + "assert iseq(r.p_optimal_t[0], r1.p_optimal_t[0], eps=1e-3)\n", + "r1" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "75dbb028-5e30-4cae-b7b5-3c5dcf1184b8", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'pstart must not be in params dict if pstart is provided as argument'" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "assert raises(O.optimize, \"USDC\", pstart=pstart, params=dict(pstart=pstart))\n", + "raises(O.optimize, \"USDC\", pstart=pstart, params=dict(pstart=pstart))" + ] + }, + { + "cell_type": "markdown", + "id": "c7c7f638-8dea-4625-b950-ac986b37fd77", + "metadata": {}, + "source": [ + "### Trade instructions" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "bd25a42e-f325-43b3-a7aa-c04cfdb14103", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "O = MargPOptimizer(CC)\n", + "r = O.optimize(\"USDC\")\n", + "assert len(r.trade_instructions()) == 2\n", + "assert r.trade_instructions() == r.trade_instructions(O.TIF_OBJECTS) " + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "e99d026a-9ed6-4157-8557-7c171a5f7d46", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(CPCArbOptimizer.TradeInstruction(cid='c10', tknin='USDC', amtin=113872.12474169489, tknout='LINK', amtout=-10891.133853090403, error=None),\n", + " CPCArbOptimizer.TradeInstruction(cid='c12', tknin='LINK', amtin=10891.133853090374, tknout='USDC', amtout=-124740.66278413543, error=None))" + ] + }, + "execution_count": 36, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ti = r.trade_instructions(O.TIF_OBJECTS)\n", + "assert len(ti) == 2\n", + "assert isinstance(ti[0], O.TradeInstruction)\n", + "assert set(tin.cid for tin in ti) == {\"c10\", \"c12\"}\n", + "assert set(tin.tknin for tin in ti) == {\"USDC\", \"LINK\"}\n", + "assert set(tin.tknout for tin in ti) == {\"USDC\", \"LINK\"}\n", + "ti" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "2c8dda8a-ce06-41af-854d-f2c51a550992", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "CPCArbOptimizer.TradeInstruction(cid='c10', tknin='USDC', amtin=113872.12474169489, tknout='LINK', amtout=-10891.133853090403, error=None)" + ] + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ti0 = [tin for tin in ti if tin.cid==\"c10\"][0]\n", + "assert ti0.cid == \"c10\"\n", + "assert ti0.tknin == \"USDC\"\n", + "assert iseq(ti0.amtin, 113872.12474169489)\n", + "assert ti0.tknout == \"LINK\"\n", + "assert iseq(ti0.amtout, -10891.133853090403)\n", + "assert ti0.error is None\n", + "ti0" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "id": "f829f99e-acbb-4c62-b813-34923783178f", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
pairpairptknintknoutUSDCLINK
cid
c10LINK/USDCLINK/USDCUSDCLINK113872.124742-10891.133853
c12LINK/USDCLINK/USDCLINKUSDC-124740.66278410891.133853
\n", + "
" + ], + "text/plain": [ + " pair pairp tknin tknout USDC LINK\n", + "cid \n", + "c10 LINK/USDC LINK/USDC USDC LINK 113872.124742 -10891.133853\n", + "c12 LINK/USDC LINK/USDC LINK USDC -124740.662784 10891.133853" + ] + }, + "execution_count": 38, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ti = r.trade_instructions(O.TIF_DFRAW)\n", + "assert len(ti) == 2\n", + "assert set(ti.index) == {'c10', 'c12'}\n", + "assert set(ti.pair) == {'LINK/USDC'}\n", + "assert set(ti.pairp) == {'LINK/USDC'}\n", + "assert set(ti.tknin) == {'LINK', 'USDC'}\n", + "assert set(ti.tknout) == {'LINK', 'USDC'}\n", + "ti" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "id": "db5e270b-1d77-450a-bb9e-1331ca3ed208", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "pair LINK/USDC\n", + "pairp LINK/USDC\n", + "tknin USDC\n", + "tknout LINK\n", + "USDC 113872.124742\n", + "LINK -10891.133853\n", + "Name: c10, dtype: object" + ] + }, + "execution_count": 39, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ti0 = ti.loc[\"c10\"]\n", + "assert ti0[\"pair\"] == \"LINK/USDC\"\n", + "assert ti0[\"pairp\"] == \"LINK/USDC\"\n", + "assert ti0[\"tknin\"] == \"USDC\"\n", + "assert iseq(ti0[\"USDC\"], 113872.124742)\n", + "assert ti0[\"tknout\"] == \"LINK\"\n", + "assert iseq(ti0[\"LINK\"], -10891.133853)\n", + "ti0" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "id": "c6e56e39-1cef-45c1-8cf2-91bcd86a4561", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
pairpairptknintknoutUSDCLINK
cid
c10LINK/USDCLINK/USDCUSDCLINK113872.124742-10891.133853
c12LINK/USDCLINK/USDCLINKUSDC-124740.66278410891.133853
\n", + "
" + ], + "text/plain": [ + " pair pairp tknin tknout USDC LINK\n", + "cid \n", + "c10 LINK/USDC LINK/USDC USDC LINK 113872.124742 -10891.133853\n", + "c12 LINK/USDC LINK/USDC LINK USDC -124740.662784 10891.133853" + ] + }, + "execution_count": 40, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "r.trade_instructions(O.TIF_DF8)" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "id": "52212fd5-fe6d-4f05-b4cd-f5f8501b9666", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
USDCLINK
c10113872.124742-1.089113e+04
c12-124740.6627841.089113e+04
PRICE1.0000001.093172e+01
AMMIn113872.1247421.089113e+04
AMMOut-124740.662784-1.089113e+04
TOTAL NET-10868.538042-2.910383e-11
\n", + "
" + ], + "text/plain": [ + " USDC LINK\n", + "c10 113872.124742 -1.089113e+04\n", + "c12 -124740.662784 1.089113e+04\n", + "PRICE 1.000000 1.093172e+01\n", + "AMMIn 113872.124742 1.089113e+04\n", + "AMMOut -124740.662784 -1.089113e+04\n", + "TOTAL NET -10868.538042 -2.910383e-11" + ] + }, + "execution_count": 41, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "r.trade_instructions(O.TIF_DFAGGR)" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "id": "18809816-75c7-4af0-820f-26d692234e0e", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
feepairamt_tknqtknqmargp0effpmargpgain_rgain_tknqgain_ttkn
exchcid
NaNc12NoneLINK/USDC-124740.662784USDC12.011.45341410.9317240.0477235952.9434535952.943453
c10NoneLINK/USDC113872.124742USDC10.010.45548810.9317240.0435654960.7862114960.786211
\n", + "
" + ], + "text/plain": [ + " fee pair amt_tknq tknq margp0 effp margp \\\n", + "exch cid \n", + "NaN c12 None LINK/USDC -124740.662784 USDC 12.0 11.453414 10.931724 \n", + " c10 None LINK/USDC 113872.124742 USDC 10.0 10.455488 10.931724 \n", + "\n", + " gain_r gain_tknq gain_ttkn \n", + "exch cid \n", + "NaN c12 0.047723 5952.943453 5952.943453 \n", + " c10 0.043565 4960.786211 4960.786211 " + ] + }, + "execution_count": 42, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "r.trade_instructions(O.TIF_DFPG)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5de61457-828c-48fc-a5dc-25fc2c2914e0", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ca17dbf8-222d-4880-9c37-06653d157610", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "jupytext": { + "encoding": "# -*- coding: utf-8 -*-", + "formats": "ipynb,py:light" + }, + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.8" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/resources/NBTest/NBTest_102_APIBasics.py b/resources/NBTest/NBTest_102_APIBasics.py index 17f5c1c03..6ef22b960 100644 --- a/resources/NBTest/NBTest_102_APIBasics.py +++ b/resources/NBTest/NBTest_102_APIBasics.py @@ -16,12 +16,12 @@ # + try: - from fastlane_bot.tools.cpc import CurveBase, ConstantProductCurve as CPC, CPCContainer + from fastlane_bot.tools.cpc import CurveBase, ConstantProductCurve as CPC, CurveContainer from fastlane_bot.tools.optimizer import MargPOptimizer from fastlane_bot.testing import * except: - from tools.cpc import CurveBase, ConstantProductCurve as CPC, CPCContainer + from tools.cpc import CurveBase, ConstantProductCurve as CPC, CurveContainer from tools.optimizer import MargPOptimizer from tools.testing import * @@ -33,7 +33,7 @@ print("{0.__name__} v{0.__VERSION__} ({0.__DATE__})".format(CurveBase)) print("{0.__name__} v{0.__VERSION__} ({0.__DATE__})".format(CPC)) -print("{0.__name__} v{0.__VERSION__} ({0.__DATE__})".format(CPCContainer)) +print("{0.__name__} v{0.__VERSION__} ({0.__DATE__})".format(CurveContainer)) print("{0.__name__} v{0.__VERSION__} ({0.__DATE__})".format(MargPOptimizer)) #plt.style.use('seaborn-dark') @@ -301,14 +301,104 @@ def invariant(self, include_target=False): # #### Uniswap v3 constructor -raises(CPC.from_univ2, y=10, **kwargs) +# + +# TODO +# - -# ### CurveContainer CPCContainer +# ### CurveContainer # # A `CurveContainer` (legacy name: `CPCContainer`) is a container object for curve objects (`CurveBase` derivatives) +# + +# TODO +# - + # ## MargPOptimizer -pass +CC = CurveContainer([ + CPC.from_pk(pair="LINK/USDC", p=10, k = 10*250_000**2, cid="c10"), + CPC.from_pk(pair="LINK/USDC", p=12, k = 10*250_000**2, cid="c12"), +]) +pstart = dict(LINK=10.3, USDC=1) + +# ### Running the optimizer + +O = MargPOptimizer(CC) +r = O.optimize("USDC") +assert not r.is_error +assert r.errormsg is None +assert iseq(r.result, -10868.538042440545) +assert iseq(r.p_optimal_t[0], 10.931723975214778) +assert r.method == 'margp' +assert r.targettkn == "USDC" +assert r.time > 0 +r + +# #### pstart + +# pstart must be a kwarg if provided + +assert raises(O.optimize, "USDC", pstart) +assert not raises(O.optimize, "USDC") +assert not raises(O.optimize, "USDC", pstart=pstart) +raises(O.optimize, "USDC", pstart) + +r1 = O.optimize("USDC", pstart=pstart) +assert iseq(r.result, r1.result, eps=1e-3) +assert iseq(r.p_optimal_t[0], r1.p_optimal_t[0], eps=1e-3) +r1 + +assert raises(O.optimize, "USDC", pstart=pstart, params=dict(pstart=pstart)) +raises(O.optimize, "USDC", pstart=pstart, params=dict(pstart=pstart)) + +# ### Trade instructions + +O = MargPOptimizer(CC) +r = O.optimize("USDC") +assert len(r.trade_instructions()) == 2 +assert r.trade_instructions() == r.trade_instructions(O.TIF_OBJECTS) + +ti = r.trade_instructions(O.TIF_OBJECTS) +assert len(ti) == 2 +assert isinstance(ti[0], O.TradeInstruction) +assert set(tin.cid for tin in ti) == {"c10", "c12"} +assert set(tin.tknin for tin in ti) == {"USDC", "LINK"} +assert set(tin.tknout for tin in ti) == {"USDC", "LINK"} +ti + +ti0 = [tin for tin in ti if tin.cid=="c10"][0] +assert ti0.cid == "c10" +assert ti0.tknin == "USDC" +assert iseq(ti0.amtin, 113872.12474169489) +assert ti0.tknout == "LINK" +assert iseq(ti0.amtout, -10891.133853090403) +assert ti0.error is None +ti0 + +ti = r.trade_instructions(O.TIF_DFRAW) +assert len(ti) == 2 +assert set(ti.index) == {'c10', 'c12'} +assert set(ti.pair) == {'LINK/USDC'} +assert set(ti.pairp) == {'LINK/USDC'} +assert set(ti.tknin) == {'LINK', 'USDC'} +assert set(ti.tknout) == {'LINK', 'USDC'} +ti + +ti0 = ti.loc["c10"] +assert ti0["pair"] == "LINK/USDC" +assert ti0["pairp"] == "LINK/USDC" +assert ti0["tknin"] == "USDC" +assert iseq(ti0["USDC"], 113872.124742) +assert ti0["tknout"] == "LINK" +assert iseq(ti0["LINK"], -10891.133853) +ti0 + +r.trade_instructions(O.TIF_DF8) + +r.trade_instructions(O.TIF_DFAGGR) + +r.trade_instructions(O.TIF_DFPG) + +