aboutsummaryrefslogtreecommitdiff
path: root/test.py
diff options
context:
space:
mode:
Diffstat (limited to 'test.py')
-rw-r--r--test.py263
1 files changed, 261 insertions, 2 deletions
diff --git a/test.py b/test.py
index edf6d01..2589896 100644
--- a/test.py
+++ b/test.py
@@ -256,6 +256,11 @@ class BalanceTest(unittest.TestCase):
256 "info": "bar", 256 "info": "bar",
257 "used": "baz", 257 "used": "baz",
258 "total": "bazz", 258 "total": "bazz",
259 "ETC": {
260 "free": 0.0,
261 "used": 0.0,
262 "total": 0.0
263 },
259 "USDT": { 264 "USDT": {
260 "free": 6.0, 265 "free": 6.0,
261 "used": 1.2, 266 "used": 1.2,
@@ -327,7 +332,12 @@ class BalanceTest(unittest.TestCase):
327 332
328 portfolio.Balance.fetch_balances(portfolio.market) 333 portfolio.Balance.fetch_balances(portfolio.market)
329 self.assertNotIn("XMR", portfolio.Balance.currencies()) 334 self.assertNotIn("XMR", portfolio.Balance.currencies())
330 self.assertEqual(["USDT", "XVG"], list(portfolio.Balance.currencies())) 335 self.assertListEqual(["USDT", "XVG"], list(portfolio.Balance.currencies()))
336
337 portfolio.Balance.known_balances["ETC"] = portfolio.Balance("ETC", "1", "0", "1")
338 portfolio.Balance.fetch_balances(portfolio.market)
339 self.assertEqual(0, portfolio.Balance.known_balances["ETC"].total)
340 self.assertListEqual(["USDT", "XVG", "ETC"], list(portfolio.Balance.currencies()))
331 341
332 @mock.patch.object(portfolio.Portfolio, "repartition_pertenthousand") 342 @mock.patch.object(portfolio.Portfolio, "repartition_pertenthousand")
333 @mock.patch.object(portfolio.market, "fetch_balance") 343 @mock.patch.object(portfolio.market, "fetch_balance")
@@ -362,7 +372,7 @@ class BalanceTest(unittest.TestCase):
362 return { "average": D("0.000001") } 372 return { "average": D("0.000001") }
363 if c1 == "XEM" and c2 == "BTC": 373 if c1 == "XEM" and c2 == "BTC":
364 return { "average": D("0.001") } 374 return { "average": D("0.001") }
365 raise Exception("Should be called with {}, {}".format(c1, c2)) 375 self.fail("Should be called with {}, {}".format(c1, c2))
366 get_ticker.side_effect = _get_ticker 376 get_ticker.side_effect = _get_ticker
367 377
368 market = mock.Mock() 378 market = mock.Mock()
@@ -388,6 +398,10 @@ class BalanceTest(unittest.TestCase):
388 self.assertEqual(D("0.2525"), call[0][1]["BTC"].value) 398 self.assertEqual(D("0.2525"), call[0][1]["BTC"].value)
389 self.assertEqual(D("0.7575"), call[0][1]["XEM"].value) 399 self.assertEqual(D("0.7575"), call[0][1]["XEM"].value)
390 400
401 @unittest.skip("TODO")
402 def test_update_trades(self):
403 pass
404
391 def test__repr(self): 405 def test__repr(self):
392 balance = portfolio.Balance("BTX", 3, 1, 2) 406 balance = portfolio.Balance("BTX", 3, 1, 2)
393 self.assertEqual("Balance(BTX [1.00000000 BTX/2.00000000 BTX/3.00000000 BTX])", repr(balance)) 407 self.assertEqual("Balance(BTX [1.00000000 BTX/2.00000000 BTX/3.00000000 BTX])", repr(balance))
@@ -520,5 +534,250 @@ class TradeTest(unittest.TestCase):
520 def tearDown(self): 534 def tearDown(self):
521 self.patcher.stop() 535 self.patcher.stop()
522 536
537class AcceptanceTest(unittest.TestCase):
538 import time
539
540 def setUp(self):
541 super(AcceptanceTest, self).setUp()
542
543 self.patchers = [
544 mock.patch.multiple(portfolio.Balance, known_balances={}),
545 mock.patch.multiple(portfolio.Portfolio, data=None, liquidities={}),
546 mock.patch.multiple(portfolio.Trade,
547 ticker_cache={},
548 ticker_cache_timestamp=self.time.time(),
549 fees_cache={},
550 trades={}),
551 mock.patch.multiple(portfolio.Computation,
552 computations=portfolio.Computation.computations)
553 ]
554 for patcher in self.patchers:
555 patcher.start()
556
557 def test_success_sell_only_necessary(self):
558 fetch_balance = {
559 "ETH": {
560 "free": D("1.0"),
561 "used": D("0.0"),
562 "total": D("1.0"),
563 },
564 "ETC": {
565 "free": D("4.0"),
566 "used": D("0.0"),
567 "total": D("4.0"),
568 },
569 "XVG": {
570 "free": D("1000.0"),
571 "used": D("0.0"),
572 "total": D("1000.0"),
573 },
574 }
575 repartition = {
576 "ETH": 2500,
577 "ETC": 2500,
578 "BTC": 4000,
579 "BTD": 500,
580 "USDT": 500,
581 }
582
583 def fetch_ticker(symbol):
584 if symbol == "ETH/BTC":
585 return {
586 "symbol": "ETH/BTC",
587 "bid": D("0.14"),
588 "ask": D("0.16")
589 }
590 if symbol == "ETC/BTC":
591 return {
592 "symbol": "ETC/BTC",
593 "bid": D("0.002"),
594 "ask": D("0.003")
595 }
596 if symbol == "XVG/BTC":
597 return {
598 "symbol": "XVG/BTC",
599 "bid": D("0.00003"),
600 "ask": D("0.00005")
601 }
602 if symbol == "BTD/BTC":
603 return {
604 "symbol": "BTD/BTC",
605 "bid": D("0.0008"),
606 "ask": D("0.0012")
607 }
608 if symbol == "USDT/BTC":
609 raise portfolio.ccxt.ExchangeError
610 if symbol == "BTC/USDT":
611 return {
612 "symbol": "BTC/USDT",
613 "bid": D("14000"),
614 "ask": D("16000")
615 }
616 self.fail("Shouldn't have been called with {}".format(symbol))
617
618 market = mock.Mock()
619 market.fetch_balance.return_value = fetch_balance
620 market.fetch_ticker.side_effect = fetch_ticker
621 with mock.patch.object(portfolio.Portfolio, "repartition_pertenthousand", return_value=repartition):
622 # Action 1
623 portfolio.Balance.prepare_trades(market)
624
625 balances = portfolio.Balance.known_balances
626 self.assertEqual(portfolio.Amount("ETH", 1), balances["ETH"].total)
627 self.assertEqual(portfolio.Amount("ETC", 4), balances["ETC"].total)
628 self.assertEqual(portfolio.Amount("XVG", 1000), balances["XVG"].total)
629
630
631 trades = portfolio.Trade.trades
632 self.assertEqual(portfolio.Amount("BTC", D("0.15")), trades["ETH"].value_from)
633 self.assertEqual(portfolio.Amount("BTC", D("0.05")), trades["ETH"].value_to)
634 self.assertEqual("sell", trades["ETH"].action)
635
636 self.assertEqual(portfolio.Amount("BTC", D("0.01")), trades["ETC"].value_from)
637 self.assertEqual(portfolio.Amount("BTC", D("0.05")), trades["ETC"].value_to)
638 self.assertEqual("buy", trades["ETC"].action)
639
640 self.assertNotIn("BTC", trades)
641
642 self.assertEqual(portfolio.Amount("BTC", D("0.00")), trades["BTD"].value_from)
643 self.assertEqual(portfolio.Amount("BTC", D("0.01")), trades["BTD"].value_to)
644 self.assertEqual("buy", trades["BTD"].action)
645
646 self.assertEqual(portfolio.Amount("BTC", D("0.00")), trades["USDT"].value_from)
647 self.assertEqual(portfolio.Amount("BTC", D("0.01")), trades["USDT"].value_to)
648 self.assertEqual("buy", trades["USDT"].action)
649
650 self.assertEqual(portfolio.Amount("BTC", D("0.04")), trades["XVG"].value_from)
651 self.assertEqual(portfolio.Amount("BTC", D("0.00")), trades["XVG"].value_to)
652 self.assertEqual("sell", trades["XVG"].action)
653
654 # Action 2
655 portfolio.Trade.prepare_orders(only="sell", compute_value=lambda x, y: x["bid"] * D("1.001"))
656
657 all_orders = portfolio.Trade.all_orders()
658 self.assertEqual(2, len(all_orders))
659 self.assertEqual(2, 3*all_orders[0].amount.value)
660 self.assertEqual(D("0.14014"), all_orders[0].rate)
661 self.assertEqual(1000, all_orders[1].amount.value)
662 self.assertEqual(D("0.00003003"), all_orders[1].rate)
663
664
665 def create_order(symbol, type, action, amount, price=None):
666 self.assertEqual("limit", type)
667 if symbol == "ETH/BTC":
668 self.assertEqual("bid", action)
669 self.assertEqual(2, 3*amount)
670 self.assertEqual(D("0.14014"), price)
671 elif symbol == "XVG/BTC":
672 self.assertEqual("bid", action)
673 self.assertEqual(1000, amount)
674 self.assertEqual(D("0.00003003"), price)
675 else:
676 self.fail("I shouldn't have been called")
677
678 return {
679 "id": symbol,
680 }
681 market.create_order.side_effect = create_order
682
683 # Action 3
684 portfolio.Trade.run_orders()
685
686 self.assertEqual("open", all_orders[0].status)
687 self.assertEqual("open", all_orders[1].status)
688
689 market.fetch_order.return_value = { "status": "closed" }
690 with mock.patch.object(portfolio.time, "sleep") as sleep:
691 # Action 4
692 portfolio.Trade.follow_orders(verbose=False)
693
694 sleep.assert_called_with(30)
695
696 for order in all_orders:
697 self.assertEqual("closed", order.status)
698
699 fetch_balance = {
700 "ETH": {
701 "free": D("1.0") / 3,
702 "used": D("0.0"),
703 "total": D("1.0") / 3,
704 },
705 "BTC": {
706 "free": D("0.134"),
707 "used": D("0.0"),
708 "total": D("0.134"),
709 },
710 "ETC": {
711 "free": D("4.0"),
712 "used": D("0.0"),
713 "total": D("4.0"),
714 },
715 "XVG": {
716 "free": D("0.0"),
717 "used": D("0.0"),
718 "total": D("0.0"),
719 },
720 }
721 market.fetch_balance.return_value = fetch_balance
722
723 with mock.patch.object(portfolio.Portfolio, "repartition_pertenthousand", return_value=repartition):
724 # Action 5
725 portfolio.Balance.update_trades(market, only="buy", compute_value="average")
726
727 balances = portfolio.Balance.known_balances
728 self.assertEqual(portfolio.Amount("ETH", 1 / D("3")), balances["ETH"].total)
729 self.assertEqual(portfolio.Amount("ETC", 4), balances["ETC"].total)
730 self.assertEqual(portfolio.Amount("BTC", D("0.134")), balances["BTC"].total)
731 self.assertEqual(portfolio.Amount("XVG", 0), balances["XVG"].total)
732
733
734 trades = portfolio.Trade.trades
735 self.assertEqual(portfolio.Amount("BTC", D("0.15")), trades["ETH"].value_from)
736 self.assertEqual(portfolio.Amount("BTC", D("0.05")), trades["ETH"].value_to)
737 self.assertEqual("sell", trades["ETH"].action)
738
739 self.assertEqual(portfolio.Amount("BTC", D("0.01")), trades["ETC"].value_from)
740 self.assertEqual(portfolio.Amount("BTC", D("0.0485")), trades["ETC"].value_to)
741 self.assertEqual("buy", trades["ETC"].action)
742
743 self.assertNotIn("BTC", trades)
744
745 self.assertEqual(portfolio.Amount("BTC", D("0.00")), trades["BTD"].value_from)
746 self.assertEqual(portfolio.Amount("BTC", D("0.0097")), trades["BTD"].value_to)
747 self.assertEqual("buy", trades["BTD"].action)
748
749 self.assertEqual(portfolio.Amount("BTC", D("0.00")), trades["USDT"].value_from)
750 self.assertEqual(portfolio.Amount("BTC", D("0.0097")), trades["USDT"].value_to)
751 self.assertEqual("buy", trades["USDT"].action)
752
753 self.assertEqual(portfolio.Amount("BTC", D("0.04")), trades["XVG"].value_from)
754 self.assertEqual(portfolio.Amount("BTC", D("0.00")), trades["XVG"].value_to)
755 self.assertEqual("sell", trades["XVG"].action)
756
757 # Action 6
758 portfolio.Trade.prepare_orders(only="buy", compute_value=lambda x, y: x["ask"] * D("0.999"))
759
760 all_orders = portfolio.Trade.all_orders(state="pending")
761 self.assertEqual(3, len(all_orders))
762 self.assertEqual(portfolio.Amount("ETC", D("15.4")), all_orders[0].amount)
763 self.assertEqual(D("0.002997"), all_orders[0].rate)
764 self.assertEqual("ask", all_orders[0].action)
765 self.assertEqual(portfolio.Amount("BTD", D("9.7")), all_orders[1].amount)
766 self.assertEqual(D("0.0011988"), all_orders[1].rate)
767 self.assertEqual("ask", all_orders[1].action)
768 self.assertEqual(portfolio.Amount("BTC", D("0.0097")), all_orders[2].amount)
769 self.assertEqual(D("15984"), all_orders[2].rate)
770 self.assertEqual("bid", all_orders[2].action)
771
772 with mock.patch.object(portfolio.time, "sleep") as sleep:
773 # Action 7
774 portfolio.Trade.follow_orders(verbose=False)
775
776 sleep.assert_called_with(30)
777
778 def tearDown(self):
779 for patcher in self.patchers:
780 patcher.stop()
781
523if __name__ == '__main__': 782if __name__ == '__main__':
524 unittest.main() 783 unittest.main()