Ejemplo n.º 1
0
class BittrexPipeline(object):
    def __init__(self, on_market_summary, poll_time=15, minor_currency="BTC"):
        '''
        on_market_summary should have 1 parameter: the json object containing the market summary
                                                   as specified by Bittrex's API.
        
        Pre: poll_time is a positive integer
        Post: on_market_summary is called every [poll_time] seconds for every market that has
              [minor_currency] as the minor currency.
        '''
        
        self.on_market_summary = on_market_summary
        self.bittrex_api = Bittrex(BittrexSecret.api_key, BittrexSecret.api_secret)
        self.poll_time = poll_time
        self._time_started = 0
        self.minor_currency = minor_currency
        
        self.stop = False
        self.thread = None

    def _start(self, get_market):
        def _go():
            last_time = 0
            while True:
                if self.stop:
                    print "Stopping Bittrex pipeline."
                    break
                elif time.time() - last_time >= self.poll_time:
                    last_time = time.time()
                    get_market()

        self.thread = Thread(target=_go)
        self.stop = False
        self.thread.start()

    def start_singlemarket(self, market):
        def _get_market():
            market_summary = self.bittrex_api.get_marketsummary(self.market)["result"][0]
            trading = market_summary["MarketName"].replace(self.minor_currency+"-", '')
            self.on_market_summary(market_summary, trading)
            
        self.market = market
        self._start(_get_market)
        print("Started Bittrex pipeline for market: " +market)
        

    def start_multimarket(self):
        def _get_market():
            market_summaries = self.bittrex_api.get_market_summaries()
            for market_summary in market_summaries["result"]:
                if market_summary["MarketName"].startswith(self.minor_currency):
                    trading = market_summary["MarketName"].replace(self.minor_currency+"-", '')
                    self.on_market_summary(market_summary, trading)

        self._start(_get_market)
        print("Started Bittrex pipeline for all markets with the minor currency "+self.minor_currency+".")

    def stop(self):
        if not self.stop:
            self.stop = True
Ejemplo n.º 2
0
    def __init__(self,
                 market="BTC-XMR",
                 minimum_trade_size=bittrex_minimum_btc_trade_size,
                 percentage_to_allocate=1,
                 percentage_per_trade=1,
                 starting_amount=1):
        '''
        Pre: options is an instance of QuadrigaOptions and must have pair and ticker set.
        Post: self.is_test = True until authenticate() is called
        '''

        # Trader is in test mode by default.
        # minimum_trade is the minimum amount of assets that can be sold on a trade.
        Trader.__init__(self, True, minimum_trade_size)

        # Will be set to a number (order ID) when an order is placed.
        self._waiting_for_order_to_fill = None

        # Used to place orders, cancel orders, get the order book during simulation mode
        self.bittrex_api = Bittrex(BittrexSecret.api_key,
                                   BittrexSecret.api_secret)

        # In test mode: Is used to prevent the same transaction from being counted twice.
        self._last_simulation_transaction_check = 0

        # In test mode: tracks how much the trader's order has been filled.
        self._expecting_simulation_balance = 0
        self._expecting_simulation_assets = 0
        self._filled_simulation_balance = 0
        self._filled_simulation_assets = 0

        # Used when aborting to determine if any positions need to be closed.
        self._active_buy_order = False
        self._active_sell_order = False

        # These variables determine how much the trader is allowed to trade with and
        # how much it will commit per trade.
        if percentage_to_allocate > 1:
            raise Warning("percentage_to_allocate cannot be greater than 1")
        self.percentage_to_allocate = Decimal(percentage_to_allocate)
        self.percentage_per_trade = Decimal(percentage_per_trade)
        self.validate_percentage_per_trade()

        # Get the market ticker and split it up for print statements.
        self.market_ticker = market
        self.minor_currency, self.major_currency = market.split("-")

        with localcontext() as context:
            context.prec = 8

            self.balance = Decimal(starting_amount)
            self.assets = Decimal(0)

            self.fee_added = Decimal(1) + bittrex_fee
            self.fee_substracted = float(1 - bittrex_fee)
