Esempio n. 1
0
class Market:
    def __init__(self):
        self.name = self.__class__.__name__
        self.btc_balance = 0.0
        self.eur_balance = 0.0
        self.usd_balance = 0.0
        self.fc = FiatConverter()

    def __str__(self):
        return "%s: %s" % (
            self.name,
            str(
                {
                    "btc_balance": self.btc_balance,
                    "eur_balance": self.eur_balance,
                    "usd_balance": self.usd_balance,
                }
            ),
        )

    def buy(self, amount, price):
        """Orders are always priced in USD"""
        local_currency_price = self.fc.convert(price, "USD", self.currency)
        logging.info(
            "Buy %f BTC at %f %s (%f USD) @%s"
            % (amount, local_currency_price, self.currency, price, self.name)
        )
        self._buy(amount, local_currency_price)

    def sell(self, amount, price):
        """Orders are always priced in USD"""
        local_currency_price = self.fc.convert(price, "USD", self.currency)
        logging.info(
            "Sell %f BTC at %f %s (%f USD) @%s"
            % (amount, local_currency_price, self.currency, price, self.name)
        )
        self._sell(amount, local_currency_price)

    def _buy(self, amount, price):
        raise NotImplementedError("%s.sell(self, amount, price)" % self.name)

    def _sell(self, amount, price):
        raise NotImplementedError("%s.sell(self, amount, price)" % self.name)

    def deposit(self):
        raise NotImplementedError("%s.sell(self, amount, price)" % self.name)

    def withdraw(self, amount, address):
        raise NotImplementedError("%s.sell(self, amount, price)" % self.name)

    def get_info(self):
        raise NotImplementedError("%s.sell(self, amount, price)" % self.name)
Esempio n. 2
0
class Market:
    def __init__(self):
        self.name = self.__class__.__name__
        self.btc_balance = 0.0
        self.eur_balance = 0.0
        self.usd_balance = 0.0
        self.fc = FiatConverter()

    def __str__(self):
        return "%s: %s" % (
            self.name,
            str({
                "btc_balance": self.btc_balance,
                "eur_balance": self.eur_balance,
                "usd_balance": self.usd_balance,
            }),
        )

    def buy(self, amount, price):
        """Orders are always priced in USD"""
        local_currency_price = self.fc.convert(price, "USD", self.currency)
        logging.info(
            "Buy %f BTC at %f %s (%f USD) @%s" %
            (amount, local_currency_price, self.currency, price, self.name))
        self._buy(amount, local_currency_price)

    def sell(self, amount, price):
        """Orders are always priced in USD"""
        local_currency_price = self.fc.convert(price, "USD", self.currency)
        logging.info(
            "Sell %f BTC at %f %s (%f USD) @%s" %
            (amount, local_currency_price, self.currency, price, self.name))
        self._sell(amount, local_currency_price)

    def _buy(self, amount, price):
        raise NotImplementedError("%s.sell(self, amount, price)" % self.name)

    def _sell(self, amount, price):
        raise NotImplementedError("%s.sell(self, amount, price)" % self.name)

    def deposit(self):
        raise NotImplementedError("%s.sell(self, amount, price)" % self.name)

    def withdraw(self, amount, address):
        raise NotImplementedError("%s.sell(self, amount, price)" % self.name)

    def get_info(self):
        raise NotImplementedError("%s.sell(self, amount, price)" % self.name)
Esempio n. 3
0
class Market(object):
    def __init__(self, currency):
        self.name = self.__class__.__name__
        self.currency = currency
        self.depth_updated = 0
        self.update_rate = 60
        self.fc = FiatConverter()
        self.fc.update()

    def get_depth(self):
        timediff = time.time() - self.depth_updated
        if timediff > self.update_rate:
            self.ask_update_depth()
        timediff = time.time() - self.depth_updated
        if timediff > config.market_expiration_time:
            logging.warn("Market: %s order book is expired" % self.name)
            self.depth = {"asks": [{"price": 0, "amount": 0}], "bids": [{"price": 0, "amount": 0}]}
        return self.depth

    def convert_to_usd(self):
        if self.currency == "USD":
            return
        for direction in ("asks", "bids"):
            for order in self.depth[direction]:
                order["price"] = self.fc.convert(order["price"], self.currency, "USD")

    def ask_update_depth(self):
        try:
            self.update_depth()
            self.convert_to_usd()
            self.depth_updated = time.time()
        except (urllib.error.HTTPError, urllib.error.URLError) as e:
            logging.error("HTTPError, can't update market: %s" % self.name)
            log_exception(logging.DEBUG)
        except Exception as e:
            logging.error("Can't update market: %s - %s" % (self.name, str(e)))
            log_exception(logging.DEBUG)

    def get_ticker(self):
        depth = self.get_depth()
        res = {"ask": 0, "bid": 0}
        if len(depth["asks"]) > 0 and len(depth["bids"]) > 0:
            res = {"ask": depth["asks"][0], "bid": depth["bids"][0]}
        return res

    ## Abstract methods
    def update_depth(self):
        pass

    def buy(self, price, amount):
        pass

    def sell(self, price, amount):
        pass
