aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIsmaël Bouya <ismael.bouya@normalesup.org>2018-02-11 22:40:30 +0100
committerIsmaël Bouya <ismael.bouya@normalesup.org>2018-02-11 22:40:30 +0100
commit5a72ded790f8b5e7c9b38a3cc91c12fbfb6cb97a (patch)
treee12aa9ec9a5c543442aa512ee0d485ccf9f02906
parent1aa7d4fa2ec3c2b3268bef31a666ca6e1aaa6563 (diff)
downloadTrader-5a72ded790f8b5e7c9b38a3cc91c12fbfb6cb97a.tar.gz
Trader-5a72ded790f8b5e7c9b38a3cc91c12fbfb6cb97a.tar.zst
Trader-5a72ded790f8b5e7c9b38a3cc91c12fbfb6cb97a.zip
Add missing tests
-rw-r--r--helper.py39
-rw-r--r--portfolio.py55
-rw-r--r--test.py511
3 files changed, 520 insertions, 85 deletions
diff --git a/helper.py b/helper.py
index 8a29f40..421e8cd 100644
--- a/helper.py
+++ b/helper.py
@@ -115,16 +115,33 @@ def print_orders(market, base_currency="BTC"):
115 print(balance) 115 print(balance)
116 TradeStore.print_all_with_order() 116 TradeStore.print_all_with_order()
117 117
118def make_orders(market, base_currency="BTC"): 118def process_sell_needed__1_sell(market, base_currency="BTC", debug=False):
119 prepare_trades(market, base_currency=base_currency) 119 prepare_trades(market, base_currency=base_currency, debug=debug)
120 for trade in TradeStore.all: 120 TradeStore.prepare_orders(compute_value="average", only="dispose")
121 print(trade) 121 print("------------------")
122 for order in trade.orders: 122 for currency, balance in BalanceStore.all.items():
123 print("\t", order, sep="") 123 print(balance)
124 order.run() 124 print("------------------")
125 TradeStore.print_all_with_order()
126 print("------------------")
127 TradeStore.run_orders()
128 follow_orders()
129
130def process_sell_needed__2_sell(market, base_currency="BTC", debug=False):
131 update_trades(market, base_currency=base_currency, debug=debug, only="acquire")
132 TradeStore.prepare_orders(compute_value="average", only="acquire")
133 print("------------------")
134 for currency, balance in BalanceStore.all.items():
135 print(balance)
136 print("------------------")
137 TradeStore.print_all_with_order()
138 print("------------------")
139 move_balances(market, debug=debug)
140 TradeStore.run_orders()
141 follow_orders()
125 142
126def process_sell_all_sell(market, base_currency="BTC", debug=False): 143def process_sell_all__1_all_sell(market, base_currency="BTC", debug=False):
127 prepare_trades_to_sell_all(market, debug=debug) 144 prepare_trades_to_sell_all(market, base_currency=base_currency, debug=debug)
128 TradeStore.prepare_orders(compute_value="average") 145 TradeStore.prepare_orders(compute_value="average")
129 print("------------------") 146 print("------------------")
130 for currency, balance in BalanceStore.all.items(): 147 for currency, balance in BalanceStore.all.items():
@@ -135,8 +152,8 @@ def process_sell_all_sell(market, base_currency="BTC", debug=False):
135 TradeStore.run_orders() 152 TradeStore.run_orders()
136 follow_orders() 153 follow_orders()
137 154
138def process_sell_all_buy(market, base_currency="BTC", debug=False): 155def process_sell_all__2_all_buy(market, base_currency="BTC", debug=False):
139 prepare_trades(market, debug=debug) 156 prepare_trades(market, base_currency=base_currency, debug=debug)
140 TradeStore.prepare_orders() 157 TradeStore.prepare_orders()
141 print("------------------") 158 print("------------------")
142 for currency, balance in BalanceStore.all.items(): 159 for currency, balance in BalanceStore.all.items():
diff --git a/portfolio.py b/portfolio.py
index b629966..e98689e 100644
--- a/portfolio.py
+++ b/portfolio.py
@@ -1,4 +1,5 @@
1import time 1import time
2from datetime import datetime
2from decimal import Decimal as D, ROUND_DOWN 3from decimal import Decimal as D, ROUND_DOWN
3# Put your poloniex api key in market.py 4# Put your poloniex api key in market.py
4from json import JSONDecodeError 5from json import JSONDecodeError
@@ -272,7 +273,7 @@ class Trade:
272 if self.base_currency == self.currency: 273 if self.base_currency == self.currency:
273 return None 274 return None
274 275
275 if self.value_from < self.value_to: 276 if abs(self.value_from) < abs(self.value_to):
276 return "acquire" 277 return "acquire"
277 else: 278 else:
278 return "dispose" 279 return "dispose"
@@ -301,19 +302,16 @@ class Trade:
301 if tick in [0, 1, 3, 4, 6]: 302 if tick in [0, 1, 3, 4, 6]:
302 print("{}, tick {}, waiting".format(order, tick)) 303 print("{}, tick {}, waiting".format(order, tick))
303 elif tick == 2: 304 elif tick == 2:
304 self.prepare_order(compute_value=lambda x, y: (x[y] + x["average"]) / 2) 305 new_order = self.prepare_order(compute_value=lambda x, y: (x[y] + x["average"]) / 2)
305 new_order = self.orders[-1]
306 print("{}, tick {}, cancelling and adjusting to {}".format(order, tick, new_order)) 306 print("{}, tick {}, cancelling and adjusting to {}".format(order, tick, new_order))
307 elif tick ==5: 307 elif tick ==5:
308 self.prepare_order(compute_value=lambda x, y: (x[y]*2 + x["average"]) / 3) 308 new_order = self.prepare_order(compute_value=lambda x, y: (x[y]*2 + x["average"]) / 3)
309 new_order = self.orders[-1]
310 print("{}, tick {}, cancelling and adjusting to {}".format(order, tick, new_order)) 309 print("{}, tick {}, cancelling and adjusting to {}".format(order, tick, new_order))
311 elif tick >= 7: 310 elif tick >= 7:
312 if tick == 7: 311 if tick == 7:
313 print("{}, tick {}, fallbacking to market value".format(order, tick)) 312 print("{}, tick {}, fallbacking to market value".format(order, tick))
314 if (tick - 7) % 3 == 0: 313 if (tick - 7) % 3 == 0:
315 self.prepare_order(compute_value="default") 314 new_order = self.prepare_order(compute_value="default")
316 new_order = self.orders[-1]
317 print("{}, tick {}, market value, cancelling and adjusting to {}".format(order, tick, new_order)) 315 print("{}, tick {}, market value, cancelling and adjusting to {}".format(order, tick, new_order))
318 316
319 if new_order is not None: 317 if new_order is not None:
@@ -322,7 +320,7 @@ class Trade:
322 320
323 def prepare_order(self, compute_value="default"): 321 def prepare_order(self, compute_value="default"):
324 if self.action is None: 322 if self.action is None:
325 return 323 return None
326 ticker = h.get_ticker(self.currency, self.base_currency, self.market) 324 ticker = h.get_ticker(self.currency, self.base_currency, self.market)
327 inverted = ticker["inverted"] 325 inverted = ticker["inverted"]
328 if inverted: 326 if inverted:
@@ -387,11 +385,13 @@ class Trade:
387 385
388 if delta <= 0: 386 if delta <= 0:
389 print("Less to do than already filled: {}".format(delta)) 387 print("Less to do than already filled: {}".format(delta))
390 return 388 return None
391 389
392 self.orders.append(Order(self.order_action(inverted), 390 order = Order(self.order_action(inverted),
393 delta, rate, base_currency, self.trade_type, 391 delta, rate, base_currency, self.trade_type,
394 self.market, self, close_if_possible=close_if_possible)) 392 self.market, self, close_if_possible=close_if_possible)
393 self.orders.append(order)
394 return order
395 395
396 def __repr__(self): 396 def __repr__(self):
397 return "Trade({} -> {} in {}, {})".format( 397 return "Trade({} -> {} in {}, {})".format(
@@ -419,6 +419,8 @@ class Order:
419 self.status = "pending" 419 self.status = "pending"
420 self.trade = trade 420 self.trade = trade
421 self.close_if_possible = close_if_possible 421 self.close_if_possible = close_if_possible
422 self.id = None
423 self.fetch_cache_timestamp = None
422 424
423 def __repr__(self): 425 def __repr__(self):
424 return "Order({} {} {} at {} {} [{}]{})".format( 426 return "Order({} {} {} at {} {} [{}]{})".format(
@@ -439,6 +441,10 @@ class Order:
439 return "margin" 441 return "margin"
440 442
441 @property 443 @property
444 def open(self):
445 return self.status == "open"
446
447 @property
442 def pending(self): 448 def pending(self):
443 return self.status == "pending" 449 return self.status == "pending"
444 450
@@ -446,10 +452,6 @@ class Order:
446 def finished(self): 452 def finished(self):
447 return self.status == "closed" or self.status == "canceled" or self.status == "error" 453 return self.status == "closed" or self.status == "canceled" or self.status == "error"
448 454
449 @property
450 def id(self):
451 return self.results[0]["id"]
452
453 def run(self): 455 def run(self):
454 symbol = "{}/{}".format(self.amount.currency, self.base_currency) 456 symbol = "{}/{}".format(self.amount.currency, self.base_currency)
455 amount = round(self.amount, self.market.order_precision(symbol)).value 457 amount = round(self.amount, self.market.order_precision(symbol)).value
@@ -457,26 +459,27 @@ class Order:
457 if TradeStore.debug: 459 if TradeStore.debug:
458 print("market.create_order('{}', 'limit', '{}', {}, price={}, account={})".format( 460 print("market.create_order('{}', 'limit', '{}', {}, price={}, account={})".format(
459 symbol, self.action, amount, self.rate, self.account)) 461 symbol, self.action, amount, self.rate, self.account))
460 self.status = "open"
461 self.results.append({"debug": True, "id": -1}) 462 self.results.append({"debug": True, "id": -1})
462 else: 463 else:
463 try: 464 try:
464 self.results.append(self.market.create_order(symbol, 'limit', self.action, amount, price=self.rate, account=self.account)) 465 self.results.append(self.market.create_order(symbol, 'limit', self.action, amount, price=self.rate, account=self.account))
465 self.status = "open"
466 except Exception as e: 466 except Exception as e:
467 self.status = "error" 467 self.status = "error"
468 print("error when running market.create_order('{}', 'limit', '{}', {}, price={}, account={})".format( 468 print("error when running market.create_order('{}', 'limit', '{}', {}, price={}, account={})".format(
469 symbol, self.action, amount, self.rate, self.account)) 469 symbol, self.action, amount, self.rate, self.account))
470 self.error_message = str("{}: {}".format(e.__class__.__name__, e)) 470 self.error_message = str("{}: {}".format(e.__class__.__name__, e))
471 print(self.error_message) 471 print(self.error_message)
472 return
473 self.id = self.results[0]["id"]
474 self.status = "open"
472 475
473 def get_status(self): 476 def get_status(self):
474 if TradeStore.debug: 477 if TradeStore.debug:
475 return self.status 478 return self.status
476 # other states are "closed" and "canceled" 479 # other states are "closed" and "canceled"
477 if self.status == "open": 480 if not self.finished:
478 self.fetch() 481 self.fetch()
479 if self.status != "open": 482 if self.finished:
480 self.mark_finished_order() 483 self.mark_finished_order()
481 return self.status 484 return self.status
482 485
@@ -487,15 +490,15 @@ class Order:
487 if self.trade_type == "short" and self.action == "buy" and self.close_if_possible: 490 if self.trade_type == "short" and self.action == "buy" and self.close_if_possible:
488 self.market.close_margin_position(self.amount.currency, self.base_currency) 491 self.market.close_margin_position(self.amount.currency, self.base_currency)
489 492
490 fetch_cache_timestamp = None
491 def fetch(self, force=False): 493 def fetch(self, force=False):
492 if TradeStore.debug or (not force and self.fetch_cache_timestamp is not None 494 if TradeStore.debug or (not force and self.fetch_cache_timestamp is not None
493 and time.time() - self.fetch_cache_timestamp < 10): 495 and time.time() - self.fetch_cache_timestamp < 10):
494 return 496 return
495 self.fetch_cache_timestamp = time.time() 497 self.fetch_cache_timestamp = time.time()
496 498
497 self.results.append(self.market.fetch_order(self.id)) 499 result = self.market.fetch_order(self.id)
498 result = self.results[-1] 500 self.results.append(result)
501
499 self.status = result["status"] 502 self.status = result["status"]
500 # Time at which the order started 503 # Time at which the order started
501 self.timestamp = result["datetime"] 504 self.timestamp = result["datetime"]
@@ -503,11 +506,9 @@ class Order:
503 506
504 # FIXME: consider open order with dust remaining as closed 507 # FIXME: consider open order with dust remaining as closed
505 508
506 @property
507 def dust_amount_remaining(self): 509 def dust_amount_remaining(self):
508 return self.remaining_amount < 0.001 510 return self.remaining_amount() < Amount(self.amount.currency, D("0.001"))
509 511
510 @property
511 def remaining_amount(self): 512 def remaining_amount(self):
512 if self.status == "open": 513 if self.status == "open":
513 self.fetch() 514 self.fetch()
@@ -536,7 +537,7 @@ class Order:
536 if TradeStore.debug: 537 if TradeStore.debug:
537 self.status = "canceled" 538 self.status = "canceled"
538 return 539 return
539 self.market.cancel_order(self.result['id']) 540 self.market.cancel_order(self.id)
540 self.fetch() 541 self.fetch()
541 542
542class Mouvement: 543class Mouvement:
@@ -552,6 +553,6 @@ class Mouvement:
552 # rate * total = total_in_base 553 # rate * total = total_in_base
553 self.total_in_base = Amount(base_currency, hash_["total"]) 554 self.total_in_base = Amount(base_currency, hash_["total"])
554 555
555if __name__ == '__main__': 556if __name__ == '__main__': # pragma: no cover
556 from market import market 557 from market import market
557 h.print_orders(market) 558 h.print_orders(market)
diff --git a/test.py b/test.py
index be3ad4a..8903815 100644
--- a/test.py
+++ b/test.py
@@ -43,7 +43,6 @@ class WebMockTestCase(unittest.TestCase):
43 for patcher in self.patchers: 43 for patcher in self.patchers:
44 patcher.start() 44 patcher.start()
45 45
46
47 def tearDown(self): 46 def tearDown(self):
48 for patcher in self.patchers: 47 for patcher in self.patchers:
49 patcher.stop() 48 patcher.stop()
@@ -702,6 +701,68 @@ class HelperTest(WebMockTestCase):
702 else: 701 else:
703 self.assertEqual("", stdout_mock.getvalue()) 702 self.assertEqual("", stdout_mock.getvalue())
704 703
704 @mock.patch.object(portfolio.BalanceStore, "fetch_balances")
705 def test_move_balance(self, fetch_balances):
706 for debug in [True, False]:
707 with self.subTest(debug=debug),\
708 mock.patch('sys.stdout', new_callable=StringIO) as stdout_mock:
709 value_from = portfolio.Amount("BTC", "1.0")
710 value_from.linked_to = portfolio.Amount("ETH", "10.0")
711 value_to = portfolio.Amount("BTC", "10.0")
712 trade1 = portfolio.Trade(value_from, value_to, "ETH")
713
714 value_from = portfolio.Amount("BTC", "0.0")
715 value_from.linked_to = portfolio.Amount("ETH", "0.0")
716 value_to = portfolio.Amount("BTC", "-3.0")
717 trade2 = portfolio.Trade(value_from, value_to, "ETH")
718
719 value_from = portfolio.Amount("USDT", "0.0")
720 value_from.linked_to = portfolio.Amount("XVG", "0.0")
721 value_to = portfolio.Amount("USDT", "-50.0")
722 trade3 = portfolio.Trade(value_from, value_to, "XVG")
723
724 portfolio.TradeStore.all = [trade1, trade2, trade3]
725 balance1 = portfolio.Balance("BTC", { "margin_free": "0" })
726 balance2 = portfolio.Balance("USDT", { "margin_free": "100" })
727 portfolio.BalanceStore.all = {"BTC": balance1, "USDT": balance2}
728
729 market = mock.Mock()
730
731 helper.move_balances(market, debug=debug)
732
733 fetch_balances.assert_called_with(market)
734 if debug:
735 self.assertRegex(stdout_mock.getvalue(), "market.transfer_balance")
736 else:
737 market.transfer_balance.assert_any_call("BTC", 3, "exchange", "margin")
738 market.transfer_balance.assert_any_call("USDT", 50, "margin", "exchange")
739
740 @mock.patch.object(helper, "prepare_trades")
741 @mock.patch.object(portfolio.TradeStore, "prepare_orders")
742 @mock.patch.object(portfolio.TradeStore, "print_all_with_order")
743 @mock.patch('sys.stdout', new_callable=StringIO)
744 def test_print_orders(self, stdout_mock, print_all_with_order, prepare_orders, prepare_trades):
745 market = mock.Mock()
746 portfolio.BalanceStore.all = {
747 "BTC": portfolio.Balance("BTC", {
748 "total": "0.65",
749 "exchange_total":"0.65",
750 "exchange_free": "0.35",
751 "exchange_used": "0.30"}),
752 "ETH": portfolio.Balance("ETH", {
753 "total": 3,
754 "exchange_total": 3,
755 "exchange_free": 3,
756 "exchange_used": 0}),
757 }
758 helper.print_orders(market)
759 prepare_trades.assert_called_with(market, base_currency="BTC",
760 compute_value="average")
761 prepare_orders.assert_called_with(compute_value="average")
762 print_all_with_order.assert_called()
763 self.assertRegex(stdout_mock.getvalue(), "Balance")
764
765
705@unittest.skipUnless("unit" in limits, "Unit skipped") 766@unittest.skipUnless("unit" in limits, "Unit skipped")
706class TradeStoreTest(WebMockTestCase): 767class TradeStoreTest(WebMockTestCase):
707 @mock.patch.object(portfolio.BalanceStore, "currencies") 768 @mock.patch.object(portfolio.BalanceStore, "currencies")
@@ -1068,7 +1129,7 @@ class TradeTest(WebMockTestCase):
1068 value_to = portfolio.Amount("BTC", "-1.0") 1129 value_to = portfolio.Amount("BTC", "-1.0")
1069 trade = portfolio.Trade(value_from, value_to, "ETH") 1130 trade = portfolio.Trade(value_from, value_to, "ETH")
1070 1131
1071 self.assertEqual("dispose", trade.action) 1132 self.assertEqual("acquire", trade.action)
1072 1133
1073 def test_order_action(self): 1134 def test_order_action(self):
1074 value_from = portfolio.Amount("BTC", "0.5") 1135 value_from = portfolio.Amount("BTC", "0.5")
@@ -1275,9 +1336,7 @@ class TradeTest(WebMockTestCase):
1275 value_from.linked_to = portfolio.Amount("ETH", "10.0") 1336 value_from.linked_to = portfolio.Amount("ETH", "10.0")
1276 value_to = portfolio.Amount("BTC", "1.0") 1337 value_to = portfolio.Amount("BTC", "1.0")
1277 trade = portfolio.Trade(value_from, value_to, "ETH") 1338 trade = portfolio.Trade(value_from, value_to, "ETH")
1278 def _prepare_order(compute_value=None): 1339 prepare_order.return_value = new_order_mock
1279 trade.orders.append(new_order_mock)
1280 prepare_order.side_effect = _prepare_order
1281 1340
1282 for i in [0, 1, 3, 4, 6]: 1341 for i in [0, 1, 3, 4, 6]:
1283 with self.subTest(tick=i), mock.patch('sys.stdout', new_callable=StringIO) as stdout_mock: 1342 with self.subTest(tick=i), mock.patch('sys.stdout', new_callable=StringIO) as stdout_mock:
@@ -1285,7 +1344,6 @@ class TradeTest(WebMockTestCase):
1285 order_mock.cancel.assert_not_called() 1344 order_mock.cancel.assert_not_called()
1286 new_order_mock.run.assert_not_called() 1345 new_order_mock.run.assert_not_called()
1287 self.assertRegex(stdout_mock.getvalue(), "tick {}, waiting".format(i)) 1346 self.assertRegex(stdout_mock.getvalue(), "tick {}, waiting".format(i))
1288 self.assertEqual(0, len(trade.orders))
1289 1347
1290 order_mock.reset_mock() 1348 order_mock.reset_mock()
1291 new_order_mock.reset_mock() 1349 new_order_mock.reset_mock()
@@ -1297,7 +1355,6 @@ class TradeTest(WebMockTestCase):
1297 new_order_mock.run.assert_called() 1355 new_order_mock.run.assert_called()
1298 prepare_order.assert_called() 1356 prepare_order.assert_called()
1299 self.assertRegex(stdout_mock.getvalue(), "tick 2, cancelling and adjusting") 1357 self.assertRegex(stdout_mock.getvalue(), "tick 2, cancelling and adjusting")
1300 self.assertEqual(1, len(trade.orders))
1301 1358
1302 order_mock.reset_mock() 1359 order_mock.reset_mock()
1303 new_order_mock.reset_mock() 1360 new_order_mock.reset_mock()
@@ -1309,7 +1366,6 @@ class TradeTest(WebMockTestCase):
1309 new_order_mock.run.assert_called() 1366 new_order_mock.run.assert_called()
1310 prepare_order.assert_called() 1367 prepare_order.assert_called()
1311 self.assertRegex(stdout_mock.getvalue(), "tick 5, cancelling and adjusting") 1368 self.assertRegex(stdout_mock.getvalue(), "tick 5, cancelling and adjusting")
1312 self.assertEqual(1, len(trade.orders))
1313 1369
1314 order_mock.reset_mock() 1370 order_mock.reset_mock()
1315 new_order_mock.reset_mock() 1371 new_order_mock.reset_mock()
@@ -1322,7 +1378,6 @@ class TradeTest(WebMockTestCase):
1322 prepare_order.assert_called_with(compute_value="default") 1378 prepare_order.assert_called_with(compute_value="default")
1323 self.assertRegex(stdout_mock.getvalue(), "tick 7, fallbacking to market value") 1379 self.assertRegex(stdout_mock.getvalue(), "tick 7, fallbacking to market value")
1324 self.assertRegex(stdout_mock.getvalue(), "tick 7, market value, cancelling and adjusting to") 1380 self.assertRegex(stdout_mock.getvalue(), "tick 7, market value, cancelling and adjusting to")
1325 self.assertEqual(1, len(trade.orders))
1326 1381
1327 order_mock.reset_mock() 1382 order_mock.reset_mock()
1328 new_order_mock.reset_mock() 1383 new_order_mock.reset_mock()
@@ -1336,7 +1391,6 @@ class TradeTest(WebMockTestCase):
1336 prepare_order.assert_called_with(compute_value="default") 1391 prepare_order.assert_called_with(compute_value="default")
1337 self.assertNotRegex(stdout_mock.getvalue(), "tick {}, fallbacking to market value".format(i)) 1392 self.assertNotRegex(stdout_mock.getvalue(), "tick {}, fallbacking to market value".format(i))
1338 self.assertRegex(stdout_mock.getvalue(), "tick {}, market value, cancelling and adjusting to".format(i)) 1393 self.assertRegex(stdout_mock.getvalue(), "tick {}, market value, cancelling and adjusting to".format(i))
1339 self.assertEqual(1, len(trade.orders))
1340 1394
1341 order_mock.reset_mock() 1395 order_mock.reset_mock()
1342 new_order_mock.reset_mock() 1396 new_order_mock.reset_mock()
@@ -1348,7 +1402,6 @@ class TradeTest(WebMockTestCase):
1348 order_mock.cancel.assert_not_called() 1402 order_mock.cancel.assert_not_called()
1349 new_order_mock.run.assert_not_called() 1403 new_order_mock.run.assert_not_called()
1350 self.assertEqual("", stdout_mock.getvalue()) 1404 self.assertEqual("", stdout_mock.getvalue())
1351 self.assertEqual(0, len(trade.orders))
1352 1405
1353 order_mock.reset_mock() 1406 order_mock.reset_mock()
1354 new_order_mock.reset_mock() 1407 new_order_mock.reset_mock()
@@ -1386,6 +1439,355 @@ class TradeTest(WebMockTestCase):
1386 1439
1387 self.assertEqual("Trade(0.50000000 BTC [10.00000000 ETH] -> 1.00000000 BTC in ETH, acquire)", str(trade)) 1440 self.assertEqual("Trade(0.50000000 BTC [10.00000000 ETH] -> 1.00000000 BTC in ETH, acquire)", str(trade))
1388 1441
1442@unittest.skipUnless("unit" in limits, "Unit skipped")
1443class OrderTest(WebMockTestCase):
1444 def test_values(self):
1445 order = portfolio.Order("buy", portfolio.Amount("ETH", 10),
1446 D("0.1"), "BTC", "long", "market", "trade")
1447 self.assertEqual("buy", order.action)
1448 self.assertEqual(10, order.amount.value)
1449 self.assertEqual("ETH", order.amount.currency)
1450 self.assertEqual(D("0.1"), order.rate)
1451 self.assertEqual("BTC", order.base_currency)
1452 self.assertEqual("market", order.market)
1453 self.assertEqual("long", order.trade_type)
1454 self.assertEqual("pending", order.status)
1455 self.assertEqual("trade", order.trade)
1456 self.assertIsNone(order.id)
1457 self.assertFalse(order.close_if_possible)
1458
1459 def test__repr(self):
1460 order = portfolio.Order("buy", portfolio.Amount("ETH", 10),
1461 D("0.1"), "BTC", "long", "market", "trade")
1462 self.assertEqual("Order(buy long 10.00000000 ETH at 0.1 BTC [pending])", repr(order))
1463
1464 order = portfolio.Order("buy", portfolio.Amount("ETH", 10),
1465 D("0.1"), "BTC", "long", "market", "trade",
1466 close_if_possible=True)
1467 self.assertEqual("Order(buy long 10.00000000 ETH at 0.1 BTC [pending] ✂)", repr(order))
1468
1469 def test_account(self):
1470 order = portfolio.Order("buy", portfolio.Amount("ETH", 10),
1471 D("0.1"), "BTC", "long", "market", "trade")
1472 self.assertEqual("exchange", order.account)
1473
1474 order = portfolio.Order("sell", portfolio.Amount("ETH", 10),
1475 D("0.1"), "BTC", "short", "market", "trade")
1476 self.assertEqual("margin", order.account)
1477
1478 def test_pending(self):
1479 order = portfolio.Order("buy", portfolio.Amount("ETH", 10),
1480 D("0.1"), "BTC", "long", "market", "trade")
1481 self.assertTrue(order.pending)
1482 order.status = "open"
1483 self.assertFalse(order.pending)
1484
1485 def test_open(self):
1486 order = portfolio.Order("buy", portfolio.Amount("ETH", 10),
1487 D("0.1"), "BTC", "long", "market", "trade")
1488 self.assertFalse(order.open)
1489 order.status = "open"
1490 self.assertTrue(order.open)
1491
1492 def test_finished(self):
1493 order = portfolio.Order("buy", portfolio.Amount("ETH", 10),
1494 D("0.1"), "BTC", "long", "market", "trade")
1495 self.assertFalse(order.finished)
1496 order.status = "closed"
1497 self.assertTrue(order.finished)
1498 order.status = "canceled"
1499 self.assertTrue(order.finished)
1500 order.status = "error"
1501 self.assertTrue(order.finished)
1502
1503 @mock.patch.object(portfolio.Order, "fetch")
1504 def test_cancel(self, fetch):
1505 market = mock.Mock()
1506 portfolio.TradeStore.debug = True
1507 order = portfolio.Order("buy", portfolio.Amount("ETH", 10),
1508 D("0.1"), "BTC", "long", market, "trade")
1509 order.status = "open"
1510
1511 order.cancel()
1512 market.cancel_order.assert_not_called()
1513 self.assertEqual("canceled", order.status)
1514
1515 portfolio.TradeStore.debug = False
1516 order = portfolio.Order("buy", portfolio.Amount("ETH", 10),
1517 D("0.1"), "BTC", "long", market, "trade")
1518 order.status = "open"
1519 order.id = 42
1520
1521 order.cancel()
1522 market.cancel_order.assert_called_with(42)
1523 fetch.assert_called_once()
1524
1525 def test_dust_amount_remaining(self):
1526 order = portfolio.Order("buy", portfolio.Amount("ETH", 10),
1527 D("0.1"), "BTC", "long", "market", "trade")
1528 order.remaining_amount = mock.Mock(return_value=portfolio.Amount("ETH", 1))
1529 self.assertFalse(order.dust_amount_remaining())
1530
1531 order.remaining_amount = mock.Mock(return_value=portfolio.Amount("ETH", D("0.0001")))
1532 self.assertTrue(order.dust_amount_remaining())
1533
1534 @mock.patch.object(portfolio.Order, "fetch")
1535 @mock.patch.object(portfolio.Order, "filled_amount", return_value=portfolio.Amount("ETH", 1))
1536 def test_remaining_amount(self, filled_amount, fetch):
1537 order = portfolio.Order("buy", portfolio.Amount("ETH", 10),
1538 D("0.1"), "BTC", "long", "market", "trade")
1539
1540 self.assertEqual(9, order.remaining_amount().value)
1541 order.fetch.assert_not_called()
1542
1543 order.status = "open"
1544 self.assertEqual(9, order.remaining_amount().value)
1545 fetch.assert_called_once()
1546
1547 @mock.patch.object(portfolio.Order, "fetch")
1548 def test_filled_amount(self, fetch):
1549 order = portfolio.Order("buy", portfolio.Amount("ETH", 10),
1550 D("0.1"), "BTC", "long", "market", "trade")
1551 order.mouvements.append(portfolio.Mouvement("ETH", "BTC", {
1552 "id": 42, "type": "buy", "fee": "0.0015",
1553 "date": "2017-12-30 12:00:12", "rate": "0.1",
1554 "amount": "3", "total": "0.3"
1555 }))
1556 order.mouvements.append(portfolio.Mouvement("ETH", "BTC", {
1557 "id": 43, "type": "buy", "fee": "0.0015",
1558 "date": "2017-12-30 13:00:12", "rate": "0.2",
1559 "amount": "2", "total": "0.4"
1560 }))
1561 self.assertEqual(portfolio.Amount("ETH", 5), order.filled_amount())
1562 fetch.assert_not_called()
1563 order.status = "open"
1564 self.assertEqual(portfolio.Amount("ETH", 5), order.filled_amount(in_base_currency=False))
1565 fetch.assert_called_once()
1566 self.assertEqual(portfolio.Amount("BTC", "0.7"), order.filled_amount(in_base_currency=True))
1567
1568 def test_fetch_mouvements(self):
1569 market = mock.Mock()
1570 market.privatePostReturnOrderTrades.return_value = [
1571 {
1572 "id": 42, "type": "buy", "fee": "0.0015",
1573 "date": "2017-12-30 12:00:12", "rate": "0.1",
1574 "amount": "3", "total": "0.3"
1575 },
1576 {
1577 "id": 43, "type": "buy", "fee": "0.0015",
1578 "date": "2017-12-30 13:00:12", "rate": "0.2",
1579 "amount": "2", "total": "0.4"
1580 }
1581 ]
1582 order = portfolio.Order("buy", portfolio.Amount("ETH", 10),
1583 D("0.1"), "BTC", "long", market, "trade")
1584 order.id = 12
1585 order.mouvements = ["Foo", "Bar", "Baz"]
1586
1587 order.fetch_mouvements()
1588
1589 market.privatePostReturnOrderTrades.assert_called_with({"orderNumber": 12})
1590 self.assertEqual(2, len(order.mouvements))
1591 self.assertEqual(42, order.mouvements[0].id)
1592 self.assertEqual(43, order.mouvements[1].id)
1593
1594 def test_mark_finished_order(self):
1595 market = mock.Mock()
1596 order = portfolio.Order("buy", portfolio.Amount("ETH", 10),
1597 D("0.1"), "BTC", "short", market, "trade",
1598 close_if_possible=True)
1599 order.status = "closed"
1600 portfolio.TradeStore.debug = False
1601
1602 order.mark_finished_order()
1603 market.close_margin_position.assert_called_with("ETH", "BTC")
1604 market.close_margin_position.reset_mock()
1605
1606 order.status = "open"
1607 order.mark_finished_order()
1608 market.close_margin_position.assert_not_called()
1609
1610 order = portfolio.Order("buy", portfolio.Amount("ETH", 10),
1611 D("0.1"), "BTC", "short", market, "trade",
1612 close_if_possible=False)
1613 order.status = "closed"
1614 order.mark_finished_order()
1615 market.close_margin_position.assert_not_called()
1616
1617 order = portfolio.Order("sell", portfolio.Amount("ETH", 10),
1618 D("0.1"), "BTC", "short", market, "trade",
1619 close_if_possible=True)
1620 order.status = "closed"
1621 order.mark_finished_order()
1622 market.close_margin_position.assert_not_called()
1623
1624 order = portfolio.Order("buy", portfolio.Amount("ETH", 10),
1625 D("0.1"), "BTC", "long", market, "trade",
1626 close_if_possible=True)
1627 order.status = "closed"
1628 order.mark_finished_order()
1629 market.close_margin_position.assert_not_called()
1630
1631 portfolio.TradeStore.debug = True
1632
1633 order = portfolio.Order("buy", portfolio.Amount("ETH", 10),
1634 D("0.1"), "BTC", "short", market, "trade",
1635 close_if_possible=True)
1636 order.status = "closed"
1637
1638 order.mark_finished_order()
1639 market.close_margin_position.assert_not_called()
1640
1641 @mock.patch.object(portfolio.Order, "fetch_mouvements")
1642 def test_fetch(self, fetch_mouvements):
1643 time = self.time.time()
1644 with mock.patch.object(portfolio.time, "time") as time_mock:
1645 market = mock.Mock()
1646 order = portfolio.Order("buy", portfolio.Amount("ETH", 10),
1647 D("0.1"), "BTC", "long", market, "trade")
1648 order.id = 45
1649 with self.subTest(debug=True):
1650 portfolio.TradeStore.debug = True
1651 order.fetch()
1652 time_mock.assert_not_called()
1653 order.fetch(force=True)
1654 time_mock.assert_not_called()
1655 market.fetch_order.assert_not_called()
1656 fetch_mouvements.assert_not_called()
1657 self.assertIsNone(order.fetch_cache_timestamp)
1658
1659 with self.subTest(debug=False):
1660 portfolio.TradeStore.debug = False
1661 time_mock.return_value = time
1662 market.fetch_order.return_value = {
1663 "status": "foo",
1664 "datetime": "timestamp"
1665 }
1666 order.fetch()
1667
1668 market.fetch_order.assert_called_once()
1669 fetch_mouvements.assert_called_once()
1670 self.assertEqual("foo", order.status)
1671 self.assertEqual("timestamp", order.timestamp)
1672 self.assertEqual(time, order.fetch_cache_timestamp)
1673 self.assertEqual(1, len(order.results))
1674
1675 market.fetch_order.reset_mock()
1676 fetch_mouvements.reset_mock()
1677
1678 time_mock.return_value = time + 8
1679 order.fetch()
1680 market.fetch_order.assert_not_called()
1681 fetch_mouvements.assert_not_called()
1682
1683 order.fetch(force=True)
1684 market.fetch_order.assert_called_once()
1685 fetch_mouvements.assert_called_once()
1686
1687 market.fetch_order.reset_mock()
1688 fetch_mouvements.reset_mock()
1689
1690 time_mock.return_value = time + 19
1691 order.fetch()
1692 market.fetch_order.assert_called_once()
1693 fetch_mouvements.assert_called_once()
1694
1695 @mock.patch.object(portfolio.Order, "fetch")
1696 @mock.patch.object(portfolio.Order, "mark_finished_order")
1697 def test_get_status(self, mark_finished_order, fetch):
1698 with self.subTest(debug=True):
1699 portfolio.TradeStore.debug = True
1700 order = portfolio.Order("buy", portfolio.Amount("ETH", 10),
1701 D("0.1"), "BTC", "long", "market", "trade")
1702 self.assertEqual("pending", order.get_status())
1703 fetch.assert_not_called()
1704
1705 with self.subTest(debug=False, finished=False):
1706 portfolio.TradeStore.debug = False
1707 order = portfolio.Order("buy", portfolio.Amount("ETH", 10),
1708 D("0.1"), "BTC", "long", "market", "trade")
1709 def _fetch(order):
1710 def update_status():
1711 order.status = "open"
1712 return update_status
1713 fetch.side_effect = _fetch(order)
1714 self.assertEqual("open", order.get_status())
1715 mark_finished_order.assert_not_called()
1716 fetch.assert_called_once()
1717
1718 mark_finished_order.reset_mock()
1719 fetch.reset_mock()
1720 with self.subTest(debug=False, finished=True):
1721 portfolio.TradeStore.debug = False
1722 order = portfolio.Order("buy", portfolio.Amount("ETH", 10),
1723 D("0.1"), "BTC", "long", "market", "trade")
1724 def _fetch(order):
1725 def update_status():
1726 order.status = "closed"
1727 return update_status
1728 fetch.side_effect = _fetch(order)
1729 self.assertEqual("closed", order.get_status())
1730 mark_finished_order.assert_called_once()
1731 fetch.assert_called_once()
1732
1733 def test_run(self):
1734 market = mock.Mock()
1735
1736 market.order_precision.return_value = 4
1737 with self.subTest(debug=True),\
1738 mock.patch('sys.stdout', new_callable=StringIO) as stdout_mock:
1739 portfolio.TradeStore.debug = True
1740 order = portfolio.Order("buy", portfolio.Amount("ETH", 10),
1741 D("0.1"), "BTC", "long", market, "trade")
1742 order.run()
1743 market.create_order.assert_not_called()
1744 self.assertEqual("market.create_order('ETH/BTC', 'limit', 'buy', 10.0000, price=0.1, account=exchange)\n", stdout_mock.getvalue())
1745 self.assertEqual("open", order.status)
1746 self.assertEqual(1, len(order.results))
1747 self.assertEqual(-1, order.id)
1748
1749 market.create_order.reset_mock()
1750 with self.subTest(debug=False):
1751 portfolio.TradeStore.debug = False
1752 order = portfolio.Order("buy", portfolio.Amount("ETH", 10),
1753 D("0.1"), "BTC", "long", market, "trade")
1754 market.create_order.return_value = { "id": 123 }
1755 order.run()
1756 market.create_order.assert_called_once()
1757 self.assertEqual(1, len(order.results))
1758 self.assertEqual("open", order.status)
1759
1760 market.create_order.reset_mock()
1761 with self.subTest(exception=True),\
1762 mock.patch('sys.stdout', new_callable=StringIO) as stdout_mock:
1763 order = portfolio.Order("buy", portfolio.Amount("ETH", 10),
1764 D("0.1"), "BTC", "long", market, "trade")
1765 market.create_order.side_effect = Exception("bouh")
1766 order.run()
1767 market.create_order.assert_called_once()
1768 self.assertEqual(0, len(order.results))
1769 self.assertEqual("error", order.status)
1770 self.assertRegex(stdout_mock.getvalue(), "error when running market.create_order")
1771 self.assertRegex(stdout_mock.getvalue(), "Exception: bouh")
1772
1773@unittest.skipUnless("unit" in limits, "Unit skipped")
1774class MouvementTest(WebMockTestCase):
1775 def test_values(self):
1776 mouvement = portfolio.Mouvement("ETH", "BTC", {
1777 "id": 42, "type": "buy", "fee": "0.0015",
1778 "date": "2017-12-30 12:00:12", "rate": "0.1",
1779 "amount": "10", "total": "1"
1780 })
1781 self.assertEqual("ETH", mouvement.currency)
1782 self.assertEqual("BTC", mouvement.base_currency)
1783 self.assertEqual(42, mouvement.id)
1784 self.assertEqual("buy", mouvement.action)
1785 self.assertEqual(D("0.0015"), mouvement.fee_rate)
1786 self.assertEqual(portfolio.datetime(2017, 12, 30, 12, 0, 12), mouvement.date)
1787 self.assertEqual(D("0.1"), mouvement.rate)
1788 self.assertEqual(portfolio.Amount("ETH", "10"), mouvement.total)
1789 self.assertEqual(portfolio.Amount("BTC", "1"), mouvement.total_in_base)
1790
1389@unittest.skipUnless("acceptance" in limits, "Acceptance skipped") 1791@unittest.skipUnless("acceptance" in limits, "Acceptance skipped")
1390class AcceptanceTest(WebMockTestCase): 1792class AcceptanceTest(WebMockTestCase):
1391 @unittest.expectedFailure 1793 @unittest.expectedFailure
@@ -1473,7 +1875,7 @@ class AcceptanceTest(WebMockTestCase):
1473 self.assertEqual(portfolio.Amount("XVG", 1000), balances["XVG"].total) 1875 self.assertEqual(portfolio.Amount("XVG", 1000), balances["XVG"].total)
1474 1876
1475 1877
1476 trades = TradeStore.all 1878 trades = portfolio.TradeStore.all
1477 self.assertEqual(portfolio.Amount("BTC", D("0.15")), trades[0].value_from) 1879 self.assertEqual(portfolio.Amount("BTC", D("0.15")), trades[0].value_from)
1478 self.assertEqual(portfolio.Amount("BTC", D("0.05")), trades[0].value_to) 1880 self.assertEqual(portfolio.Amount("BTC", D("0.05")), trades[0].value_to)
1479 self.assertEqual("dispose", trades[0].action) 1881 self.assertEqual("dispose", trades[0].action)
@@ -1488,7 +1890,7 @@ class AcceptanceTest(WebMockTestCase):
1488 1890
1489 self.assertEqual(portfolio.Amount("BTC", D("0.00")), trades[3].value_from) 1891 self.assertEqual(portfolio.Amount("BTC", D("0.00")), trades[3].value_from)
1490 self.assertEqual(portfolio.Amount("BTC", D("-0.002")), trades[3].value_to) 1892 self.assertEqual(portfolio.Amount("BTC", D("-0.002")), trades[3].value_to)
1491 self.assertEqual("dispose", trades[3].action) 1893 self.assertEqual("acquire", trades[3].action)
1492 1894
1493 self.assertEqual(portfolio.Amount("BTC", D("0.00")), trades[4].value_from) 1895 self.assertEqual(portfolio.Amount("BTC", D("0.00")), trades[4].value_from)
1494 self.assertEqual(portfolio.Amount("BTC", D("0.008")), trades[4].value_to) 1896 self.assertEqual(portfolio.Amount("BTC", D("0.008")), trades[4].value_to)
@@ -1499,9 +1901,9 @@ class AcceptanceTest(WebMockTestCase):
1499 self.assertEqual("acquire", trades[5].action) 1901 self.assertEqual("acquire", trades[5].action)
1500 1902
1501 # Action 2 1903 # Action 2
1502 portfolio.Trade.prepare_orders(only="dispose", compute_value=lambda x, y: x["bid"] * D("1.001")) 1904 portfolio.TradeStore.prepare_orders(only="dispose", compute_value=lambda x, y: x["bid"] * D("1.001"))
1503 1905
1504 all_orders = portfolio.Trade.all_orders() 1906 all_orders = portfolio.TradeStore.all_orders(state="pending")
1505 self.assertEqual(2, len(all_orders)) 1907 self.assertEqual(2, len(all_orders))
1506 self.assertEqual(2, 3*all_orders[0].amount.value) 1908 self.assertEqual(2, 3*all_orders[0].amount.value)
1507 self.assertEqual(D("0.14014"), all_orders[0].rate) 1909 self.assertEqual(D("0.14014"), all_orders[0].rate)
@@ -1534,7 +1936,14 @@ class AcceptanceTest(WebMockTestCase):
1534 self.assertEqual("open", all_orders[0].status) 1936 self.assertEqual("open", all_orders[0].status)
1535 self.assertEqual("open", all_orders[1].status) 1937 self.assertEqual("open", all_orders[1].status)
1536 1938
1537 market.fetch_order.return_value = { "status": "closed" } 1939 market.fetch_order.return_value = { "status": "closed", "datetime": "2018-01-20 13:40:00" }
1940 market.privatePostReturnOrderTrades.return_value = [
1941 {
1942 "id": 42, "type": "buy", "fee": "0.0015",
1943 "date": "2017-12-30 12:00:12", "rate": "0.1",
1944 "amount": "10", "total": "1"
1945 }
1946 ]
1538 with mock.patch.object(portfolio.time, "sleep") as sleep: 1947 with mock.patch.object(portfolio.time, "sleep") as sleep:
1539 # Action 4 1948 # Action 4
1540 helper.follow_orders(verbose=False) 1949 helper.follow_orders(verbose=False)
@@ -1546,31 +1955,39 @@ class AcceptanceTest(WebMockTestCase):
1546 1955
1547 fetch_balance = { 1956 fetch_balance = {
1548 "ETH": { 1957 "ETH": {
1549 "free": D("1.0") / 3, 1958 "exchange_free": D("1.0") / 3,
1550 "used": D("0.0"), 1959 "exchange_used": D("0.0"),
1960 "exchange_total": D("1.0") / 3,
1961 "margin_total": 0,
1551 "total": D("1.0") / 3, 1962 "total": D("1.0") / 3,
1552 }, 1963 },
1553 "BTC": { 1964 "BTC": {
1554 "free": D("0.134"), 1965 "exchange_free": D("0.134"),
1555 "used": D("0.0"), 1966 "exchange_used": D("0.0"),
1967 "exchange_total": D("0.134"),
1968 "margin_total": 0,
1556 "total": D("0.134"), 1969 "total": D("0.134"),
1557 }, 1970 },
1558 "ETC": { 1971 "ETC": {
1559 "free": D("4.0"), 1972 "exchange_free": D("4.0"),
1560 "used": D("0.0"), 1973 "exchange_used": D("0.0"),
1974 "exchange_total": D("4.0"),
1975 "margin_total": 0,
1561 "total": D("4.0"), 1976 "total": D("4.0"),
1562 }, 1977 },
1563 "XVG": { 1978 "XVG": {
1564 "free": D("0.0"), 1979 "exchange_free": D("0.0"),
1565 "used": D("0.0"), 1980 "exchange_used": D("0.0"),
1981 "exchange_total": D("0.0"),
1982 "margin_total": 0,
1566 "total": D("0.0"), 1983 "total": D("0.0"),
1567 }, 1984 },
1568 } 1985 }
1569 market.fetch_balance.return_value = fetch_balance 1986 market.fetch_all_balances.return_value = fetch_balance
1570 1987
1571 with mock.patch.object(portfolio.Portfolio, "repartition", return_value=repartition): 1988 with mock.patch.object(portfolio.Portfolio, "repartition", return_value=repartition):
1572 # Action 5 1989 # Action 5
1573 helper.update_trades(market, only="buy", compute_value="average") 1990 helper.update_trades(market, only="acquire", compute_value="average")
1574 1991
1575 balances = portfolio.BalanceStore.all 1992 balances = portfolio.BalanceStore.all
1576 self.assertEqual(portfolio.Amount("ETH", 1 / D("3")), balances["ETH"].total) 1993 self.assertEqual(portfolio.Amount("ETH", 1 / D("3")), balances["ETH"].total)
@@ -1579,37 +1996,37 @@ class AcceptanceTest(WebMockTestCase):
1579 self.assertEqual(portfolio.Amount("XVG", 0), balances["XVG"].total) 1996 self.assertEqual(portfolio.Amount("XVG", 0), balances["XVG"].total)
1580 1997
1581 1998
1582 trades = TradeStore.all 1999 trades = portfolio.TradeStore.all
1583 self.assertEqual(portfolio.Amount("BTC", D("0.15")), trades["ETH"].value_from) 2000 self.assertEqual(portfolio.Amount("BTC", D("0.15")), trades[0].value_from)
1584 self.assertEqual(portfolio.Amount("BTC", D("0.05")), trades["ETH"].value_to) 2001 self.assertEqual(portfolio.Amount("BTC", D("0.05")), trades[0].value_to)
1585 self.assertEqual("sell", trades["ETH"].action) 2002 self.assertEqual("dispose", trades[0].action)
1586 2003
1587 self.assertEqual(portfolio.Amount("BTC", D("0.01")), trades["ETC"].value_from) 2004 self.assertEqual(portfolio.Amount("BTC", D("0.01")), trades[1].value_from)
1588 self.assertEqual(portfolio.Amount("BTC", D("0.0485")), trades["ETC"].value_to) 2005 self.assertEqual(portfolio.Amount("BTC", D("0.05")), trades[1].value_to)
1589 self.assertEqual("buy", trades["ETC"].action) 2006 self.assertEqual("acquire", trades[1].action)
1590 2007
1591 self.assertNotIn("BTC", trades) 2008 self.assertNotIn("BTC", trades)
1592 2009
1593 self.assertEqual(portfolio.Amount("BTC", D("0.00")), trades["BTD"].value_from) 2010 self.assertEqual(portfolio.Amount("BTC", D("0.04")), trades[2].value_from)
1594 self.assertEqual(portfolio.Amount("BTC", D("0.00194")), trades["BTD"].value_to) 2011 self.assertEqual(portfolio.Amount("BTC", D("0.00")), trades[2].value_to)
1595 self.assertEqual("buy", trades["BTD"].action) 2012 self.assertEqual("dispose", trades[2].action)
1596 2013
1597 self.assertEqual(portfolio.Amount("BTC", D("0.00")), trades["B2X"].value_from) 2014 self.assertEqual(portfolio.Amount("BTC", D("0.00")), trades[3].value_from)
1598 self.assertEqual(portfolio.Amount("BTC", D("0.00776")), trades["B2X"].value_to) 2015 self.assertEqual(portfolio.Amount("BTC", D("-0.002")), trades[3].value_to)
1599 self.assertEqual("buy", trades["B2X"].action) 2016 self.assertEqual("acquire", trades[3].action)
1600 2017
1601 self.assertEqual(portfolio.Amount("BTC", D("0.00")), trades["USDT"].value_from) 2018 self.assertEqual(portfolio.Amount("BTC", D("0.00")), trades[4].value_from)
1602 self.assertEqual(portfolio.Amount("BTC", D("0.0097")), trades["USDT"].value_to) 2019 self.assertEqual(portfolio.Amount("BTC", D("0.008")), trades[4].value_to)
1603 self.assertEqual("buy", trades["USDT"].action) 2020 self.assertEqual("acquire", trades[4].action)
1604 2021
1605 self.assertEqual(portfolio.Amount("BTC", D("0.04")), trades["XVG"].value_from) 2022 self.assertEqual(portfolio.Amount("BTC", D("0.00")), trades[5].value_from)
1606 self.assertEqual(portfolio.Amount("BTC", D("0.00")), trades["XVG"].value_to) 2023 self.assertEqual(portfolio.Amount("BTC", D("0.01")), trades[5].value_to)
1607 self.assertEqual("sell", trades["XVG"].action) 2024 self.assertEqual("acquire", trades[5].action)
1608 2025
1609 # Action 6 2026 # Action 6
1610 portfolio.Trade.prepare_orders(only="buy", compute_value=lambda x, y: x["ask"]) 2027 portfolio.TradeStore.prepare_orders(only="acquire", compute_value=lambda x, y: x["ask"])
1611 2028
1612 all_orders = portfolio.Trade.all_orders(state="pending") 2029 all_orders = portfolio.TradeStore.all_orders(state="pending")
1613 self.assertEqual(4, len(all_orders)) 2030 self.assertEqual(4, len(all_orders))
1614 self.assertEqual(portfolio.Amount("ETC", D("12.83333333")), round(all_orders[0].amount)) 2031 self.assertEqual(portfolio.Amount("ETC", D("12.83333333")), round(all_orders[0].amount))
1615 self.assertEqual(D("0.003"), all_orders[0].rate) 2032 self.assertEqual(D("0.003"), all_orders[0].rate)