示例#1
0
    def __init__(self, args: list):
        parser = argparse.ArgumentParser(prog='oasis-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("--oasis-address", help="Ethereum address of the OasisDEX contract", 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("--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("--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.buy_token = self.arguments.buy_token
        self.buy_token_address = Address(self.arguments.buy_token_address)
        self.sell_token = self.arguments.sell_token
        self.sell_token_address = Address(self.arguments.sell_token_address)
        self.market_maker_address = Address(self.arguments.market_maker_address)
        self.otc = SimpleMarket(web3=self.web3, address=Address(self.arguments.oasis_address))

        logging.basicConfig(format='%(asctime)-15s %(levelname)-8s %(message)s', level=logging.INFO)
        logging.getLogger("filelock").setLevel(logging.WARNING)
示例#2
0
    def __init__(self, args: list):
        parser = argparse.ArgumentParser(prog='oasis-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("--oasis-address", help="Ethereum address of the OasisDEX contract", 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("--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("--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("--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.market_maker_address = Address(self.arguments.market_maker_address)
        self.otc = SimpleMarket(web3=self.web3, address=Address(self.arguments.oasis_address))

        initialize_charting(self.arguments.output)
        initialize_logging()
    def __init__(self, args: list):
        parser = argparse.ArgumentParser(prog='oasis-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("--oasis-address",
                            help="Ethereum address of the OasisDEX 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.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.otc = SimpleMarket(web3=self.web3,
                                address=Address(self.arguments.oasis_address))

        if self.arguments.output:
            import matplotlib
            matplotlib.use('Agg')
示例#4
0
    def __init__(self, args: list):
        parser = argparse.ArgumentParser(prog='mkr-price-history')
        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("--oasis-address", help="Ethereum address of the OasisDEX contract", required=True, type=str)
        parser.add_argument("--mkr-address", help="Ethereum address of the MKR token", required=True, type=str)
        parser.add_argument("--weth-address", help="Ethereum address of the WETH token", required=True, type=str)
        parser.add_argument("--past-blocks", help="Number of past blocks to analyze", required=True, type=int)
        parser.add_argument("--target-mkr-eth-history-file", type=str, help="Target file for the MKR/ETH price history")
        parser.add_argument("--target-mkr-btc-history-file", type=str, help="Target file for the MKR/BTC price history")
        parser.add_argument("--target-mkr-usd-history-file", type=str, help="Target file for the MKR/USD price history")

        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.mkr_address = Address(self.arguments.mkr_address)
        self.weth_address = Address(self.arguments.weth_address)
        self.otc = SimpleMarket(web3=self.web3, address=Address(self.arguments.oasis_address))

        logging.basicConfig(format='%(asctime)-15s %(levelname)-8s %(message)s', level=logging.INFO)
        logging.getLogger("filelock").setLevel(logging.WARNING)
示例#5
0
 def test_fail_when_no_contract_under_that_address(self):
     # expect
     with pytest.raises(Exception):
         SimpleMarket(
             web3=self.web3,
             address=Address('0xdeadadd1e5500000000000000000000000000000'))
示例#6
0
 def setup_method(self):
     GeneralMarketTest.setup_method(self)
     self.otc = SimpleMarket.deploy(self.web3)
class OasisMarketMakerChart:
    """Tool to analyze the OasisDEX Market Maker keeper performance."""
    def __init__(self, args: list):
        parser = argparse.ArgumentParser(prog='oasis-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("--oasis-address",
                            help="Ethereum address of the OasisDEX 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.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.otc = SimpleMarket(web3=self.web3,
                                address=Address(self.arguments.oasis_address))

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

    def main(self):
        past_make = self.otc.past_make(self.arguments.past_blocks)
        past_take = self.otc.past_take(self.arguments.past_blocks)
        past_kill = self.otc.past_kill(self.arguments.past_blocks)

        def reduce_func(states, timestamp):
            if len(states) == 0:
                order_book = []
            else:
                order_book = states[-1].order_book

            # apply all LogMake events having this timestamp
            for log_make in filter(
                    lambda log_make: log_make.timestamp == timestamp,
                    past_make):
                order_book = self.apply_make(order_book, log_make)
                order_book = list(
                    filter(
                        lambda order: order.maker == self.market_maker_address,
                        order_book))

            # apply all LogTake events having this timestamp
            for log_take in filter(
                    lambda log_take: log_take.timestamp == timestamp,
                    past_take):
                order_book = self.apply_take(order_book, log_take)

            # apply all LogKill events having this timestamp
            for log_kill in filter(
                    lambda log_kill: log_kill.timestamp == timestamp,
                    past_kill):
                order_book = self.apply_kill(order_book, log_kill)

            return states + [
                State(timestamp=timestamp,
                      order_book=order_book,
                      market_price=None,
                      sai_address=self.sai_address,
                      weth_address=self.weth_address)
            ]

        def sell_trades() -> List[Trade]:
            regular = map(
                lambda log_take: Trade(
                    log_take.timestamp, log_take.give_amount / log_take.
                    take_amount, log_take.give_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_take))
            matched = map(
                lambda log_take: Trade(
                    log_take.timestamp, log_take.take_amount / log_take.
                    give_amount, log_take.take_amount, False, True),
                filter(
                    lambda log_take: log_take.taker == self.
                    market_maker_address and log_take.buy_token == self.
                    weth_address and log_take.pay_token == self.sai_address,
                    past_take))
            return list(regular) + list(matched)

        def buy_trades() -> List[Trade]:
            regular = map(
                lambda log_take: Trade(
                    log_take.timestamp, log_take.take_amount / log_take.
                    give_amount, log_take.take_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_take))
            matched = map(
                lambda log_take: Trade(
                    log_take.timestamp, log_take.give_amount / log_take.
                    take_amount, log_take.give_amount, True, False),
                filter(
                    lambda log_take: log_take.taker == self.
                    market_maker_address and log_take.buy_token == self.
                    sai_address and log_take.pay_token == self.weth_address,
                    past_take))
            return list(regular) + list(matched)

        event_timestamps = sorted(
            set(
                map(lambda event: event.timestamp,
                    past_make + past_take + past_kill)))
        oasis_states = reduce(reduce_func, event_timestamps, [])
        gdax_states = self.get_gdax_states(event_timestamps)

        states = sorted(oasis_states + gdax_states,
                        key=lambda state: state.timestamp)
        states = self.consolidate_states(states)

        trades = sell_trades() + buy_trades()

        self.draw(states, trades)

    def consolidate_states(self, states):
        last_market_price = None
        last_order_book = []
        for i in range(0, len(states)):
            state = states[i]

            if state.order_book is None:
                state.order_book = last_order_book
            if state.market_price is None:
                state.market_price = last_market_price

            last_order_book = state.order_book
            last_market_price = state.market_price

        return states

    def get_gdax_states(self, timestamps: List[int]):
        first_timestamp = timestamps[0]
        last_timestamp = max(timestamps[-1], int(time.time()))

        states = []
        timestamp = first_timestamp
        while timestamp <= last_timestamp:
            timestamp_range_start = timestamp
            timestamp_range_end = int(
                (datetime.datetime.fromtimestamp(timestamp) +
                 datetime.timedelta(hours=3)).timestamp())
            states = states + list(
                filter(
                    lambda state: state.timestamp >= first_timestamp and state.
                    timestamp <= last_timestamp,
                    self.get_gdax_partial(timestamp_range_start,
                                          timestamp_range_end)))
            timestamp = timestamp_range_end

        return states

    def get_gdax_partial(self, timestamp_range_start: int,
                         timestamp_range_end: int):
        start = datetime.datetime.fromtimestamp(timestamp_range_start,
                                                pytz.UTC)
        end = datetime.datetime.fromtimestamp(timestamp_range_end, pytz.UTC)

        url = f"https://api.gdax.com/products/ETH-USD/candles?" \
              f"start={iso_8601(start)}&" \
              f"end={iso_8601(end)}&" \
              f"granularity=60"

        print(f"Downloading: {url}")

        # data is: [[ time, low, high, open, close, volume ], [...]]
        try:
            data = requests.get(url).json()
        except:
            print("GDAX API network error, waiting 10 secs...")
            time.sleep(10)
            return self.get_gdax_partial(timestamp_range_start,
                                         timestamp_range_end)

        if 'message' in data:
            print("GDAX API rate limiting, slowing down for 2 secs...")
            time.sleep(2)
            return self.get_gdax_partial(timestamp_range_start,
                                         timestamp_range_end)
        else:
            return list(
                map(
                    lambda array: State(
                        timestamp=array[0],
                        order_book=None,
                        market_price=array[3],  # array[3] is 'open'
                        sai_address=self.sai_address,
                        weth_address=self.weth_address),
                    data))

    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, states: List[State], 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 state: state.timestamp, states)))
        closest_sell_prices = list(
            map(lambda state: state.closest_sell_price(), states))
        closest_buy_prices = list(
            map(lambda state: state.closest_buy_price(), states))
        market_prices = list(map(lambda state: state.market_price, states))

        plt.plot_date(timestamps, closest_sell_prices, 'b-', zorder=1)
        plt.plot_date(timestamps, closest_buy_prices, 'g-', zorder=1)
        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()

    def apply_make(self, order_book: List[Order],
                   log_make: LogMake) -> List[Order]:
        return order_book + [
            Order(self.otc,
                  order_id=log_make.order_id,
                  pay_amount=log_make.pay_amount,
                  pay_token=log_make.pay_token,
                  buy_amount=log_make.buy_amount,
                  buy_token=log_make.buy_token,
                  maker=log_make.maker,
                  timestamp=log_make.timestamp)
        ]

    def apply_take(self, order_book: List[Order], log_take: LogTake):
        this_order = next(
            filter(lambda order: order.order_id == log_take.order_id,
                   order_book), None)

        if this_order is not None:
            assert this_order.pay_token == log_take.pay_token
            assert this_order.buy_token == log_take.buy_token

            remaining_orders = list(
                filter(lambda order: order.order_id != log_take.order_id,
                       order_book))
            this_order = Order(
                self.otc,
                order_id=this_order.order_id,
                pay_amount=this_order.pay_amount - log_take.take_amount,
                pay_token=this_order.pay_token,
                buy_amount=this_order.buy_amount - log_take.give_amount,
                buy_token=this_order.buy_token,
                maker=this_order.maker,
                timestamp=this_order.timestamp)

            if this_order.pay_amount > Wad(0) and this_order.buy_amount > Wad(
                    0):
                return remaining_orders + [this_order]
            else:
                return remaining_orders
        else:
            return order_book

    def apply_kill(self, order_book: List[Order],
                   log_kill: LogKill) -> List[Order]:
        return list(
            filter(lambda order: order.order_id != log_kill.order_id,
                   order_book))