Ejemplo n.º 3
0
 def __init__(self, on_market_summary, poll_time=15, minor_currency="BTC"):
     '''
     on_market_summary should have 1 parameter: the json object containing the market summary
                                                as specified by Bittrex's API.
     
     Pre: poll_time is a positive integer
     Post: on_market_summary is called every [poll_time] seconds for every market that has
           [minor_currency] as the minor currency.
     '''
     
     self.on_market_summary = on_market_summary
     self.bittrex_api = Bittrex(BittrexSecret.api_key, BittrexSecret.api_secret)
     self.poll_time = poll_time
     self._time_started = 0
     self.minor_currency = minor_currency
     
     self.stop = False
     self.thread = None
Ejemplo n.º 4
0
    def test_handles_invalid_key_or_secret(self):
        self.bittrex = Bittrex('invalidkey', self.secrets['secret'], api_version=API_V2_0)
        actual = self.bittrex.get_balance('BTC')
        test_auth_basic_failures(self, actual, 'Invalid key, valid secret')

        self.bittrex = Bittrex(None, self.secrets['secret'], api_version=API_V2_0)
        actual = self.bittrex.get_balance('BTC')
        test_auth_basic_failures(self, actual, 'None key, valid secret')

        self.bittrex = Bittrex(self.secrets['key'], 'invalidsecret', api_version=API_V2_0)
        actual = self.bittrex.get_balance('BTC')
        test_auth_basic_failures(self, actual, 'valid key, invalid secret')

        self.bittrex = Bittrex(self.secrets['key'], None, api_version=API_V2_0)
        actual = self.bittrex.get_balance('BTC')
        test_auth_basic_failures(self, actual, 'valid key, None secret')

        self.bittrex = Bittrex('invalidkey', 'invalidsecret', api_version=API_V2_0)
        actual = self.bittrex.get_balance('BTC')
        test_auth_basic_failures(self, actual, 'invalid key, invalid secret')
Ejemplo n.º 5
0
    def test_handles_none_key_or_secret(self):
        self.bittrex = Bittrex(None, None, api_version=API_V2_0)
        # could call any public method here
        actual = self.bittrex.get_markets()
        self.assertTrue(actual['success'], "failed with None key and None secret")

        self.bittrex = Bittrex("123", None, api_version=API_V2_0)
        actual = self.bittrex.get_markets()
        self.assertTrue(actual['success'], "failed with None secret")

        self.bittrex = Bittrex(None, "123", api_version=API_V2_0)
        actual = self.bittrex.get_markets()
        self.assertTrue(actual['success'], "failed with None key")
Ejemplo n.º 6
0
def what_is_profitable():

    spread_size_indicator = SpreadSize(minimum_return=1,
                                       market_fee=bittrex_fee)

    # Get the markets using a library.
    market_summaries = Bittrex(
        BittrexSecret.api_key,
        BittrexSecret.api_secret).get_market_summaries()
    something_was_profitable = False
    for market_summary in market_summaries["result"]:
        if market_summary != None:
            if market_summary["MarketName"].startswith("ETH"):
                _undercut = bittrex_eth_undercut
            elif market_summary["MarketName"].startswith("BTC"):
                _undercut = bittrex_btc_undercut
            else:
                _undercut = bittrex_usd_undercut
            highest_bid = Decimal(market_summary["Bid"]) + _undercut
            lowest_ask = Decimal(market_summary["Ask"]) - _undercut
            is_profitable = spread_size_indicator.is_profitable(
                highest_bid, lowest_ask)

            if is_profitable:
                something_was_profitable = True
                spread = lowest_ask - highest_bid
                roi = (spread_size_indicator.keep_after_fee_squared +
                       spread_size_indicator.keep_after_fee_squared * spread /
                       highest_bid) - 1
                roi *= 100
                print(market_summary["MarketName"] +
                      " is profitable. Expected return: " +
                      str(round(roi, 3)) + "%")

    if something_was_profitable == False:
        print("Nothing is profitable right now.")
