]> git.immae.eu Git - perso/Immae/Projets/Cryptomonnaies/Cryptoportfolio/Trader.git/commitdiff
Add method to wait for portfolio update
authorIsmaël Bouya <ismael.bouya@normalesup.org>
Mon, 12 Feb 2018 12:57:28 +0000 (13:57 +0100)
committerIsmaël Bouya <ismael.bouya@normalesup.org>
Mon, 12 Feb 2018 12:57:28 +0000 (13:57 +0100)
portfolio.py
test.py

index 21a98342f15fa03ba7753be2a69579bda16cd7c9..b77f975e9cdf2d01cae09c07a72f3b8b15d16aa4 100644 (file)
@@ -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 c496e11a916adb2aaeb0a371fb4695ae8b4fb5a7..56167f4043c94207d532557542a31459ff591eb1 100644 (file)
--- 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):