X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=tests%2Ftest_store.py;h=3097f6d5d49d30f97bea413c3138cac6c21683ce;hb=5f721612111af5c56b5757cb2f21da5f2fa388bf;hp=58e76e0f6f081d77a0775c97e25b463fd52f972a;hpb=bb127bc87c2b2880469bfab230415c85e589421a;p=perso%2FImmae%2FProjets%2FCryptomonnaies%2FCryptoportfolio%2FTrader.git diff --git a/tests/test_store.py b/tests/test_store.py index 58e76e0..3097f6d 100644 --- a/tests/test_store.py +++ b/tests/test_store.py @@ -392,7 +392,6 @@ class BalanceStoreTest(WebMockTestCase): type='type') balance_store = market.BalanceStore(self.m) - with self.subTest(add_portfolio=True),\ mock.patch.object(market.Portfolio, "repartition") as repartition: repartition.return_value = { @@ -402,6 +401,207 @@ class BalanceStoreTest(WebMockTestCase): balance_store.fetch_balances(add_portfolio=True) self.assertListEqual(["USDT", "XVG", "XMR", "DOGE"], list(balance_store.currencies())) + self.m.ccxt.fetch_all_balances.return_value = { + "ETC": { + "exchange_free": 0, + "exchange_used": 0, + "exchange_total": 0, + "margin_total": 0, + }, + "XVG": { + "exchange_free": 16, + "exchange_used": 0, + "exchange_total": 16, + "margin_total": 0, + }, + "XMR": { + "exchange_free": 0, + "exchange_used": 0, + "exchange_total": 0, + "margin_total": D("-1.0"), + "margin_free": 0, + }, + } + + balance_store = market.BalanceStore(self.m) + with self.subTest(add_usdt=True),\ + mock.patch.object(market.Portfolio, "repartition") as repartition: + repartition.return_value = { + "DOGE": D("0.5"), + "ETH": D("0.5"), + } + balance_store.fetch_balances(add_usdt=True) + self.assertListEqual(["XVG", "XMR", "USDT"], list(balance_store.currencies())) + + @mock.patch.object(market.Portfolio, "repartition") + def test_available_balances_for_repartition(self, repartition): + with self.subTest(available_balance_only=True): + def _get_ticker(c1, c2): + if c1 == "ZRC" and c2 == "BTC": + return { "average": D("0.0001") } + if c1 == "DOGE" and c2 == "BTC": + return { "average": D("0.000001") } + if c1 == "ETH" and c2 == "BTC": + return { "average": D("0.1") } + if c1 == "FOO" and c2 == "BTC": + return { "average": D("0.1") } + self.fail("Should not be called with {}, {}".format(c1, c2)) + self.m.get_ticker.side_effect = _get_ticker + + repartition.return_value = { + "DOGE": (D("0.20"), "short"), + "BTC": (D("0.20"), "long"), + "ETH": (D("0.20"), "long"), + "XMR": (D("0.20"), "long"), + "FOO": (D("0.20"), "long"), + } + self.m.ccxt.fetch_all_balances.return_value = { + "ZRC": { + "exchange_free": D("2.0"), + "exchange_used": D("0.0"), + "exchange_total": D("2.0"), + "total": D("2.0") + }, + "DOGE": { + "exchange_free": D("5.0"), + "exchange_used": D("0.0"), + "exchange_total": D("5.0"), + "total": D("5.0") + }, + "BTC": { + "exchange_free": D("0.065"), + "exchange_used": D("0.02"), + "exchange_total": D("0.085"), + "margin_available": D("0.035"), + "margin_in_position": D("0.01"), + "margin_total": D("0.045"), + "total": D("0.13") + }, + "ETH": { + "exchange_free": D("1.0"), + "exchange_used": D("0.0"), + "exchange_total": D("1.0"), + "total": D("1.0") + }, + "FOO": { + "exchange_free": D("0.1"), + "exchange_used": D("0.0"), + "exchange_total": D("0.1"), + "total": D("0.1"), + }, + } + + balance_store = market.BalanceStore(self.m) + balance_store.fetch_balances() + _repartition, total_base_value, amount_in_position = balance_store.available_balances_for_repartition() + repartition.assert_called_with(liquidity="medium") + self.assertEqual((D("0.20"), "short"), _repartition["DOGE"]) + self.assertEqual((D("0.20"), "long"), _repartition["BTC"]) + self.assertEqual((D("0.20"), "long"), _repartition["XMR"]) + self.assertEqual((D("0.20"), "long"), _repartition["FOO"]) + self.assertIsNone(_repartition.get("ETH")) + self.assertEqual(portfolio.Amount("BTC", "0.1"), total_base_value) + self.assertEqual(0, amount_in_position["DOGE"]) + self.assertEqual(0, amount_in_position["BTC"]) + self.assertEqual(0, amount_in_position["XMR"]) + self.assertEqual(portfolio.Amount("BTC", "0.1"), amount_in_position["ETH"]) + self.assertEqual(portfolio.Amount("BTC", "0.01"), amount_in_position["FOO"]) + + with self.subTest(available_balance_only=True, balance=0): + def _get_ticker(c1, c2): + if c1 == "ETH" and c2 == "BTC": + return { "average": D("0.1") } + self.fail("Should not be called with {}, {}".format(c1, c2)) + self.m.get_ticker.side_effect = _get_ticker + + repartition.return_value = { + "BTC": (D("0.5"), "long"), + "ETH": (D("0.5"), "long"), + } + self.m.ccxt.fetch_all_balances.return_value = { + "ETH": { + "exchange_free": D("1.0"), + "exchange_used": D("0.0"), + "exchange_total": D("1.0"), + "total": D("1.0") + }, + } + + balance_store = market.BalanceStore(self.m) + balance_store.fetch_balances() + _repartition, total_base_value, amount_in_position = balance_store.available_balances_for_repartition(liquidity="high") + + repartition.assert_called_with(liquidity="high") + self.assertEqual((D("0.5"), "long"), _repartition["BTC"]) + self.assertIsNone(_repartition.get("ETH")) + self.assertEqual(0, total_base_value) + self.assertEqual(0, amount_in_position["BTC"]) + self.assertEqual(0, amount_in_position["BTC"]) + + repartition.reset_mock() + with self.subTest(available_balance_only=True, balance=0, + repartition="present"): + def _get_ticker(c1, c2): + if c1 == "ETH" and c2 == "BTC": + return { "average": D("0.1") } + self.fail("Should not be called with {}, {}".format(c1, c2)) + self.m.get_ticker.side_effect = _get_ticker + + _repartition = { + "BTC": (D("0.5"), "long"), + "ETH": (D("0.5"), "long"), + } + self.m.ccxt.fetch_all_balances.return_value = { + "ETH": { + "exchange_free": D("1.0"), + "exchange_used": D("0.0"), + "exchange_total": D("1.0"), + "total": D("1.0") + }, + } + + balance_store = market.BalanceStore(self.m) + balance_store.fetch_balances() + _repartition, total_base_value, amount_in_position = balance_store.available_balances_for_repartition(repartition=_repartition) + repartition.assert_not_called() + + self.assertEqual((D("0.5"), "long"), _repartition["BTC"]) + self.assertIsNone(_repartition.get("ETH")) + self.assertEqual(0, total_base_value) + self.assertEqual(0, amount_in_position["BTC"]) + self.assertEqual(portfolio.Amount("BTC", "0.1"), amount_in_position["ETH"]) + + repartition.reset_mock() + with self.subTest(available_balance_only=True, balance=0, + repartition="present", base_currency="ETH"): + def _get_ticker(c1, c2): + if c1 == "ETH" and c2 == "BTC": + return { "average": D("0.1") } + self.fail("Should not be called with {}, {}".format(c1, c2)) + self.m.get_ticker.side_effect = _get_ticker + + _repartition = { + "BTC": (D("0.5"), "long"), + "ETH": (D("0.5"), "long"), + } + self.m.ccxt.fetch_all_balances.return_value = { + "ETH": { + "exchange_free": D("1.0"), + "exchange_used": D("0.0"), + "exchange_total": D("1.0"), + "total": D("1.0") + }, + } + + balance_store = market.BalanceStore(self.m) + balance_store.fetch_balances() + _repartition, total_base_value, amount_in_position = balance_store.available_balances_for_repartition(repartition=_repartition, base_currency="ETH") + + self.assertEqual((D("0.5"), "long"), _repartition["BTC"]) + self.assertEqual((D("0.5"), "long"), _repartition["ETH"]) + self.assertEqual(portfolio.Amount("ETH", 1), total_base_value) + self.assertEqual(0, amount_in_position["BTC"]) + self.assertEqual(0, amount_in_position["ETH"]) @mock.patch.object(market.Portfolio, "repartition") def test_dispatch_assets(self, repartition): @@ -1313,30 +1513,42 @@ class PortfolioTest(WebMockTestCase): with self.subTest(from_cache=False): market.Portfolio.liquidities = store.LockedVar({ "medium": { - "2018-03-01": "medium_2018-03-01", - "2018-03-08": "medium_2018-03-08", + "2018-03-01": ["medium_2018-03-01"], + "2018-03-08": ["medium_2018-03-08"], }, "high": { - "2018-03-01": "high_2018-03-01", - "2018-03-08": "high_2018-03-08", + "2018-03-01": ["high_2018-03-01"], + "2018-03-08": ["high_2018-03-08"], } }) market.Portfolio.last_date = store.LockedVar("2018-03-08") - self.assertEqual("medium_2018-03-08", market.Portfolio.repartition()) + self.assertEqual(["medium_2018-03-08"], market.Portfolio.repartition()) get_cryptoportfolio.assert_called_once_with() retrieve_cryptoportfolio.assert_not_called() - self.assertEqual("medium_2018-03-08", market.Portfolio.repartition(liquidity="medium")) - self.assertEqual("high_2018-03-08", market.Portfolio.repartition(liquidity="high")) + self.assertEqual(["medium_2018-03-08"], market.Portfolio.repartition(liquidity="medium")) + self.assertEqual(["high_2018-03-08"], market.Portfolio.repartition(liquidity="high")) retrieve_cryptoportfolio.reset_mock() get_cryptoportfolio.reset_mock() with self.subTest(from_cache=True): - self.assertEqual("medium_2018-03-08", market.Portfolio.repartition(from_cache=True)) + self.assertEqual(["medium_2018-03-08"], market.Portfolio.repartition(from_cache=True)) get_cryptoportfolio.assert_called_once_with() retrieve_cryptoportfolio.assert_called_once_with() + retrieve_cryptoportfolio.reset_mock() + get_cryptoportfolio.reset_mock() + + with self.subTest("absent liquidities"): + market.Portfolio.last_date = store.LockedVar("2018-03-15") + self.assertIsNone(market.Portfolio.repartition()) + + with self.subTest("no liquidities"): + market.Portfolio.liquidities = store.LockedVar({}) + market.Portfolio.last_date = store.LockedVar("2018-03-08") + self.assertIsNone(market.Portfolio.repartition()) + @mock.patch.object(market.time, "sleep") @mock.patch.object(market.Portfolio, "get_cryptoportfolio") def test_wait_for_recent(self, get_cryptoportfolio, sleep):