Ejemplo n.º 7
0
class BittrexTrader(Trader):

    simulation_buy_order_id = "1234"
    simulation_sell_order_id = "4321"

    def __init__(self,
                 market="BTC-XMR",
                 minimum_trade_size=bittrex_minimum_btc_trade_size,
                 percentage_to_allocate=1,
                 percentage_per_trade=1,
                 starting_amount=1):
        '''
        Pre: options is an instance of QuadrigaOptions and must have pair and ticker set.
        Post: self.is_test = True until authenticate() is called
        '''

        # Trader is in test mode by default.
        # minimum_trade is the minimum amount of assets that can be sold on a trade.
        Trader.__init__(self, True, minimum_trade_size)

        # Will be set to a number (order ID) when an order is placed.
        self._waiting_for_order_to_fill = None

        # Used to place orders, cancel orders, get the order book during simulation mode
        self.bittrex_api = Bittrex(BittrexSecret.api_key,
                                   BittrexSecret.api_secret)

        # In test mode: Is used to prevent the same transaction from being counted twice.
        self._last_simulation_transaction_check = 0

        # In test mode: tracks how much the trader's order has been filled.
        self._expecting_simulation_balance = 0
        self._expecting_simulation_assets = 0
        self._filled_simulation_balance = 0
        self._filled_simulation_assets = 0

        # Used when aborting to determine if any positions need to be closed.
        self._active_buy_order = False
        self._active_sell_order = False

        # These variables determine how much the trader is allowed to trade with and
        # how much it will commit per trade.
        if percentage_to_allocate > 1:
            raise Warning("percentage_to_allocate cannot be greater than 1")
        self.percentage_to_allocate = Decimal(percentage_to_allocate)
        self.percentage_per_trade = Decimal(percentage_per_trade)
        self.validate_percentage_per_trade()

        # Get the market ticker and split it up for print statements.
        self.market_ticker = market
        self.minor_currency, self.major_currency = market.split("-")

        with localcontext() as context:
            context.prec = 8

            self.balance = Decimal(starting_amount)
            self.assets = Decimal(0)

            self.fee_added = Decimal(1) + bittrex_fee
            self.fee_substracted = float(1 - bittrex_fee)

    def authenticate(self):
        self.is_test = False
        self.fetch_balance_and_assets()

    def validate_percentage_per_trade(self):
        if self.percentage_per_trade > 1:
            raise Warning("percentage_per_trade cannot be greater than 1")

    def should_default_to(self, default_position):
        '''
        True == hold/buy major currency when the market is unprofitable
        False == hold/sell to get minor currency when market is unprofitable 
        None == hold whatever the trader has
        '''
        self.default_position = default_position

    def fetch_balance_and_assets(self):
        '''
        Get the balance and assets this trader has permission to spend in the exchange.
        Pre: API Key, client, and API secret have been set.
        Post: self.balance and self.assets are set. They are a percentage of the actual balance/assets
              if percentage_to_trade is set in the constructor.
        '''

        if self.is_test:
            print(
                "Warning: fetch_balance was called when trader is in test mode."
            )
        else:
            #Fetch the two availability of the two currencies from the exchange.
            minor_currency_available = self.bittrex_api.get_balance(
                self.minor_currency)["result"]["Available"]
            if minor_currency_available == None:
                minor_currency_available = 0
            self.balance = Decimal(
                float(minor_currency_available)) * self.percentage_to_allocate
            major_currency_available = self.bittrex_api.get_balance(
                self.major_currency)["result"]["Available"]
            if major_currency_available == None:
                major_currency_available = 0
            self.assets = Decimal(
                float(major_currency_available)) * self.percentage_to_allocate
            print("Trading with: " + str(round(self.balance, 3)) +
                  self.minor_currency + " and " + str(round(self.assets, 3)) +
                  self.major_currency)

    def buy(self, market_value):
        if self.can_buy == True:

            if self._waiting_for_order_to_fill != None:
                self.was_order_filled(self._waiting_for_order_to_fill)

            # Prevent buying while a sell order is active.
            if self._waiting_for_order_to_fill == None:

                #Only trade the percentage of the balance allocated to a single trade.
                #Bittrex charges its commission on top of the amount requested. (Divide by the fee + 1)
                balance_for_this_buy = (
                    self.balance * self.percentage_per_trade) / self.fee_added
                assets_to_buy = balance_for_this_buy / market_value

                assets_to_buy = round(assets_to_buy, bittrex_precision)
                market_value = round(market_value, bittrex_precision)
                if assets_to_buy >= self.minimum_trade:

                    self._active_buy_order = True

                    if self.is_test:
                        self.simulation_buy(assets_to_buy)
                    else:
                        self.limit_buy_order(assets_to_buy, market_value)

                    print("Buying in " + self.market_ticker +
                          ". Planning to spend: " + str(self.balance) +
                          self.minor_currency)
                    self.balance = Decimal(0)
                else:
                    sys.stdout.write('b ')

            else:
                sys.stdout.write('wb ')

    def limit_buy_order(self, quantity, market_value):
        if self.bittrex_api is not None:
            result = self.bittrex_api.buy_limit(self.market_ticker, quantity,
                                                market_value)
            if result["result"] is not None:
                self._waiting_for_order_to_fill = result["result"]["uuid"]
            self._active_buy_order = True
        else:
            raise Warning("self.bittrex_api cannot be None")

    def simulation_buy(self, quantity):
        self._waiting_for_order_to_fill = BittrexTrader.simulation_buy_order_id

        # Order will not be "filled" until
        # filled_simulation_assets == expecting_simulation_assets
        self._expecting_simulation_assets = quantity * float(self.fee_added)
        self._filled_simulation_assets = 0

        # Only orders that matter are the ones that might fill us which can only
        # happen in the future.
        self._last_simulation_transaction_check = datetime.datetime.now()

        self._active_buy_order = True

    def sell(self, market_value):
        if self.can_sell:
            if self._waiting_for_order_to_fill != None:
                self.was_order_filled(self._waiting_for_order_to_fill)

            # Prevent selling while a buy order is active.
            if self._waiting_for_order_to_fill == None:

                #Always sell all assets.
                assets_to_sell = round(self.assets, bittrex_precision)
                market_value = round(market_value, bittrex_precision)
                if self.assets >= self.minimum_trade:

                    self._active_sell_order = True

                    if self.is_test:
                        self.simulation_sell(assets_to_sell, market_value)
                    else:
                        self.limit_sell_order(assets_to_sell, market_value)

                    print(
                        "Selling. Planning to get balance: " +
                        str(assets_to_sell * market_value *
                            self.fee_substracted) + self.minor_currency)
                    self.assets = Decimal(0)
                else:
                    sys.stdout.write('s ')

            else:
                sys.stdout.write('ws ')

    def limit_sell_order(self, quantity, market_value):
        if self.bittrex_api is not None:
            result = self.bittrex_api.sell_limit(self.market_ticker, quantity,
                                                 market_value)
            if result["result"] is not None:
                self._waiting_for_order_to_fill = result["result"]["uuid"]
            self._active_sell_order = True
        else:
            raise Warning("self.bittrex_api cannot be None")

    def simulation_sell(self, quantity, market_value):
        self._waiting_for_order_to_fill = BittrexTrader.simulation_sell_order_id

        # Order will not be "filled" until
        # _filled_simulation_balance == _expecting_simulation_balance
        self._expecting_simulation_balance = quantity * market_value
        self._filled_simulation_balance = 0

        # Used to track how much balance is earned from partial fills.
        self._limit_order_price = market_value

        # Only orders that matter are the ones that might fill us which can only
        # happen in the future.
        self._last_simulation_transaction_check = datetime.datetime.now()

        self._active_sell_order = True

    def was_order_filled(self, order_id):
        '''
        Post: Internal balance/assets is updated if the order was filled.
        '''

        if self.is_test:
            try:
                assert (order_id == BittrexTrader.simulation_buy_order_id
                        or order_id == BittrexTrader.simulation_sell_order_id)
            except AssertionError as e:
                e.args += ("Invalid order ID: ", order_id)
                raise

            # Simulate the trader's order being filled by watching what the market.
            # It is likely that simulation mode results in higher profits as in reality
            # other bots undercut our own trades so our orders are filled less frequently.

            history = self.bittrex_api.get_market_history(
                self.market_ticker)["result"]

            for trade in history:
                if "." in trade["TimeStamp"]:
                    timestamp = datetime.datetime.strptime(
                        trade["TimeStamp"], "%Y-%m-%dT%H:%M:%S.%f")
                else:
                    timestamp = datetime.datetime.strptime(
                        trade["TimeStamp"], "%Y-%m-%dT%H:%M:%S")
                if timestamp < self._last_simulation_transaction_check:
                    break
                else:
                    with localcontext() as context:
                        context.prec = 8

                        if order_id == BittrexTrader.simulation_buy_order_id and trade[
                                "OrderType"] == "SELL":
                            self._filled_simulation_assets += trade["Quantity"]
                            if self._filled_simulation_assets >= self._expecting_simulation_assets:
                                self.assets = self._expecting_simulation_assets * self.fee_substracted
                                self._active_buy_order = False
                                self._waiting_for_order_to_fill = None
                        elif order_id == BittrexTrader.simulation_sell_order_id and trade[
                                "OrderType"] == "BUY":
                            incoming_balance = trade[
                                "Quantity"] * self._limit_order_price
                            self._filled_simulation_balance += incoming_balance
                            if self._filled_simulation_balance >= self._expecting_simulation_balance:
                                self.balance = Decimal(
                                    self._expecting_simulation_balance *
                                    self.fee_substracted)
                                self._active_sell_order = False
                                self._waiting_for_order_to_fill = None

            # Orders up to this moment have been processed, don't process them again.
            self._last_simulation_transaction_check = datetime.datetime.now()

        else:

            # Lookup the order on the market and check its status.
            # The trader will stop if the order was cancelled as a human intervened.
            # Note: The pipeline never knows the Trader's status so the pipeline will continue
            #       to pass data to the market observer.

            json_result = self.bittrex_api.get_order(order_id)["result"]

            if json_result["CancelInitiated"] == True:
                print(
                    "The order was cancelled, likely because a human intervened."
                )
                self._waiting_for_order_to_fill = None
                self.abort()
            elif json_result["Quantity"] > json_result[
                    "Quantity"] - json_result["QuantityRemaining"] > 0:
                print(
                    "The order has been partially filled. Waiting until it is fully filled."
                )
            elif json_result["IsOpen"] == False:
                order_type = json_result["Type"]
                if order_type == "LIMIT_BUY":
                    self.assets = Decimal(json_result["Quantity"] -
                                          json_result["CommissionPaid"])
                    self._active_buy_order = False
                    self._waiting_for_order_to_fill = None
                elif order_type == "LIMIT_SELL":
                    self.balance = Decimal((json_result["price"]) *
                                           Decimal(json_result["amount"]) -
                                           json_result["CommissionPaid"])
                    self._active_sell_order = False
                    self._waiting_for_order_to_fill = None
                else:
                    print "Unexpected order type: " + order_type

    def hold(self, market_value):
        ''' Cancel any open orders and revert back to the default position depending on aggressiveness. '''

        sys.stdout.write('h ')

        if self._waiting_for_order_to_fill != None:
            self.was_order_filled(self._waiting_for_order_to_fill)

        # Keep orders open if they help reach the default position.
        if self._active_sell_order and self.default_position != DefaultPosition.SELL:
            if not self.is_test:
                self.cancel_order(self._waiting_for_order_to_fill)
            self._waiting_for_order_to_fill = None
            self._active_sell_order = False

        if self._active_buy_order and self.default_position != DefaultPosition.BUY:
            if not self.is_test:
                self.cancel_order(self._waiting_for_order_to_fill)
            self._waiting_for_order_to_fill = None
            self._active_buy_order = False

    def cancel_order(self, order_id):
        order_info = self.bittrex_api.get_order(order_id)["result"]
        if order_info is not None:
            quantity_remaining = Decimal(order_info["QuantityRemaining"])
            self.balance = (quantity_remaining * Decimal(
                order_info["Limit"])) - Decimal(order_info["CommissionPaid"])
            self.assets = Decimal(order_info["Quantity"]) - quantity_remaining
            self.bittrex_api.cancel(order_id)

    def abort(self):
        Trader.abort(self)
        self._waiting_for_order_to_fill = None
        print("BittrexTrader is shutting down.")
