From fbd4defecf5b8fbc24ab75934e70c96ad0ff4bd0 Mon Sep 17 00:00:00 2001 From: fryd Date: Fri, 14 Oct 2022 16:56:18 +0200 Subject: [PATCH] chore: use our existing market proposals --- config/config.go | 32 +++- config/config_test.go | 20 ++- go.mod | 4 + go.sum | 22 +++ market/interfaces.go | 1 + market/proposal.go | 327 +++++++++++++++++++++++++++++++++++++++++ market/service.go | 119 ++++----------- node/datanode.go | 37 +++++ types/networkparams.go | 37 +++++ util/rand.go | 22 +++ 10 files changed, 521 insertions(+), 100 deletions(-) create mode 100644 market/proposal.go create mode 100644 types/networkparams.go create mode 100644 util/rand.go diff --git a/config/config.go b/config/config.go index 1f76b6f..e5e7657 100644 --- a/config/config.go +++ b/config/config.go @@ -61,8 +61,20 @@ func (cfg *Config) CheckConfig() error { if err := bot.StrategyDetails.validateStrategyConfig(); err != nil { return fmt.Errorf("failed to validate strategy config for bot '%s': %s", bot.Name, err) } - if len(bot.DataSubmitterPubKey) == 0 { - return fmt.Errorf("%s: %s", errors.ErrMissingEmptyConfigSection.Error(), "bots.dataSubmitterPubKey") + if len(bot.MarketProposalConfig.DataSubmitterPubKey) == 0 { + return fmt.Errorf("%s: %s", errors.ErrMissingEmptyConfigSection.Error(), "bots.marketProposalConfig.dataSubmitterPubKey") + } + if len(bot.MarketProposalConfig.InstrumentCode) == 0 { + return fmt.Errorf("%s: %s", errors.ErrMissingEmptyConfigSection.Error(), "bots.marketProposalConfig.instrumentCode") + } + if len(bot.MarketProposalConfig.Name) == 0 { + return fmt.Errorf("%s: %s", errors.ErrMissingEmptyConfigSection.Error(), "bots.marketProposalConfig.name") + } + if len(bot.MarketProposalConfig.Title) == 0 { + return fmt.Errorf("%s: %s", errors.ErrMissingEmptyConfigSection.Error(), "bots.marketProposalConfig.title") + } + if len(bot.MarketProposalConfig.Description) == 0 { + return fmt.Errorf("%s: %s", errors.ErrMissingEmptyConfigSection.Error(), "bots.marketProposalConfig.description") } } @@ -161,8 +173,7 @@ type BotConfig struct { // SettlementAssetID is the asset used for settlement. SettlementAssetID string `yaml:"settlementAssetID"` - // DataSubmitterPubKey is a vega pub key of a party that can set settlement price and terminate market. - DataSubmitterPubKey string `yaml:"dataSubmitterPubKey"` + MarketProposalConfig MarketProposalConfig `yaml:"marketProposalConfig"` // StrategyDetails contains the parameters needed by the strategy algorithm. StrategyDetails Strategy `yaml:"strategyDetails"` @@ -179,3 +190,16 @@ type TokenConfig struct { StakingBridgeAddress string `yaml:"stakingBridgeAddress"` SyncTimeoutSec int `yaml:"syncTimeoutSec"` } + +type MarketProposalConfig struct { + // DataSubmitterPubKey is a vega pub key of a party that can set settlement price and terminate market. + DataSubmitterPubKey string `yaml:"dataSubmitterPubKey"` + + InstrumentCode string `yaml:"instrumentCode"` + + Name string `yaml:"name"` + Title string `yaml:"title"` + Description string `yaml:"description"` + DecimalPlaces uint64 `yaml:"decimalPlaces"` + Metadata []string `yaml:"metadata"` +} diff --git a/config/config_test.go b/config/config_test.go index c60bf0b..44a3d7d 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -45,13 +45,29 @@ func TestCheckConfig(t *testing.T) { assert.True(t, strings.HasPrefix(err.Error(), errors.ErrMissingEmptyConfigSection.Error())) botConfig := config.BotConfig{ - Name: "test", - DataSubmitterPubKey: "0xDEADBEEF", + Name: "test", StrategyDetails: config.Strategy{ PosManagementSleepMilliseconds: 101, MarketPriceSteeringRatePerSecond: 1, PriceSteerOrderScale: 12, }, + InstrumentBase: "AAPL", + InstrumentQuote: "USD", + SettlementAssetID: "c9fe6fc24fce121b2cc72680543a886055abb560043fda394ba5376203b7527d", + MarketProposalConfig: config.MarketProposalConfig{ + DataSubmitterPubKey: "0xDEADBEEF", + InstrumentCode: "AAPL.MF21", + Name: "Apple Monthly (Feb 2024)", + Title: "New USD market", + Description: "New USD market", + DecimalPlaces: 18, + Metadata: []string{ + "class:equities/single-stock-futures", + "sector:tech", + "listing_venue:NASDAQ", + "country:US", + }, + }, } cfg.Bots = append(cfg.Bots, botConfig) err = cfg.CheckConfig() diff --git a/go.mod b/go.mod index 80b285e..b23da2a 100644 --- a/go.mod +++ b/go.mod @@ -50,6 +50,7 @@ require ( github.com/gorilla/websocket v1.5.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.9.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf // indirect github.com/jmhodges/levigo v1.0.0 // indirect github.com/oasisprotocol/curve25519-voi v0.0.0-20220317090546-adb2f9614b17 // indirect github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect @@ -67,6 +68,9 @@ require ( github.com/tyler-smith/go-bip39 v1.1.0 // indirect github.com/vegaprotocol/go-slip10 v0.1.0 // indirect go.etcd.io/bbolt v1.3.6 // indirect + go.uber.org/atomic v1.9.0 // indirect + go.uber.org/multierr v1.8.0 // indirect + go.uber.org/zap v1.21.0 // indirect golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect golang.org/x/exp v0.0.0-20220426173459-3bcf042a4bf5 // indirect golang.org/x/net v0.0.0-20220726230323-06994584191e // indirect diff --git a/go.sum b/go.sum index 76cb697..f1382ff 100644 --- a/go.sum +++ b/go.sum @@ -24,6 +24,8 @@ github.com/adrg/xdg v0.4.0/go.mod h1:N6ag73EX4wyxeaoeHctc1mas01KZgsj5tYiAIwqJE/E github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= @@ -177,6 +179,7 @@ github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaBfAKrE1Cwb61YDtYq9JxChK1c7AKce7s= +github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf/go.mod h1:yrqSXGoD/4EKfF26AOGzscPOgTTJcyAwM2rpixWT+t4= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jinzhu/configor v1.2.1 h1:OKk9dsR8i6HPOCZR8BcMtcEImAFjIhbJFZNyn5GCZko= github.com/jinzhu/configor v1.2.1/go.mod h1:nX89/MOmDba7ZX7GCyU/VIaQ2Ar2aizBl2d3JLF/rDc= @@ -269,6 +272,7 @@ github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 h1:Gb2Tyox57N github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -298,13 +302,22 @@ github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1: github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= +go.nanomsg.org/mangos/v3 v3.2.1 h1:/7pG6tUJO5ZGznG+waoMy6WrurArODDRJu18848oQnw= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= +go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= +go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8= +go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -334,10 +347,12 @@ golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+o golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -352,6 +367,7 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= @@ -387,7 +403,9 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -421,6 +439,7 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= @@ -468,6 +487,7 @@ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= @@ -479,10 +499,12 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/market/interfaces.go b/market/interfaces.go index 61f27e0..22bb1e9 100644 --- a/market/interfaces.go +++ b/market/interfaces.go @@ -31,6 +31,7 @@ type tradingDataService interface { MustDialConnection(ctx context.Context) Target() string Markets(req *dataapipb.MarketsRequest) (*dataapipb.MarketsResponse, error) // TODO: bot should probably not have to worry about finding markets + GetAllNetworkParameters() (*types.NetworkParameters, error) } type accountService interface { diff --git a/market/proposal.go b/market/proposal.go new file mode 100644 index 0000000..04a0e26 --- /dev/null +++ b/market/proposal.go @@ -0,0 +1,327 @@ +package market + +import ( + "fmt" + "time" + + "code.vegaprotocol.io/liqbot/util" + "code.vegaprotocol.io/vega/protos/vega" + commandspb "code.vegaprotocol.io/vega/protos/vega/commands/v1" + oraclespb "code.vegaprotocol.io/vega/protos/vega/oracles/v1" +) + +type ShortMarketProposalConfig struct { + Name string + Title string + Description string + InstrumentBase string + InstrumentQuote string + InstrumentCode string + + DataSubmitterPubKey string + SettlementVegaAssetId string + DecimalPlaces uint64 + + ClosingTime time.Time + EnactmentTime time.Time + ExtraMetadata []string +} + +func NewMarketProposal(config ShortMarketProposalConfig) *commandspb.ProposalSubmission { + var ( + reference = util.RandAlpaNumericString(40) + settlementDataPropertyKey = fmt.Sprintf("prices.%s.value", config.InstrumentBase) + tradingTerminationPropertyKey = fmt.Sprintf("termination.%s.value", config.InstrumentBase) + ) + + return &commandspb.ProposalSubmission{ + Reference: reference, + Rationale: &vega.ProposalRationale{ + Title: config.Title, + Description: config.Description, + }, + Terms: &vega.ProposalTerms{ + ClosingTimestamp: config.ClosingTime.Unix(), + EnactmentTimestamp: config.EnactmentTime.Unix(), + Change: &vega.ProposalTerms_NewMarket{ + NewMarket: &vega.NewMarket{ + Changes: &vega.NewMarketConfiguration{ + DecimalPlaces: config.DecimalPlaces, + Instrument: &vega.InstrumentConfiguration{ + Name: config.Name, + Code: config.InstrumentCode, + Product: &vega.InstrumentConfiguration_Future{ + Future: &vega.FutureProduct{ + SettlementAsset: config.SettlementVegaAssetId, + QuoteName: config.InstrumentQuote, + OracleSpecForSettlementData: &oraclespb.OracleSpecConfiguration{ + PubKeys: []string{config.DataSubmitterPubKey}, + Filters: []*oraclespb.Filter{ + { + Key: &oraclespb.PropertyKey{ + Name: settlementDataPropertyKey, + Type: oraclespb.PropertyKey_TYPE_INTEGER, + }, + Conditions: []*oraclespb.Condition{ + { + Operator: oraclespb.Condition_OPERATOR_EQUALS, + Value: "1", + }, + }, + }, + }, + }, + OracleSpecForTradingTermination: &oraclespb.OracleSpecConfiguration{ + PubKeys: []string{config.DataSubmitterPubKey}, + Filters: []*oraclespb.Filter{ + { + Key: &oraclespb.PropertyKey{ + Name: tradingTerminationPropertyKey, + Type: oraclespb.PropertyKey_TYPE_BOOLEAN, + }, + Conditions: []*oraclespb.Condition{ + { + Operator: oraclespb.Condition_OPERATOR_EQUALS, + Value: "1", + }, + }, + }, + }, + }, + OracleSpecBinding: &vega.OracleSpecToFutureBinding{ + SettlementDataProperty: settlementDataPropertyKey, + TradingTerminationProperty: tradingTerminationPropertyKey, + }, + }, + }, + }, + Metadata: append([]string{ + fmt.Sprintf("quote:%s", config.InstrumentQuote), + fmt.Sprintf("ticker:%s", config.InstrumentBase), + fmt.Sprintf("base:%s", config.InstrumentBase), + }, config.ExtraMetadata...), + PriceMonitoringParameters: &vega.PriceMonitoringParameters{ + Triggers: []*vega.PriceMonitoringTrigger{ + { + Horizon: 43200, + Probability: "0.9999999", + AuctionExtension: 600, + }, + // { + // Horizon: 300, + // Probability: "0.9999", + // AuctionExtension: 60, + // }, + }, + }, + LiquidityMonitoringParameters: &vega.LiquidityMonitoringParameters{ + TargetStakeParameters: &vega.TargetStakeParameters{ + TimeWindow: 3600, + ScalingFactor: 10, + }, + TriggeringRatio: 0.7, // 0.0 + AuctionExtension: 1, + }, + RiskParameters: &vega.NewMarketConfiguration_LogNormal{ + LogNormal: &vega.LogNormalRiskModel{ + RiskAversionParameter: 0.1, // 0.0001 // 0.01 + Tau: 0.0001140771161, // 0.0000190129 + Params: &vega.LogNormalModelParams{ + Mu: 0, + R: 0.016, + Sigma: 0.3, // 0.8 // 0.5 // 1.25 + }, + }, + }, + }, + }, + }, + }, + } +} + +// +// Example of predefined markets +// + +func NewAAPLMarketProposal( + dataSubmitterPubKey string, + settlementVegaAssetId string, + decimalPlaces uint64, + closingTime time.Time, + enactmentTime time.Time, + extraMetadata []string, +) *commandspb.ProposalSubmission { + return NewMarketProposal( + ShortMarketProposalConfig{ + Name: fmt.Sprintf("Apple Monthly (%s)", time.Now().AddDate(0, 1, 0).Format("Jan 2006")), // Now + 1 months + Title: "New USD market", + Description: "New USD market", + InstrumentBase: "AAPL", + InstrumentQuote: "USD", + InstrumentCode: "AAPL.MF21", + DataSubmitterPubKey: dataSubmitterPubKey, + SettlementVegaAssetId: settlementVegaAssetId, + DecimalPlaces: decimalPlaces, + ClosingTime: closingTime, + EnactmentTime: enactmentTime, + ExtraMetadata: append([]string{ + "class:equities/single-stock-futures", + "sector:tech", + "listing_venue:NASDAQ", + "country:US", + }, extraMetadata...), + }, + ) +} + +func NewAAVEDAIMarketProposal( + dataSubmitterPubKey string, + settlementVegaAssetId string, + decimalPlaces uint64, + closingTime time.Time, + enactmentTime time.Time, + extraMetadata []string, +) *commandspb.ProposalSubmission { + return NewMarketProposal( + ShortMarketProposalConfig{ + Name: fmt.Sprintf("AAVEDAI Monthly (%s)", time.Now().AddDate(0, 1, 0).Format("Jan 2006")), // Now + 1 months + Title: "New DAI market", + Description: "New DAI market", + InstrumentBase: "AAVE", + InstrumentQuote: "DAI", + InstrumentCode: "AAVEDAI.MF21", + DataSubmitterPubKey: dataSubmitterPubKey, + SettlementVegaAssetId: settlementVegaAssetId, + DecimalPlaces: decimalPlaces, + ClosingTime: closingTime, + EnactmentTime: enactmentTime, + ExtraMetadata: append([]string{ + "class:fx/crypto", + "monthly", + "sector:defi", + }, extraMetadata...), + }, + ) +} + +func NewBTCUSDMarketProposal( + dataSubmitterPubKey string, + settlementVegaAssetId string, + decimalPlaces uint64, + closingTime time.Time, + enactmentTime time.Time, + extraMetadata []string, +) *commandspb.ProposalSubmission { + return NewMarketProposal( + ShortMarketProposalConfig{ + Name: fmt.Sprintf("BTCUSD Monthly (%s)", time.Now().AddDate(0, 1, 0).Format("Jan 2006")), // Now + 1 months + Title: "New BTCUSD market", + Description: "New BTCUSD market", + InstrumentBase: "BTC", + InstrumentQuote: "USD", + InstrumentCode: "BTCUSD.MF21", + DataSubmitterPubKey: dataSubmitterPubKey, + SettlementVegaAssetId: settlementVegaAssetId, + DecimalPlaces: decimalPlaces, + ClosingTime: closingTime, + EnactmentTime: enactmentTime, + ExtraMetadata: append([]string{ + "class:fx/crypto", + "monthly", + "sector:crypto", + }, extraMetadata...), + }, + ) +} + +func NewETHBTCMarketProposal( + dataSubmitterPubKey string, + settlementVegaAssetId string, + decimalPlaces uint64, + closingTime time.Time, + enactmentTime time.Time, + extraMetadata []string, +) *commandspb.ProposalSubmission { + return NewMarketProposal( + ShortMarketProposalConfig{ + Name: fmt.Sprintf("ETHBTC Quarterly (%s)", time.Now().AddDate(0, 3, 0).Format("Jan 2006")), // Now + 3 months + Title: "New BTC market", + Description: "New BTC market", + InstrumentBase: "ETH", + InstrumentQuote: "BTC", + InstrumentCode: "ETHBTC.QM21", + DataSubmitterPubKey: dataSubmitterPubKey, + SettlementVegaAssetId: settlementVegaAssetId, + DecimalPlaces: decimalPlaces, + ClosingTime: closingTime, + EnactmentTime: enactmentTime, + ExtraMetadata: append([]string{ + "class:fx/crypto", + "quarterly", + "sector:crypto", + }, extraMetadata...), + }, + ) +} + +func NewTSLAMarketProposal( + dataSubmitterPubKey string, + settlementVegaAssetId string, + decimalPlaces uint64, + closingTime time.Time, + enactmentTime time.Time, + extraMetadata []string, +) *commandspb.ProposalSubmission { + return NewMarketProposal( + ShortMarketProposalConfig{ + Name: fmt.Sprintf("Tesla Quarterly (%s)", time.Now().AddDate(0, 3, 0).Format("Jan 2006")), // Now + 3 months + Title: "New EURO market", + Description: "New EURO market", + InstrumentBase: "TSLA", + InstrumentQuote: "EURO", + InstrumentCode: "TSLA.QM21", + DataSubmitterPubKey: dataSubmitterPubKey, + SettlementVegaAssetId: settlementVegaAssetId, + DecimalPlaces: decimalPlaces, + ClosingTime: closingTime, + EnactmentTime: enactmentTime, + ExtraMetadata: append([]string{ + "class:equities/single-stock-futures", + "sector:tech", + "listing_venue:NASDAQ", + "country:US", + }, extraMetadata...), + }, + ) +} + +func NewUNIDAIMarketProposal( + dataSubmitterPubKey string, + settlementVegaAssetId string, + decimalPlaces uint64, + closingTime time.Time, + enactmentTime time.Time, + extraMetadata []string, +) *commandspb.ProposalSubmission { + return NewMarketProposal( + ShortMarketProposalConfig{ + Name: fmt.Sprintf("UNIDAI Monthly (%s)", time.Now().AddDate(0, 1, 0).Format("Jan 2006")), // Now + 1 month + Title: "New DAI market", + Description: "New DAI market", + InstrumentBase: "UNI", + InstrumentQuote: "DAI", + InstrumentCode: "UNIDAI.MF21", + DataSubmitterPubKey: dataSubmitterPubKey, + SettlementVegaAssetId: settlementVegaAssetId, + DecimalPlaces: decimalPlaces, + ClosingTime: closingTime, + EnactmentTime: enactmentTime, + ExtraMetadata: append([]string{ + "class:fx/crypto", + "monthly", + "sector:defi", + }, extraMetadata...), + }, + ) +} diff --git a/market/service.go b/market/service.go index 41ce924..8b06876 100644 --- a/market/service.go +++ b/market/service.go @@ -19,7 +19,6 @@ import ( "code.vegaprotocol.io/vega/protos/vega" commandspb "code.vegaprotocol.io/vega/protos/vega/commands/v1" v1 "code.vegaprotocol.io/vega/protos/vega/commands/v1" - oraclesv1 "code.vegaprotocol.io/vega/protos/vega/oracles/v1" walletpb "code.vegaprotocol.io/vega/protos/vega/wallet/v1" ) @@ -32,6 +31,7 @@ type Service struct { store data.MarketStore account accountService config config.BotConfig + networkParams *types.NetworkParameters log *log.Entry decimalPlaces uint64 @@ -73,8 +73,13 @@ func (m *Service) Init(pubKey string, pauseCh chan types.PauseSignal) error { if err != nil { return err } + networkParams, err := m.node.GetAllNetworkParameters() + if err != nil { + return err + } m.store = store m.walletPubKey = pubKey + m.networkParams = networkParams return nil } @@ -232,8 +237,26 @@ func (m *Service) CreateMarket(ctx context.Context) error { } func (m *Service) sendNewMarketProposal(ctx context.Context) error { + proposalParams, err := m.networkParams.GetMarketProposalParams() + if err != nil { + return err + } + marketProposal := NewMarketProposal(ShortMarketProposalConfig{ + Name: m.config.MarketProposalConfig.Name, + Title: m.config.MarketProposalConfig.Title, + Description: m.config.MarketProposalConfig.Description, + InstrumentBase: m.config.InstrumentBase, + InstrumentQuote: m.config.InstrumentQuote, + InstrumentCode: m.config.MarketProposalConfig.InstrumentCode, + DataSubmitterPubKey: m.config.MarketProposalConfig.DataSubmitterPubKey, + SettlementVegaAssetId: m.config.SettlementAssetID, + DecimalPlaces: m.config.MarketProposalConfig.DecimalPlaces, + ExtraMetadata: m.config.MarketProposalConfig.Metadata, + ClosingTime: time.Now().Add(time.Second * 20).Add(proposalParams.MinClose), + EnactmentTime: time.Now().Add(time.Second * 30).Add(proposalParams.MinClose).Add(proposalParams.MinEnact), + }) cmd := &walletpb.SubmitTransactionRequest_ProposalSubmission{ - ProposalSubmission: m.getExampleMarketProposal(), + ProposalSubmission: marketProposal, } submitTxReq := &walletpb.SubmitTransactionRequest{ @@ -400,95 +423,3 @@ func (m *Service) GetExternalPrice() (*num.Uint, error) { externalPriceNum := num.NewUint(uint64(externalPrice)) return externalPriceNum, nil } - -func (m *Service) getExampleMarketProposal() *v1.ProposalSubmission { - return &v1.ProposalSubmission{ - Rationale: &vega.ProposalRationale{ - Title: "Example Market", - Description: "some description", - }, - Reference: "ProposalReference", - Terms: &vega.ProposalTerms{ - ClosingTimestamp: secondsFromNowInSecs(15), - EnactmentTimestamp: secondsFromNowInSecs(15), - Change: &vega.ProposalTerms_NewMarket{ - NewMarket: m.getExampleMarket(), - }, - }, - } -} - -func (m *Service) getExampleMarket() *vega.NewMarket { - return &vega.NewMarket{ - Changes: &vega.NewMarketConfiguration{ - Instrument: &vega.InstrumentConfiguration{ - Code: fmt.Sprintf("CRYPTO:%s%s/NOV22", m.config.InstrumentBase, m.config.InstrumentQuote), - Name: fmt.Sprintf("NOV 2022 %s vs %s future", m.config.InstrumentBase, m.config.InstrumentQuote), - Product: m.getExampleProduct(), - }, - DecimalPlaces: 5, - Metadata: []string{"base:" + m.config.InstrumentBase, "quote:" + m.config.InstrumentQuote, "class:fx/crypto", "monthly", "sector:crypto"}, - RiskParameters: &vega.NewMarketConfiguration_LogNormal{ - LogNormal: &vega.LogNormalRiskModel{ - RiskAversionParameter: 0.01, - Tau: 0.0001140771161, - Params: &vega.LogNormalModelParams{ - Mu: 0, - R: 0.016, - Sigma: 0.5, - }, - }, - }, - }, - /* - TODO: is this needed? - LiquidityCommitment: &vega.NewMarketCommitment{ - Fee: fmt.Sprint(m.config.StrategyDetails.Fee), - CommitmentAmount: m.config.StrategyDetails.CommitmentAmount, - Buys: m.config.StrategyDetails.ShorteningShape.Buys.ToVegaLiquidityOrders(), - Sells: m.config.StrategyDetails.LongeningShape.Sells.ToVegaLiquidityOrders(), - },*/ - } -} - -func (m *Service) getExampleProduct() *vega.InstrumentConfiguration_Future { - return &vega.InstrumentConfiguration_Future{ - Future: &vega.FutureProduct{ - SettlementAsset: m.config.SettlementAssetID, - QuoteName: fmt.Sprintf("%s%s", m.config.InstrumentBase, m.config.InstrumentQuote), - OracleSpecForSettlementData: &oraclesv1.OracleSpecConfiguration{ - PubKeys: []string{m.config.DataSubmitterPubKey}, - Filters: []*oraclesv1.Filter{ - { - Key: &oraclesv1.PropertyKey{ - Name: "prices.ETH.value", - Type: oraclesv1.PropertyKey_TYPE_INTEGER, - }, - Conditions: []*oraclesv1.Condition{}, - }, - }, - }, - OracleSpecForTradingTermination: &oraclesv1.OracleSpecConfiguration{ - PubKeys: []string{m.config.DataSubmitterPubKey}, - Filters: []*oraclesv1.Filter{ - { - Key: &oraclesv1.PropertyKey{ - Name: "trading.termination", - Type: oraclesv1.PropertyKey_TYPE_BOOLEAN, - }, - Conditions: []*oraclesv1.Condition{}, - }, - }, - }, - OracleSpecBinding: &vega.OracleSpecToFutureBinding{ - SettlementDataProperty: "prices.ETH.value", - TradingTerminationProperty: "trading.termination", - }, - }, - } -} - -// secondsFromNowInSecs : Creates a timestamp relative to the current time in seconds. -func secondsFromNowInSecs(seconds int64) int64 { - return time.Now().Unix() + seconds -} diff --git a/node/datanode.go b/node/datanode.go index ffb1907..bee021e 100644 --- a/node/datanode.go +++ b/node/datanode.go @@ -12,9 +12,11 @@ import ( "google.golang.org/grpc/credentials/insecure" dataapipb "code.vegaprotocol.io/vega/protos/data-node/api/v1" + dataapipbv2 "code.vegaprotocol.io/vega/protos/data-node/api/v2" vegaapipb "code.vegaprotocol.io/vega/protos/vega/api/v1" e "code.vegaprotocol.io/liqbot/errors" + "code.vegaprotocol.io/liqbot/types" ) // DataNode stores state for a Vega Data node. @@ -280,3 +282,38 @@ func (n *DataNode) AssetByID(req *dataapipb.AssetByIDRequest) (*dataapipb.AssetB func (n *DataNode) WaitForStateChange(ctx context.Context, state connectivity.State) bool { return n.conn.WaitForStateChange(ctx, state) } + +// All Network Parameters +func (n *DataNode) ListNetworkParameters(req *dataapipbv2.ListNetworkParametersRequest) (*dataapipbv2.ListNetworkParametersResponse, error) { + msg := "gRPC call failed (data-node v2): ListNetworkParameters: %w" + if n == nil { + return nil, fmt.Errorf(msg, e.ErrNil) + } + + if n.conn.GetState() != connectivity.Ready { + return nil, fmt.Errorf(msg, e.ErrConnectionNotReady) + } + + c := dataapipbv2.NewTradingDataServiceClient(n.conn) + ctx, cancel := context.WithTimeout(context.Background(), n.callTimeout) + defer cancel() + + response, err := c.ListNetworkParameters(ctx, req) + if err != nil { + return nil, fmt.Errorf(msg, e.ErrorDetail(err)) + } + + return response, nil +} + +func (n *DataNode) GetAllNetworkParameters() (*types.NetworkParameters, error) { + res, err := n.ListNetworkParameters(&dataapipbv2.ListNetworkParametersRequest{}) + if err != nil { + return nil, err + } + networkParams := map[string]string{} + for _, edge := range res.NetworkParameters.Edges { + networkParams[edge.Node.Key] = edge.Node.Value + } + return types.NewNetworkParameters(networkParams) +} diff --git a/types/networkparams.go b/types/networkparams.go new file mode 100644 index 0000000..56907c0 --- /dev/null +++ b/types/networkparams.go @@ -0,0 +1,37 @@ +package types + +import ( + "time" + + "code.vegaprotocol.io/vega/core/netparams" +) + +type NetworkParameters struct { + Params map[string]string +} + +func NewNetworkParameters(params map[string]string) (*NetworkParameters, error) { + return &NetworkParameters{ + Params: params, + }, nil +} + +type MarketProposalParams struct { + MinClose time.Duration + MinEnact time.Duration +} + +func (n *NetworkParameters) GetMarketProposalParams() (*MarketProposalParams, error) { + minClose, err := time.ParseDuration(n.Params[netparams.GovernanceProposalMarketMinClose]) + if err != nil { + return nil, err + } + minEnact, err := time.ParseDuration(n.Params[netparams.GovernanceProposalMarketMinEnact]) + if err != nil { + return nil, err + } + return &MarketProposalParams{ + MinClose: minClose, + MinEnact: minEnact, + }, nil +} diff --git a/util/rand.go b/util/rand.go new file mode 100644 index 0000000..6615136 --- /dev/null +++ b/util/rand.go @@ -0,0 +1,22 @@ +package util + +import ( + "crypto/rand" + "fmt" + "math/big" +) + +func RandAlpaNumericString(l int) string { + const letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + lettersLen := big.NewInt(int64(len(letters))) + ret := make([]byte, l) + for i := 0; i < l; i++ { + num, err := rand.Int(rand.Reader, lettersLen) + if err != nil { + panic(fmt.Sprintf("Failed to random word %+v", err)) + } + ret[i] = letters[num.Int64()] + } + + return string(ret) +}