Esempio n. 4
0
class Market(object):
    def __init__(self, currency):
        self.name = self.__class__.__name__
        self.currency = currency
        self.depth_updated = 0
        self.update_rate = 60
        self.fc = FiatConverter()
        self.fc.update()

    def get_depth(self):
        timediff = time.time() - self.depth_updated
        if timediff > self.update_rate:
            self.ask_update_depth()
        timediff = time.time() - self.depth_updated
        if timediff > config.market_expiration_time:
            logging.warn("Market: %s order book is expired" % self.name)
            self.depth = {
                "asks": [{
                    "price": 0,
                    "amount": 0
                }],
                "bids": [{
                    "price": 0,
                    "amount": 0
                }]
            }
        return self.depth

    def convert_to_usd(self):
        if self.currency == "USD":
            return
        for direction in ("asks", "bids"):
            for order in self.depth[direction]:
                order["price"] = self.fc.convert(order["price"], self.currency,
                                                 "USD")

    def ask_update_depth(self):
        try:
            self.update_depth()
            self.convert_to_usd()
            self.depth_updated = time.time()
        except (urllib.error.HTTPError, urllib.error.URLError) as e:
            logging.error("HTTPError, can't update market: %s" % self.name)
            log_exception(logging.DEBUG)
        except Exception as e:
            logging.error("Can't update market: %s - %s" % (self.name, str(e)))
            log_exception(logging.DEBUG)

    def get_ticker(self):
        depth = self.get_depth()
        res = {"ask": 0, "bid": 0}
        if len(depth["asks"]) > 0 and len(depth["bids"]) > 0:
            res = {"ask": depth["asks"][0], "bid": depth["bids"][0]}
        return res

    ## Abstract methods
    def update_depth(self):
        pass

    def buy(self, price, amount):
        pass

    def sell(self, price, amount):
        pass
Esempio n. 5
0
class Market(object):
    def __init__(self, currency):
        self.name = self.__class__.__name__
        self.currency = currency
        self.depth_updated = 0
        self.update_rate = 0.5
        self.isWebsocket = False
        self.shouldReportWebsocketTimeout = False
        if currency == "BTC":
            self.fiat = False
        else:
            self.fiat = True
            self.fc = FiatConverter()
            self.fc.update()

    def get_depth(self):
        timediff = time.time() - self.depth_updated
        if timediff > self.update_rate:
            self.ask_update_depth()
        timediff = time.time() - self.depth_updated
        if timediff > config.market_expiration_time:
            _str = 'Market: %s order book is expired' % self.name
            logging.warn(_str)
            send_message(_str)
            self.depth = {
                'asks': [{
                    'price': 0,
                    'amount': 0
                }],
                'bids': [{
                    'price': 0,
                    'amount': 0
                }]
            }
            raise Exception('get depth timeout.')
        return self.depth

    def convert_to_usd(self):
        if self.currency == "USD":
            return
        for direction in ("asks", "bids"):
            for order in self.depth[direction]:
                order["price"] = self.fc.convert(order["price"], self.currency,
                                                 "USD")

    def ask_update_depth(self):
        try:
            self.update_depth()
            if self.fiat:
                self.convert_to_usd()
            self.depth_updated = time.time()
            self.shouldReportWebsocketTimeout = True
        except (urllib.error.HTTPError, urllib.error.URLError) as e:
            logging.error("HTTPError, can't update market: %s" % self.name)
            log_exception(logging.DEBUG)
        except Exception as e:
            if not self.isWebsocket:
                logging.error("Can't update market: %s - %s" %
                              (self.name, str(e)))
                log_exception(logging.DEBUG)
            else:
                #don't repeat report
                if self.shouldReportWebsocketTimeout:
                    logging.error(str(e))
                    self.shouldReportWebsocketTimeout = False

    def get_ticker(self):
        depth = self.get_depth()
        res = {'ask': 0, 'bid': 0}
        if len(depth['asks']) > 0 and len(depth["bids"]) > 0:
            res = {'ask': depth['asks'][0], 'bid': depth['bids'][0]}
        return res

    ## Abstract methods
    def update_depth(self):
        pass

    def buy(self, price, amount):
        pass

    def sell(self, price, amount):
        pass
