aboutsummaryrefslogtreecommitdiff
path: root/test.py
diff options
context:
space:
mode:
Diffstat (limited to 'test.py')
-rw-r--r--test.py344
1 files changed, 195 insertions, 149 deletions
diff --git a/test.py b/test.py
index 778fc14..141c9e0 100644
--- a/test.py
+++ b/test.py
@@ -35,10 +35,6 @@ class WebMockTestCase(unittest.TestCase):
35 mock.patch.multiple(portfolio.Portfolio, last_date=None, data=None, liquidities={}), 35 mock.patch.multiple(portfolio.Portfolio, last_date=None, data=None, liquidities={}),
36 mock.patch.multiple(portfolio.Computation, 36 mock.patch.multiple(portfolio.Computation,
37 computations=portfolio.Computation.computations), 37 computations=portfolio.Computation.computations),
38 mock.patch.multiple(market.Market,
39 fees_cache={},
40 ticker_cache={},
41 ticker_cache_timestamp=self.time.time()),
42 ] 38 ]
43 for patcher in self.patchers: 39 for patcher in self.patchers:
44 patcher.start() 40 patcher.start()
@@ -472,8 +468,9 @@ class BalanceTest(WebMockTestCase):
472 "exchange_free": "0.35", 468 "exchange_free": "0.35",
473 "exchange_used": "0.30", 469 "exchange_used": "0.30",
474 "margin_total": "-10", 470 "margin_total": "-10",
475 "margin_borrowed": "-10", 471 "margin_borrowed": "10",
476 "margin_free": "0", 472 "margin_available": "0",
473 "margin_in_position": "0",
477 "margin_position_type": "short", 474 "margin_position_type": "short",
478 "margin_borrowed_base_currency": "USDT", 475 "margin_borrowed_base_currency": "USDT",
479 "margin_liquidation_price": "1.20", 476 "margin_liquidation_price": "1.20",
@@ -489,11 +486,11 @@ class BalanceTest(WebMockTestCase):
489 self.assertEqual("BTC", balance.exchange_total.currency) 486 self.assertEqual("BTC", balance.exchange_total.currency)
490 487
491 self.assertEqual(portfolio.D("-10"), balance.margin_total.value) 488 self.assertEqual(portfolio.D("-10"), balance.margin_total.value)
492 self.assertEqual(portfolio.D("-10"), balance.margin_borrowed.value) 489 self.assertEqual(portfolio.D("10"), balance.margin_borrowed.value)
493 self.assertEqual(portfolio.D("0"), balance.margin_free.value) 490 self.assertEqual(portfolio.D("0"), balance.margin_available.value)
494 self.assertEqual("BTC", balance.margin_total.currency) 491 self.assertEqual("BTC", balance.margin_total.currency)
495 self.assertEqual("BTC", balance.margin_borrowed.currency) 492 self.assertEqual("BTC", balance.margin_borrowed.currency)
496 self.assertEqual("BTC", balance.margin_free.currency) 493 self.assertEqual("BTC", balance.margin_available.currency)
497 494
498 self.assertEqual("BTC", balance.currency) 495 self.assertEqual("BTC", balance.currency)
499 496
@@ -511,10 +508,10 @@ class BalanceTest(WebMockTestCase):
511 self.assertEqual("Balance(BTX Exch: [❌1.00000000 BTX])", repr(balance)) 508 self.assertEqual("Balance(BTX Exch: [❌1.00000000 BTX])", repr(balance))
512 509
513 balance = portfolio.Balance("BTX", { "margin_total": 3, 510 balance = portfolio.Balance("BTX", { "margin_total": 3,
514 "margin_borrowed": 1, "margin_free": 2 }) 511 "margin_in_position": 1, "margin_available": 2 })
515 self.assertEqual("Balance(BTX Margin: [✔2.00000000 BTX + borrowed 1.00000000 BTX = 3.00000000 BTX])", repr(balance)) 512 self.assertEqual("Balance(BTX Margin: [✔2.00000000 BTX + 1.00000000 BTX = 3.00000000 BTX])", repr(balance))
516 513
517 balance = portfolio.Balance("BTX", { "margin_total": 2, "margin_free": 2 }) 514 balance = portfolio.Balance("BTX", { "margin_total": 2, "margin_available": 2 })
518 self.assertEqual("Balance(BTX Margin: [✔2.00000000 BTX])", repr(balance)) 515 self.assertEqual("Balance(BTX Margin: [✔2.00000000 BTX])", repr(balance))
519 516
520 balance = portfolio.Balance("BTX", { "margin_total": -3, 517 balance = portfolio.Balance("BTX", { "margin_total": -3,
@@ -524,8 +521,8 @@ class BalanceTest(WebMockTestCase):
524 self.assertEqual("Balance(BTX Margin: [-3.00000000 BTX @@ 0.10000000 BTC/0.00200000 BTC])", repr(balance)) 521 self.assertEqual("Balance(BTX Margin: [-3.00000000 BTX @@ 0.10000000 BTC/0.00200000 BTC])", repr(balance))
525 522
526 balance = portfolio.Balance("BTX", { "margin_total": 1, 523 balance = portfolio.Balance("BTX", { "margin_total": 1,
527 "margin_borrowed": 1, "exchange_free": 2, "exchange_total": 2}) 524 "margin_in_position": 1, "exchange_free": 2, "exchange_total": 2})
528 self.assertEqual("Balance(BTX Exch: [✔2.00000000 BTX] Margin: [borrowed 1.00000000 BTX] Total: [0.00000000 BTX])", repr(balance)) 525 self.assertEqual("Balance(BTX Exch: [✔2.00000000 BTX] Margin: [❌1.00000000 BTX] Total: [0.00000000 BTX])", repr(balance))
529 526
530 def test_as_json(self): 527 def test_as_json(self):
531 balance = portfolio.Balance("BTX", { "exchange_free": 2, "exchange_total": 2 }) 528 balance = portfolio.Balance("BTX", { "exchange_free": 2, "exchange_total": 2 })
@@ -536,7 +533,7 @@ class BalanceTest(WebMockTestCase):
536 self.assertEqual(D(2), as_json["exchange_free"]) 533 self.assertEqual(D(2), as_json["exchange_free"])
537 self.assertEqual(D(0), as_json["exchange_used"]) 534 self.assertEqual(D(0), as_json["exchange_used"])
538 self.assertEqual(D(0), as_json["margin_total"]) 535 self.assertEqual(D(0), as_json["margin_total"])
539 self.assertEqual(D(0), as_json["margin_free"]) 536 self.assertEqual(D(0), as_json["margin_available"])
540 self.assertEqual(D(0), as_json["margin_borrowed"]) 537 self.assertEqual(D(0), as_json["margin_borrowed"])
541 538
542@unittest.skipUnless("unit" in limits, "Unit skipped") 539@unittest.skipUnless("unit" in limits, "Unit skipped")
@@ -583,77 +580,69 @@ class MarketTest(WebMockTestCase):
583 m = market.Market.from_config({"key": "key", "secred": "secret"}, debug=True) 580 m = market.Market.from_config({"key": "key", "secred": "secret"}, debug=True)
584 self.assertEqual(True, m.debug) 581 self.assertEqual(True, m.debug)
585 582
586 def test_get_ticker(self): 583 def test_get_tickers(self):
587 m = market.Market(self.ccxt) 584 self.ccxt.fetch_tickers.side_effect = [
588 self.ccxt.fetch_ticker.side_effect = [ 585 "tickers",
589 { "bid": 1, "ask": 3 }, 586 market.NotSupported
590 market.ExchangeError("foo"),
591 { "bid": 10, "ask": 40 },
592 market.ExchangeError("foo"),
593 market.ExchangeError("foo"),
594 ] 587 ]
595 588
596 ticker = m.get_ticker("ETH", "ETC") 589 m = market.Market(self.ccxt)
597 self.ccxt.fetch_ticker.assert_called_with("ETH/ETC") 590 self.assertEqual("tickers", m.get_tickers())
598 self.assertEqual(1, ticker["bid"]) 591 self.assertEqual("tickers", m.get_tickers())
599 self.assertEqual(3, ticker["ask"]) 592 self.ccxt.fetch_tickers.assert_called_once()
600 self.assertEqual(2, ticker["average"])
601 self.assertFalse(ticker["inverted"])
602
603 ticker = m.get_ticker("ETH", "XVG")
604 self.assertEqual(0.0625, ticker["average"])
605 self.assertTrue(ticker["inverted"])
606 self.assertIn("original", ticker)
607 self.assertEqual(10, ticker["original"]["bid"])
608
609 ticker = m.get_ticker("XVG", "XMR")
610 self.assertIsNone(ticker)
611
612 self.ccxt.fetch_ticker.assert_has_calls([
613 mock.call("ETH/ETC"),
614 mock.call("ETH/XVG"),
615 mock.call("XVG/ETH"),
616 mock.call("XVG/XMR"),
617 mock.call("XMR/XVG"),
618 ])
619 593
620 self.ccxt = mock.Mock(spec=market.ccxt.poloniexE) 594 self.assertIsNone(m.get_tickers(refresh=self.time.time()))
621 m1b = market.Market(self.ccxt) 595
622 m1b.get_ticker("ETH", "ETC") 596 def test_get_ticker(self):
623 self.ccxt.fetch_ticker.assert_not_called() 597 with self.subTest(get_tickers=True):
624 598 self.ccxt.fetch_tickers.return_value = {
625 self.ccxt = mock.Mock(spec=market.ccxt.poloniex) 599 "ETH/ETC": { "bid": 1, "ask": 3 },
626 m2 = market.Market(self.ccxt) 600 "XVG/ETH": { "bid": 10, "ask": 40 },
627 self.ccxt.fetch_ticker.side_effect = [ 601 }
628 { "bid": 1, "ask": 3 }, 602 m = market.Market(self.ccxt)
629 { "bid": 1.2, "ask": 3.5 }, 603
630 ] 604 ticker = m.get_ticker("ETH", "ETC")
631 ticker1 = m2.get_ticker("ETH", "ETC") 605 self.assertEqual(1, ticker["bid"])
632 ticker2 = m2.get_ticker("ETH", "ETC") 606 self.assertEqual(3, ticker["ask"])
633 ticker3 = m2.get_ticker("ETC", "ETH") 607 self.assertEqual(2, ticker["average"])
634 self.ccxt.fetch_ticker.assert_called_once_with("ETH/ETC") 608 self.assertFalse(ticker["inverted"])
635 self.assertEqual(1, ticker1["bid"]) 609
636 self.assertDictEqual(ticker1, ticker2) 610 ticker = m.get_ticker("ETH", "XVG")
637 self.assertDictEqual(ticker1, ticker3["original"]) 611 self.assertEqual(0.0625, ticker["average"])
638 612 self.assertTrue(ticker["inverted"])
639 ticker4 = m2.get_ticker("ETH", "ETC", refresh=True) 613 self.assertIn("original", ticker)
640 ticker5 = m2.get_ticker("ETH", "ETC") 614 self.assertEqual(10, ticker["original"]["bid"])
641 self.assertEqual(1.2, ticker4["bid"]) 615
642 self.assertDictEqual(ticker4, ticker5) 616 ticker = m.get_ticker("XVG", "XMR")
643 617 self.assertIsNone(ticker)
644 self.ccxt = mock.Mock(spec=market.ccxt.binance) 618
645 m3 = market.Market(self.ccxt) 619 with self.subTest(get_tickers=False):
646 self.ccxt.fetch_ticker.side_effect = [ 620 self.ccxt.fetch_tickers.return_value = None
647 { "bid": 1, "ask": 3 }, 621 self.ccxt.fetch_ticker.side_effect = [
648 { "bid": 1.2, "ask": 3.5 }, 622 { "bid": 1, "ask": 3 },
649 ] 623 market.ExchangeError("foo"),
650 ticker6 = m3.get_ticker("ETH", "ETC") 624 { "bid": 10, "ask": 40 },
651 m3.ticker_cache_timestamp -= 4 625 market.ExchangeError("foo"),
652 ticker7 = m3.get_ticker("ETH", "ETC") 626 market.ExchangeError("foo"),
653 m3.ticker_cache_timestamp -= 2 627 ]
654 ticker8 = m3.get_ticker("ETH", "ETC") 628
655 self.assertDictEqual(ticker6, ticker7) 629 m = market.Market(self.ccxt)
656 self.assertEqual(1.2, ticker8["bid"]) 630
631 ticker = m.get_ticker("ETH", "ETC")
632 self.ccxt.fetch_ticker.assert_called_with("ETH/ETC")
633 self.assertEqual(1, ticker["bid"])
634 self.assertEqual(3, ticker["ask"])
635 self.assertEqual(2, ticker["average"])
636 self.assertFalse(ticker["inverted"])
637
638 ticker = m.get_ticker("ETH", "XVG")
639 self.assertEqual(0.0625, ticker["average"])
640 self.assertTrue(ticker["inverted"])
641 self.assertIn("original", ticker)
642 self.assertEqual(10, ticker["original"]["bid"])
643
644 ticker = m.get_ticker("XVG", "XMR")
645 self.assertIsNone(ticker)
657 646
658 def test_fetch_fees(self): 647 def test_fetch_fees(self):
659 m = market.Market(self.ccxt) 648 m = market.Market(self.ccxt)
@@ -906,9 +895,9 @@ class MarketTest(WebMockTestCase):
906 trade3 = portfolio.Trade(value_from, value_to, "XVG", m) 895 trade3 = portfolio.Trade(value_from, value_to, "XVG", m)
907 896
908 m.trades.all = [trade1, trade2, trade3] 897 m.trades.all = [trade1, trade2, trade3]
909 balance1 = portfolio.Balance("BTC", { "margin_free": "0" }) 898 balance1 = portfolio.Balance("BTC", { "margin_in_position": "0", "margin_available": "0" })
910 balance2 = portfolio.Balance("USDT", { "margin_free": "100" }) 899 balance2 = portfolio.Balance("USDT", { "margin_in_position": "100", "margin_available": "50" })
911 balance3 = portfolio.Balance("ETC", { "margin_free": "10" }) 900 balance3 = portfolio.Balance("ETC", { "margin_in_position": "10", "margin_available": "15" })
912 m.balances.all = {"BTC": balance1, "USDT": balance2, "ETC": balance3} 901 m.balances.all = {"BTC": balance1, "USDT": balance2, "ETC": balance3}
913 902
914 m.move_balances() 903 m.move_balances()
@@ -921,8 +910,8 @@ class MarketTest(WebMockTestCase):
921 self.assertEqual(3, m.report.log_debug_action.call_count) 910 self.assertEqual(3, m.report.log_debug_action.call_count)
922 else: 911 else:
923 self.ccxt.transfer_balance.assert_any_call("BTC", 3, "exchange", "margin") 912 self.ccxt.transfer_balance.assert_any_call("BTC", 3, "exchange", "margin")
924 self.ccxt.transfer_balance.assert_any_call("USDT", 50, "margin", "exchange") 913 self.ccxt.transfer_balance.assert_any_call("USDT", 100, "exchange", "margin")
925 self.ccxt.transfer_balance.assert_any_call("ETC", 10, "margin", "exchange") 914 self.ccxt.transfer_balance.assert_any_call("ETC", 5, "margin", "exchange")
926 915
927@unittest.skipUnless("unit" in limits, "Unit skipped") 916@unittest.skipUnless("unit" in limits, "Unit skipped")
928class TradeStoreTest(WebMockTestCase): 917class TradeStoreTest(WebMockTestCase):
@@ -1001,16 +990,24 @@ class TradeStoreTest(WebMockTestCase):
1001 990
1002 trade_mock1 = mock.Mock() 991 trade_mock1 = mock.Mock()
1003 trade_mock2 = mock.Mock() 992 trade_mock2 = mock.Mock()
993 trade_mock3 = mock.Mock()
1004 994
1005 trade_mock1.prepare_order.return_value = 1 995 trade_mock1.prepare_order.return_value = 1
1006 trade_mock2.prepare_order.return_value = 2 996 trade_mock2.prepare_order.return_value = 2
997 trade_mock3.prepare_order.return_value = 3
998
999 trade_mock1.is_fullfiled = False
1000 trade_mock2.is_fullfiled = False
1001 trade_mock3.is_fullfiled = True
1007 1002
1008 trade_store.all.append(trade_mock1) 1003 trade_store.all.append(trade_mock1)
1009 trade_store.all.append(trade_mock2) 1004 trade_store.all.append(trade_mock2)
1005 trade_store.all.append(trade_mock3)
1010 1006
1011 trade_store.prepare_orders() 1007 trade_store.prepare_orders()
1012 trade_mock1.prepare_order.assert_called_with(compute_value="default") 1008 trade_mock1.prepare_order.assert_called_with(compute_value="default")
1013 trade_mock2.prepare_order.assert_called_with(compute_value="default") 1009 trade_mock2.prepare_order.assert_called_with(compute_value="default")
1010 trade_mock3.prepare_order.assert_not_called()
1014 self.m.report.log_orders.assert_called_once_with([1, 2], None, "default") 1011 self.m.report.log_orders.assert_called_once_with([1, 2], None, "default")
1015 1012
1016 self.m.report.log_orders.reset_mock() 1013 self.m.report.log_orders.reset_mock()
@@ -1108,6 +1105,21 @@ class TradeStoreTest(WebMockTestCase):
1108 order_mock2.get_status.assert_called() 1105 order_mock2.get_status.assert_called()
1109 order_mock3.get_status.assert_called() 1106 order_mock3.get_status.assert_called()
1110 1107
1108 def test_pending(self):
1109 trade_mock1 = mock.Mock()
1110 trade_mock1.is_fullfiled = False
1111 trade_mock2 = mock.Mock()
1112 trade_mock2.is_fullfiled = False
1113 trade_mock3 = mock.Mock()
1114 trade_mock3.is_fullfiled = True
1115
1116 trade_store = market.TradeStore(self.m)
1117
1118 trade_store.all.append(trade_mock1)
1119 trade_store.all.append(trade_mock2)
1120 trade_store.all.append(trade_mock3)
1121
1122 self.assertEqual([trade_mock1, trade_mock2], trade_store.pending)
1111 1123
1112@unittest.skipUnless("unit" in limits, "Unit skipped") 1124@unittest.skipUnless("unit" in limits, "Unit skipped")
1113class BalanceStoreTest(WebMockTestCase): 1125class BalanceStoreTest(WebMockTestCase):
@@ -1301,13 +1313,16 @@ class TradeTest(WebMockTestCase):
1301 self.assertEqual(self.m, trade.market) 1313 self.assertEqual(self.m, trade.market)
1302 1314
1303 with self.assertRaises(AssertionError): 1315 with self.assertRaises(AssertionError):
1304 portfolio.Trade(value_from, value_to, "ETC", self.m) 1316 portfolio.Trade(value_from, -value_to, "ETH", self.m)
1305 with self.assertRaises(AssertionError): 1317 with self.assertRaises(AssertionError):
1306 value_from.linked_to = None 1318 portfolio.Trade(value_from, value_to, "ETC", self.m)
1307 portfolio.Trade(value_from, value_to, "ETH", self.m)
1308 with self.assertRaises(AssertionError): 1319 with self.assertRaises(AssertionError):
1309 value_from.currency = "ETH" 1320 value_from.currency = "ETH"
1310 portfolio.Trade(value_from, value_to, "ETH", self.m) 1321 portfolio.Trade(value_from, value_to, "ETH", self.m)
1322 value_from.currency = "BTC"
1323 with self.assertRaises(AssertionError):
1324 value_from2 = portfolio.Amount("BTC", "1.0")
1325 portfolio.Trade(value_from2, value_to, "ETH", self.m)
1311 1326
1312 value_from = portfolio.Amount("BTC", 0) 1327 value_from = portfolio.Amount("BTC", 0)
1313 trade = portfolio.Trade(value_from, value_to, "ETH", self.m) 1328 trade = portfolio.Trade(value_from, value_to, "ETH", self.m)
@@ -1374,6 +1389,28 @@ class TradeTest(WebMockTestCase):
1374 1389
1375 self.assertEqual("short", trade.trade_type) 1390 self.assertEqual("short", trade.trade_type)
1376 1391
1392 def test_is_fullfiled(self):
1393 value_from = portfolio.Amount("BTC", "0.5")
1394 value_from.linked_to = portfolio.Amount("ETH", "10.0")
1395 value_to = portfolio.Amount("BTC", "1.0")
1396 trade = portfolio.Trade(value_from, value_to, "ETH", self.m)
1397
1398 order1 = mock.Mock()
1399 order1.filled_amount.return_value = portfolio.Amount("BTC", "0.3")
1400
1401 order2 = mock.Mock()
1402 order2.filled_amount.return_value = portfolio.Amount("BTC", "0.01")
1403 trade.orders.append(order1)
1404 trade.orders.append(order2)
1405
1406 self.assertFalse(trade.is_fullfiled)
1407
1408 order3 = mock.Mock()
1409 order3.filled_amount.return_value = portfolio.Amount("BTC", "0.19")
1410 trade.orders.append(order3)
1411
1412 self.assertTrue(trade.is_fullfiled)
1413
1377 def test_filled_amount(self): 1414 def test_filled_amount(self):
1378 value_from = portfolio.Amount("BTC", "0.5") 1415 value_from = portfolio.Amount("BTC", "0.5")
1379 value_from.linked_to = portfolio.Amount("ETH", "10.0") 1416 value_from.linked_to = portfolio.Amount("ETH", "10.0")
@@ -1588,7 +1625,7 @@ class TradeTest(WebMockTestCase):
1588 self.assertEqual(2, self.m.report.log_order.call_count) 1625 self.assertEqual(2, self.m.report.log_order.call_count)
1589 calls = [ 1626 calls = [
1590 mock.call(order_mock, 2, update="adjusting", 1627 mock.call(order_mock, 2, update="adjusting",
1591 compute_value='lambda x, y: (x[y] + x["average"]) / 2', 1628 compute_value=mock.ANY,
1592 new_order=new_order_mock), 1629 new_order=new_order_mock),
1593 mock.call(order_mock, 2, new_order=new_order_mock), 1630 mock.call(order_mock, 2, new_order=new_order_mock),
1594 ] 1631 ]
@@ -1607,7 +1644,7 @@ class TradeTest(WebMockTestCase):
1607 self.m.report.log_order.assert_called() 1644 self.m.report.log_order.assert_called()
1608 calls = [ 1645 calls = [
1609 mock.call(order_mock, 5, update="adjusting", 1646 mock.call(order_mock, 5, update="adjusting",
1610 compute_value='lambda x, y: (x[y]*2 + x["average"]) / 3', 1647 compute_value=mock.ANY,
1611 new_order=new_order_mock), 1648 new_order=new_order_mock),
1612 mock.call(order_mock, 5, new_order=new_order_mock), 1649 mock.call(order_mock, 5, new_order=new_order_mock),
1613 ] 1650 ]
@@ -1831,7 +1868,7 @@ class OrderTest(WebMockTestCase):
1831 1868
1832 order.cancel() 1869 order.cancel()
1833 self.m.ccxt.cancel_order.assert_called_with(42) 1870 self.m.ccxt.cancel_order.assert_called_with(42)
1834 fetch.assert_called_once_with(force=True) 1871 fetch.assert_called_once_with()
1835 self.m.report.log_debug_action.assert_not_called() 1872 self.m.report.log_debug_action.assert_not_called()
1836 1873
1837 def test_dust_amount_remaining(self): 1874 def test_dust_amount_remaining(self):
@@ -1850,11 +1887,9 @@ class OrderTest(WebMockTestCase):
1850 D("0.1"), "BTC", "long", self.m, "trade") 1887 D("0.1"), "BTC", "long", self.m, "trade")
1851 1888
1852 self.assertEqual(9, order.remaining_amount().value) 1889 self.assertEqual(9, order.remaining_amount().value)
1853 order.fetch.assert_not_called()
1854 1890
1855 order.status = "open" 1891 order.status = "open"
1856 self.assertEqual(9, order.remaining_amount().value) 1892 self.assertEqual(9, order.remaining_amount().value)
1857 fetch.assert_called_once()
1858 1893
1859 @mock.patch.object(portfolio.Order, "fetch") 1894 @mock.patch.object(portfolio.Order, "fetch")
1860 def test_filled_amount(self, fetch): 1895 def test_filled_amount(self, fetch):
@@ -1957,61 +1992,38 @@ class OrderTest(WebMockTestCase):
1957 1992
1958 @mock.patch.object(portfolio.Order, "fetch_mouvements") 1993 @mock.patch.object(portfolio.Order, "fetch_mouvements")
1959 def test_fetch(self, fetch_mouvements): 1994 def test_fetch(self, fetch_mouvements):
1960 time = self.time.time() 1995 order = portfolio.Order("buy", portfolio.Amount("ETH", 10),
1961 with mock.patch.object(portfolio.time, "time") as time_mock: 1996 D("0.1"), "BTC", "long", self.m, "trade")
1962 order = portfolio.Order("buy", portfolio.Amount("ETH", 10), 1997 order.id = 45
1963 D("0.1"), "BTC", "long", self.m, "trade") 1998 with self.subTest(debug=True):
1964 order.id = 45 1999 self.m.debug = True
1965 with self.subTest(debug=True): 2000 order.fetch()
1966 self.m.debug = True 2001 self.m.report.log_debug_action.assert_called_once()
1967 order.fetch() 2002 self.m.report.log_debug_action.reset_mock()
1968 time_mock.assert_not_called() 2003 self.m.ccxt.fetch_order.assert_not_called()
1969 self.m.report.log_debug_action.assert_called_once() 2004 fetch_mouvements.assert_not_called()
1970 self.m.report.log_debug_action.reset_mock()
1971 order.fetch(force=True)
1972 time_mock.assert_not_called()
1973 self.m.ccxt.fetch_order.assert_not_called()
1974 fetch_mouvements.assert_not_called()
1975 self.m.report.log_debug_action.assert_called_once()
1976 self.m.report.log_debug_action.reset_mock()
1977 self.assertIsNone(order.fetch_cache_timestamp)
1978
1979 with self.subTest(debug=False):
1980 self.m.debug = False
1981 time_mock.return_value = time
1982 self.m.ccxt.fetch_order.return_value = {
1983 "status": "foo",
1984 "datetime": "timestamp"
1985 }
1986 order.fetch()
1987
1988 self.m.ccxt.fetch_order.assert_called_once_with(45, symbol="ETH")
1989 fetch_mouvements.assert_called_once()
1990 self.assertEqual("foo", order.status)
1991 self.assertEqual("timestamp", order.timestamp)
1992 self.assertEqual(time, order.fetch_cache_timestamp)
1993 self.assertEqual(1, len(order.results))
1994
1995 self.m.ccxt.fetch_order.reset_mock()
1996 fetch_mouvements.reset_mock()
1997
1998 time_mock.return_value = time + 8
1999 order.fetch()
2000 self.m.ccxt.fetch_order.assert_not_called()
2001 fetch_mouvements.assert_not_called()
2002 2005
2003 order.fetch(force=True) 2006 with self.subTest(debug=False):
2004 self.m.ccxt.fetch_order.assert_called_once_with(45, symbol="ETH") 2007 self.m.debug = False
2005 fetch_mouvements.assert_called_once() 2008 self.m.ccxt.fetch_order.return_value = {
2009 "status": "foo",
2010 "datetime": "timestamp"
2011 }
2012 order.fetch()
2006 2013
2007 self.m.ccxt.fetch_order.reset_mock() 2014 self.m.ccxt.fetch_order.assert_called_once_with(45, symbol="ETH")
2008 fetch_mouvements.reset_mock() 2015 fetch_mouvements.assert_called_once()
2016 self.assertEqual("foo", order.status)
2017 self.assertEqual("timestamp", order.timestamp)
2018 self.assertEqual(1, len(order.results))
2019 self.m.report.log_debug_action.assert_not_called()
2009 2020
2010 time_mock.return_value = time + 19 2021 with self.subTest(missing_order=True):
2022 self.m.ccxt.fetch_order.side_effect = [
2023 portfolio.OrderNotCached,
2024 ]
2011 order.fetch() 2025 order.fetch()
2012 self.m.ccxt.fetch_order.assert_called_once_with(45, symbol="ETH") 2026 self.assertEqual("closed_unknown", order.status)
2013 fetch_mouvements.assert_called_once()
2014 self.m.report.log_debug_action.assert_not_called()
2015 2027
2016 @mock.patch.object(portfolio.Order, "fetch") 2028 @mock.patch.object(portfolio.Order, "fetch")
2017 @mock.patch.object(portfolio.Order, "mark_finished_order") 2029 @mock.patch.object(portfolio.Order, "mark_finished_order")
@@ -2315,6 +2327,25 @@ class ReportStoreTest(WebMockTestCase):
2315 'total': D('10.3') 2327 'total': D('10.3')
2316 }) 2328 })
2317 2329
2330 add_log.reset_mock()
2331 compute_value = lambda x: x["bid"]
2332 report_store.log_tickers(amounts, "BTC", compute_value, "total")
2333 add_log.assert_called_once_with({
2334 'type': 'tickers',
2335 'compute_value': 'compute_value = lambda x: x["bid"]',
2336 'balance_type': 'total',
2337 'currency': 'BTC',
2338 'balances': {
2339 'BTC': D('10'),
2340 'ETH': D('0.3')
2341 },
2342 'rates': {
2343 'BTC': None,
2344 'ETH': D('0.1')
2345 },
2346 'total': D('10.3')
2347 })
2348
2318 @mock.patch.object(market.ReportStore, "print_log") 2349 @mock.patch.object(market.ReportStore, "print_log")
2319 @mock.patch.object(market.ReportStore, "add_log") 2350 @mock.patch.object(market.ReportStore, "add_log")
2320 def test_log_dispatch(self, add_log, print_log): 2351 def test_log_dispatch(self, add_log, print_log):
@@ -2393,6 +2424,20 @@ class ReportStoreTest(WebMockTestCase):
2393 'orders': ['order1', 'order2'] 2424 'orders': ['order1', 'order2']
2394 }) 2425 })
2395 2426
2427 add_log.reset_mock()
2428 def compute_value(x, y):
2429 return x[y]
2430 report_store.log_orders(orders, tick="tick",
2431 only="only", compute_value=compute_value)
2432 add_log.assert_called_with({
2433 'type': 'orders',
2434 'only': 'only',
2435 'compute_value': 'def compute_value(x, y):\n return x[y]',
2436 'tick': 'tick',
2437 'orders': ['order1', 'order2']
2438 })
2439
2440
2396 @mock.patch.object(market.ReportStore, "print_log") 2441 @mock.patch.object(market.ReportStore, "print_log")
2397 @mock.patch.object(market.ReportStore, "add_log") 2442 @mock.patch.object(market.ReportStore, "add_log")
2398 def test_log_order(self, add_log, print_log): 2443 def test_log_order(self, add_log, print_log):
@@ -2436,16 +2481,17 @@ class ReportStoreTest(WebMockTestCase):
2436 add_log.reset_mock() 2481 add_log.reset_mock()
2437 print_log.reset_mock() 2482 print_log.reset_mock()
2438 with self.subTest(update="adjusting"): 2483 with self.subTest(update="adjusting"):
2484 compute_value = lambda x: (x["bid"] + x["ask"]*2)/3
2439 report_store.log_order(order_mock, 3, 2485 report_store.log_order(order_mock, 3,
2440 update="adjusting", new_order=new_order_mock, 2486 update="adjusting", new_order=new_order_mock,
2441 compute_value="default") 2487 compute_value=compute_value)
2442 print_log.assert_called_once_with("[Order] Order Mock, tick 3, cancelling and adjusting to New order Mock") 2488 print_log.assert_called_once_with("[Order] Order Mock, tick 3, cancelling and adjusting to New order Mock")
2443 add_log.assert_called_once_with({ 2489 add_log.assert_called_once_with({
2444 'type': 'order', 2490 'type': 'order',
2445 'tick': 3, 2491 'tick': 3,
2446 'update': 'adjusting', 2492 'update': 'adjusting',
2447 'order': 'order', 2493 'order': 'order',
2448 'compute_value': "default", 2494 'compute_value': 'compute_value = lambda x: (x["bid"] + x["ask"]*2)/3',
2449 'new_order': 'new_order' 2495 'new_order': 'new_order'
2450 }) 2496 })
2451 2497