Exemplo n.º 1
0
class ZrxMarketMakerChart:
    """Tool to generate a chart displaying the 0x market maker keeper trades."""

    def __init__(self, args: list):
        parser = argparse.ArgumentParser(prog='0x-market-maker-chart')
        parser.add_argument("--rpc-host", help="JSON-RPC host (default: `localhost')", default="localhost", type=str)
        parser.add_argument("--rpc-port", help="JSON-RPC port (default: `8545')", default=8545, type=int)
        parser.add_argument("--rpc-timeout", help="JSON-RPC timeout (in seconds, default: 60)", type=int, default=60)
        parser.add_argument("--exchange-address", help="Ethereum address of the 0x contract", required=True, type=str)
        parser.add_argument("--buy-token-address", help="Ethereum address of the buy token", required=True, type=str)
        parser.add_argument("--buy-token-decimals", help="Number of decimals for the buy token", type=int, default=18)
        parser.add_argument("--sell-token-address", help="Ethereum address of the sell token", required=True, type=str)
        parser.add_argument("--sell-token-decimals", help="Number of decimals for the sell token", type=int, default=18)
        parser.add_argument("--old-sell-token-address", help="Ethereum address of the old sell token", required=False, type=str)
        parser.add_argument("--market-maker-address", help="Ethereum account of the market maker to analyze", required=True, type=str)
        parser.add_argument("--gdax-price", help="GDAX product (ETH-USD, BTC-USD) to use as the price history source", type=str)
        parser.add_argument("--price-feed", help="Price endpoint to use as the price history source", type=str)
        parser.add_argument("--alternative-price-feed", help="Price endpoint to use as the alternative price history source", type=str)
        parser.add_argument("--order-history", help="Order history endpoint from which to fetch our order history", type=str)
        parser.add_argument("--past-blocks", help="Number of past blocks to analyze", required=True, type=int)
        parser.add_argument("-o", "--output", help="Name of the filename to save to chart to."
                                                   " Will get displayed on-screen if empty", required=False, type=str)
        self.arguments = parser.parse_args(args)

        self.web3 = Web3(HTTPProvider(endpoint_uri=f"http://{self.arguments.rpc_host}:{self.arguments.rpc_port}",
                                      request_kwargs={'timeout': self.arguments.rpc_timeout}))
        self.infura = Web3(HTTPProvider(endpoint_uri=f"https://mainnet.infura.io/", request_kwargs={'timeout': 120}))
        self.buy_token_address = Address(self.arguments.buy_token_address)
        self.sell_token_address = Address(self.arguments.sell_token_address)
        self.old_sell_token_address = Address(self.arguments.old_sell_token_address) if self.arguments.old_sell_token_address else None
        self.sell_token_addresses = list(filter(lambda address: address is not None, [self.sell_token_address, self.old_sell_token_address]))
        self.market_maker_address = Address(self.arguments.market_maker_address)
        self.exchange = ZrxExchange(web3=self.web3, address=Address(self.arguments.exchange_address))

        initialize_charting(self.arguments.output)
        initialize_logging()

    def main(self):
        start_timestamp = get_block_timestamp(self.infura, self.web3.eth.blockNumber - self.arguments.past_blocks)
        end_timestamp = int(time.time())

        events = self.exchange.past_fill(self.arguments.past_blocks, {'maker': self.market_maker_address.address})
        trades = zrx_trades(self.infura, self.market_maker_address, 'DAI', self.buy_token_address, self.arguments.buy_token_decimals, 'WETH', self.sell_token_addresses, self.arguments.sell_token_decimals, events, '-')

        prices = get_prices(self.arguments.gdax_price, self.arguments.price_feed, None, start_timestamp, end_timestamp)
        alternative_prices = get_prices(None, self.arguments.alternative_price_feed, None, start_timestamp, end_timestamp)

        order_history = get_order_history(self.arguments.order_history, start_timestamp, end_timestamp)
        order_history = prepare_order_history_for_charting(order_history)

        draw_chart(start_timestamp, end_timestamp, prices, alternative_prices, 180, order_history, trades, [], self.arguments.output)