Esempio n. 6
0
class Market(object):
    def __init__(self, currency):
        self.name = self.__class__.__name__
        self.currency = currency
        self.depth_updated = 0
        self.update_rate = 60
        self.fc = FiatConverter()
        self.fc.update()

    def get_depth(self):
        """
        @todo Use websocket and reduce the update_rate to realtime, only fall back to RESTful when wss is broken.
        """
        timediff = time.time() - self.depth_updated
        if timediff > self.update_rate:
            self.ask_update_depth()
        timediff = time.time() - self.depth_updated
        if timediff > config.market_expiration_time:  # depth data not updated properly. why? FIXME
            logging.warn("Market: %s order book is expired" % self.name)
            self.depth = {
                "asks": [{
                    "price": 0,
                    "amount": 0
                }],
                "bids": [{
                    "price": 0,
                    "amount": 0
                }]
            }
        return self.depth

    def convert_to_usd(self):
        if self.currency == "USD":
            return
        for direction in ("asks", "bids"):
            for order in self.depth[direction]:
                order["price"] = self.fc.convert(order["price"], self.currency,
                                                 "USD")

    def ask_update_depth(self):
        try:
            self.update_depth()
            self.convert_to_usd()
            self.depth_updated = time.time()
        except (urllib.error.HTTPError, urllib.error.URLError) as e:
            logging.error("HTTPError, can't update market: %s" % self.name)
            log_exception(logging.DEBUG)
        except Exception as e:
            logging.error("Can't update market: %s - %s" % (self.name, str(e)))
            log_exception(logging.DEBUG)

    def get_ticker(self):
        depth = self.get_depth()
        res = {"ask": 0, "bid": 0}
        if len(depth["asks"]) > 0 and len(depth["bids"]) > 0:
            res = {"ask": depth["asks"][0], "bid": depth["bids"][0]}
        return res

    ## Abstract methods
    def update_depth(self):
        pass

    def buy(self, price, amount):
        pass

    def sell(self, price, amount):
        pass

    def _depth_pct(self, pct):
        bid1 = float(self.depth['bids'][0]['price'])
        ask1 = float(self.depth['asks'][0]['price'])
        fair = bid1 * 0.5 + ask1 * 0.5
        ceiling, floor = fair * (1 + pct / 100), fair * (1 - pct / 100)

        bid_sum = 0
        for bid in self.depth['bids']:
            if float(bid['price']) > floor:
                bid_sum += float(bid['amount'])
            else:
                break

        ask_sum = 0
        for ask in self.depth['asks']:
            if float(ask['price']) < ceiling:
                ask_sum += float(ask['amount'])
            else:
                break

        def _f(v):
            return int(v * 100) / 100

        return 'pct depth [bid, ask]: [ %s, %s ]' % (_f(bid_sum), _f(ask_sum))

    def depth_1pct(self):
        return self._depth_pct(1)

    def depth_01pct(self):
        return self._depth_pct(0.1)
