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 *
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(
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:
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
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"
}))
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"
}
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),
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"
})
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
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"
}