]> git.immae.eu Git - perso/Immae/Projets/Cryptomonnaies/Cryptoportfolio/Trader.git/commitdiff
Fix some errors in api responses
authorIsmaël Bouya <ismael.bouya@normalesup.org>
Sun, 11 Feb 2018 23:13:24 +0000 (00:13 +0100)
committerIsmaël Bouya <ismael.bouya@normalesup.org>
Sun, 11 Feb 2018 23:13:24 +0000 (00:13 +0100)
Handle some exceptions

portfolio.py
test.py

index e98689ee4c2599fc63f77b6236057e9df0b2519e..17a17ba51e3c1672d4d174c1ba2f7872439bca4a 100644 (file)
@@ -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 890381541368f5d683d942584152e0dfbd5324f0..f7df9a861ffc46240515f5868d5a508567122313 100644 (file)
--- 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"
                     }