def fetch_ticker(self, symbol, params={}): self.load_markets() request = { 'symbol': self.market_id(symbol), } res = getattr(self, 'public_get_ticker')(self.extend(request, params)) if res['status'] != 0: raise ccxt.BaseError(res['messages']) ticker = res['data'][0] timestamp = self.parse8601(ticker['timestamp']) last = float(ticker['last']) return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': self.iso8601(timestamp), 'high': float(ticker['high']), 'low': float(ticker['low']), 'bid': float(ticker['bid']), 'bidVolume': None, 'ask': float(ticker['ask']), 'askVolume': None, 'vwap': None, 'open': None, 'close': last, 'last': last, 'previousClose': None, 'change': None, 'percentage': None, 'average': None, 'baseVolume': float(ticker['volume']), 'quoteVolume': None, 'info': ticker, }
def test_stoploss_order_kraken(default_conf, mocker): api_mock = MagicMock() order_id = 'test_prod_buy_{}'.format(randint(0, 10 ** 6)) order_type = 'stop-loss' api_mock.create_order = MagicMock(return_value={ 'id': order_id, 'info': { 'foo': 'bar' } }) default_conf['dry_run'] = False mocker.patch('freqtrade.exchange.Exchange.amount_to_precision', lambda s, x, y: y) mocker.patch('freqtrade.exchange.Exchange.price_to_precision', lambda s, x, y: y) exchange = get_patched_exchange(mocker, default_conf, api_mock, 'kraken') # stoploss_on_exchange_limit_ratio is irrelevant for kraken market orders order = exchange.stoploss(pair='ETH/BTC', amount=1, stop_price=190, order_types={'stoploss_on_exchange_limit_ratio': 1.05}) assert api_mock.create_order.call_count == 1 api_mock.create_order.reset_mock() order = exchange.stoploss(pair='ETH/BTC', amount=1, stop_price=220, order_types={}) assert 'id' in order assert 'info' in order assert order['id'] == order_id assert api_mock.create_order.call_args_list[0][1]['symbol'] == 'ETH/BTC' assert api_mock.create_order.call_args_list[0][1]['type'] == order_type assert api_mock.create_order.call_args_list[0][1]['side'] == 'sell' assert api_mock.create_order.call_args_list[0][1]['amount'] == 1 assert api_mock.create_order.call_args_list[0][1]['price'] == 220 assert api_mock.create_order.call_args_list[0][1]['params'] == {'trading_agreement': 'agree'} # test exception handling with pytest.raises(DependencyException): api_mock.create_order = MagicMock(side_effect=ccxt.InsufficientFunds("0 balance")) exchange = get_patched_exchange(mocker, default_conf, api_mock, 'kraken') exchange.stoploss(pair='ETH/BTC', amount=1, stop_price=220, order_types={}) with pytest.raises(InvalidOrderException): api_mock.create_order = MagicMock( side_effect=ccxt.InvalidOrder("kraken Order would trigger immediately.")) exchange = get_patched_exchange(mocker, default_conf, api_mock, 'kraken') exchange.stoploss(pair='ETH/BTC', amount=1, stop_price=220, order_types={}) with pytest.raises(TemporaryError): api_mock.create_order = MagicMock(side_effect=ccxt.NetworkError("No connection")) exchange = get_patched_exchange(mocker, default_conf, api_mock, 'kraken') exchange.stoploss(pair='ETH/BTC', amount=1, stop_price=220, order_types={}) with pytest.raises(OperationalException, match=r".*DeadBeef.*"): api_mock.create_order = MagicMock(side_effect=ccxt.BaseError("DeadBeef")) exchange = get_patched_exchange(mocker, default_conf, api_mock, 'kraken') exchange.stoploss(pair='ETH/BTC', amount=1, stop_price=220, order_types={})
def test_stoploss_limit_order(default_conf, mocker): api_mock = MagicMock() order_id = 'test_prod_buy_{}'.format(randint(0, 10 ** 6)) order_type = 'stop_loss_limit' api_mock.create_order = MagicMock(return_value={ 'id': order_id, 'info': { 'foo': 'bar' } }) default_conf['dry_run'] = False mocker.patch('freqtrade.exchange.Exchange.symbol_amount_prec', lambda s, x, y: y) mocker.patch('freqtrade.exchange.Exchange.symbol_price_prec', lambda s, x, y: y) exchange = get_patched_exchange(mocker, default_conf, api_mock, 'binance') with pytest.raises(OperationalException): order = exchange.stoploss_limit(pair='ETH/BTC', amount=1, stop_price=190, rate=200) api_mock.create_order.reset_mock() order = exchange.stoploss_limit(pair='ETH/BTC', amount=1, stop_price=220, rate=200) assert 'id' in order assert 'info' in order assert order['id'] == order_id assert api_mock.create_order.call_args[0][0] == 'ETH/BTC' assert api_mock.create_order.call_args[0][1] == order_type assert api_mock.create_order.call_args[0][2] == 'sell' assert api_mock.create_order.call_args[0][3] == 1 assert api_mock.create_order.call_args[0][4] == 200 assert api_mock.create_order.call_args[0][5] == {'stopPrice': 220} # test exception handling with pytest.raises(DependencyException): api_mock.create_order = MagicMock(side_effect=ccxt.InsufficientFunds("0 balance")) exchange = get_patched_exchange(mocker, default_conf, api_mock, 'binance') exchange.stoploss_limit(pair='ETH/BTC', amount=1, stop_price=220, rate=200) with pytest.raises(InvalidOrderException): api_mock.create_order = MagicMock( side_effect=ccxt.InvalidOrder("binance Order would trigger immediately.")) exchange = get_patched_exchange(mocker, default_conf, api_mock, 'binance') exchange.stoploss_limit(pair='ETH/BTC', amount=1, stop_price=220, rate=200) with pytest.raises(TemporaryError): api_mock.create_order = MagicMock(side_effect=ccxt.NetworkError("No connection")) exchange = get_patched_exchange(mocker, default_conf, api_mock, 'binance') exchange.stoploss_limit(pair='ETH/BTC', amount=1, stop_price=220, rate=200) with pytest.raises(OperationalException, match=r".*DeadBeef.*"): api_mock.create_order = MagicMock(side_effect=ccxt.BaseError("DeadBeef")) exchange = get_patched_exchange(mocker, default_conf, api_mock, 'binance') exchange.stoploss_limit(pair='ETH/BTC', amount=1, stop_price=220, rate=200)
def cancel_order(self, id_, symbol=None, params={}): self.load_markets() request = { 'orderId': id_, } res = getattr(self, 'private_post_cancelorder')(self.extend(request, params)) if res['status'] != 0: raise ccxt.BaseError(res['messages']) return res
def test__load_async_markets(default_conf, mocker, caplog): exchange = get_patched_exchange(mocker, default_conf) exchange._api_async.load_markets = get_mock_coro(None) exchange._load_async_markets() assert exchange._api_async.load_markets.call_count == 1 caplog.set_level(logging.DEBUG) exchange._api_async.load_markets = Mock(side_effect=ccxt.BaseError("deadbeef")) exchange._load_async_markets() assert log_has('Could not load async markets. Reason: deadbeef', caplog.record_tuples)
def fetch_order(self, id_, symbol=None, params={}): self.load_markets() request = { 'orderId': id_, } res = getattr(self, 'private_get_orders')(self.extend(request, params)) if res['status'] != 0: raise ccxt.BaseError(res['messages']) orders = res['data'].get('list') if not orders: raise ccxt.OrderNotFound(f'{self.id} No order found with id {id_}') return self.parse_order(orders[0])
def fetch_trades(self, symbol, since=None, limit=None, params={}): self.load_markets() market = self.market(symbol) request = { 'symbol': market['id'], } res = getattr(self, 'public_get_trades')(self.extend(request, params)) if res['status'] != 0: raise ccxt.BaseError(res['messages']) trades = res['data'].get('list', []) return self.parse_trades(trades, market, since, limit)
def fetch_order_book(self, symbol, limit=None, params={}): self.load_markets() request = { 'symbol': self.market_id(symbol), } res = getattr(self, 'public_get_orderbooks')(self.extend(request, params)) if res['status'] != 0: raise ccxt.BaseError(res['messages']) orderbook = res['data'] return self.parse_order_book(orderbook, None, 'bids', 'asks', 'price', 'size')
def fetch_balance(self, params={}): self.load_markets() res = getattr(self, 'private_get_account_assets')() if res['status'] != 0: raise ccxt.BaseError(res['messages']) result = {'info': res} for balance in res['data']: currency_id = balance['symbol'] code = currency_id account = getattr(self, 'account')() account['total'] = float(balance['amount']) account['free'] = float(balance['available']) result[code] = account return self.parse_balance(result)
def fetch_my_trades(self, symbol=None, since=None, limit=None, params={}): if symbol is None: raise ccxt.ArgumentsRequired( f'{self.id} fetchMyTrades requires a `symbol` argument') self.load_markets() market = self.market(symbol) request = { 'symbol': market['id'], } res = getattr(self, 'private_get_latestexecutions')(self.extend( request, params)) if res['status'] != 0: raise ccxt.BaseError(res['messages']) trades = res['data'].get('list', []) return self.parse_trades(trades, market, since, limit)
def fetch_open_orders(self, symbol=None, since=None, limit=100, params={}): if symbol is None: raise ccxt.ArgumentsRequired( f'{self.id} fetch_open_orders() requires a `symbol` argument') self.load_markets() market = self.market(symbol) request = { 'symbol': market['id'], 'count': limit, } res = getattr(self, 'private_get_activeorders')(self.extend(request, params)) if res['status'] != 0: raise ccxt.BaseError(res['messages']) orders = res['data'].get('list', []) return self.parse_orders(orders, market, since, limit)
def fetch_markets(self, params={}): res = getattr(self, 'public_get_ticker')() if res['status'] != 0: raise ccxt.BaseError(res['messages']) result = [] for market in res['data']: id_ = market['symbol'] currencies = id_.split('_') symbol = id_ if len(currencies) == 1: type_ = 'spot' base_id = currencies[0] quote_id = 'JPY' fees = self.fees maker = fees['trading']['maker'] taker = fees['trading']['taker'] spot = True future = False else: type_ = 'future' base_id = currencies[0] quote_id = currencies[1] maker = 0 taker = 0 spot = False future = True base = base_id quote = quote_id result.append({ 'id': id_, 'symbol': symbol, 'base': base, 'quote': quote, 'baseId': base_id, 'quoteId': quote_id, 'maker': maker, 'taker': taker, 'type': type_, 'spot': spot, 'future': future, 'info': market, }) return result
def test_validate_pairs_exception(default_conf, mocker, caplog): caplog.set_level(logging.INFO) api_mock = MagicMock() mocker.patch('freqtrade.exchange.Exchange.name', PropertyMock(return_value='Binance')) api_mock.load_markets = MagicMock(return_value={}) mocker.patch('freqtrade.exchange.Exchange._init_ccxt', api_mock) with pytest.raises(OperationalException, match=r'Pair ETH/BTC is not available at Binance'): Exchange(default_conf) api_mock.load_markets = MagicMock(side_effect=ccxt.BaseError()) mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock)) Exchange(default_conf) assert log_has( 'Unable to validate pairs (assuming they are correct). Reason: ', caplog.record_tuples)
def test__load_markets(default_conf, mocker, caplog): caplog.set_level(logging.INFO) api_mock = MagicMock() mocker.patch('freqtrade.exchange.Exchange.name', PropertyMock(return_value='Binance')) api_mock.load_markets = MagicMock(return_value={}) mocker.patch('freqtrade.exchange.Exchange._init_ccxt', api_mock) mocker.patch('freqtrade.exchange.Exchange.validate_timeframes', MagicMock()) mocker.patch('freqtrade.exchange.Exchange._load_async_markets', MagicMock()) expected_return = {'ETH/BTC': 'available'} api_mock.load_markets = MagicMock(return_value=expected_return) mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock)) default_conf['exchange']['pair_whitelist'] = ['ETH/BTC'] ex = Exchange(default_conf) assert ex.markets == expected_return api_mock.load_markets = MagicMock(side_effect=ccxt.BaseError()) mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock)) Exchange(default_conf) assert log_has('Unable to initialize markets. Reason: ', caplog.record_tuples)