Exemplo n.º 2
0
class ZrxMarketMakerPnl:
    """Tool to calculate profitability for the 0x market maker keeper."""
    def __init__(self, args: list):
        parser = argparse.ArgumentParser(prog='0x-market-maker-pnl')
        parser.add_argument("--rpc-host",
                            help="JSON-RPC host (default: `localhost')",
                            default="localhost",
                            type=str)
        parser.add_argument("--rpc-port",
                            help="JSON-RPC port (default: `8545')",
                            default=8545,
                            type=int)
        parser.add_argument("--rpc-timeout",
                            help="JSON-RPC timeout (in seconds, default: 60)",
                            type=int,
                            default=60)
        parser.add_argument("--exchange-address",
                            help="Ethereum address of the 0x contract",
                            required=True,
                            type=str)
        parser.add_argument(
            "--market-maker-address",
            help="Ethereum account of the market maker to analyze",
            required=True,
            type=str)
        parser.add_argument(
            "--gdax-price",
            help=
            "GDAX product (ETH-USD, BTC-USD) to use as the price history source",
            type=str)
        parser.add_argument(
            "--price-feed",
            help="Price endpoint to use as the price history source",
            type=str)
        parser.add_argument("--price-history-file",
                            help="File to use as the price history source",
                            type=str)
        parser.add_argument("--vwap-minutes",
                            help="Rolling VWAP window size (default: 240)",
                            type=int,
                            default=240)
        parser.add_argument("--buy-token",
                            help="Name of the buy token",
                            required=True,
                            type=str)
        parser.add_argument("--buy-token-address",
                            help="Ethereum address of the buy token",
                            required=True,
                            type=str)
        parser.add_argument("--buy-token-decimals",
                            help="Number of decimals for the buy token",
                            type=int,
                            default=18)
        parser.add_argument("--sell-token",
                            help="Name of the sell token",
                            required=True,
                            type=str)
        parser.add_argument("--sell-token-address",
                            help="Ethereum address of the sell token",
                            required=True,
                            type=str)
        parser.add_argument("--sell-token-decimals",
                            help="Number of decimals for the sell token",
                            type=int,
                            default=18)
        parser.add_argument("--old-sell-token-address",
                            help="Ethereum address of the old sell token",
                            required=False,
                            type=str)
        parser.add_argument("--past-blocks",
                            help="Number of past blocks to analyze",
                            required=True,
                            type=int)
        parser.add_argument("-o",
                            "--output",
                            help="File to save the chart or the table to",
                            required=False,
                            type=str)

        parser_mode = parser.add_mutually_exclusive_group(required=True)
        parser_mode.add_argument('--text',
                                 help="Show PnL as a text table",
                                 dest='text',
                                 action='store_true')
        parser_mode.add_argument('--chart',
                                 help="Show PnL on a cumulative graph",
                                 dest='chart',
                                 action='store_true')

        self.arguments = parser.parse_args(args)

        self.web3 = Web3(
            HTTPProvider(
                endpoint_uri=
                f"http://{self.arguments.rpc_host}:{self.arguments.rpc_port}",
                request_kwargs={'timeout': self.arguments.rpc_timeout}))
        self.infura = Web3(
            HTTPProvider(endpoint_uri=f"https://mainnet.infura.io/",
                         request_kwargs={'timeout': 120}))
        self.buy_token_address = Address(self.arguments.buy_token_address)
        self.sell_token_address = Address(self.arguments.sell_token_address)
        self.old_sell_token_address = Address(
            self.arguments.old_sell_token_address
        ) if self.arguments.old_sell_token_address else None
        self.sell_token_addresses = list(
            filter(lambda address: address is not None,
                   [self.sell_token_address, self.old_sell_token_address]))
        self.market_maker_address = Address(
            self.arguments.market_maker_address)
        self.exchange = ZrxExchange(web3=self.web3,
                                    address=Address(
                                        self.arguments.exchange_address))

        if self.arguments.chart and self.arguments.output:
            import matplotlib
            matplotlib.use('Agg')

        logging.basicConfig(
            format='%(asctime)-15s %(levelname)-8s %(message)s',
            level=logging.INFO)
        logging.getLogger("filelock").setLevel(logging.WARNING)

    def main(self):
        start_timestamp = get_block_timestamp(
            self.infura,
            self.web3.eth.blockNumber - self.arguments.past_blocks)
        end_timestamp = int(time.time())

        events = self.exchange.past_fill(
            self.arguments.past_blocks,
            {'maker': self.market_maker_address.address})
        trades = zrx_trades(self.infura, self.market_maker_address,
                            self.arguments.buy_token, self.buy_token_address,
                            self.arguments.buy_token_decimals,
                            self.arguments.sell_token,
                            self.sell_token_addresses,
                            self.arguments.sell_token_decimals, events, '-')
        trades = sort_trades_for_pnl(trades)

        prices = get_prices(self.arguments.gdax_price,
                            self.arguments.price_feed,
                            self.arguments.price_history_file, start_timestamp,
                            end_timestamp)
        vwaps = get_approx_vwaps(prices, self.arguments.vwap_minutes)
        vwaps_start = prices[0].timestamp

        if self.arguments.text:
            pnl_text(trades, vwaps, vwaps_start, self.arguments.buy_token,
                     self.arguments.sell_token, self.arguments.vwap_minutes,
                     self.arguments.output)

        if self.arguments.chart:
            pnl_chart(start_timestamp, end_timestamp, prices, trades, vwaps,
                      vwaps_start, self.arguments.buy_token,
                      self.arguments.sell_token, self.arguments.output)