Ejemplo n.º 8
0
 def setUp(self):
     self.bittrex = Bittrex(None, None, api_version=API_V2_0)
Ejemplo n.º 9
0
class TestBittrexV20PublicAPI(unittest.TestCase):
    """
    Integration tests for the Bittrex public API.
    These will fail in the absence of an internet connection or if bittrex API goes down
    """

    def setUp(self):
        self.bittrex = Bittrex(None, None, api_version=API_V2_0)

    def test_handles_none_key_or_secret(self):
        self.bittrex = Bittrex(None, None, api_version=API_V2_0)
        # could call any public method here
        actual = self.bittrex.get_markets()
        self.assertTrue(actual['success'], "failed with None key and None secret")

        self.bittrex = Bittrex("123", None, api_version=API_V2_0)
        actual = self.bittrex.get_markets()
        self.assertTrue(actual['success'], "failed with None secret")

        self.bittrex = Bittrex(None, "123", api_version=API_V2_0)
        actual = self.bittrex.get_markets()
        self.assertTrue(actual['success'], "failed with None key")

    def test_get_markets(self):
        actual = self.bittrex.get_markets()
        test_basic_response(self, actual, "get_markets")
        self.assertTrue(isinstance(actual['result'], list), "result is not a list")
        self.assertTrue(len(actual['result']) > 0, "result list is 0-length")

    def test_get_currencies(self):
        actual = self.bittrex.get_currencies()
        test_basic_response(self, actual, "get_currencies")

    def test_get_ticker(self):
        self.assertRaisesRegexp(Exception, 'method call not available', self.bittrex.get_ticker,
                                market='BTC-LTC')

    def test_get_market_summaries(self):
        actual = self.bittrex.get_market_summaries()
        test_basic_response(self, actual, "get_market_summaries")

    def test_get_market_summary(self):
        actual = self.bittrex.get_marketsummary(market='BTC-LTC')
        test_basic_response(self, actual, "get_marketsummary")

    def test_get_orderbook(self):
        actual = self.bittrex.get_orderbook('BTC-LTC')
        test_basic_response(self, actual, "get_orderbook")

    def test_get_market_history(self):
        actual = self.bittrex.get_market_history('BTC-LTC')
        test_basic_response(self, actual, "get_market_history")

    def test_list_markets_by_currency(self):
        actual = self.bittrex.list_markets_by_currency('LTC')
        self.assertListEqual(['BTC-LTC', 'ETH-LTC', 'USDT-LTC'], actual)

    def test_get_wallet_health(self):
        actual = self.bittrex.get_wallet_health()
        test_basic_response(self, actual, "get_wallet_health")
        self.assertIsInstance(actual['result'], list)

    @unittest.skip("Endpoint 404s.  Is this still a valid 2.0 API?")
    def test_get_balance_distribution(self):
        actual = self.bittrex.get_balance_distribution()
        test_basic_response(self, actual, "get_balance_distribution")
        self.assertIsInstance(actual['result'], list)

    def test_get_candles(self):
        actual = self.bittrex.get_candles('BTC-LTC', tick_interval=TICKINTERVAL_ONEMIN)
        test_basic_response(self, actual, "test_get_candles")
        self.assertIsInstance(actual['result'], list)
