decred.org/dcrdex@v1.0.3/client/mm/config.go (about) 1 package mm 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "strconv" 7 ) 8 9 // MarketMakingConfig is the overall configuration of the market maker. 10 type MarketMakingConfig struct { 11 BotConfigs []*BotConfig `json:"botConfigs"` 12 CexConfigs []*CEXConfig `json:"cexConfigs"` 13 } 14 15 func (cfg *MarketMakingConfig) Copy() *MarketMakingConfig { 16 c := &MarketMakingConfig{ 17 BotConfigs: make([]*BotConfig, len(cfg.BotConfigs)), 18 CexConfigs: make([]*CEXConfig, len(cfg.CexConfigs)), 19 } 20 copy(c.BotConfigs, cfg.BotConfigs) 21 copy(c.CexConfigs, cfg.CexConfigs) 22 return c 23 } 24 25 // CEXConfig is a configuration for connecting to a CEX API. 26 type CEXConfig struct { 27 // Name is the name of the cex. 28 Name string `json:"name"` 29 // APIKey is the API key for the CEX. 30 APIKey string `json:"apiKey"` 31 // APISecret is the API secret for the CEX. 32 APISecret string `json:"apiSecret"` 33 } 34 35 // AutoRebalanceConfig configures deposits and withdrawals by setting minimum 36 // transfer sizes. Minimum transfer sizes should be set to prevent excessive 37 // fees on high-fee blockchains. To calculate a minimum transfer size for an 38 // asset, choose a fee-loss tolerance <= your profit target. If you only wanted to 39 // lose a maximum of 1% to transfers, and the fees associated with a transfer 40 // are 350 Sats, then your minimum transfer size might be set to 41 // 350 * (1 / 0.01) = 35000 Sats. 42 // For low-fee assets, a transfer size of zero would be perfectly fine in most 43 // cases, but using a higher value prevents churn. 44 // For obvious reasons, minimum transfer sizes should never be more than the 45 // total amount allocated for trading. 46 // The way these are configured will probably be changed to better capture the 47 // reasoning above. 48 type AutoRebalanceConfig struct { 49 MinBaseTransfer uint64 `json:"minBaseTransfer"` 50 MinQuoteTransfer uint64 `json:"minQuoteTransfer"` 51 } 52 53 // BotBalanceAllocation is the initial allocation of funds for a bot. 54 type BotBalanceAllocation struct { 55 DEX map[uint32]uint64 `json:"dex"` 56 CEX map[uint32]uint64 `json:"cex"` 57 } 58 59 // BotInventoryDiffs is the amount of funds to add or remove from a bot's 60 // allocation. 61 type BotInventoryDiffs struct { 62 DEX map[uint32]int64 `json:"dex"` 63 CEX map[uint32]int64 `json:"cex"` 64 } 65 66 // balanceDiffsToAllocations converts a BotInventoryDiffs to a 67 // BotBalanceAllocation by removing all negative diffs. 68 func balanceDiffsToAllocation(diffs *BotInventoryDiffs) *BotBalanceAllocation { 69 allocations := &BotBalanceAllocation{ 70 DEX: make(map[uint32]uint64, len(diffs.DEX)), 71 CEX: make(map[uint32]uint64, len(diffs.CEX)), 72 } 73 74 for assetID, diff := range diffs.DEX { 75 if diff > 0 { 76 allocations.DEX[assetID] += uint64(diff) 77 } 78 } 79 for assetID, diff := range diffs.CEX { 80 if diff > 0 { 81 allocations.CEX[assetID] += uint64(diff) 82 } 83 } 84 85 return allocations 86 } 87 88 // #### IMPORTANT ### 89 // If non-backwards compatible changes are made to the BotConfig, a new version 90 // should be created and the event log db should be updated to support both 91 // versions. 92 93 // BotConfig is the configuration for a market making bot. 94 // The balance fields are the initial amounts that will be reserved to use for 95 // this bot. As the bot trades, the amounts reserved for it will be updated. 96 type BotConfig struct { 97 Host string `json:"host"` 98 BaseID uint32 `json:"baseID"` 99 QuoteID uint32 `json:"quoteID"` 100 101 BaseWalletOptions map[string]string `json:"baseWalletOptions"` 102 QuoteWalletOptions map[string]string `json:"quoteWalletOptions"` 103 104 CEXName string `json:"cexName"` 105 106 // UIConfig is settings defined and used by the front end to determine 107 // allocations. 108 UIConfig json.RawMessage `json:"uiConfig,omitempty"` 109 110 // RPCConfig can be used for file-based initial allocations and 111 // auto-rebalance settings. 112 RPCConfig *struct { 113 Alloc *BotBalanceAllocation `json:"alloc"` 114 AutoRebalance *AutoRebalanceConfig `json:"autoRebalance"` 115 } `json:"rpcConfig"` 116 117 // Only one of the following configs should be set 118 BasicMMConfig *BasicMarketMakingConfig `json:"basicMarketMakingConfig,omitempty"` 119 SimpleArbConfig *SimpleArbConfig `json:"simpleArbConfig,omitempty"` 120 ArbMarketMakerConfig *ArbMarketMakerConfig `json:"arbMarketMakingConfig,omitempty"` 121 } 122 123 func (c *BotConfig) requiresPriceOracle() bool { 124 return c.BasicMMConfig != nil 125 } 126 127 func (c *BotConfig) requiresCEX() bool { 128 return c.SimpleArbConfig != nil || c.ArbMarketMakerConfig != nil 129 } 130 131 // multiSplitBuffer returns the additional buffer to add to the order size 132 // when doing a multi-split. This only applies to the quote asset. 133 func (c *BotConfig) multiSplitBuffer() float64 { 134 if c.QuoteWalletOptions == nil { 135 return 0 136 } 137 multiSplitBuffer, ok := c.QuoteWalletOptions["multisplitbuffer"] 138 if !ok { 139 return 0 140 } 141 multiSplitBufferFloat, err := strconv.ParseFloat(multiSplitBuffer, 64) 142 if err != nil { 143 return 0 144 } 145 return multiSplitBufferFloat 146 } 147 148 // maxPlacements returns the max amount of placements this bot will place on 149 // either side of the market in an epoch. 150 func (c *BotConfig) maxPlacements() (buy, sell uint32) { 151 switch { 152 case c.SimpleArbConfig != nil: 153 return 1, 1 154 case c.ArbMarketMakerConfig != nil: 155 return uint32(len(c.ArbMarketMakerConfig.BuyPlacements)), uint32(len(c.ArbMarketMakerConfig.SellPlacements)) 156 case c.BasicMMConfig != nil: 157 return uint32(len(c.BasicMMConfig.BuyPlacements)), uint32(len(c.BasicMMConfig.SellPlacements)) 158 default: 159 return 1, 1 160 } 161 } 162 163 func dexMarketID(host string, base, quote uint32) string { 164 return fmt.Sprintf("%s-%d-%d", host, base, quote) 165 }