diff options
author | Ismaël Bouya <ismael.bouya@normalesup.org> | 2018-02-06 15:42:40 +0100 |
---|---|---|
committer | Ismaël Bouya <ismael.bouya@normalesup.org> | 2018-02-06 15:45:49 +0100 |
commit | 80cdd672da2f0a4997a792bd1a2de19d4f516e5b (patch) | |
tree | 15cf19bbf1a7a904b18531ef929bf0851604a0d0 /test.py | |
parent | 006a20846236ad365ec814f848f5fbf7e3dc7d3c (diff) | |
download | Trader-80cdd672da2f0a4997a792bd1a2de19d4f516e5b.tar.gz Trader-80cdd672da2f0a4997a792bd1a2de19d4f516e5b.tar.zst Trader-80cdd672da2f0a4997a792bd1a2de19d4f516e5b.zip |
Implement order following
- Change urllib to requests and use it in tests
- Add debug mode for sensitive actions
- Follow orders when trade is running
- Fetch order from the api and store the mouvements already filled
- Start rewriting tests
Diffstat (limited to 'test.py')
-rw-r--r-- | test.py | 435 |
1 files changed, 256 insertions, 179 deletions
@@ -2,8 +2,140 @@ import portfolio | |||
2 | import unittest | 2 | import unittest |
3 | from decimal import Decimal as D | 3 | from decimal import Decimal as D |
4 | from unittest import mock | 4 | from unittest import mock |
5 | import requests | ||
6 | import requests_mock | ||
5 | 7 | ||
6 | class AmountTest(unittest.TestCase): | 8 | class WebMockTestCase(unittest.TestCase): |
9 | import time | ||
10 | |||
11 | def setUp(self): | ||
12 | super(WebMockTestCase, self).setUp() | ||
13 | self.wm = requests_mock.Mocker() | ||
14 | self.wm.start() | ||
15 | |||
16 | self.patchers = [ | ||
17 | mock.patch.multiple(portfolio.Balance, known_balances={}), | ||
18 | mock.patch.multiple(portfolio.Portfolio, data=None, liquidities={}), | ||
19 | mock.patch.multiple(portfolio.Trade, | ||
20 | ticker_cache={}, | ||
21 | ticker_cache_timestamp=self.time.time(), | ||
22 | fees_cache={}, | ||
23 | trades={}), | ||
24 | mock.patch.multiple(portfolio.Computation, | ||
25 | computations=portfolio.Computation.computations) | ||
26 | ] | ||
27 | for patcher in self.patchers: | ||
28 | patcher.start() | ||
29 | |||
30 | |||
31 | def tearDown(self): | ||
32 | for patcher in self.patchers: | ||
33 | patcher.stop() | ||
34 | self.wm.stop() | ||
35 | super(WebMockTestCase, self).tearDown() | ||
36 | |||
37 | class PortfolioTest(WebMockTestCase): | ||
38 | def fill_data(self): | ||
39 | if self.json_response is not None: | ||
40 | portfolio.Portfolio.data = self.json_response | ||
41 | |||
42 | def setUp(self): | ||
43 | super(PortfolioTest, self).setUp() | ||
44 | |||
45 | with open("test_portfolio.json") as example: | ||
46 | self.json_response = example.read() | ||
47 | |||
48 | self.wm.get(portfolio.Portfolio.URL, text=self.json_response) | ||
49 | |||
50 | def test_get_cryptoportfolio(self): | ||
51 | self.wm.get(portfolio.Portfolio.URL, [ | ||
52 | {"text":'{ "foo": "bar" }', "status_code": 200}, | ||
53 | {"text": "System Error", "status_code": 500}, | ||
54 | {"exc": requests.exceptions.ConnectTimeout}, | ||
55 | ]) | ||
56 | portfolio.Portfolio.get_cryptoportfolio() | ||
57 | self.assertIn("foo", portfolio.Portfolio.data) | ||
58 | self.assertEqual("bar", portfolio.Portfolio.data["foo"]) | ||
59 | self.assertTrue(self.wm.called) | ||
60 | self.assertEqual(1, self.wm.call_count) | ||
61 | |||
62 | portfolio.Portfolio.get_cryptoportfolio() | ||
63 | self.assertIsNone(portfolio.Portfolio.data) | ||
64 | self.assertEqual(2, self.wm.call_count) | ||
65 | |||
66 | portfolio.Portfolio.data = "Foo" | ||
67 | portfolio.Portfolio.get_cryptoportfolio() | ||
68 | self.assertEqual("Foo", portfolio.Portfolio.data) | ||
69 | self.assertEqual(3, self.wm.call_count) | ||
70 | |||
71 | def test_parse_cryptoportfolio(self): | ||
72 | portfolio.Portfolio.parse_cryptoportfolio() | ||
73 | |||
74 | self.assertListEqual( | ||
75 | ["medium", "high"], | ||
76 | list(portfolio.Portfolio.liquidities.keys())) | ||
77 | |||
78 | liquidities = portfolio.Portfolio.liquidities | ||
79 | self.assertEqual(10, len(liquidities["medium"].keys())) | ||
80 | self.assertEqual(10, len(liquidities["high"].keys())) | ||
81 | |||
82 | expected = { | ||
83 | 'BTC': (D("0.2857"), "long"), | ||
84 | 'DGB': (D("0.1015"), "long"), | ||
85 | 'DOGE': (D("0.1805"), "long"), | ||
86 | 'SC': (D("0.0623"), "long"), | ||
87 | 'ZEC': (D("0.3701"), "long"), | ||
88 | } | ||
89 | self.assertDictEqual(expected, liquidities["high"]['2018-01-08']) | ||
90 | |||
91 | expected = { | ||
92 | 'BTC': (D("1.1102e-16"), "long"), | ||
93 | 'ETC': (D("0.1"), "long"), | ||
94 | 'FCT': (D("0.1"), "long"), | ||
95 | 'GAS': (D("0.1"), "long"), | ||
96 | 'NAV': (D("0.1"), "long"), | ||
97 | 'OMG': (D("0.1"), "long"), | ||
98 | 'OMNI': (D("0.1"), "long"), | ||
99 | 'PPC': (D("0.1"), "long"), | ||
100 | 'RIC': (D("0.1"), "long"), | ||
101 | 'VIA': (D("0.1"), "long"), | ||
102 | 'XCP': (D("0.1"), "long"), | ||
103 | } | ||
104 | self.assertDictEqual(expected, liquidities["medium"]['2018-01-08']) | ||
105 | |||
106 | # It doesn't refetch the data when available | ||
107 | portfolio.Portfolio.parse_cryptoportfolio() | ||
108 | |||
109 | self.assertEqual(1, self.wm.call_count) | ||
110 | |||
111 | def test_repartition(self): | ||
112 | expected_medium = { | ||
113 | 'BTC': (D("1.1102e-16"), "long"), | ||
114 | 'USDT': (D("0.1"), "long"), | ||
115 | 'ETC': (D("0.1"), "long"), | ||
116 | 'FCT': (D("0.1"), "long"), | ||
117 | 'OMG': (D("0.1"), "long"), | ||
118 | 'STEEM': (D("0.1"), "long"), | ||
119 | 'STRAT': (D("0.1"), "long"), | ||
120 | 'XEM': (D("0.1"), "long"), | ||
121 | 'XMR': (D("0.1"), "long"), | ||
122 | 'XVC': (D("0.1"), "long"), | ||
123 | 'ZRX': (D("0.1"), "long"), | ||
124 | } | ||
125 | expected_high = { | ||
126 | 'USDT': (D("0.1226"), "long"), | ||
127 | 'BTC': (D("0.1429"), "long"), | ||
128 | 'ETC': (D("0.1127"), "long"), | ||
129 | 'ETH': (D("0.1569"), "long"), | ||
130 | 'FCT': (D("0.3341"), "long"), | ||
131 | 'GAS': (D("0.1308"), "long"), | ||
132 | } | ||
133 | |||
134 | self.assertEqual(expected_medium, portfolio.Portfolio.repartition()) | ||
135 | self.assertEqual(expected_medium, portfolio.Portfolio.repartition(liquidity="medium")) | ||
136 | self.assertEqual(expected_high, portfolio.Portfolio.repartition(liquidity="high")) | ||
137 | |||
138 | class AmountTest(WebMockTestCase): | ||
7 | def test_values(self): | 139 | def test_values(self): |
8 | amount = portfolio.Amount("BTC", "0.65") | 140 | amount = portfolio.Amount("BTC", "0.65") |
9 | self.assertEqual(D("0.65"), amount.value) | 141 | self.assertEqual(D("0.65"), amount.value) |
@@ -43,6 +175,11 @@ class AmountTest(unittest.TestCase): | |||
43 | converted_amount = amount.in_currency("ETH", None, rate=D("0.02")) | 175 | converted_amount = amount.in_currency("ETH", None, rate=D("0.02")) |
44 | self.assertEqual(D("0.2"), converted_amount.value) | 176 | self.assertEqual(D("0.2"), converted_amount.value) |
45 | 177 | ||
178 | def test__round(self): | ||
179 | amount = portfolio.Amount("BAR", portfolio.D("1.23456789876")) | ||
180 | self.assertEqual(D("1.23456789"), round(amount).value) | ||
181 | self.assertEqual(D("1.23"), round(amount, 2).value) | ||
182 | |||
46 | def test__abs(self): | 183 | def test__abs(self): |
47 | amount = portfolio.Amount("SC", -120) | 184 | amount = portfolio.Amount("SC", -120) |
48 | self.assertEqual(120, abs(amount).value) | 185 | self.assertEqual(120, abs(amount).value) |
@@ -108,7 +245,7 @@ class AmountTest(unittest.TestCase): | |||
108 | self.assertEqual(D("5.5"), (amount / 2).value) | 245 | self.assertEqual(D("5.5"), (amount / 2).value) |
109 | self.assertEqual(D("4.4"), (amount / D("2.5")).value) | 246 | self.assertEqual(D("4.4"), (amount / D("2.5")).value) |
110 | 247 | ||
111 | def test__div(self): | 248 | def test__truediv(self): |
112 | amount = portfolio.Amount("XEM", 11) | 249 | amount = portfolio.Amount("XEM", 11) |
113 | 250 | ||
114 | self.assertEqual(D("5.5"), (amount / 2).value) | 251 | self.assertEqual(D("5.5"), (amount / 2).value) |
@@ -126,6 +263,42 @@ class AmountTest(unittest.TestCase): | |||
126 | with self.assertRaises(Exception): | 263 | with self.assertRaises(Exception): |
127 | amount1 < amount3 | 264 | amount1 < amount3 |
128 | 265 | ||
266 | def test__le(self): | ||
267 | amount1 = portfolio.Amount("BTD", 11.3) | ||
268 | amount2 = portfolio.Amount("BTD", 13.1) | ||
269 | |||
270 | self.assertTrue(amount1 <= amount2) | ||
271 | self.assertFalse(amount2 <= amount1) | ||
272 | self.assertTrue(amount1 <= amount1) | ||
273 | |||
274 | amount3 = portfolio.Amount("BTC", 1.6) | ||
275 | with self.assertRaises(Exception): | ||
276 | amount1 <= amount3 | ||
277 | |||
278 | def test__gt(self): | ||
279 | amount1 = portfolio.Amount("BTD", 11.3) | ||
280 | amount2 = portfolio.Amount("BTD", 13.1) | ||
281 | |||
282 | self.assertTrue(amount2 > amount1) | ||
283 | self.assertFalse(amount1 > amount2) | ||
284 | self.assertFalse(amount1 > amount1) | ||
285 | |||
286 | amount3 = portfolio.Amount("BTC", 1.6) | ||
287 | with self.assertRaises(Exception): | ||
288 | amount3 > amount1 | ||
289 | |||
290 | def test__ge(self): | ||
291 | amount1 = portfolio.Amount("BTD", 11.3) | ||
292 | amount2 = portfolio.Amount("BTD", 13.1) | ||
293 | |||
294 | self.assertTrue(amount2 >= amount1) | ||
295 | self.assertFalse(amount1 >= amount2) | ||
296 | self.assertTrue(amount1 >= amount1) | ||
297 | |||
298 | amount3 = portfolio.Amount("BTC", 1.6) | ||
299 | with self.assertRaises(Exception): | ||
300 | amount3 >= amount1 | ||
301 | |||
129 | def test__eq(self): | 302 | def test__eq(self): |
130 | amount1 = portfolio.Amount("BTD", 11.3) | 303 | amount1 = portfolio.Amount("BTD", 11.3) |
131 | amount2 = portfolio.Amount("BTD", 13.1) | 304 | amount2 = portfolio.Amount("BTD", 13.1) |
@@ -143,6 +316,28 @@ class AmountTest(unittest.TestCase): | |||
143 | amount5 = portfolio.Amount("BTD", 0) | 316 | amount5 = portfolio.Amount("BTD", 0) |
144 | self.assertTrue(amount5 == 0) | 317 | self.assertTrue(amount5 == 0) |
145 | 318 | ||
319 | def test__ne(self): | ||
320 | amount1 = portfolio.Amount("BTD", 11.3) | ||
321 | amount2 = portfolio.Amount("BTD", 13.1) | ||
322 | amount3 = portfolio.Amount("BTD", 11.3) | ||
323 | |||
324 | self.assertTrue(amount1 != amount2) | ||
325 | self.assertTrue(amount2 != amount1) | ||
326 | self.assertFalse(amount1 != amount3) | ||
327 | self.assertTrue(amount2 != 0) | ||
328 | |||
329 | amount4 = portfolio.Amount("BTC", 1.6) | ||
330 | with self.assertRaises(Exception): | ||
331 | amount1 != amount4 | ||
332 | |||
333 | amount5 = portfolio.Amount("BTD", 0) | ||
334 | self.assertFalse(amount5 != 0) | ||
335 | |||
336 | def test__neg(self): | ||
337 | amount1 = portfolio.Amount("BTD", "11.3") | ||
338 | |||
339 | self.assertEqual(portfolio.D("-11.3"), (-amount1).value) | ||
340 | |||
146 | def test__str(self): | 341 | def test__str(self): |
147 | amount1 = portfolio.Amount("BTX", 32) | 342 | amount1 = portfolio.Amount("BTX", 32) |
148 | self.assertEqual("32.00000000 BTX", str(amount1)) | 343 | self.assertEqual("32.00000000 BTX", str(amount1)) |
@@ -163,125 +358,7 @@ class AmountTest(unittest.TestCase): | |||
163 | amount2.linked_to = amount3 | 358 | amount2.linked_to = amount3 |
164 | self.assertEqual("Amount(32.00000000 BTX -> Amount(12000.00000000 USDT -> Amount(0.10000000 BTC)))", repr(amount1)) | 359 | self.assertEqual("Amount(32.00000000 BTX -> Amount(12000.00000000 USDT -> Amount(0.10000000 BTC)))", repr(amount1)) |
165 | 360 | ||
166 | class PortfolioTest(unittest.TestCase): | 361 | class BalanceTest(WebMockTestCase): |
167 | import urllib3 | ||
168 | def fill_data(self): | ||
169 | if self.json_response is not None: | ||
170 | portfolio.Portfolio.data = self.json_response | ||
171 | |||
172 | def setUp(self): | ||
173 | super(PortfolioTest, self).setUp() | ||
174 | |||
175 | with open("test_portfolio.json") as example: | ||
176 | import json | ||
177 | self.json_response = json.load(example, parse_int=portfolio.D, parse_float=portfolio.D) | ||
178 | |||
179 | self.patcher = mock.patch.multiple(portfolio.Portfolio, data=None, liquidities={}) | ||
180 | self.patcher.start() | ||
181 | |||
182 | @mock.patch.object(urllib3, "disable_warnings") | ||
183 | @mock.patch.object(urllib3.poolmanager.PoolManager, "request") | ||
184 | @mock.patch.object(portfolio.Portfolio, "URL", new="foo://bar") | ||
185 | def test_get_cryptoportfolio(self, request, disable_warnings): | ||
186 | request.side_effect = [ | ||
187 | type('', (), { "data": '{ "foo": "bar" }' }), | ||
188 | type('', (), { "data": 'System Error' }), | ||
189 | Exception("Connection error"), | ||
190 | ] | ||
191 | |||
192 | portfolio.Portfolio.get_cryptoportfolio() | ||
193 | self.assertIn("foo", portfolio.Portfolio.data) | ||
194 | self.assertEqual("bar", portfolio.Portfolio.data["foo"]) | ||
195 | request.assert_called_with("GET", "foo://bar") | ||
196 | |||
197 | request.reset_mock() | ||
198 | portfolio.Portfolio.get_cryptoportfolio() | ||
199 | self.assertIsNone(portfolio.Portfolio.data) | ||
200 | request.assert_called_with("GET", "foo://bar") | ||
201 | |||
202 | request.reset_mock() | ||
203 | portfolio.Portfolio.data = "foo" | ||
204 | portfolio.Portfolio.get_cryptoportfolio() | ||
205 | request.assert_called_with("GET", "foo://bar") | ||
206 | self.assertEqual("foo", portfolio.Portfolio.data) | ||
207 | disable_warnings.assert_called_with() | ||
208 | |||
209 | @mock.patch.object(portfolio.Portfolio, "get_cryptoportfolio") | ||
210 | def test_parse_cryptoportfolio(self, mock_get): | ||
211 | mock_get.side_effect = self.fill_data | ||
212 | |||
213 | portfolio.Portfolio.parse_cryptoportfolio() | ||
214 | |||
215 | self.assertListEqual( | ||
216 | ["medium", "high"], | ||
217 | list(portfolio.Portfolio.liquidities.keys())) | ||
218 | |||
219 | liquidities = portfolio.Portfolio.liquidities | ||
220 | self.assertEqual(10, len(liquidities["medium"].keys())) | ||
221 | self.assertEqual(10, len(liquidities["high"].keys())) | ||
222 | |||
223 | expected = { | ||
224 | 'BTC': (D("0.2857"), "long"), | ||
225 | 'DGB': (D("0.1015"), "long"), | ||
226 | 'DOGE': (D("0.1805"), "long"), | ||
227 | 'SC': (D("0.0623"), "long"), | ||
228 | 'ZEC': (D("0.3701"), "long"), | ||
229 | } | ||
230 | self.assertDictEqual(expected, liquidities["high"]['2018-01-08']) | ||
231 | |||
232 | expected = { | ||
233 | 'BTC': (D("1.1102e-16"), "long"), | ||
234 | 'ETC': (D("0.1"), "long"), | ||
235 | 'FCT': (D("0.1"), "long"), | ||
236 | 'GAS': (D("0.1"), "long"), | ||
237 | 'NAV': (D("0.1"), "long"), | ||
238 | 'OMG': (D("0.1"), "long"), | ||
239 | 'OMNI': (D("0.1"), "long"), | ||
240 | 'PPC': (D("0.1"), "long"), | ||
241 | 'RIC': (D("0.1"), "long"), | ||
242 | 'VIA': (D("0.1"), "long"), | ||
243 | 'XCP': (D("0.1"), "long"), | ||
244 | } | ||
245 | self.assertDictEqual(expected, liquidities["medium"]['2018-01-08']) | ||
246 | |||
247 | # It doesn't refetch the data when available | ||
248 | portfolio.Portfolio.parse_cryptoportfolio() | ||
249 | mock_get.assert_called_once_with() | ||
250 | |||
251 | @mock.patch.object(portfolio.Portfolio, "get_cryptoportfolio") | ||
252 | def test_repartition(self, mock_get): | ||
253 | mock_get.side_effect = self.fill_data | ||
254 | |||
255 | expected_medium = { | ||
256 | 'BTC': (D("1.1102e-16"), "long"), | ||
257 | 'USDT': (D("0.1"), "long"), | ||
258 | 'ETC': (D("0.1"), "long"), | ||
259 | 'FCT': (D("0.1"), "long"), | ||
260 | 'OMG': (D("0.1"), "long"), | ||
261 | 'STEEM': (D("0.1"), "long"), | ||
262 | 'STRAT': (D("0.1"), "long"), | ||
263 | 'XEM': (D("0.1"), "long"), | ||
264 | 'XMR': (D("0.1"), "long"), | ||
265 | 'XVC': (D("0.1"), "long"), | ||
266 | 'ZRX': (D("0.1"), "long"), | ||
267 | } | ||
268 | expected_high = { | ||
269 | 'USDT': (D("0.1226"), "long"), | ||
270 | 'BTC': (D("0.1429"), "long"), | ||
271 | 'ETC': (D("0.1127"), "long"), | ||
272 | 'ETH': (D("0.1569"), "long"), | ||
273 | 'FCT': (D("0.3341"), "long"), | ||
274 | 'GAS': (D("0.1308"), "long"), | ||
275 | } | ||
276 | |||
277 | self.assertEqual(expected_medium, portfolio.Portfolio.repartition()) | ||
278 | self.assertEqual(expected_medium, portfolio.Portfolio.repartition(liquidity="medium")) | ||
279 | self.assertEqual(expected_high, portfolio.Portfolio.repartition(liquidity="high")) | ||
280 | |||
281 | def tearDown(self): | ||
282 | self.patcher.stop() | ||
283 | |||
284 | class BalanceTest(unittest.TestCase): | ||
285 | def setUp(self): | 362 | def setUp(self): |
286 | super(BalanceTest, self).setUp() | 363 | super(BalanceTest, self).setUp() |
287 | 364 | ||
@@ -311,27 +388,54 @@ class BalanceTest(unittest.TestCase): | |||
311 | "total": 0.0 | 388 | "total": 0.0 |
312 | }, | 389 | }, |
313 | } | 390 | } |
314 | self.patcher = mock.patch.multiple(portfolio.Balance, known_balances={}) | ||
315 | self.patcher.start() | ||
316 | 391 | ||
317 | def test_values(self): | 392 | def test_values(self): |
318 | balance = portfolio.Balance("BTC", 0.65, 0.35, 0.30) | 393 | balance = portfolio.Balance("BTC", { |
319 | self.assertEqual(0.65, balance.total.value) | 394 | "exchange_total": "0.65", |
320 | self.assertEqual(0.35, balance.free.value) | 395 | "exchange_free": "0.35", |
321 | self.assertEqual(0.30, balance.used.value) | 396 | "exchange_used": "0.30", |
322 | self.assertEqual("BTC", balance.currency) | 397 | "margin_total": "-10", |
398 | "margin_borrowed": "-10", | ||
399 | "margin_free": "0", | ||
400 | "margin_position_type": "short", | ||
401 | "margin_borrowed_base_currency": "USDT", | ||
402 | "margin_liquidation_price": "1.20", | ||
403 | "margin_pending_gain": "10", | ||
404 | "margin_lending_fees": "0.4", | ||
405 | "margin_borrowed_base_price": "0.15", | ||
406 | }) | ||
407 | self.assertEqual(portfolio.D("0.65"), balance.exchange_total.value) | ||
408 | self.assertEqual(portfolio.D("0.35"), balance.exchange_free.value) | ||
409 | self.assertEqual(portfolio.D("0.30"), balance.exchange_used.value) | ||
410 | self.assertEqual("BTC", balance.exchange_total.currency) | ||
411 | self.assertEqual("BTC", balance.exchange_free.currency) | ||
412 | self.assertEqual("BTC", balance.exchange_total.currency) | ||
413 | |||
414 | self.assertEqual(portfolio.D("-10"), balance.margin_total.value) | ||
415 | self.assertEqual(portfolio.D("-10"), balance.margin_borrowed.value) | ||
416 | self.assertEqual(portfolio.D("0"), balance.margin_free.value) | ||
417 | self.assertEqual("BTC", balance.margin_total.currency) | ||
418 | self.assertEqual("BTC", balance.margin_borrowed.currency) | ||
419 | self.assertEqual("BTC", balance.margin_free.currency) | ||
323 | 420 | ||
324 | balance = portfolio.Balance.from_hash("BTC", { "total": 0.65, "free": 0.35, "used": 0.30}) | ||
325 | self.assertEqual(0.65, balance.total.value) | ||
326 | self.assertEqual(0.35, balance.free.value) | ||
327 | self.assertEqual(0.30, balance.used.value) | ||
328 | self.assertEqual("BTC", balance.currency) | 421 | self.assertEqual("BTC", balance.currency) |
329 | 422 | ||
423 | self.assertEqual(portfolio.D("0.4"), balance.margin_lending_fees.value) | ||
424 | self.assertEqual("USDT", balance.margin_lending_fees.currency) | ||
425 | |||
330 | @mock.patch.object(portfolio.Trade, "get_ticker") | 426 | @mock.patch.object(portfolio.Trade, "get_ticker") |
331 | def test_in_currency(self, get_ticker): | 427 | def test_in_currency(self, get_ticker): |
332 | portfolio.Balance.known_balances = { | 428 | portfolio.Balance.known_balances = { |
333 | "BTC": portfolio.Balance("BTC", "0.65", "0.35", "0.30"), | 429 | "BTC": portfolio.Balance("BTC", { |
334 | "ETH": portfolio.Balance("ETH", 3, 3, 0), | 430 | "total": "0.65", |
431 | "exchange_total":"0.65", | ||
432 | "exchange_free": "0.35", | ||
433 | "exchange_used": "0.30"}), | ||
434 | "ETH": portfolio.Balance("ETH", { | ||
435 | "total": 3, | ||
436 | "exchange_total": 3, | ||
437 | "exchange_free": 3, | ||
438 | "exchange_used": 0}), | ||
335 | } | 439 | } |
336 | market = mock.Mock() | 440 | market = mock.Mock() |
337 | get_ticker.return_value = { | 441 | get_ticker.return_value = { |
@@ -349,17 +453,26 @@ class BalanceTest(unittest.TestCase): | |||
349 | self.assertEqual(D("0.65"), amounts["BTC"].value) | 453 | self.assertEqual(D("0.65"), amounts["BTC"].value) |
350 | self.assertEqual(D("0.27"), amounts["ETH"].value) | 454 | self.assertEqual(D("0.27"), amounts["ETH"].value) |
351 | 455 | ||
352 | amounts = portfolio.Balance.in_currency("BTC", market, compute_value="bid", type="used") | 456 | amounts = portfolio.Balance.in_currency("BTC", market, compute_value="bid", type="exchange_used") |
353 | self.assertEqual(D("0.30"), amounts["BTC"].value) | 457 | self.assertEqual(D("0.30"), amounts["BTC"].value) |
354 | self.assertEqual(0, amounts["ETH"].value) | 458 | self.assertEqual(0, amounts["ETH"].value) |
355 | 459 | ||
356 | def test_currencies(self): | 460 | def test_currencies(self): |
357 | portfolio.Balance.known_balances = { | 461 | portfolio.Balance.known_balances = { |
358 | "BTC": portfolio.Balance("BTC", "0.65", "0.35", "0.30"), | 462 | "BTC": portfolio.Balance("BTC", { |
359 | "ETH": portfolio.Balance("ETH", 3, 3, 0), | 463 | "total": "0.65", |
464 | "exchange_total":"0.65", | ||
465 | "exchange_free": "0.35", | ||
466 | "exchange_used": "0.30"}), | ||
467 | "ETH": portfolio.Balance("ETH", { | ||
468 | "total": 3, | ||
469 | "exchange_total": 3, | ||
470 | "exchange_free": 3, | ||
471 | "exchange_used": 0}), | ||
360 | } | 472 | } |
361 | self.assertListEqual(["BTC", "ETH"], list(portfolio.Balance.currencies())) | 473 | self.assertListEqual(["BTC", "ETH"], list(portfolio.Balance.currencies())) |
362 | 474 | ||
475 | @unittest.expectedFailure | ||
363 | @mock.patch.object(portfolio.market, "fetch_balance") | 476 | @mock.patch.object(portfolio.market, "fetch_balance") |
364 | def test_fetch_balances(self, fetch_balance): | 477 | def test_fetch_balances(self, fetch_balance): |
365 | fetch_balance.return_value = self.fetch_balance | 478 | fetch_balance.return_value = self.fetch_balance |
@@ -373,6 +486,7 @@ class BalanceTest(unittest.TestCase): | |||
373 | self.assertEqual(0, portfolio.Balance.known_balances["ETC"].total) | 486 | self.assertEqual(0, portfolio.Balance.known_balances["ETC"].total) |
374 | self.assertListEqual(["USDT", "XVG", "ETC"], list(portfolio.Balance.currencies())) | 487 | self.assertListEqual(["USDT", "XVG", "ETC"], list(portfolio.Balance.currencies())) |
375 | 488 | ||
489 | @unittest.expectedFailure | ||
376 | @mock.patch.object(portfolio.Portfolio, "repartition") | 490 | @mock.patch.object(portfolio.Portfolio, "repartition") |
377 | @mock.patch.object(portfolio.market, "fetch_balance") | 491 | @mock.patch.object(portfolio.market, "fetch_balance") |
378 | def test_dispatch_assets(self, fetch_balance, repartition): | 492 | def test_dispatch_assets(self, fetch_balance, repartition): |
@@ -391,6 +505,7 @@ class BalanceTest(unittest.TestCase): | |||
391 | self.assertEqual(D("2.6"), amounts["BTC"].value) | 505 | self.assertEqual(D("2.6"), amounts["BTC"].value) |
392 | self.assertEqual(D("7.5"), amounts["XEM"].value) | 506 | self.assertEqual(D("7.5"), amounts["XEM"].value) |
393 | 507 | ||
508 | @unittest.expectedFailure | ||
394 | @mock.patch.object(portfolio.Portfolio, "repartition") | 509 | @mock.patch.object(portfolio.Portfolio, "repartition") |
395 | @mock.patch.object(portfolio.Trade, "get_ticker") | 510 | @mock.patch.object(portfolio.Trade, "get_ticker") |
396 | @mock.patch.object(portfolio.Trade, "compute_trades") | 511 | @mock.patch.object(portfolio.Trade, "compute_trades") |
@@ -436,25 +551,12 @@ class BalanceTest(unittest.TestCase): | |||
436 | def test_update_trades(self): | 551 | def test_update_trades(self): |
437 | pass | 552 | pass |
438 | 553 | ||
554 | @unittest.expectedFailure | ||
439 | def test__repr(self): | 555 | def test__repr(self): |
440 | balance = portfolio.Balance("BTX", 3, 1, 2) | 556 | balance = portfolio.Balance("BTX", 3, 1, 2) |
441 | self.assertEqual("Balance(BTX [1.00000000 BTX/2.00000000 BTX/3.00000000 BTX])", repr(balance)) | 557 | self.assertEqual("Balance(BTX [1.00000000 BTX/2.00000000 BTX/3.00000000 BTX])", repr(balance)) |
442 | 558 | ||
443 | def tearDown(self): | 559 | class TradeTest(WebMockTestCase): |
444 | self.patcher.stop() | ||
445 | |||
446 | class TradeTest(unittest.TestCase): | ||
447 | import time | ||
448 | |||
449 | def setUp(self): | ||
450 | super(TradeTest, self).setUp() | ||
451 | |||
452 | self.patcher = mock.patch.multiple(portfolio.Trade, | ||
453 | ticker_cache={}, | ||
454 | ticker_cache_timestamp=self.time.time(), | ||
455 | fees_cache={}, | ||
456 | trades={}) | ||
457 | self.patcher.start() | ||
458 | 560 | ||
459 | def test_get_ticker(self): | 561 | def test_get_ticker(self): |
460 | market = mock.Mock() | 562 | market = mock.Mock() |
@@ -579,29 +681,8 @@ class TradeTest(unittest.TestCase): | |||
579 | def test__repr(self): | 681 | def test__repr(self): |
580 | pass | 682 | pass |
581 | 683 | ||
582 | def tearDown(self): | 684 | class AcceptanceTest(WebMockTestCase): |
583 | self.patcher.stop() | 685 | @unittest.expectedFailure |
584 | |||
585 | class AcceptanceTest(unittest.TestCase): | ||
586 | import time | ||
587 | |||
588 | def setUp(self): | ||
589 | super(AcceptanceTest, self).setUp() | ||
590 | |||
591 | self.patchers = [ | ||
592 | mock.patch.multiple(portfolio.Balance, known_balances={}), | ||
593 | mock.patch.multiple(portfolio.Portfolio, data=None, liquidities={}), | ||
594 | mock.patch.multiple(portfolio.Trade, | ||
595 | ticker_cache={}, | ||
596 | ticker_cache_timestamp=self.time.time(), | ||
597 | fees_cache={}, | ||
598 | trades={}), | ||
599 | mock.patch.multiple(portfolio.Computation, | ||
600 | computations=portfolio.Computation.computations) | ||
601 | ] | ||
602 | for patcher in self.patchers: | ||
603 | patcher.start() | ||
604 | |||
605 | def test_success_sell_only_necessary(self): | 686 | def test_success_sell_only_necessary(self): |
606 | fetch_balance = { | 687 | fetch_balance = { |
607 | "ETH": { | 688 | "ETH": { |
@@ -858,9 +939,5 @@ class AcceptanceTest(unittest.TestCase): | |||
858 | 939 | ||
859 | sleep.assert_called_with(30) | 940 | sleep.assert_called_with(30) |
860 | 941 | ||
861 | def tearDown(self): | ||
862 | for patcher in self.patchers: | ||
863 | patcher.stop() | ||
864 | |||
865 | if __name__ == '__main__': | 942 | if __name__ == '__main__': |
866 | unittest.main() | 943 | unittest.main() |