Ejemplo n.º 10
0
 def setUp(self):
     with open("secrets.json") as secrets_file:
         self.secrets = json.load(secrets_file)
         secrets_file.close()
     self.bittrex = Bittrex(self.secrets['key'], self.secrets['secret'], api_version=API_V2_0)
Ejemplo n.º 11
0
class TestBittrexV20AccountAPI(unittest.TestCase):
    """
    Integration tests for the Bittrex Account API.
      * These will fail in the absence of an internet connection or if bittrex API goes down.
      * They require a valid API key and secret issued by Bittrex.
      * They also require the presence of a JSON file called secrets.json.
      It is structured as such:
    {
      "key": "12341253456345",
      "secret": "3345745634234534"
    }
    """

    def setUp(self):
        with open("secrets.json") as secrets_file:
            self.secrets = json.load(secrets_file)
            secrets_file.close()
        self.bittrex = Bittrex(self.secrets['key'], self.secrets['secret'], api_version=API_V2_0)

    def test_handles_invalid_key_or_secret(self):
        self.bittrex = Bittrex('invalidkey', self.secrets['secret'], api_version=API_V2_0)
        actual = self.bittrex.get_balance('BTC')
        test_auth_basic_failures(self, actual, 'Invalid key, valid secret')

        self.bittrex = Bittrex(None, self.secrets['secret'], api_version=API_V2_0)
        actual = self.bittrex.get_balance('BTC')
        test_auth_basic_failures(self, actual, 'None key, valid secret')

        self.bittrex = Bittrex(self.secrets['key'], 'invalidsecret', api_version=API_V2_0)
        actual = self.bittrex.get_balance('BTC')
        test_auth_basic_failures(self, actual, 'valid key, invalid secret')

        self.bittrex = Bittrex(self.secrets['key'], None, api_version=API_V2_0)
        actual = self.bittrex.get_balance('BTC')
        test_auth_basic_failures(self, actual, 'valid key, None secret')

        self.bittrex = Bittrex('invalidkey', 'invalidsecret', api_version=API_V2_0)
        actual = self.bittrex.get_balance('BTC')
        test_auth_basic_failures(self, actual, 'invalid key, invalid secret')

    def test_get_openorders(self):
        actual = self.bittrex.get_open_orders('BTC-LTC')
        test_basic_response(self, actual, "get_openorders")
        self.assertTrue(isinstance(actual['result'], list), "result is not a list")

    def test_get_balances(self):
        actual = self.bittrex.get_balances()
        test_basic_response(self, actual, "get_balances")
        self.assertTrue(isinstance(actual['result'], list), "result is not a list")

    @unittest.skip("the return result is an empty dict.  API bug?  the 2.0 get_balances works as expected")
    def test_get_balance(self):
        actual = self.bittrex.get_balance('BTC')
        test_basic_response(self, actual, "get_balance")
        self.assertTrue(isinstance(actual['result'], dict), "result is not a dict")
        self.assertEqual(actual['result']['Currency'],
                         "BTC",
                         "requested currency {0:s} does not match returned currency {1:s}"
                         .format("BTC", actual['result']['Currency']))

    @unittest.skip("my testing account is acting funny this should work")
    def test_get_depositaddress(self):
        actual = self.bittrex.get_deposit_address('BTC')
        test_basic_response(self, actual, "get_deposit_address")

    def test_get_order_history_all_markets(self):
        actual = self.bittrex.get_order_history()
        test_basic_response(self, actual, "get_order_history")
        self.assertIsInstance(actual['result'], list, "result is not a list")

    def test_get_order_history_one_market(self):
        actual = self.bittrex.get_order_history(market='BTC-LTC')
        test_basic_response(self, actual, "get_order_history")
        self.assertIsInstance(actual['result'], list, "result is not a list")

    def test_get_withdrawlhistory_all_currencies(self):
        actual = self.bittrex.get_withdrawal_history()
        test_basic_response(self, actual, "get_withdrawal_history")
        self.assertIsInstance(actual['result'], list, "result is not a list")

    def test_get_withdrawlhistory_one_currency(self):
        actual = self.bittrex.get_withdrawal_history('BTC')
        test_basic_response(self, actual, "get_withdrawal_history")
        self.assertIsInstance(actual['result'], list, "result is not a list")

    def test_get_deposithistory_all_currencies(self):
        actual = self.bittrex.get_deposit_history()
        test_basic_response(self, actual, "get_deposit_history")
        self.assertIsInstance(actual['result'], list, "result is not a list")

    def test_get_deposithistory_one_currency(self):
        actual = self.bittrex.get_deposit_history('BTC')
        test_basic_response(self, actual, "get_deposit_history")
        self.assertIsInstance(actual['result'], list, "result is not a list")

    def test_get_pending_withdrawls_all_currencies(self):
        actual = self.bittrex.get_pending_withdrawls()
        test_basic_response(self, actual, "get_pending_withdrawls")
        self.assertIsInstance(actual['result'], list, "result is not a list")

    def test_get_pending_withdrawls_one_currency(self):
        actual = self.bittrex.get_pending_withdrawls('BTC')
        test_basic_response(self, actual, "get_pending_withdrawls")
        self.assertIsInstance(actual['result'], list, "result is not a list")

    def test_get_pending_deposits_all_currencies(self):
        actual = self.bittrex.get_pending_deposits()
        test_basic_response(self, actual, "get_pending_deposits")
        self.assertIsInstance(actual['result'], list, "result is not a list")

    def test_get_pending_deposits_one_currency(self):
        actual = self.bittrex.get_pending_deposits('BTC')
        test_basic_response(self, actual, "get_pending_deposits")
        self.assertIsInstance(actual['result'], list, "result is not a list")

    def test_generate_deposit_address(self):
        actual = self.bittrex.generate_deposit_address(currency='BTC')
        test_basic_response(self, actual, "generate_deposit_address")
        self.assertIsInstance(actual['result'], list, "result is not a list")
