From df9e4e7f30a3505675bf61f7da19af4453647772 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Isma=C3=ABl=20Bouya?= Date: Mon, 12 Feb 2018 00:13:24 +0100 Subject: [PATCH] Fix some errors in api responses Handle some exceptions --- portfolio.py | 28 ++++++++++++++++++++-------- test.py | 40 ++++++++++++++++++++++++++++++++++------ 2 files changed, 54 insertions(+), 14 deletions(-) diff --git a/portfolio.py b/portfolio.py index e98689e..17a17ba 100644 --- a/portfolio.py +++ b/portfolio.py @@ -3,6 +3,7 @@ from datetime import datetime from decimal import Decimal as D, ROUND_DOWN # Put your poloniex api key in market.py from json import JSONDecodeError +from ccxt import ExchangeError, ExchangeNotAvailable import requests import helper as h from store import * @@ -463,6 +464,11 @@ class Order: else: try: self.results.append(self.market.create_order(symbol, 'limit', self.action, amount, price=self.rate, account=self.account)) + except ExchangeNotAvailable: + # Impossible to honor the order (dust amount) + self.status = "closed" + self.mark_finished_order() + return except Exception as e: self.status = "error" print("error when running market.create_order('{}', 'limit', '{}', {}, price={}, account={})".format( @@ -526,7 +532,10 @@ class Order: return filled_amount def fetch_mouvements(self): - mouvements = self.market.privatePostReturnOrderTrades({"orderNumber": self.id}) + try: + mouvements = self.market.privatePostReturnOrderTrades({"orderNumber": self.id}) + except ExchangeError: + mouvements = [] self.mouvements = [] for mouvement_hash in mouvements: @@ -544,14 +553,17 @@ class Mouvement: def __init__(self, currency, base_currency, hash_): self.currency = currency self.base_currency = base_currency - self.id = hash_["id"] - self.action = hash_["type"] - self.fee_rate = D(hash_["fee"]) - self.date = datetime.strptime(hash_["date"], '%Y-%m-%d %H:%M:%S') - self.rate = D(hash_["rate"]) - self.total = Amount(currency, hash_["amount"]) + self.id = hash_.get("tradeID") + self.action = hash_.get("type") + self.fee_rate = D(hash_.get("fee", -1)) + try: + self.date = datetime.strptime(hash_.get("date", ""), '%Y-%m-%d %H:%M:%S') + except ValueError: + self.date = None + self.rate = D(hash_.get("rate", 0)) + self.total = Amount(currency, hash_.get("amount", 0)) # rate * total = total_in_base - self.total_in_base = Amount(base_currency, hash_["total"]) + self.total_in_base = Amount(base_currency, hash_.get("total", 0)) if __name__ == '__main__': # pragma: no cover from market import market diff --git a/test.py b/test.py index 8903815..f7df9a8 100644 --- a/test.py +++ b/test.py @@ -1549,12 +1549,12 @@ class OrderTest(WebMockTestCase): order = portfolio.Order("buy", portfolio.Amount("ETH", 10), D("0.1"), "BTC", "long", "market", "trade") order.mouvements.append(portfolio.Mouvement("ETH", "BTC", { - "id": 42, "type": "buy", "fee": "0.0015", + "tradeID": 42, "type": "buy", "fee": "0.0015", "date": "2017-12-30 12:00:12", "rate": "0.1", "amount": "3", "total": "0.3" })) order.mouvements.append(portfolio.Mouvement("ETH", "BTC", { - "id": 43, "type": "buy", "fee": "0.0015", + "tradeID": 43, "type": "buy", "fee": "0.0015", "date": "2017-12-30 13:00:12", "rate": "0.2", "amount": "2", "total": "0.4" })) @@ -1569,12 +1569,12 @@ class OrderTest(WebMockTestCase): market = mock.Mock() market.privatePostReturnOrderTrades.return_value = [ { - "id": 42, "type": "buy", "fee": "0.0015", + "tradeID": 42, "type": "buy", "fee": "0.0015", "date": "2017-12-30 12:00:12", "rate": "0.1", "amount": "3", "total": "0.3" }, { - "id": 43, "type": "buy", "fee": "0.0015", + "tradeID": 43, "type": "buy", "fee": "0.0015", "date": "2017-12-30 13:00:12", "rate": "0.2", "amount": "2", "total": "0.4" } @@ -1591,6 +1591,12 @@ class OrderTest(WebMockTestCase): self.assertEqual(42, order.mouvements[0].id) self.assertEqual(43, order.mouvements[1].id) + market.privatePostReturnOrderTrades.side_effect = portfolio.ExchangeError + order = portfolio.Order("buy", portfolio.Amount("ETH", 10), + D("0.1"), "BTC", "long", market, "trade") + order.fetch_mouvements() + self.assertEqual(0, len(order.mouvements)) + def test_mark_finished_order(self): market = mock.Mock() order = portfolio.Order("buy", portfolio.Amount("ETH", 10), @@ -1770,11 +1776,24 @@ class OrderTest(WebMockTestCase): self.assertRegex(stdout_mock.getvalue(), "error when running market.create_order") self.assertRegex(stdout_mock.getvalue(), "Exception: bouh") + market.create_order.reset_mock() + with self.subTest(dust_amount_exception=True),\ + mock.patch.object(portfolio.Order, "mark_finished_order") as mark_finished_order: + order = portfolio.Order("buy", portfolio.Amount("ETH", 0.001), + D("0.1"), "BTC", "long", market, "trade") + market.create_order.side_effect = portfolio.ExchangeNotAvailable + order.run() + market.create_order.assert_called_once() + self.assertEqual(0, len(order.results)) + self.assertEqual("closed", order.status) + mark_finished_order.assert_called_once() + + @unittest.skipUnless("unit" in limits, "Unit skipped") class MouvementTest(WebMockTestCase): def test_values(self): mouvement = portfolio.Mouvement("ETH", "BTC", { - "id": 42, "type": "buy", "fee": "0.0015", + "tradeID": 42, "type": "buy", "fee": "0.0015", "date": "2017-12-30 12:00:12", "rate": "0.1", "amount": "10", "total": "1" }) @@ -1788,6 +1807,15 @@ class MouvementTest(WebMockTestCase): self.assertEqual(portfolio.Amount("ETH", "10"), mouvement.total) self.assertEqual(portfolio.Amount("BTC", "1"), mouvement.total_in_base) + mouvement = portfolio.Mouvement("ETH", "BTC", { "foo": "bar" }) + self.assertIsNone(mouvement.date) + self.assertIsNone(mouvement.id) + self.assertIsNone(mouvement.action) + self.assertEqual(-1, mouvement.fee_rate) + self.assertEqual(0, mouvement.rate) + self.assertEqual(portfolio.Amount("ETH", 0), mouvement.total) + self.assertEqual(portfolio.Amount("BTC", 0), mouvement.total_in_base) + @unittest.skipUnless("acceptance" in limits, "Acceptance skipped") class AcceptanceTest(WebMockTestCase): @unittest.expectedFailure @@ -1939,7 +1967,7 @@ class AcceptanceTest(WebMockTestCase): market.fetch_order.return_value = { "status": "closed", "datetime": "2018-01-20 13:40:00" } market.privatePostReturnOrderTrades.return_value = [ { - "id": 42, "type": "buy", "fee": "0.0015", + "tradeID": 42, "type": "buy", "fee": "0.0015", "date": "2017-12-30 12:00:12", "rate": "0.1", "amount": "10", "total": "1" } -- 2.41.0