Skip to content

Maker Keeper Framework: Market maker keepers for OasisDEX, EtherDelta and RadarRelay.

License

Notifications You must be signed in to change notification settings

destenson/makerdao--market-maker-keeper

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

market-maker-keeper

Build Status codecov

The DAI Stablecoin System incentivizes external agents, called keepers, to automate certain operations around the Ethereum blockchain.

market-maker-keeper is actually a set of keepers that facilitate SAI/W-ETH and SAI/ETH market making of the following exchanges:

  • OasisDEX (oasis-market-maker-keeper),
  • EtherDelta (etherdelta-market-maker-keeper),
  • RadarRelay (radarrelay-market-maker-keeper).

All these three keepers share some logic and operate in a similar way. They create a series of orders in so called bands, which are configured with a JSON file containing parameters like spreads, maximum engagement etc. Please see the "Bands configuration" section below for more details regarding keeper mechanics.

All these keepers are currently only capable of market-making on the SAI/W-ETH (for OasisDEX and RadarRelay) and SAI/ETH (for EtherDelta) pairs. Changing it would require making some changes to their source code. Having said that, that change seems to be pretty trivial.

This repo also contains an auxiliary tool called oasis-market-maker-cancel, which may be used for emergency cancelling all market maker orders on OasisDEX if the keeper gets stuck or dies for some reason, or if the network becomes congested.

https://chat.makerdao.com/channel/keeper

Installation

This project uses Python 3.6.2.

In order to clone the project and install required third-party packages please execute:

git clone https://github.com/makerdao/market-maker-keeper.git
git submodule update --init --recursive
pip3 install -r requirements.txt

Known macOS issues

In order for the Python requirements to install correctly on macOS, please install openssl, libtool and pkg-config using Homebrew:

brew install openssl libtool pkg-config

and set the LDFLAGS environment variable before you run pip3 install -r requirements.txt:

export LDFLAGS="-L$(brew --prefix openssl)/lib" CFLAGS="-I$(brew --prefix openssl)/include" 

Installation of etherdelta-client

The etherdelta-market-maker-keeper keeper utilizes etherdelta-client (present in the lib/pymaker/utils directory) to place orders on EtherDelta using socket.io. In order to use it, a node installation must be present and npm install needs to be run in the lib/pymaker/utils/etherdelta-client folder.

This step is not necessary if you only want to use the other keepers from this project.

Installation of setzer

All market maker keepers use setzer in order to access price feeds like GDAX, Kraken etc. This interface is built on top of setzer so in order for it to work correctly, setzer and its dependencies must be installed and available to the keepers. Please see: https://github.com/makerdao/setzer.

Without setzer installed, the --price-feed argument can not be used and only the default price feed (provided by Tub) will be available.

Bands configuration

Description

Bands configuration file is directly related to how market maker keepers work. They continuously monitor and adjusts its positions in the order to book, maintaining open buy and sell orders in multiple bands at the same time.

In each buy band, the keepers aim to have open SAI sell orders for at least minSaiAmount. In each sell band they aim to have open WETH (or ETH) sell orders for at least minWEthAmount. In both cases, they will ensure the price of open orders stays within the <minMargin,maxMargin> range from the current SAI/ETH price.

When started, keepers places orders for the average amounts (avgSaiAmount and avgWEthAmount) in each band, using use avgMargin to calculate the order price.

As long as the price of orders stays within the band (i.e. is in the <minMargin,maxMargin> range from the current SAI/ETH price, which is of course constantly moving), the keepers keep them open. If some orders leave the band, they either enter another adjacent band or fall outside all bands. In case of the latter, they get immediately cancelled. In case of the former, keepers can keep these orders open as long as their amount is within the <minSaiAmount,maxSaiAmount> (for buy bands) or <minWEthAmount,maxWEthAmount> (for sell bands) ranges for the band they just entered. If it is above the maximum, some open orders will get cancelled and potentially new one will be created to bring the total amount back within the range. If it is below the minimum, a new order gets created for the remaining amount so the total amount of orders in this band is equal to avgSaiAmount or avgWEthAmount.

The same thing will happen if the total amount of open orders in a band falls below either minSaiAmount or minWEthAmount as a result of other market participants taking these orders. In this case also a new order gets created for the remaining amount so the total amount of orders in this band is equal to avgSaiAmount / avgWEthAmount.

Keeper will constantly use gas to cancel orders (for OasisDEX, EtherDelta and RadarRelay) and create new ones (OasisDEX only) as the SAI/ETH price changes. Gas usage can be limited by setting the margin and amount ranges wide enough and also by making sure that bands are always adjacent to each other and that their <min,max> amount ranges overlap.

File format

Bands configuration file consists of two main sections: buyBands (configuration determining how the keeper buys WETH (or ETH) with SAI) and sellBands (configuration determining how the keeper sells WETH (or ETH) for SAI). Each section is an array containing one object per each band.