Ejemplo n.º 12
0
class TestBittrexV11AccountAPI(unittest.TestCase):
    """
    Integration tests for the Bittrex Account API.
      * These will fail in the absence of an internet connection or if bittrex API goes down.
      * They require a valid API key and secret issued by Bittrex.
      * They also require the presence of a JSON file called secrets.json.
      It is structured as such:
    {
      "key": "12341253456345",
      "secret": "3345745634234534"
    }
    """

    def setUp(self):
        with open("secrets.json") as secrets_file:
            self.secrets = json.load(secrets_file)
            secrets_file.close()
        self.bittrex = Bittrex(self.secrets['key'], self.secrets['secret'])

    def test_handles_invalid_key_or_secret(self):
        self.bittrex = Bittrex('invalidkey', self.secrets['secret'])
        actual = self.bittrex.get_balance('BTC')
        test_auth_basic_failures(self, actual, 'Invalid key, valid secret')

        self.bittrex = Bittrex(None, self.secrets['secret'])
        actual = self.bittrex.get_balance('BTC')
        test_auth_basic_failures(self, actual, 'None key, valid secret')

        self.bittrex = Bittrex(self.secrets['key'], 'invalidsecret')
        actual = self.bittrex.get_balance('BTC')
        test_auth_basic_failures(self, actual, 'valid key, invalid secret')

        self.bittrex = Bittrex(self.secrets['key'], None)
        actual = self.bittrex.get_balance('BTC')
        test_auth_basic_failures(self, actual, 'valid key, None secret')

        self.bittrex = Bittrex('invalidkey', 'invalidsecret')
        actual = self.bittrex.get_balance('BTC')
        test_auth_basic_failures(self, actual, 'invalid key, invalid secret')

    def test_get_openorders(self):
        actual = self.bittrex.get_open_orders('BTC-LTC')
        test_basic_response(self, actual, "get_openorders")
        self.assertTrue(isinstance(actual['result'], list), "result is not a list")

    def test_get_balances(self):
        actual = self.bittrex.get_balances()
        test_basic_response(self, actual, "get_balances")
        self.assertTrue(isinstance(actual['result'], list), "result is not a list")

    def test_get_balance(self):
        actual = self.bittrex.get_balance('BTC')
        test_basic_response(self, actual, "get_balance")
        self.assertTrue(isinstance(actual['result'], dict), "result is not a dict")
        self.assertEqual(actual['result']['Currency'],
                         "BTC",
                         "requested currency {0:s} does not match returned currency {1:s}"
                         .format("BTC", actual['result']['Currency']))

    def test_get_depositaddress(self):
        actual = self.bittrex.get_deposit_address('BTC')
        if not actual['success']:
            self.assertTrue(actual['message'], 'ADDRESS_GENERATING')
        else:
            test_basic_response(self, actual, "get_deposit_address")

    def test_get_order_history_all_markets(self):
        actual = self.bittrex.get_order_history()
        test_basic_response(self, actual, "get_order_history")
        self.assertIsInstance(actual['result'], list, "result is not a list")

    def test_get_order_history_one_market(self):
        actual = self.bittrex.get_order_history(market='BTC-LTC')
        test_basic_response(self, actual, "get_order_history")
        self.assertIsInstance(actual['result'], list, "result is not a list")

    def test_get_withdrawlhistory_all_currencies(self):
        actual = self.bittrex.get_withdrawal_history()
        test_basic_response(self, actual, "get_withdrawal_history")
        self.assertIsInstance(actual['result'], list, "result is not a list")

    def test_get_withdrawlhistory_one_currency(self):
        actual = self.bittrex.get_withdrawal_history('BTC')
        test_basic_response(self, actual, "get_withdrawal_history")
        self.assertIsInstance(actual['result'], list, "result is not a list")

    def test_get_deposithistory_all_currencies(self):
        actual = self.bittrex.get_deposit_history()
        test_basic_response(self, actual, "get_deposit_history")
        self.assertIsInstance(actual['result'], list, "result is not a list")

    def test_get_deposithistory_one_currency(self):
        actual = self.bittrex.get_deposit_history('BTC')
        test_basic_response(self, actual, "get_deposit_history")
        self.assertIsInstance(actual['result'], list, "result is not a list")

    def test_get_pending_withdrawls(self):
        self.assertRaisesRegexp(Exception, 'method call not available', self.bittrex.get_pending_withdrawls)

    def test_get_pending_deposits(self):
        self.assertRaisesRegexp(Exception, 'method call not available', self.bittrex.get_pending_deposits)

    def test_generate_deposit_address(self):
        self.assertRaisesRegexp(Exception, 'method call not available', self.bittrex.generate_deposit_address, currency='BTC')