diff options
Diffstat (limited to 'test.py')
-rw-r--r-- | test.py | 344 |
1 files changed, 195 insertions, 149 deletions
@@ -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") |
928 | class TradeStoreTest(WebMockTestCase): | 917 | class 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") |
1113 | class BalanceStoreTest(WebMockTestCase): | 1125 | class 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 | ||