The minMargin and maxMargin fields in each band object represent the margin (spread) range of that band. These ranges may not overlap for bands of the same type (buy or sell), and should be adjacent to each other for better keeper performance (less orders will likely get cancelled if they are adjacent). The avgMargin represents the margin (spread) of newly created orders within a band.

The next three fields (minSaiAmount, avgSaiAmount and maxSaiAmount for buy bands, or minWEthAmount, avgWEthAmount and maxWEthAmount for sell bands) are the minimum, target and maximum keeper engagement per each band. The dustCutoff field is the minimum value of order created in each individual band, expressed in SAI for buy bands and in WETH (or ETH) for sell bands. Setting it to a non-zero value prevents keepers from creating of lot of very tiny orders, which can cost a lot of gas in case of OasisDEX.

Sample bands configuration file:

{
    "buyBands": [
        {
            "minMargin": 0.005,
            "avgMargin": 0.01,
            "maxMargin": 0.02,
            "minSaiAmount": 20.0,
            "avgSaiAmount": 30.0,
            "maxSaiAmount": 40.0,
            "dustCutoff": 0.0
        },
        {
            "minMargin": 0.02,
            "avgMargin": 0.025,
            "maxMargin": 0.03,
            "minSaiAmount": 40.0,
            "avgSaiAmount": 60.0,
            "maxSaiAmount": 80.0,
            "dustCutoff": 0.0
        }
    ],
    "sellBands": [
        {
            "minMargin": 0.005,
            "avgMargin": 0.01,
            "maxMargin": 0.02,
            "minWEthAmount": 2.5,
            "avgWEthAmount": 5.0,
            "maxWEthAmount": 7.5,
            "dustCutoff": 0.0
        },
        {
            "minMargin": 0.02,
            "avgMargin": 0.025,
            "maxMargin": 0.03,
            "minWEthAmount": 4.0,
            "avgWEthAmount": 6.0,
            "maxWEthAmount": 8.0,
            "dustCutoff": 0.0
        }
    ]
}

Data templating language

The Jsonnet data templating language can be used for the bands config file.

oasis-market-maker-keeper

This keeper supports market-making on the OasisDEX exchange.

Usage

usage: oasis-market-maker-keeper [-h] [--rpc-host RPC_HOST]
                                 [--rpc-port RPC_PORT] --eth-from ETH_FROM
                                 --tub-address TUB_ADDRESS --oasis-address
                                 OASIS_ADDRESS --config CONFIG
                                 [--price-feed PRICE_FEED]
                                 [--round-places ROUND_PLACES]
                                 [--min-eth-balance MIN_ETH_BALANCE]
                                 [--gas-price GAS_PRICE]
                                 [--gas-price-increase GAS_PRICE_INCREASE]
                                 [--gas-price-increase-every GAS_PRICE_INCREASE_EVERY]
                                 [--gas-price-max GAS_PRICE_MAX]
                                 [--gas-price-file GAS_PRICE_FILE]
                                 [--smart-gas-price] [--debug]

