aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIsmaël Bouya <ismael.bouya@normalesup.org>2018-02-12 13:57:28 +0100
committerIsmaël Bouya <ismael.bouya@normalesup.org>2018-02-12 13:57:28 +0100
commit9f54fd9acf98692ff7601fd3236c46745eb26e15 (patch)
tree28b7778dcca169fa6594849034b51e303fd22f40
parentf320eb8aafbceafbbfca02617db4846b3571e598 (diff)
downloadTrader-9f54fd9acf98692ff7601fd3236c46745eb26e15.tar.gz
Trader-9f54fd9acf98692ff7601fd3236c46745eb26e15.tar.zst
Trader-9f54fd9acf98692ff7601fd3236c46745eb26e15.zip
Add method to wait for portfolio update
-rw-r--r--portfolio.py23
-rw-r--r--test.py53
2 files changed, 66 insertions, 10 deletions
diff --git a/portfolio.py b/portfolio.py
index 21a9834..b77f975 100644
--- a/portfolio.py
+++ b/portfolio.py
@@ -1,5 +1,5 @@
1import time 1import time
2from datetime import datetime 2from datetime import datetime, timedelta
3from decimal import Decimal as D, ROUND_DOWN 3from decimal import Decimal as D, ROUND_DOWN
4# Put your poloniex api key in market.py 4# Put your poloniex api key in market.py
5from json import JSONDecodeError 5from json import JSONDecodeError
@@ -14,12 +14,19 @@ class Portfolio:
14 URL = "https://cryptoportfolio.io/wp-content/uploads/portfolio/json/cryptoportfolio.json" 14 URL = "https://cryptoportfolio.io/wp-content/uploads/portfolio/json/cryptoportfolio.json"
15 liquidities = {} 15 liquidities = {}
16 data = None 16 data = None
17 last_date = None
17 18
18 @classmethod 19 @classmethod
19 def repartition(cls, liquidity="medium"): 20 def wait_for_recent(cls, delta=4):
20 cls.parse_cryptoportfolio() 21 cls.repartition(refetch=True)
22 while cls.last_date is None or datetime.now() - cls.last_date > timedelta(delta):
23 time.sleep(30)
24 cls.repartition(refetch=True)
25
26 @classmethod
27 def repartition(cls, liquidity="medium", refetch=False):
28 cls.parse_cryptoportfolio(refetch=refetch)
21 liquidities = cls.liquidities[liquidity] 29 liquidities = cls.liquidities[liquidity]
22 cls.last_date = sorted(liquidities.keys())[-1]
23 return liquidities[cls.last_date] 30 return liquidities[cls.last_date]
24 31
25 @classmethod 32 @classmethod
@@ -34,8 +41,8 @@ class Portfolio:
34 cls.data = None 41 cls.data = None
35 42
36 @classmethod 43 @classmethod
37 def parse_cryptoportfolio(cls): 44 def parse_cryptoportfolio(cls, refetch=False):
38 if cls.data is None: 45 if refetch or cls.data is None:
39 cls.get_cryptoportfolio() 46 cls.get_cryptoportfolio()
40 47
41 def filter_weights(weight_hash): 48 def filter_weights(weight_hash):
@@ -57,7 +64,8 @@ class Portfolio:
57 weights_hash = portfolio_hash["weights"] 64 weights_hash = portfolio_hash["weights"]
58 weights = {} 65 weights = {}
59 for i in range(len(weights_hash["_row"])): 66 for i in range(len(weights_hash["_row"])):
60 weights[weights_hash["_row"][i]] = dict(filter( 67 date = datetime.strptime(weights_hash["_row"][i], "%Y-%m-%d")
68 weights[date] = dict(filter(
61 filter_weights, 69 filter_weights,
62 map(clean_weights(i), weights_hash.items()))) 70 map(clean_weights(i), weights_hash.items())))
63 return weights 71 return weights
@@ -69,6 +77,7 @@ class Portfolio:
69 "medium": medium_liquidity, 77 "medium": medium_liquidity,
70 "high": high_liquidity, 78 "high": high_liquidity,
71 } 79 }
80 cls.last_date = max(max(medium_liquidity.keys()), max(high_liquidity.keys()))
72 81
73class Computation: 82class Computation:
74 computations = { 83 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):
32 mock.patch.multiple(portfolio.TradeStore, 32 mock.patch.multiple(portfolio.TradeStore,
33 all=[], 33 all=[],
34 debug=False), 34 debug=False),
35 mock.patch.multiple(portfolio.Portfolio, 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(helper, 38 mock.patch.multiple(helper,
@@ -102,7 +102,8 @@ class PortfolioTest(WebMockTestCase):
102 'SC': (D("0.0623"), "long"), 102 'SC': (D("0.0623"), "long"),
103 'ZEC': (D("0.3701"), "long"), 103 'ZEC': (D("0.3701"), "long"),
104 } 104 }
105 self.assertDictEqual(expected, liquidities["high"]['2018-01-08']) 105 date = portfolio.datetime(2018, 1, 8)
106 self.assertDictEqual(expected, liquidities["high"][date])
106 107
107 expected = { 108 expected = {
108 'BTC': (D("1.1102e-16"), "long"), 109 'BTC': (D("1.1102e-16"), "long"),
@@ -117,13 +118,17 @@ class PortfolioTest(WebMockTestCase):
117 'VIA': (D("0.1"), "long"), 118 'VIA': (D("0.1"), "long"),
118 'XCP': (D("0.1"), "long"), 119 'XCP': (D("0.1"), "long"),
119 } 120 }
120 self.assertDictEqual(expected, liquidities["medium"]['2018-01-08']) 121 self.assertDictEqual(expected, liquidities["medium"][date])
122 self.assertEqual(portfolio.datetime(2018, 1, 15), portfolio.Portfolio.last_date)
121 123
122 # It doesn't refetch the data when available 124 # It doesn't refetch the data when available
123 portfolio.Portfolio.parse_cryptoportfolio() 125 portfolio.Portfolio.parse_cryptoportfolio()
124 126
125 self.assertEqual(1, self.wm.call_count) 127 self.assertEqual(1, self.wm.call_count)
126 128
129 portfolio.Portfolio.parse_cryptoportfolio(refetch=True)
130 self.assertEqual(2, self.wm.call_count)
131
127 def test_repartition(self): 132 def test_repartition(self):
128 expected_medium = { 133 expected_medium = {
129 'BTC': (D("1.1102e-16"), "long"), 134 'BTC': (D("1.1102e-16"), "long"),
@@ -151,6 +156,48 @@ class PortfolioTest(WebMockTestCase):
151 self.assertEqual(expected_medium, portfolio.Portfolio.repartition(liquidity="medium")) 156 self.assertEqual(expected_medium, portfolio.Portfolio.repartition(liquidity="medium"))
152 self.assertEqual(expected_high, portfolio.Portfolio.repartition(liquidity="high")) 157 self.assertEqual(expected_high, portfolio.Portfolio.repartition(liquidity="high"))
153 158
159 self.assertEqual(1, self.wm.call_count)
160
161 portfolio.Portfolio.repartition()
162 self.assertEqual(1, self.wm.call_count)
163
164 portfolio.Portfolio.repartition(refetch=True)
165 self.assertEqual(2, self.wm.call_count)
166
167 @mock.patch.object(portfolio.time, "sleep")
168 @mock.patch.object(portfolio.Portfolio, "repartition")
169 def test_wait_for_recent(self, repartition, sleep):
170 self.call_count = 0
171 def _repartition(refetch):
172 self.assertTrue(refetch)
173 self.call_count += 1
174 portfolio.Portfolio.last_date = portfolio.datetime.now()\
175 - portfolio.timedelta(10)\
176 + portfolio.timedelta(self.call_count)
177 repartition.side_effect = _repartition
178
179 portfolio.Portfolio.wait_for_recent()
180 sleep.assert_called_with(30)
181 self.assertEqual(6, sleep.call_count)
182 self.assertEqual(7, repartition.call_count)
183
184 sleep.reset_mock()
185 repartition.reset_mock()
186 portfolio.Portfolio.last_date = None
187 self.call_count = 0
188 portfolio.Portfolio.wait_for_recent(delta=15)
189 sleep.assert_not_called()
190 self.assertEqual(1, repartition.call_count)
191
192 sleep.reset_mock()
193 repartition.reset_mock()
194 portfolio.Portfolio.last_date = None
195 self.call_count = 0
196 portfolio.Portfolio.wait_for_recent(delta=1)
197 sleep.assert_called_with(30)
198 self.assertEqual(9, sleep.call_count)
199 self.assertEqual(10, repartition.call_count)
200
154@unittest.skipUnless("unit" in limits, "Unit skipped") 201@unittest.skipUnless("unit" in limits, "Unit skipped")
155class AmountTest(WebMockTestCase): 202class AmountTest(WebMockTestCase):
156 def test_values(self): 203 def test_values(self):