+ def test_create_order(self):
+ with mock.patch.object(self.s, "create_exchange_order") as exchange,\
+ mock.patch.object(self.s, "create_margin_order") as margin:
+ with self.subTest(account="unspecified"):
+ self.s.create_order("symbol", "type", "side", "amount", price="price", lending_rate="lending_rate", params="params")
+ exchange.assert_called_once_with("symbol", "type", "side", "amount", price="price", params="params")
+ margin.assert_not_called()
+ exchange.reset_mock()
+ margin.reset_mock()
+
+ with self.subTest(account="exchange"):
+ self.s.create_order("symbol", "type", "side", "amount", account="exchange", price="price", lending_rate="lending_rate", params="params")
+ exchange.assert_called_once_with("symbol", "type", "side", "amount", price="price", params="params")
+ margin.assert_not_called()
+ exchange.reset_mock()
+ margin.reset_mock()
+
+ with self.subTest(account="margin"):
+ self.s.create_order("symbol", "type", "side", "amount", account="margin", price="price", lending_rate="lending_rate", params="params")
+ margin.assert_called_once_with("symbol", "type", "side", "amount", lending_rate="lending_rate", price="price", params="params")
+ exchange.assert_not_called()
+ exchange.reset_mock()
+ margin.reset_mock()
+
+ with self.subTest(account="unknown"), self.assertRaises(NotImplementedError):
+ self.s.create_order("symbol", "type", "side", "amount", account="unknown")
+
+ def test_parse_ticker(self):
+ ticker = {
+ "high24hr": "12",
+ "low24hr": "10",
+ "highestBid": "10.5",
+ "lowestAsk": "11.5",
+ "last": "11",
+ "percentChange": "0.1",
+ "quoteVolume": "10",
+ "baseVolume": "20"
+ }
+ market = {
+ "symbol": "BTC/ETC"
+ }
+ with mock.patch.object(self.s, "milliseconds") as ms:
+ ms.return_value = 1520292715123
+ result = self.s.parse_ticker(ticker, market)
+
+ expected = {
+ "symbol": "BTC/ETC",
+ "timestamp": 1520292715123,
+ "datetime": "2018-03-05T23:31:55.123Z",
+ "high": D("12"),
+ "low": D("10"),
+ "bid": D("10.5"),
+ "ask": D("11.5"),
+ "vwap": None,
+ "open": None,
+ "close": None,
+ "first": None,
+ "last": D("11"),
+ "change": D("0.1"),
+ "percentage": None,
+ "average": None,
+ "baseVolume": D("10"),
+ "quoteVolume": D("20"),
+ "info": ticker
+ }
+ self.assertEqual(expected, result)
+
+ def test_fetch_margin_balance(self):
+ with mock.patch.object(self.s, "privatePostGetMarginPosition") as get_margin_position:
+ get_margin_position.return_value = {
+ "BTC_DASH": {
+ "amount": "-0.1",
+ "basePrice": "0.06818560",
+ "lendingFees": "0.00000001",
+ "liquidationPrice": "0.15107132",
+ "pl": "-0.00000371",
+ "total": "0.00681856",
+ "type": "short"
+ },
+ "BTC_ETC": {
+ "amount": "-0.6",
+ "basePrice": "0.1",
+ "lendingFees": "0.00000001",
+ "liquidationPrice": "0.6",
+ "pl": "0.00000371",
+ "total": "0.06",
+ "type": "short"
+ },
+ "BTC_ETH": {
+ "amount": "0",
+ "basePrice": "0",
+ "lendingFees": "0",
+ "liquidationPrice": "-1",
+ "pl": "0",
+ "total": "0",
+ "type": "none"
+ }
+ }
+ balances = self.s.fetch_margin_balance()
+ self.assertEqual(2, len(balances))
+ expected = {
+ "DASH": {
+ "amount": D("-0.1"),
+ "borrowedPrice": D("0.06818560"),
+ "lendingFees": D("1E-8"),
+ "pl": D("-0.00000371"),
+ "liquidationPrice": D("0.15107132"),
+ "type": "short",
+ "total": D("0.00681856"),
+ "baseCurrency": "BTC"
+ },
+ "ETC": {
+ "amount": D("-0.6"),
+ "borrowedPrice": D("0.1"),
+ "lendingFees": D("1E-8"),
+ "pl": D("0.00000371"),
+ "liquidationPrice": D("0.6"),
+ "type": "short",
+ "total": D("0.06"),
+ "baseCurrency": "BTC"
+ }
+ }
+ self.assertEqual(expected, balances)
+
+ def test_sum(self):
+ self.assertEqual(D("1.1"), self.s.sum(D("1"), D("0.1")))
+
+ def test_fetch_balance(self):
+ with mock.patch.object(self.s, "load_markets") as load_markets,\
+ mock.patch.object(self.s, "privatePostReturnCompleteBalances") as balances,\
+ mock.patch.object(self.s, "common_currency_code") as ccc:
+ ccc.side_effect = ["ETH", "BTC", "DASH"]
+ balances.return_value = {
+ "ETH": {
+ "available": "10",
+ "onOrders": "1",
+ },
+ "BTC": {
+ "available": "1",
+ "onOrders": "0",
+ },
+ "DASH": {
+ "available": "0",
+ "onOrders": "3"
+ }
+ }
+
+ expected = {
+ "info": {
+ "ETH": {"available": "10", "onOrders": "1"},
+ "BTC": {"available": "1", "onOrders": "0"},
+ "DASH": {"available": "0", "onOrders": "3"}
+ },
+ "ETH": {"free": D("10"), "used": D("1"), "total": D("11")},
+ "BTC": {"free": D("1"), "used": D("0"), "total": D("1")},
+ "DASH": {"free": D("0"), "used": D("3"), "total": D("3")},
+ "free": {"ETH": D("10"), "BTC": D("1"), "DASH": D("0")},
+ "used": {"ETH": D("1"), "BTC": D("0"), "DASH": D("3")},
+ "total": {"ETH": D("11"), "BTC": D("1"), "DASH": D("3")}
+ }
+ result = self.s.fetch_balance()
+ load_markets.assert_called_once()
+ self.assertEqual(expected, result)
+
+ def test_fetch_balance_per_type(self):
+ with mock.patch.object(self.s, "privatePostReturnAvailableAccountBalances") as balances:
+ balances.return_value = {
+ "exchange": {
+ "BLK": "159.83673869",
+ "BTC": "0.00005959",
+ "USDT": "0.00002625",
+ "XMR": "0.18719303"
+ },
+ "margin": {
+ "BTC": "0.03019227"
+ }
+ }
+ expected = {
+ "info": {
+ "exchange": {
+ "BLK": "159.83673869",
+ "BTC": "0.00005959",
+ "USDT": "0.00002625",
+ "XMR": "0.18719303"
+ },
+ "margin": {
+ "BTC": "0.03019227"
+ }
+ },
+ "exchange": {
+ "BLK": D("159.83673869"),
+ "BTC": D("0.00005959"),
+ "USDT": D("0.00002625"),
+ "XMR": D("0.18719303")
+ },
+ "margin": {"BTC": D("0.03019227")},
+ "BLK": {"exchange": D("159.83673869")},
+ "BTC": {"exchange": D("0.00005959"), "margin": D("0.03019227")},
+ "USDT": {"exchange": D("0.00002625")},
+ "XMR": {"exchange": D("0.18719303")}
+ }
+ result = self.s.fetch_balance_per_type()
+ self.assertEqual(expected, result)
+
+ def test_fetch_all_balances(self):
+ import json
+ with mock.patch.object(self.s, "load_markets") as load_markets,\
+ mock.patch.object(self.s, "privatePostGetMarginPosition") as margin_balance,\
+ mock.patch.object(self.s, "privatePostReturnCompleteBalances") as balance,\
+ mock.patch.object(self.s, "privatePostReturnAvailableAccountBalances") as balance_per_type:
+
+ with open("test_samples/poloniexETest.test_fetch_all_balances.1.json") as f:
+ balance.return_value = json.load(f)
+ with open("test_samples/poloniexETest.test_fetch_all_balances.2.json") as f:
+ margin_balance.return_value = json.load(f)
+ with open("test_samples/poloniexETest.test_fetch_all_balances.3.json") as f:
+ balance_per_type.return_value = json.load(f)
+
+ result = self.s.fetch_all_balances()
+ expected_doge = {
+ "total": D("-12779.79821852"),
+ "exchange_used": D("0E-8"),
+ "exchange_total": D("0E-8"),
+ "exchange_free": D("0E-8"),
+ "margin_available": 0,
+ "margin_in_position": 0,
+ "margin_borrowed": D("12779.79821852"),
+ "margin_total": D("-12779.79821852"),
+ "margin_pending_gain": 0,
+ "margin_lending_fees": D("-9E-8"),
+ "margin_pending_base_gain": D("0.00024059"),
+ "margin_position_type": "short",
+ "margin_liquidation_price": D("0.00000246"),
+ "margin_borrowed_base_price": D("0.00599149"),
+ "margin_borrowed_base_currency": "BTC"
+ }
+ expected_btc = {"total": D("0.05432165"),
+ "exchange_used": D("0E-8"),
+ "exchange_total": D("0.00005959"),
+ "exchange_free": D("0.00005959"),
+ "margin_available": D("0.03019227"),
+ "margin_in_position": D("0.02406979"),
+ "margin_borrowed": 0,
+ "margin_total": D("0.05426206"),
+ "margin_pending_gain": D("0.00093955"),
+ "margin_lending_fees": 0,
+ "margin_pending_base_gain": 0,
+ "margin_position_type": None,
+ "margin_liquidation_price": 0,
+ "margin_borrowed_base_price": 0,
+ "margin_borrowed_base_currency": None
+ }
+ expected_xmr = {"total": D("0.18719303"),
+ "exchange_used": D("0E-8"),
+ "exchange_total": D("0.18719303"),
+ "exchange_free": D("0.18719303"),
+ "margin_available": 0,
+ "margin_in_position": 0,
+ "margin_borrowed": 0,
+ "margin_total": 0,
+ "margin_pending_gain": 0,
+ "margin_lending_fees": 0,
+ "margin_pending_base_gain": 0,
+ "margin_position_type": None,
+ "margin_liquidation_price": 0,
+ "margin_borrowed_base_price": 0,
+ "margin_borrowed_base_currency": None
+ }
+ self.assertEqual(expected_xmr, result["XMR"])
+ self.assertEqual(expected_doge, result["DOGE"])
+ self.assertEqual(expected_btc, result["BTC"])
+
+ def test_create_margin_order(self):
+ with self.assertRaises(market.ExchangeError):
+ self.s.create_margin_order("FOO", "market", "buy", "10")
+
+ with mock.patch.object(self.s, "load_markets") as load_markets,\
+ mock.patch.object(self.s, "privatePostMarginBuy") as margin_buy,\
+ mock.patch.object(self.s, "privatePostMarginSell") as margin_sell,\
+ mock.patch.object(self.s, "market") as market_mock,\
+ mock.patch.object(self.s, "price_to_precision") as ptp,\
+ mock.patch.object(self.s, "amount_to_precision") as atp:
+
+ margin_buy.return_value = {
+ "orderNumber": 123
+ }
+ margin_sell.return_value = {
+ "orderNumber": 456
+ }
+ market_mock.return_value = { "id": "BTC_ETC", "symbol": "BTC_ETC" }
+ ptp.return_value = D("0.1")
+ atp.return_value = D("12")
+
+ order = self.s.create_margin_order("BTC_ETC", "margin", "buy", "12", price="0.1")
+ self.assertEqual(123, order["id"])
+ margin_buy.assert_called_once_with({"currencyPair": "BTC_ETC", "rate": D("0.1"), "amount": D("12")})
+ margin_sell.assert_not_called()
+ margin_buy.reset_mock()
+ margin_sell.reset_mock()
+
+ order = self.s.create_margin_order("BTC_ETC", "margin", "sell", "12", lending_rate="0.01", price="0.1")
+ self.assertEqual(456, order["id"])
+ margin_sell.assert_called_once_with({"currencyPair": "BTC_ETC", "rate": D("0.1"), "amount": D("12"), "lendingRate": "0.01"})
+ margin_buy.assert_not_called()
+
+ def test_create_exchange_order(self):
+ with mock.patch.object(market.ccxt.poloniex, "create_order") as create_order:
+ self.s.create_order("symbol", "type", "side", "amount", price="price", params="params")
+
+ create_order.assert_called_once_with("symbol", "type", "side", "amount", price="price", params="params")
+