aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIsmaël Bouya <ismael.bouya@normalesup.org>2018-05-01 17:24:40 +0200
committerIsmaël Bouya <ismael.bouya@normalesup.org>2018-05-01 17:24:40 +0200
commit2b1ee8f4d54fa1672510141a71a5817120ac031c (patch)
tree762d3a59d666bf6e1d4d1ea5901c31ab06f7e88e
parent37b64a97021220df0bee5fd927184b92b10e8d76 (diff)
downloadTrader-2b1ee8f4d54fa1672510141a71a5817120ac031c.tar.gz
Trader-2b1ee8f4d54fa1672510141a71a5817120ac031c.tar.zst
Trader-2b1ee8f4d54fa1672510141a71a5817120ac031c.zip
Store tickers in balance log
-rw-r--r--market.py4
-rw-r--r--store.py31
-rw-r--r--tests/test_market.py4
-rw-r--r--tests/test_store.py133
4 files changed, 116 insertions, 56 deletions
diff --git a/market.py b/market.py
index eff670c..fc6f9f6 100644
--- a/market.py
+++ b/market.py
@@ -391,14 +391,14 @@ class Processor:
391 process_name = "process_{}__{}_{}".format(scenario_name, step["number"], step["name"]) 391 process_name = "process_{}__{}_{}".format(scenario_name, step["number"], step["name"])
392 self.market.report.log_stage("{}_begin".format(process_name)) 392 self.market.report.log_stage("{}_begin".format(process_name))
393 if "begin" in step.get("fetch_balances", []): 393 if "begin" in step.get("fetch_balances", []):
394 self.market.balances.fetch_balances(tag="{}_begin".format(process_name)) 394 self.market.balances.fetch_balances(tag="{}_begin".format(process_name), log_tickers=True)
395 395
396 for action in self.ordered_actions: 396 for action in self.ordered_actions:
397 if action in step: 397 if action in step:
398 self.run_action(action, step[action], kwargs) 398 self.run_action(action, step[action], kwargs)
399 399
400 if "end" in step.get("fetch_balances", []): 400 if "end" in step.get("fetch_balances", []):
401 self.market.balances.fetch_balances(tag="{}_end".format(process_name)) 401 self.market.balances.fetch_balances(tag="{}_end".format(process_name), log_tickers=True)
402 self.market.report.log_stage("{}_end".format(process_name)) 402 self.market.report.log_stage("{}_end".format(process_name))
403 403
404 def method_arguments(self, action): 404 def method_arguments(self, action):
diff --git a/store.py b/store.py
index 072d3a2..cd0bf7b 100644
--- a/store.py
+++ b/store.py
@@ -98,7 +98,8 @@ class ReportStore:
98 "args": args, 98 "args": args,
99 }) 99 })
100 100
101 def log_balances(self, tag=None): 101 def log_balances(self, tag=None, tickers=None,
102 ticker_currency=None, compute_value=None, type=None):
102 self.print_log("[Balance]") 103 self.print_log("[Balance]")
103 for currency, balance in self.market.balances.all.items(): 104 for currency, balance in self.market.balances.all.items():
104 self.print_log("\t{}".format(balance)) 105 self.print_log("\t{}".format(balance))
@@ -109,11 +110,22 @@ class ReportStore:
109 "balances": self.market.balances.as_json() 110 "balances": self.market.balances.as_json()
110 } 111 }
111 112
113 if tickers is not None:
114 log["tickers"] = self._ticker_hash(tickers, ticker_currency,
115 compute_value, type)
116
112 self.add_log(log.copy()) 117 self.add_log(log.copy())
113 self.add_redis_status(log) 118 self.add_redis_status(log)
114 119
115 def log_tickers(self, amounts, other_currency, 120 def log_tickers(self, amounts, other_currency,
116 compute_value, type): 121 compute_value, type):
122 log = self._ticker_hash(amounts, other_currency, compute_value,
123 type)
124 log["type"] = "tickers"
125
126 self.add_log(log)
127
128 def _ticker_hash(self, amounts, other_currency, compute_value, type):
117 values = {} 129 values = {}
118 rates = {} 130 rates = {}
119 if callable(compute_value): 131 if callable(compute_value):
@@ -122,8 +134,7 @@ class ReportStore:
122 for currency, amount in amounts.items(): 134 for currency, amount in amounts.items():
123 values[currency] = amount.as_json()["value"] 135 values[currency] = amount.as_json()["value"]
124 rates[currency] = amount.rate 136 rates[currency] = amount.rate
125 log = { 137 return {
126 "type": "tickers",
127 "compute_value": compute_value, 138 "compute_value": compute_value,
128 "balance_type": type, 139 "balance_type": type,
129 "currency": other_currency, 140 "currency": other_currency,
@@ -132,9 +143,6 @@ class ReportStore:
132 "total": sum(amounts.values()).as_json()["value"] 143 "total": sum(amounts.values()).as_json()["value"]
133 } 144 }
134 145
135 self.add_log(log.copy())
136 self.add_redis_status(log)
137
138 def log_dispatch(self, amount, amounts, liquidity, repartition): 146 def log_dispatch(self, amount, amounts, liquidity, repartition):
139 self.add_log({ 147 self.add_log({
140 "type": "dispatch", 148 "type": "dispatch",
@@ -294,13 +302,20 @@ class BalanceStore:
294 compute_value, type) 302 compute_value, type)
295 return amounts 303 return amounts
296 304
297 def fetch_balances(self, tag=None): 305 def fetch_balances(self, tag=None, log_tickers=False,
306 ticker_currency="BTC", ticker_compute_value="average", ticker_type="total"):
298 all_balances = self.market.ccxt.fetch_all_balances() 307 all_balances = self.market.ccxt.fetch_all_balances()
299 for currency, balance in all_balances.items(): 308 for currency, balance in all_balances.items():
300 if balance["exchange_total"] != 0 or balance["margin_total"] != 0 or \ 309 if balance["exchange_total"] != 0 or balance["margin_total"] != 0 or \
301 currency in self.all: 310 currency in self.all:
302 self.all[currency] = portfolio.Balance(currency, balance) 311 self.all[currency] = portfolio.Balance(currency, balance)
303 self.market.report.log_balances(tag=tag) 312 if log_tickers:
313 tickers = self.in_currency(ticker_currency, compute_value=ticker_compute_value, type=ticker_type)
314 self.market.report.log_balances(tag=tag,
315 tickers=tickers, ticker_currency=ticker_currency,
316 compute_value=ticker_compute_value, type=ticker_type)
317 else:
318 self.market.report.log_balances(tag=tag)
304 319
305 def dispatch_assets(self, amount, liquidity="medium", repartition=None): 320 def dispatch_assets(self, amount, liquidity="medium", repartition=None):
306 if repartition is None: 321 if repartition is None:
diff --git a/tests/test_market.py b/tests/test_market.py
index 53630b7..6a3322c 100644
--- a/tests/test_market.py
+++ b/tests/test_market.py
@@ -993,8 +993,8 @@ class ProcessorTest(WebMockTestCase):
993 mock.call("process_foo__1_sell_end"), 993 mock.call("process_foo__1_sell_end"),
994 ]) 994 ])
995 self.m.balances.fetch_balances.assert_has_calls([ 995 self.m.balances.fetch_balances.assert_has_calls([
996 mock.call(tag="process_foo__1_sell_begin"), 996 mock.call(tag="process_foo__1_sell_begin", log_tickers=True),
997 mock.call(tag="process_foo__1_sell_end"), 997 mock.call(tag="process_foo__1_sell_end", log_tickers=True),
998 ]) 998 ])
999 999
1000 self.assertEqual(5, run_action.call_count) 1000 self.assertEqual(5, run_action.call_count)
diff --git a/tests/test_store.py b/tests/test_store.py
index df113b7..12999d3 100644
--- a/tests/test_store.py
+++ b/tests/test_store.py
@@ -369,17 +369,27 @@ class BalanceStoreTest(WebMockTestCase):
369 369
370 balance_store = market.BalanceStore(self.m) 370 balance_store = market.BalanceStore(self.m)
371 371
372 balance_store.fetch_balances() 372 with self.subTest(log_tickers=False):
373 self.assertNotIn("ETC", balance_store.currencies()) 373 balance_store.fetch_balances()
374 self.assertListEqual(["USDT", "XVG", "XMR"], list(balance_store.currencies())) 374 self.assertNotIn("ETC", balance_store.currencies())
375 375 self.assertListEqual(["USDT", "XVG", "XMR"], list(balance_store.currencies()))
376 balance_store.all["ETC"] = portfolio.Balance("ETC", { 376
377 "exchange_total": "1", "exchange_free": "0", 377 balance_store.all["ETC"] = portfolio.Balance("ETC", {
378 "exchange_used": "1" }) 378 "exchange_total": "1", "exchange_free": "0",
379 balance_store.fetch_balances(tag="foo") 379 "exchange_used": "1" })
380 self.assertEqual(0, balance_store.all["ETC"].total) 380 balance_store.fetch_balances(tag="foo")
381 self.assertListEqual(["USDT", "XVG", "XMR", "ETC"], list(balance_store.currencies())) 381 self.assertEqual(0, balance_store.all["ETC"].total)
382 self.m.report.log_balances.assert_called_with(tag="foo") 382 self.assertListEqual(["USDT", "XVG", "XMR", "ETC"], list(balance_store.currencies()))
383 self.m.report.log_balances.assert_called_with(tag="foo")
384
385 with self.subTest(log_tickers=True),\
386 mock.patch.object(balance_store, "in_currency") as in_currency:
387 in_currency.return_value = "tickers"
388 balance_store.fetch_balances(log_tickers=True, ticker_currency="FOO",
389 ticker_compute_value="compute", ticker_type="type")
390 self.m.report.log_balances.assert_called_with(compute_value='compute',
391 tag=None, ticker_currency='FOO', tickers='tickers',
392 type='type')
383 393
384 @mock.patch.object(market.Portfolio, "repartition") 394 @mock.patch.object(market.Portfolio, "repartition")
385 def test_dispatch_assets(self, repartition): 395 def test_dispatch_assets(self, repartition):
@@ -586,27 +596,77 @@ class ReportStoreTest(WebMockTestCase):
586 self.m.balances.as_json.return_value = "json" 596 self.m.balances.as_json.return_value = "json"
587 self.m.balances.all = { "FOO": "bar", "BAR": "baz" } 597 self.m.balances.all = { "FOO": "bar", "BAR": "baz" }
588 598
589 report_store.log_balances(tag="tag") 599 with self.subTest(tickers=None):
590 print_log.assert_has_calls([ 600 report_store.log_balances(tag="tag")
591 mock.call("[Balance]"), 601 print_log.assert_has_calls([
592 mock.call("\tbar"), 602 mock.call("[Balance]"),
593 mock.call("\tbaz"), 603 mock.call("\tbar"),
594 ]) 604 mock.call("\tbaz"),
595 add_log.assert_called_once_with({ 605 ])
596 'type': 'balance', 606 add_log.assert_called_once_with({
597 'balances': 'json', 607 'type': 'balance',
598 'tag': 'tag' 608 'balances': 'json',
599 }) 609 'tag': 'tag'
600 add_redis_status.assert_called_once_with({ 610 })
601 'type': 'balance', 611 add_redis_status.assert_called_once_with({
602 'balances': 'json', 612 'type': 'balance',
603 'tag': 'tag' 613 'balances': 'json',
604 }) 614 'tag': 'tag'
615 })
616 add_log.reset_mock()
617 add_redis_status.reset_mock()
618 with self.subTest(tickers="present"):
619 amounts = {
620 "BTC": portfolio.Amount("BTC", 10),
621 "ETH": portfolio.Amount("BTC", D("0.3"))
622 }
623 amounts["ETH"].rate = D("0.1")
624
625 report_store.log_balances(tag="tag", tickers=amounts,
626 ticker_currency="BTC", compute_value="default",
627 type="total")
628 add_log.assert_called_once_with({
629 'type': 'balance',
630 'balances': 'json',
631 'tag': 'tag',
632 'tickers': {
633 'compute_value': 'default',
634 'balance_type': 'total',
635 'currency': 'BTC',
636 'balances': {
637 'BTC': D('10'),
638 'ETH': D('0.3')
639 },
640 'rates': {
641 'BTC': None,
642 'ETH': D('0.1')
643 },
644 'total': D('10.3')
645 },
646 })
647 add_redis_status.assert_called_once_with({
648 'type': 'balance',
649 'balances': 'json',
650 'tag': 'tag',
651 'tickers': {
652 'compute_value': 'default',
653 'balance_type': 'total',
654 'currency': 'BTC',
655 'balances': {
656 'BTC': D('10'),
657 'ETH': D('0.3')
658 },
659 'rates': {
660 'BTC': None,
661 'ETH': D('0.1')
662 },
663 'total': D('10.3')
664 },
665 })
605 666
606 @mock.patch.object(market.ReportStore, "print_log") 667 @mock.patch.object(market.ReportStore, "print_log")
607 @mock.patch.object(market.ReportStore, "add_log") 668 @mock.patch.object(market.ReportStore, "add_log")
608 @mock.patch.object(market.ReportStore, "add_redis_status") 669 def test_log_tickers(self, add_log, print_log):
609 def test_log_tickers(self, add_redis_status, add_log, print_log):
610 report_store = market.ReportStore(self.m) 670 report_store = market.ReportStore(self.m)
611 amounts = { 671 amounts = {
612 "BTC": portfolio.Amount("BTC", 10), 672 "BTC": portfolio.Amount("BTC", 10),
@@ -631,21 +691,6 @@ class ReportStoreTest(WebMockTestCase):
631 }, 691 },
632 'total': D('10.3') 692 'total': D('10.3')
633 }) 693 })
634 add_redis_status.assert_called_once_with({
635 'type': 'tickers',
636 'compute_value': 'default',
637 'balance_type': 'total',
638 'currency': 'BTC',
639 'balances': {
640 'BTC': D('10'),
641 'ETH': D('0.3')
642 },
643 'rates': {
644 'BTC': None,
645 'ETH': D('0.1')
646 },
647 'total': D('10.3')
648 })
649 694
650 add_log.reset_mock() 695 add_log.reset_mock()
651 compute_value = lambda x: x["bid"] 696 compute_value = lambda x: x["bid"]