示例#8
0
class OasisMarketMakerChart:
    """Tool to generate a chart displaying the OasisDEX market maker keeper trades."""

    def __init__(self, args: list):
        parser = argparse.ArgumentParser(prog='oasis-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("--oasis-address", help="Ethereum address of the OasisDEX contract", 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("--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("--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("--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.market_maker_address = Address(self.arguments.market_maker_address)
        self.otc = SimpleMarket(web3=self.web3, address=Address(self.arguments.oasis_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())

        # If we only fetch log events from the last `past_blocks` blocks, the left hand side of the chart
        # will have some bid and ask lines missing as these orders were very likely created some blocks
        # earlier. So we also retrieve events from the blocks from the 24h before in order to minimize
        # the chance of it happening.
        block_lookback = 15*60*24

        past_make = self.otc.past_make(self.arguments.past_blocks + block_lookback)
        past_take = self.otc.past_take(self.arguments.past_blocks + block_lookback)
        past_kill = self.otc.past_kill(self.arguments.past_blocks + block_lookback)

        def reduce_func(states, timestamp):
            if len(states) == 0:
                order_book = []
            else:
                order_book = states[-1].order_book

            # apply all LogMake events having this timestamp
            for log_make in filter(lambda log_make: log_make.timestamp == timestamp, past_make):
                order_book = self.apply_make(order_book, log_make)
                order_book = list(filter(lambda order: order.maker == self.market_maker_address, order_book))

            # apply all LogTake events having this timestamp
            for log_take in filter(lambda log_take: log_take.timestamp == timestamp, past_take):
                order_book = self.apply_take(order_book, log_take)

            # apply all LogKill events having this timestamp
            for log_kill in filter(lambda log_kill: log_kill.timestamp == timestamp, past_kill):
                order_book = self.apply_kill(order_book, log_kill)

            return states + [State(timestamp=timestamp,
                                   order_book=order_book,
                                   buy_token_address=self.buy_token_address,
                                   sell_token_address=self.sell_token_address)]

        event_timestamps = sorted(set(map(lambda event: event.timestamp, past_make + past_take + past_kill)))
        states_timestamps = self.tighten_timestamps(event_timestamps) + [end_timestamp]
        states = list(filter(lambda state: state.timestamp >= start_timestamp, reduce(reduce_func, states_timestamps, [])))
        states = sorted(states, key=lambda state: state.timestamp)

        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)

        takes = list(filter(lambda log_take: log_take.timestamp >= start_timestamp, past_take))
        pair = self.arguments.sell_token + "-" + self.arguments.buy_token
        our_trades = our_oasis_trades(self.market_maker_address, self.buy_token_address, self.sell_token_address, takes, pair)
        all_trades = all_oasis_trades(self.buy_token_address, self.sell_token_address, takes, pair)

        draw_chart(start_timestamp, end_timestamp, prices, alternative_prices, 180, states, our_trades, all_trades, self.arguments.output)

    def tighten_timestamps(self, timestamps: list) -> list:
        if len(timestamps) == 0:
            return []

        result = [timestamps[0]]
        for index in range(1, len(timestamps)):
            last_ts = timestamps[index-1]
            while True:
                last_ts += 60
                if last_ts >= timestamps[index]:
                    break
                result.append(last_ts)

            result.append(timestamps[index])

        return result

    def apply_make(self, order_book: List[Order], log_make: LogMake) -> List[Order]:
        return order_book + [Order(self.otc,
                                   order_id=log_make.order_id,
                                   pay_amount=log_make.pay_amount,
                                   pay_token=log_make.pay_token,
                                   buy_amount=log_make.buy_amount,
                                   buy_token=log_make.buy_token,
                                   maker=log_make.maker,
                                   timestamp=log_make.timestamp)]

    def apply_take(self, order_book: List[Order], log_take: LogTake):
        this_order = next(filter(lambda order: order.order_id == log_take.order_id, order_book), None)

        if this_order is not None:
            assert this_order.pay_token == log_take.pay_token
            assert this_order.buy_token == log_take.buy_token

            remaining_orders = list(filter(lambda order: order.order_id != log_take.order_id, order_book))
            this_order = Order(self.otc,
                               order_id=this_order.order_id,
                               pay_amount=this_order.pay_amount - log_take.take_amount,
                               pay_token=this_order.pay_token,
                               buy_amount=this_order.buy_amount - log_take.give_amount,
                               buy_token=this_order.buy_token,
                               maker=this_order.maker,
                               timestamp=this_order.timestamp)

            if this_order.pay_amount > Wad(0) and this_order.buy_amount > Wad(0):
                return remaining_orders + [this_order]
            else:
                return remaining_orders
        else:
            return order_book

    def apply_kill(self, order_book: List[Order], log_kill: LogKill) -> List[Order]:
        return list(filter(lambda order: order.order_id != log_kill.order_id, order_book))
示例#9
0
from web3 import HTTPProvider, Web3

from pymaker import Address, Contract
from pymaker.oasis import SimpleMarket
from pymaker.sai import Tub, Tap
from pymaker.token import ERC20Token
from pymaker.numeric import Ray

market_contract = '0x14FBCA95be7e99C15Cc2996c6C9d841e54B79425'
w_eth_address = '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2'
dai_eth_address = '0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359'

web3 = Web3(HTTPProvider(endpoint_uri=mainnet))

# Over the counter
otc = SimpleMarket(web3=web3, address=Address(market_contract))
otc.get_orders(pay_token=Address(w_eth_address),
               buy_token=Address(dai_eth_address))


# New Class
class ArbExp(SimpleMarket):
    def __init__(self, **kwargs):
        super(ArbExp, self).__init__(**kwargs)

    def get_orders_x(self,
                     pay_token: Address = None,
                     buy_token: Address = None,
                     norders=10):
        """Get all active orders.
示例#10
0
class MkrPriceHistory:
    """Tool to dump archival MKR price history from Oasis for MKR market making PnL calculation."""

    def __init__(self, args: list):
        parser = argparse.ArgumentParser(prog='mkr-price-history')
        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("--oasis-address", help="Ethereum address of the OasisDEX contract", required=True, type=str)
        parser.add_argument("--mkr-address", help="Ethereum address of the MKR token", required=True, type=str)
        parser.add_argument("--weth-address", help="Ethereum address of the WETH token", required=True, type=str)
        parser.add_argument("--past-blocks", help="Number of past blocks to analyze", required=True, type=int)
        parser.add_argument("--target-mkr-eth-history-file", type=str, help="Target file for the MKR/ETH price history")
        parser.add_argument("--target-mkr-btc-history-file", type=str, help="Target file for the MKR/BTC price history")
        parser.add_argument("--target-mkr-usd-history-file", type=str, help="Target file for the MKR/USD price history")

        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.mkr_address = Address(self.arguments.mkr_address)
        self.weth_address = Address(self.arguments.weth_address)
        self.otc = SimpleMarket(web3=self.web3, address=Address(self.arguments.oasis_address))

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

    def main(self):
        # Get Oasis take events from which we will get the main MKR/ETH price source
        takes = self.otc.past_take(self.arguments.past_blocks)
        start_timestamp = min(map(lambda log_take: log_take.timestamp, takes))
        end_timestamp = max(map(lambda log_take: log_take.timestamp, takes))

        # Get auxiliary prices (ETH/USD and BTC/USD)
        prices_eth_usd = get_gdax_prices('ETH-USD', start_timestamp, end_timestamp)
        prices_btc_usd = get_gdax_prices('BTC-USD', start_timestamp, end_timestamp)

        prices_mkr_eth = self.get_mkr_eth_prices(takes)
        prices_mkr_usd = self.convert_prices(prices_mkr_eth, prices_eth_usd, operator.mul)
        prices_mkr_btc = self.convert_prices(prices_mkr_usd, prices_btc_usd, operator.truediv)

        self.save_prices(prices_mkr_eth, self.arguments.target_mkr_eth_history_file)
        self.save_prices(prices_mkr_btc, self.arguments.target_mkr_btc_history_file)
        self.save_prices(prices_mkr_usd, self.arguments.target_mkr_usd_history_file)

    def get_mkr_eth_prices(self, takes):
        takes_1 = filter(lambda log_take: log_take.buy_token == self.mkr_address and log_take.pay_token == self.weth_address, takes)
        takes_2 = filter(lambda log_take: log_take.buy_token == self.weth_address and log_take.pay_token == self.mkr_address, takes)

        prices_mkr_eth = list(map(lambda log_take: Price(timestamp=log_take.timestamp,
                                                         price=float(log_take.take_amount / log_take.give_amount),
                                                         buy_price=None,
                                                         sell_price=None,
                                                         volume=float(log_take.give_amount)), takes_1)) \
                         + list(map(lambda log_take: Price(timestamp=log_take.timestamp,
                                                           price=float(log_take.give_amount / log_take.take_amount),
                                                           buy_price=None,
                                                           sell_price=None,
                                                           volume=float(log_take.take_amount)), takes_2))

        return prices_mkr_eth

    def convert_prices(self, source: List[Price], target: List[Price], operator):
        result = []
        for price in source:
            matching_target = next(filter(lambda target_price: target_price.timestamp >= price.timestamp, target), None)
            if matching_target is not None:
                result.append(Price(timestamp=price.timestamp,
                                    price=operator(price.price, matching_target.price),
                                    buy_price=None,
                                    sell_price=None,
                                    volume=price.volume))
            else:
                logging.warning(f"No matching price found at {price.timestamp}")

        return result

    def save_prices(self, prices: List[Price], filename: Optional[str]):
        if filename is not None:
            with open(filename, "w") as file:
                for price in prices:
                    file.write(json.dumps({"timestamp": price.timestamp,
                                           "price": float(price.price),
                                           "volume": float(price.volume)}) + "\n")