From: Ismaƫl Bouya Date: Mon, 12 Feb 2018 12:57:28 +0000 (+0100) Subject: Add method to wait for portfolio update X-Git-Tag: v0.1~8 X-Git-Url: https://git.immae.eu/?p=perso%2FImmae%2FProjets%2FCryptomonnaies%2FCryptoportfolio%2FTrader.git;a=commitdiff_plain;h=9f54fd9acf98692ff7601fd3236c46745eb26e15 Add method to wait for portfolio update --- diff --git a/portfolio.py b/portfolio.py index 21a9834..b77f975 100644 --- a/portfolio.py +++ b/portfolio.py @@ -1,5 +1,5 @@ import time -from datetime import datetime +from datetime import datetime, timedelta from decimal import Decimal as D, ROUND_DOWN # Put your poloniex api key in market.py from json import JSONDecodeError @@ -14,12 +14,19 @@ class Portfolio: URL = "https://cryptoportfolio.io/wp-content/uploads/portfolio/json/cryptoportfolio.json" liquidities = {} data = None + last_date = None @classmethod - def repartition(cls, liquidity="medium"): - cls.parse_cryptoportfolio() + def wait_for_recent(cls, delta=4): + cls.repartition(refetch=True) + while cls.last_date is None or datetime.now() - cls.last_date > timedelta(delta): + time.sleep(30) + cls.repartition(refetch=True) + + @classmethod + def repartition(cls, liquidity="medium", refetch=False): + cls.parse_cryptoportfolio(refetch=refetch) liquidities = cls.liquidities[liquidity] - cls.last_date = sorted(liquidities.keys())[-1] return liquidities[cls.last_date] @classmethod @@ -34,8 +41,8 @@ class Portfolio: cls.data = None @classmethod - def parse_cryptoportfolio(cls): - if cls.data is None: + def parse_cryptoportfolio(cls, refetch=False): + if refetch or cls.data is None: cls.get_cryptoportfolio() def filter_weights(weight_hash): @@ -57,7 +64,8 @@ class Portfolio: weights_hash = portfolio_hash["weights"] weights = {} for i in range(len(weights_hash["_row"])): - weights[weights_hash["_row"][i]] = dict(filter( + date = datetime.strptime(weights_hash["_row"][i], "%Y-%m-%d") + weights[date] = dict(filter( filter_weights, map(clean_weights(i), weights_hash.items()))) return weights @@ -69,6 +77,7 @@ class Portfolio: "medium": medium_liquidity, "high": high_liquidity, } + cls.last_date = max(max(medium_liquidity.keys()), max(high_liquidity.keys())) class Computation: computations = { diff --git a/test.py b/test.py index c496e11..56167f4 100644 --- a/test.py +++ b/test.py @@ -32,7 +32,7 @@ class WebMockTestCase(unittest.TestCase): mock.patch.multiple(portfolio.TradeStore, all=[], debug=False), - mock.patch.multiple(portfolio.Portfolio, data=None, liquidities={}), + mock.patch.multiple(portfolio.Portfolio, last_date=None, data=None, liquidities={}), mock.patch.multiple(portfolio.Computation, computations=portfolio.Computation.computations), mock.patch.multiple(helper, @@ -102,7 +102,8 @@ class PortfolioTest(WebMockTestCase): 'SC': (D("0.0623"), "long"), 'ZEC': (D("0.3701"), "long"), } - self.assertDictEqual(expected, liquidities["high"]['2018-01-08']) + date = portfolio.datetime(2018, 1, 8) + self.assertDictEqual(expected, liquidities["high"][date]) expected = { 'BTC': (D("1.1102e-16"), "long"), @@ -117,13 +118,17 @@ class PortfolioTest(WebMockTestCase): 'VIA': (D("0.1"), "long"), 'XCP': (D("0.1"), "long"), } - self.assertDictEqual(expected, liquidities["medium"]['2018-01-08']) + self.assertDictEqual(expected, liquidities["medium"][date]) + self.assertEqual(portfolio.datetime(2018, 1, 15), portfolio.Portfolio.last_date) # It doesn't refetch the data when available portfolio.Portfolio.parse_cryptoportfolio() self.assertEqual(1, self.wm.call_count) + portfolio.Portfolio.parse_cryptoportfolio(refetch=True) + self.assertEqual(2, self.wm.call_count) + def test_repartition(self): expected_medium = { 'BTC': (D("1.1102e-16"), "long"), @@ -151,6 +156,48 @@ class PortfolioTest(WebMockTestCase): self.assertEqual(expected_medium, portfolio.Portfolio.repartition(liquidity="medium")) self.assertEqual(expected_high, portfolio.Portfolio.repartition(liquidity="high")) + self.assertEqual(1, self.wm.call_count) + + portfolio.Portfolio.repartition() + self.assertEqual(1, self.wm.call_count) + + portfolio.Portfolio.repartition(refetch=True) + self.assertEqual(2, self.wm.call_count) + + @mock.patch.object(portfolio.time, "sleep") + @mock.patch.object(portfolio.Portfolio, "repartition") + def test_wait_for_recent(self, repartition, sleep): + self.call_count = 0 + def _repartition(refetch): + self.assertTrue(refetch) + self.call_count += 1 + portfolio.Portfolio.last_date = portfolio.datetime.now()\ + - portfolio.timedelta(10)\ + + portfolio.timedelta(self.call_count) + repartition.side_effect = _repartition + + portfolio.Portfolio.wait_for_recent() + sleep.assert_called_with(30) + self.assertEqual(6, sleep.call_count) + self.assertEqual(7, repartition.call_count) + + sleep.reset_mock() + repartition.reset_mock() + portfolio.Portfolio.last_date = None + self.call_count = 0 + portfolio.Portfolio.wait_for_recent(delta=15) + sleep.assert_not_called() + self.assertEqual(1, repartition.call_count) + + sleep.reset_mock() + repartition.reset_mock() + portfolio.Portfolio.last_date = None + self.call_count = 0 + portfolio.Portfolio.wait_for_recent(delta=1) + sleep.assert_called_with(30) + self.assertEqual(9, sleep.call_count) + self.assertEqual(10, repartition.call_count) + @unittest.skipUnless("unit" in limits, "Unit skipped") class AmountTest(WebMockTestCase): def test_values(self):