class RadarRelayMarketMakerChart:
    """Tool to analyze the RadarRelay Market Maker keeper performance."""

    def __init__(self, args: list):
        parser = argparse.ArgumentParser(prog='radarrelay-market-maker-chart')
        parser.add_argument("--rpc-host", help="JSON-RPC host (default: `localhost')", default="localhost", type=str)
        parser.add_argument("--rpc-port", help="JSON-RPC port (default: `8545')", default=8545, type=int)
        parser.add_argument("--exchange-address", help="Ethereum address of the 0x contract", required=True, type=str)
        parser.add_argument("--sai-address", help="Ethereum address of the SAI token", required=True, type=str)
        parser.add_argument("--weth-address", help="Ethereum address of the WETH token", required=True, type=str)
        parser.add_argument("--market-maker-address", help="Ethereum account of the market maker to analyze", required=True, type=str)
        parser.add_argument("--past-blocks", help="Number of past blocks to analyze", required=True, type=int)
        parser.add_argument("-o", "--output", help="Name of the filename to save to chart to."
                                                   " Will get displayed on-screen if empty", required=False, type=str)
        self.arguments = parser.parse_args(args)

        self.web3 = Web3(HTTPProvider(endpoint_uri=f"http://{self.arguments.rpc_host}:{self.arguments.rpc_port}", request_kwargs={'timeout': 120}))
        self.infura = Web3(HTTPProvider(endpoint_uri=f"https://mainnet.infura.io/", request_kwargs={'timeout': 120}))
        self.sai_address = Address(self.arguments.sai_address)
        self.weth_address = Address(self.arguments.weth_address)
        self.market_maker_address = Address(self.arguments.market_maker_address)
        self.exchange = ZrxExchange(web3=self.web3, address=Address(self.arguments.exchange_address))

        if self.arguments.output:
            import matplotlib
            matplotlib.use('Agg')

    def main(self):
        past_trade = self.exchange.past_fill(self.arguments.past_blocks)

        def sell_trades() -> List[Trade]:
            return list(map(lambda log_take: Trade(self.get_event_timestamp(log_take), log_take.filled_buy_amount / log_take.filled_pay_amount, log_take.filled_buy_amount, False, True),
                            filter(lambda log_take: log_take.maker == self.market_maker_address and log_take.buy_token == self.sai_address and log_take.pay_token == self.weth_address, past_trade)))

        def buy_trades() -> List[Trade]:
            return list(map(lambda log_take: Trade(self.get_event_timestamp(log_take), log_take.filled_pay_amount / log_take.filled_buy_amount, log_take.filled_pay_amount, True, False),
                            filter(lambda log_take: log_take.maker == self.market_maker_address and log_take.buy_token == self.weth_address and log_take.pay_token == self.sai_address, past_trade)))

        start_timestamp = self.get_event_timestamp(past_trade[0])
        end_timestamp = int(time.time())

        prices = get_gdax_prices(start_timestamp, end_timestamp)
        trades = sell_trades() + buy_trades()

        self.draw(prices, trades)

    def get_event_timestamp(self, event):
        return self.infura.eth.getBlock(event.raw['blockHash']).timestamp

    def convert_timestamp(self, timestamp):
        from matplotlib.dates import date2num

        return date2num(datetime.datetime.fromtimestamp(timestamp))

    def to_size(self, trade: Trade):
        return amount_in_sai_to_size(trade.value_in_sai)

    def draw(self, prices: List[Price], trades: List[Trade]):
        import matplotlib.dates as md
        import matplotlib.pyplot as plt

        plt.subplots_adjust(bottom=0.2)
        plt.xticks(rotation=25)
        ax=plt.gca()
        ax.xaxis.set_major_formatter(md.DateFormatter('%Y-%m-%d %H:%M:%S'))

        timestamps = list(map(self.convert_timestamp, map(lambda price: price.timestamp, prices)))
        market_prices = list(map(lambda price: price.market_price, prices))
        plt.plot_date(timestamps, market_prices, 'r-', zorder=1)

        sell_trades = list(filter(lambda trade: trade.is_sell, trades))
        sell_x = list(map(self.convert_timestamp, map(lambda trade: trade.timestamp, sell_trades)))
        sell_y = list(map(lambda trade: trade.price, sell_trades))
        sell_s = list(map(self.to_size, sell_trades))
        plt.scatter(x=sell_x, y=sell_y, s=sell_s, c='blue', zorder=2)

        buy_trades = list(filter(lambda trade: trade.is_buy, trades))
        buy_x = list(map(self.convert_timestamp, map(lambda trade: trade.timestamp, buy_trades)))
        buy_y = list(map(lambda trade: trade.price, buy_trades))
        buy_s = list(map(self.to_size, buy_trades))
        plt.scatter(x=buy_x, y=buy_y, s=buy_s, c='green', zorder=2)

        if self.arguments.output:
            plt.savefig(fname=self.arguments.output, dpi=300, bbox_inches='tight', pad_inches=0)
        else:
            plt.show()
