aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIsmaël Bouya <ismael.bouya@normalesup.org>2018-02-12 00:13:24 +0100
committerIsmaël Bouya <ismael.bouya@normalesup.org>2018-02-12 00:13:24 +0100
commitdf9e4e7f30a3505675bf61f7da19af4453647772 (patch)
treefb799d4dec96993e7892c4385df34f03349cc0b9
parent5a72ded790f8b5e7c9b38a3cc91c12fbfb6cb97a (diff)
downloadTrader-df9e4e7f30a3505675bf61f7da19af4453647772.tar.gz
Trader-df9e4e7f30a3505675bf61f7da19af4453647772.tar.zst
Trader-df9e4e7f30a3505675bf61f7da19af4453647772.zip
Fix some errors in api responses
Handle some exceptions
-rw-r--r--portfolio.py28
-rw-r--r--test.py40
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
3from decimal import Decimal as D, ROUND_DOWN 3from decimal import Decimal as D, ROUND_DOWN
4# Put your poloniex api key in market.py 4# Put your poloniex api key in market.py
5from json import JSONDecodeError 5from json import JSONDecodeError
6from ccxt import ExchangeError, ExchangeNotAvailable
6import requests 7import requests
7import helper as h 8import helper as h
8from store import * 9from store import *
@@ -463,6 +464,11 @@ class Order:
463 else: 464 else:
464 try: 465 try:
465 self.results.append(self.market.create_order(symbol, 'limit', self.action, amount, price=self.rate, account=self.account)) 466 self.results.append(self.market.create_order(symbol, 'limit', self.action, amount, price=self.rate, account=self.account))
467 except ExchangeNotAvailable:
468 # Impossible to honor the order (dust amount)
469 self.status = "closed"
470 self.mark_finished_order()
471 return
466 except Exception as e: 472 except Exception as e:
467 self.status = "error" 473 self.status = "error"
468 print("error when running market.create_order('{}', 'limit', '{}', {}, price={}, account={})".format( 474 print("error when running market.create_order('{}', 'limit', '{}', {}, price={}, account={})".format(
@@ -526,7 +532,10 @@ class Order:
526 return filled_amount 532 return filled_amount
527 533
528 def fetch_mouvements(self): 534 def fetch_mouvements(self):
529 mouvements = self.market.privatePostReturnOrderTrades({"orderNumber": self.id}) 535 try:
536 mouvements = self.market.privatePostReturnOrderTrades({"orderNumber": self.id})
537 except ExchangeError:
538 mouvements = []
530 self.mouvements = [] 539 self.mouvements = []
531 540
532 for mouvement_hash in mouvements: 541 for mouvement_hash in mouvements:
@@ -544,14 +553,17 @@ class Mouvement:
544 def __init__(self, currency, base_currency, hash_): 553 def __init__(self, currency, base_currency, hash_):
545 self.currency = currency 554 self.currency = currency
546 self.base_currency = base_currency 555 self.base_currency = base_currency
547 self.id = hash_["id"] 556 self.id = hash_.get("tradeID")
548 self.action = hash_["type"] 557 self.action = hash_.get("type")
549 self.fee_rate = D(hash_["fee"]) 558 self.fee_rate = D(hash_.get("fee", -1))
550 self.date = datetime.strptime(hash_["date"], '%Y-%m-%d %H:%M:%S') 559 try:
551 self.rate = D(hash_["rate"]) 560 self.date = datetime.strptime(hash_.get("date", ""), '%Y-%m-%d %H:%M:%S')
552 self.total = Amount(currency, hash_["amount"]) 561 except ValueError:
562 self.date = None
563 self.rate = D(hash_.get("rate", 0))
564 self.total = Amount(currency, hash_.get("amount", 0))
553 # rate * total = total_in_base 565 # rate * total = total_in_base
554 self.total_in_base = Amount(base_currency, hash_["total"]) 566 self.total_in_base = Amount(base_currency, hash_.get("total", 0))
555 567
556if __name__ == '__main__': # pragma: no cover 568if __name__ == '__main__': # pragma: no cover
557 from market import market 569 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):
1549 order = portfolio.Order("buy", portfolio.Amount("ETH", 10), 1549 order = portfolio.Order("buy", portfolio.Amount("ETH", 10),
1550 D("0.1"), "BTC", "long", "market", "trade") 1550 D("0.1"), "BTC", "long", "market", "trade")
1551 order.mouvements.append(portfolio.Mouvement("ETH", "BTC", { 1551 order.mouvements.append(portfolio.Mouvement("ETH", "BTC", {
1552 "id": 42, "type": "buy", "fee": "0.0015", 1552 "tradeID": 42, "type": "buy", "fee": "0.0015",
1553 "date": "2017-12-30 12:00:12", "rate": "0.1", 1553 "date": "2017-12-30 12:00:12", "rate": "0.1",
1554 "amount": "3", "total": "0.3" 1554 "amount": "3", "total": "0.3"
1555 })) 1555 }))
1556 order.mouvements.append(portfolio.Mouvement("ETH", "BTC", { 1556 order.mouvements.append(portfolio.Mouvement("ETH", "BTC", {
1557 "id": 43, "type": "buy", "fee": "0.0015", 1557 "tradeID": 43, "type": "buy", "fee": "0.0015",
1558 "date": "2017-12-30 13:00:12", "rate": "0.2", 1558 "date": "2017-12-30 13:00:12", "rate": "0.2",
1559 "amount": "2", "total": "0.4" 1559 "amount": "2", "total": "0.4"
1560 })) 1560 }))
@@ -1569,12 +1569,12 @@ class OrderTest(WebMockTestCase):
1569 market = mock.Mock() 1569 market = mock.Mock()
1570 market.privatePostReturnOrderTrades.return_value = [ 1570 market.privatePostReturnOrderTrades.return_value = [
1571 { 1571 {
1572 "id": 42, "type": "buy", "fee": "0.0015", 1572 "tradeID": 42, "type": "buy", "fee": "0.0015",
1573 "date": "2017-12-30 12:00:12", "rate": "0.1", 1573 "date": "2017-12-30 12:00:12", "rate": "0.1",
1574 "amount": "3", "total": "0.3" 1574 "amount": "3", "total": "0.3"
1575 }, 1575 },
1576 { 1576 {
1577 "id": 43, "type": "buy", "fee": "0.0015", 1577 "tradeID": 43, "type": "buy", "fee": "0.0015",
1578 "date": "2017-12-30 13:00:12", "rate": "0.2", 1578 "date": "2017-12-30 13:00:12", "rate": "0.2",
1579 "amount": "2", "total": "0.4" 1579 "amount": "2", "total": "0.4"
1580 } 1580 }
@@ -1591,6 +1591,12 @@ class OrderTest(WebMockTestCase):
1591 self.assertEqual(42, order.mouvements[0].id) 1591 self.assertEqual(42, order.mouvements[0].id)
1592 self.assertEqual(43, order.mouvements[1].id) 1592 self.assertEqual(43, order.mouvements[1].id)
1593 1593
1594 market.privatePostReturnOrderTrades.side_effect = portfolio.ExchangeError
1595 order = portfolio.Order("buy", portfolio.Amount("ETH", 10),
1596 D("0.1"), "BTC", "long", market, "trade")
1597 order.fetch_mouvements()
1598 self.assertEqual(0, len(order.mouvements))
1599
1594 def test_mark_finished_order(self): 1600 def test_mark_finished_order(self):
1595 market = mock.Mock() 1601 market = mock.Mock()
1596 order = portfolio.Order("buy", portfolio.Amount("ETH", 10), 1602 order = portfolio.Order("buy", portfolio.Amount("ETH", 10),
@@ -1770,11 +1776,24 @@ class OrderTest(WebMockTestCase):
1770 self.assertRegex(stdout_mock.getvalue(), "error when running market.create_order") 1776 self.assertRegex(stdout_mock.getvalue(), "error when running market.create_order")
1771 self.assertRegex(stdout_mock.getvalue(), "Exception: bouh") 1777 self.assertRegex(stdout_mock.getvalue(), "Exception: bouh")
1772 1778
1779 market.create_order.reset_mock()
1780 with self.subTest(dust_amount_exception=True),\
1781 mock.patch.object(portfolio.Order, "mark_finished_order") as mark_finished_order:
1782 order = portfolio.Order("buy", portfolio.Amount("ETH", 0.001),
1783 D("0.1"), "BTC", "long", market, "trade")
1784 market.create_order.side_effect = portfolio.ExchangeNotAvailable
1785 order.run()
1786 market.create_order.assert_called_once()
1787 self.assertEqual(0, len(order.results))
1788 self.assertEqual("closed", order.status)
1789 mark_finished_order.assert_called_once()
1790
1791
1773@unittest.skipUnless("unit" in limits, "Unit skipped") 1792@unittest.skipUnless("unit" in limits, "Unit skipped")
1774class MouvementTest(WebMockTestCase): 1793class MouvementTest(WebMockTestCase):
1775 def test_values(self): 1794 def test_values(self):
1776 mouvement = portfolio.Mouvement("ETH", "BTC", { 1795 mouvement = portfolio.Mouvement("ETH", "BTC", {
1777 "id": 42, "type": "buy", "fee": "0.0015", 1796 "tradeID": 42, "type": "buy", "fee": "0.0015",
1778 "date": "2017-12-30 12:00:12", "rate": "0.1", 1797 "date": "2017-12-30 12:00:12", "rate": "0.1",
1779 "amount": "10", "total": "1" 1798 "amount": "10", "total": "1"
1780 }) 1799 })
@@ -1788,6 +1807,15 @@ class MouvementTest(WebMockTestCase):
1788 self.assertEqual(portfolio.Amount("ETH", "10"), mouvement.total) 1807 self.assertEqual(portfolio.Amount("ETH", "10"), mouvement.total)
1789 self.assertEqual(portfolio.Amount("BTC", "1"), mouvement.total_in_base) 1808 self.assertEqual(portfolio.Amount("BTC", "1"), mouvement.total_in_base)
1790 1809
1810 mouvement = portfolio.Mouvement("ETH", "BTC", { "foo": "bar" })
1811 self.assertIsNone(mouvement.date)
1812 self.assertIsNone(mouvement.id)
1813 self.assertIsNone(mouvement.action)
1814 self.assertEqual(-1, mouvement.fee_rate)
1815 self.assertEqual(0, mouvement.rate)
1816 self.assertEqual(portfolio.Amount("ETH", 0), mouvement.total)
1817 self.assertEqual(portfolio.Amount("BTC", 0), mouvement.total_in_base)
1818
1791@unittest.skipUnless("acceptance" in limits, "Acceptance skipped") 1819@unittest.skipUnless("acceptance" in limits, "Acceptance skipped")
1792class AcceptanceTest(WebMockTestCase): 1820class AcceptanceTest(WebMockTestCase):
1793 @unittest.expectedFailure 1821 @unittest.expectedFailure
@@ -1939,7 +1967,7 @@ class AcceptanceTest(WebMockTestCase):
1939 market.fetch_order.return_value = { "status": "closed", "datetime": "2018-01-20 13:40:00" } 1967 market.fetch_order.return_value = { "status": "closed", "datetime": "2018-01-20 13:40:00" }
1940 market.privatePostReturnOrderTrades.return_value = [ 1968 market.privatePostReturnOrderTrades.return_value = [
1941 { 1969 {
1942 "id": 42, "type": "buy", "fee": "0.0015", 1970 "tradeID": 42, "type": "buy", "fee": "0.0015",
1943 "date": "2017-12-30 12:00:12", "rate": "0.1", 1971 "date": "2017-12-30 12:00:12", "rate": "0.1",
1944 "amount": "10", "total": "1" 1972 "amount": "10", "total": "1"
1945 } 1973 }