Esempio n. 7
0
class Market(object):
    def __init__(self, currency, cryptowatch_code=None):
        self.name = self.__class__.__name__
        self.currency = currency
        self.cryptowatch_code = cryptowatch_code
        self.cryptowatch_price = 0
        self.depth_updated = 0
        self.update_rate = 60
        self.fc = FiatConverter()
        self.fc.update()

    def get_cryptowatch_price(self):
        if not self.cryptowatch_code:
            return

        url = ('https://api.cryptowat.ch/markets/' +
               self.name.lower().replace('usd', '').replace('eur', '') + '/' +
               self.cryptowatch_code + '/price')

        res = urllib.request.urlopen(url)
        jsonstr = res.read().decode('utf8')
        try:
            price = json.loads(jsonstr)
        except Exception:
            logging.error("Cryptowatch %s - Can't parse json: %s" %
                          (self.name, jsonstr))
        self.cryptowatch_price = self.fc.convert(price["result"]["price"],
                                                 self.currency, "USD")

    def double_ckeck_price(self, price, direction, allowed_percent=None):
        if self.cryptowatch_price == 0:
            self.get_cryptowatch_price()

        allowed_percent = allowed_percent if allowed_percent else 10

        if abs(price - self.cryptowatch_price
               ) > self.cryptowatch_price * allowed_percent / 100:
            logging.error(
                "Big diff. @%s depth price(%s) vs Cryptowatch price %f / %f" %
                (self.name, direction, price, self.cryptowatch_price))
            return False

        return True

    def get_depth(self):
        timediff = time.time() - self.depth_updated
        if timediff > self.update_rate:
            self.ask_update_depth()
        timediff = time.time() - self.depth_updated
        if timediff > config.market_expiration_time:
            logging.warning('Market: %s order book is expired' % self.name)
            self.depth = {
                'asks': [{
                    'price': 0,
                    'amount': 0
                }],
                'bids': [{
                    'price': 0,
                    'amount': 0
                }]
            }
        return self.depth

    def convert_to_usd(self):
        if self.currency == "USD":
            return
        for direction in ("asks", "bids"):
            for order in self.depth[direction]:
                # self.double_ckeck_price(order["price"], direction, order)
                # we don't do it here any more
                order["price"] = self.fc.convert(order["price"], self.currency,
                                                 "USD")

    # there are some prices inside the market depth that are ment to de destabilize the market
    # clear them out
    def sort_out_market_crush_prices(self):
        new_depth = {'asks': [], 'bids': []}
        for direction in ("asks", "bids"):
            for order in self.depth[direction]:
                if self.double_ckeck_price(order["price"], direction, 30):
                    new_depth[direction].append(order)

        if len(new_depth["ask"]) != len(self.depth["ask"]) or len(
                new_depth["bids"]) != len(self.depth["bids"]):
            logging.warning(
                'Market: %s removed some market crush crush items' % self.name)

        self.depth = new_depth

    def ask_update_depth(self):
        try:
            self.update_depth()
            self.convert_to_usd()
            self.get_cryptowatch_price()
            self.depth_updated = time.time()
        except (urllib.error.HTTPError, urllib.error.URLError) as e:
            logging.error("HTTPError, can't update market: %s" % self.name)
            log_exception(logging.DEBUG)
        except Exception as e:
            logging.error("Can't update market: %s - %s" % (self.name, str(e)))
            log_exception(logging.DEBUG)

    def get_ticker(self):
        depth = self.get_depth()
        res = {'ask': 0, 'bid': 0}
        if len(depth['asks']) > 0 and len(depth["bids"]) > 0:
            res = {'ask': depth['asks'][0], 'bid': depth['bids'][0]}
        return res

    ## Abstract methods
    def update_depth(self):
        pass

    def buy(self, price, amount):
        pass

    def sell(self, price, amount):
        pass
Esempio n. 8
0
class MarketBase(object, metaclass=Plugin):
    """"""
    def __init__(self, currency, config):
        self.name = self.__class__.__name__
        self.currency = currency
        self.depth_updated = 0
        self.config = config or Configuration()
        self.update_rate = self.config.default_market_update_rate
        self.depth = None
        self.fc = FiatConverter(config)
        self.fc.update()

    def set_config(self, config):
        self.config = config

    def get_depth(self):
        time_diff = time.time() - self.depth_updated
        if time_diff > self.update_rate:
            self.ask_update_depth()
        time_diff = time.time() - self.depth_updated
        if time_diff > self.config.market_expiration_time:
            LOG.warning('Market: %s order book is expired' % self.name)
            self.depth = {
                'asks': [{
                    'price': 0,
                    'amount': 0
                }],
                'bids': [{
                    'price': 0,
                    'amount': 0
                }]
            }
        return self.depth

    def convert_to_usd(self):
        if self.currency == "USD":
            return
        for direction in ("asks", "bids"):
            for order in self.depth[direction]:
                order["price"] = self.fc.convert(order["price"], self.currency,
                                                 "USD")

    def ask_update_depth(self):
        try:
            self.update_depth()
            self.convert_to_usd()
            self.depth_updated = time.time()
        except (urllib.error.HTTPError, urllib.error.URLError) as e:
            LOG.exception("HTTPError, can't update market: %s" % self.name)
        except Exception as e:
            LOG.exception("Can't update market: %s - %s" % (self.name, str(e)))

    def get_ticker(self):
        depth = self.get_depth()
        res = {'ask': 0, 'bid': 0}
        if len(depth['asks']) > 0 and len(depth["bids"]) > 0:
            res = {'ask': depth['asks'][0], 'bid': depth['bids'][0]}
        return res

    def update_depth(self):
        pass

    def buy(self, price, amount):
        pass

    def sell(self, price, amount):
        pass