Exemplo n.º 4
0
class ZrxMarketMakerTrades:
    """Tool to list historical trades for the 0x market maker keeper."""
    def __init__(self, args: list):
        parser = argparse.ArgumentParser(prog='0x-market-maker-trades')
        parser.add_argument("--rpc-host",
                            help="JSON-RPC host (default: `localhost')",
                            default="localhost",
                            type=str)
        parser.add_argument("--rpc-port",
                            help="JSON-RPC port (default: `8545')",
                            default=8545,
                            type=int)
        parser.add_argument("--rpc-timeout",
                            help="JSON-RPC timeout (in seconds, default: 60)",
                            type=int,
                            default=60)
        parser.add_argument("--exchange-address",
                            help="Ethereum address of the 0x contract",
                            required=True,
                            type=str)
        parser.add_argument(
            "--exchange-name",
            help="Exchange name for including in the JSON file",
            required=True,
            type=str)
        parser.add_argument("--buy-token",
                            help="Name of the buy token",
                            required=True,
                            type=str)
        parser.add_argument("--buy-token-address",
                            help="Ethereum address of the buy token",
                            required=True,
                            type=str)
        parser.add_argument("--buy-token-decimals",
                            help="Number of decimals for the buy token",
                            type=int,
                            default=18)
        parser.add_argument("--sell-token",
                            help="Name of the sell token",
                            required=True,
                            type=str)
        parser.add_argument("--sell-token-address",
                            help="Ethereum address of the sell token",
                            required=True,
                            type=str)
        parser.add_argument("--sell-token-decimals",
                            help="Number of decimals for the sell token",
                            type=int,
                            default=18)
        parser.add_argument("--old-sell-token-address",
                            help="Ethereum address of the old sell token",
                            required=False,
                            type=str)
        parser.add_argument(
            "--market-maker-address",
            help="Ethereum account of the market maker to analyze",
            required=True,
            type=str)
        parser.add_argument("--past-blocks",
                            help="Number of past blocks to analyze",
                            required=True,
                            type=int)
        parser.add_argument("-o",
                            "--output",
                            help="File to save the table or the JSON to",
                            required=False,
                            type=str)

        parser_mode = parser.add_mutually_exclusive_group(required=True)
        parser_mode.add_argument('--text',
                                 help="List trades as a text table",
                                 dest='text',
                                 action='store_true')
        parser_mode.add_argument('--json',
                                 help="List trades as a JSON document",
                                 dest='json',
                                 action='store_true')

        self.arguments = parser.parse_args(args)

        self.web3 = Web3(
            HTTPProvider(
                endpoint_uri=
                f"http://{self.arguments.rpc_host}:{self.arguments.rpc_port}",
                request_kwargs={'timeout': self.arguments.rpc_timeout}))
        self.infura = Web3(
            HTTPProvider(endpoint_uri=f"https://mainnet.infura.io/",
                         request_kwargs={'timeout': 120}))
        self.buy_token_address = Address(self.arguments.buy_token_address)
        self.sell_token_address = Address(self.arguments.sell_token_address)
        self.old_sell_token_address = Address(
            self.arguments.old_sell_token_address
        ) if self.arguments.old_sell_token_address else None
        self.sell_token_addresses = list(
            filter(lambda address: address is not None,
                   [self.sell_token_address, self.old_sell_token_address]))
        self.market_maker_address = Address(
            self.arguments.market_maker_address)
        self.exchange = ZrxExchange(web3=self.web3,
                                    address=Address(
                                        self.arguments.exchange_address))

        logging.basicConfig(
            format='%(asctime)-15s %(levelname)-8s %(message)s',
            level=logging.INFO)
        logging.getLogger("filelock").setLevel(logging.WARNING)

    def main(self):
        past_fills = self.exchange.past_fill(
            self.arguments.past_blocks,
            {'maker': self.market_maker_address.address})
        trades = zrx_trades(self.infura, self.market_maker_address,
                            self.arguments.buy_token, self.buy_token_address,
                            self.arguments.buy_token_decimals,
                            self.arguments.sell_token,
                            self.sell_token_addresses,
                            self.arguments.sell_token_decimals, past_fills,
                            self.arguments.exchange_name)
        trades = sort_trades(trades)

        if self.arguments.text:
            text_trades(self.arguments.buy_token,
                        self.arguments.sell_token,
                        trades,
                        self.arguments.output,
                        include_taker=True)

        if self.arguments.json:
            json_trades(trades, self.arguments.output, include_taker=True)