optional arguments:
  -h, --help            show this help message and exit
  --rpc-host RPC_HOST   JSON-RPC host (default: `localhost')
  --rpc-port RPC_PORT   JSON-RPC port (default: `8545')
  --eth-from ETH_FROM   Ethereum account from which to send transactions
  --tub-address TUB_ADDRESS
                        Ethereum address of the Tub contract
  --oasis-address OASIS_ADDRESS
                        Ethereum address of the OasisDEX contract
  --config CONFIG       Buy/sell bands configuration file
  --price-feed PRICE_FEED
                        Source of price feed. Tub price feed will be used if
                        not specified
  --round-places ROUND_PLACES
                        Number of decimal places to round order prices to
                        (default=2)
  --min-eth-balance MIN_ETH_BALANCE
                        Minimum ETH balance below which keeper with either
                        terminate or not start at all
  --gas-price GAS_PRICE
                        Gas price (in Wei)
  --gas-price-increase GAS_PRICE_INCREASE
                        Gas price increase (in Wei) if no confirmation within
                        `--gas-price-increase-every` seconds
  --gas-price-increase-every GAS_PRICE_INCREASE_EVERY
                        Gas price increase frequency (in seconds, default:
                        120)
  --gas-price-max GAS_PRICE_MAX
                        Maximum gas price (in Wei)
  --gas-price-file GAS_PRICE_FILE
                        Gas price configuration file
  --smart-gas-price     Use smart gas pricing strategy, based on the
                        ethgasstation.info feed
  --debug               Enable debug output

oasis-market-maker-cancel

This tool immediately cancels all our open orders on OasisDEX. It may be used if the oasis-market-maker-keeper gets stuck or dies for some reason, or if the network becomes congested.

Usage

usage: oasis-market-maker-cancel [-h] [--rpc-host RPC_HOST]
                                 [--rpc-port RPC_PORT] --eth-from ETH_FROM
                                 --oasis-address OASIS_ADDRESS
                                 [--gas-price GAS_PRICE]

optional arguments:
  -h, --help            show this help message and exit
  --rpc-host RPC_HOST   JSON-RPC host (default: `localhost')
  --rpc-port RPC_PORT   JSON-RPC port (default: `8545')
  --eth-from ETH_FROM   Ethereum account from which to send transactions
  --oasis-address OASIS_ADDRESS
                        Ethereum address of the OasisDEX contract
  --gas-price GAS_PRICE
                        Gas price in Wei (default: node default)

etherdelta-market-maker-keeper

This keeper supports market-making on the EtherDelta exchange.

Usage

usage: etherdelta-market-maker-keeper [-h] [--rpc-host RPC_HOST]
                                      [--rpc-port RPC_PORT] --eth-from
                                      ETH_FROM --tub-address TUB_ADDRESS
                                      --etherdelta-address ETHERDELTA_ADDRESS
                                      --etherdelta-socket ETHERDELTA_SOCKET
                                      [--etherdelta-number-of-attempts ETHERDELTA_NUMBER_OF_ATTEMPTS]
                                      [--etherdelta-retry-interval ETHERDELTA_RETRY_INTERVAL]
                                      [--etherdelta-timeout ETHERDELTA_TIMEOUT]
                                      --config CONFIG
                                      [--price-feed PRICE_FEED] --order-age
                                      ORDER_AGE
                                      [--order-expiry-threshold ORDER_EXPIRY_THRESHOLD]
                                      [--order-no-cancel-threshold ORDER_NO_CANCEL_THRESHOLD]
                                      --eth-reserve ETH_RESERVE
                                      [--min-eth-balance MIN_ETH_BALANCE]
                                      --min-eth-deposit MIN_ETH_DEPOSIT
                                      --min-sai-deposit MIN_SAI_DEPOSIT
                                      [--cancel-on-shutdown]
                                      [--withdraw-on-shutdown]
                                      [--gas-price GAS_PRICE]
                                      [--gas-price-increase GAS_PRICE_INCREASE]
                                      [--gas-price-increase-every GAS_PRICE_INCREASE_EVERY]
                                      [--gas-price-max GAS_PRICE_MAX]
                                      [--gas-price-file GAS_PRICE_FILE]
                                      [--smart-gas-price] [--debug]

optional arguments:
  -h, --help            show this help message and exit
  --rpc-host RPC_HOST   JSON-RPC host (default: `localhost')
  --rpc-port RPC_PORT   JSON-RPC port (default: `8545')
  --eth-from ETH_FROM   Ethereum account from which to send transactions
  --tub-address TUB_ADDRESS
                        Ethereum address of the Tub contract
  --etherdelta-address ETHERDELTA_ADDRESS
                        Ethereum address of the EtherDelta contract
  --etherdelta-socket ETHERDELTA_SOCKET
                        Ethereum address of the EtherDelta API socket
  --etherdelta-number-of-attempts ETHERDELTA_NUMBER_OF_ATTEMPTS
                        Number of attempts of running the tool to talk to the
                        EtherDelta API socket
  --etherdelta-retry-interval ETHERDELTA_RETRY_INTERVAL
                        Retry interval for sending orders over the EtherDelta
                        API socket
  --etherdelta-timeout ETHERDELTA_TIMEOUT
                        Timeout for sending orders over the EtherDelta API
                        socket
  --config CONFIG       Buy/sell bands configuration file
  --price-feed PRICE_FEED
                        Source of price feed. Tub price feed will be used if
                        not specified
  --order-age ORDER_AGE
                        Age of created orders (in blocks)
  --order-expiry-threshold ORDER_EXPIRY_THRESHOLD
                        Remaining order age (in blocks) at which order is
                        considered already expired, which means the keeper
                        will send a new replacement order slightly ahead
  --order-no-cancel-threshold ORDER_NO_CANCEL_THRESHOLD
                        Remaining order age (in blocks) below which keeper
                        does not try to cancel orders, assuming that they will
                        probably expire before the cancel transaction gets
                        mined
  --eth-reserve ETH_RESERVE
                        Amount of ETH which will never be deposited so the
                        keeper can cover gas
  --min-eth-balance MIN_ETH_BALANCE
                        Minimum ETH balance below which keeper with either
                        terminate or not start at all
  --min-eth-deposit MIN_ETH_DEPOSIT
                        Minimum amount of ETH that can be deposited in one
                        transaction
  --min-sai-deposit MIN_SAI_DEPOSIT
                        Minimum amount of SAI that can be deposited in one
                        transaction
  --cancel-on-shutdown  Whether should cancel all open orders on EtherDelta on
                        keeper shutdown
  --withdraw-on-shutdown
                        Whether should withdraw all tokens from EtherDelta on
                        keeper shutdown
  --gas-price GAS_PRICE
                        Gas price (in Wei)
  --gas-price-increase GAS_PRICE_INCREASE
                        Gas price increase (in Wei) if no confirmation within
                        `--gas-price-increase-every` seconds
  --gas-price-increase-every GAS_PRICE_INCREASE_EVERY
                        Gas price increase frequency (in seconds, default:
                        120)
  --gas-price-max GAS_PRICE_MAX
                        Maximum gas price (in Wei)
  --gas-price-file GAS_PRICE_FILE
                        Gas price configuration file
  --smart-gas-price     Use smart gas pricing strategy, based on the
                        ethgasstation.info feed
  --debug               Enable debug output

Known limitations

  • Because of some random database errors, creating some orders randomly fails. This issue has been reported to the EtherDelta team (etherdelta/etherdelta.github.io#275), but it hasn't been solved yet.

  • There is no way to reliably get the current status of the EtherDelta order book, so the keeper relies on an assumption that if an order has been sent to EtherDelta it has actually made its way to the order book. If it doesn't happen (because of the error mentioned above for example), it will be missing from the exchange until its expiration time passes and it will get placed again (refreshed) by the keeper.

  • Due to the same issue with retrieving the current order book status, the keeper starts with the assumption that the order book is empty. If there are already some keeper orders in it, they may get recreated again by the keeper so duplicates will exist until the older ones expire. That's why it is recommended to wait for the existing orders to expire before starting the keeper.

  • There is a limit of 10 active orders per side (see: etherdelta/etherdelta.github.io#274).

radarrelay-market-maker-keeper

This keeper supports market-making on the RadarRelay exchange. As RadarRelay is a regular 0x Exchange implementing the 0x Standard Relayer API, this keeper can be easily adapted to market-make on other 0x exchanges as well.

Usage

usage: radarrelay-market-maker-keeper [-h] [--rpc-host RPC_HOST]
                                      [--rpc-port RPC_PORT] --eth-from
                                      ETH_FROM --tub-address TUB_ADDRESS
                                      --exchange-address EXCHANGE_ADDRESS
                                      --weth-address WETH_ADDRESS
                                      --relayer-api-server RELAYER_API_SERVER
                                      --config CONFIG
                                      [--price-feed PRICE_FEED] --order-expiry
                                      ORDER_EXPIRY
                                      [--order-expiry-threshold ORDER_EXPIRY_THRESHOLD]
                                      [--min-eth-balance MIN_ETH_BALANCE]
                                      [--cancel-on-shutdown]
                                      [--gas-price GAS_PRICE] [--debug]

optional arguments:
  -h, --help            show this help message and exit
  --rpc-host RPC_HOST   JSON-RPC host (default: `localhost')
  --rpc-port RPC_PORT   JSON-RPC port (default: `8545')
  --eth-from ETH_FROM   Ethereum account from which to send transactions
  --tub-address TUB_ADDRESS
                        Ethereum address of the Tub contract
  --exchange-address EXCHANGE_ADDRESS
                        Ethereum address of the 0x Exchange contract
  --weth-address WETH_ADDRESS
                        Ethereum address of the WETH token
  --relayer-api-server RELAYER_API_SERVER
                        Address of the 0x Relayer API
  --config CONFIG       Buy/sell bands configuration file
  --price-feed PRICE_FEED
                        Source of price feed. Tub price feed will be used if
                        not specified
  --order-expiry ORDER_EXPIRY
                        Expiration time of created orders (in seconds)
  --order-expiry-threshold ORDER_EXPIRY_THRESHOLD
                        Order expiration time at which order is considered
                        already expired (in seconds)
  --min-eth-balance MIN_ETH_BALANCE
                        Minimum ETH balance below which keeper with either
                        terminate or not start at all
  --cancel-on-shutdown  Whether should cancel all open orders on RadarRelay on
                        keeper shutdown
  --gas-price GAS_PRICE
                        Gas price (in Wei)
  --debug               Enable debug output

Known limitations

  • Expired and/or taken orders to not disappear from the RadarRelay UI immediately. Apparently they run a backend process called chain watching service, which for tokens with little liquidity kicks in only every 10 minutes and does order pruning. Because of that, if we configure the keeper to refresh the orders too frequently (i.e. if the --order-expiry will be too low), the exchange users will see two or even more duplicates of market maker orders.

License

See COPYING file.

About

Maker Keeper Framework: Market maker keepers for OasisDEX, EtherDelta and RadarRelay.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Python 99.6%
  • Shell 0.4%