aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.py8
-rw-r--r--market.py11
-rw-r--r--test.py51
3 files changed, 43 insertions, 27 deletions
diff --git a/main.py b/main.py
index 856d449..55981bf 100644
--- a/main.py
+++ b/main.py
@@ -63,7 +63,8 @@ def make_order(market, value, currency, action="acquire",
63def get_user_market(config_path, user_id, debug=False): 63def get_user_market(config_path, user_id, debug=False):
64 pg_config, report_path = parse_config(config_path) 64 pg_config, report_path = parse_config(config_path)
65 market_config = list(fetch_markets(pg_config, str(user_id)))[0][0] 65 market_config = list(fetch_markets(pg_config, str(user_id)))[0][0]
66 return market.Market.from_config(market_config, debug=debug) 66 args = type('Args', (object,), { "debug": debug, "quiet": False })()
67 return market.Market.from_config(market_config, args, user_id=user_id, report_path=report_path)
67 68
68def fetch_markets(pg_config, user): 69def fetch_markets(pg_config, user):
69 connection = psycopg2.connect(**pg_config) 70 connection = psycopg2.connect(**pg_config)
@@ -109,6 +110,9 @@ def parse_args(argv):
109 parser.add_argument("--after", 110 parser.add_argument("--after",
110 default=False, action='store_const', const=True, 111 default=False, action='store_const', const=True,
111 help="Run the steps after the cryptoportfolio update") 112 help="Run the steps after the cryptoportfolio update")
113 parser.add_argument("--quiet",
114 default=False, action='store_const', const=True,
115 help="Don't print messages")
112 parser.add_argument("--debug", 116 parser.add_argument("--debug",
113 default=False, action='store_const', const=True, 117 default=False, action='store_const', const=True,
114 help="Run in debug mode") 118 help="Run in debug mode")
@@ -131,7 +135,7 @@ def parse_args(argv):
131def process(market_config, user_id, report_path, args): 135def process(market_config, user_id, report_path, args):
132 try: 136 try:
133 market.Market\ 137 market.Market\
134 .from_config(market_config, debug=args.debug, user_id=user_id, report_path=report_path)\ 138 .from_config(market_config, args, user_id=user_id, report_path=report_path)\
135 .process(args.action, before=args.before, after=args.after) 139 .process(args.action, before=args.before, after=args.after)
136 except Exception as e: 140 except Exception as e:
137 print("{}: {}".format(e.__class__.__name__, e)) 141 print("{}: {}".format(e.__class__.__name__, e))
diff --git a/market.py b/market.py
index 2ddebfa..fc5832c 100644
--- a/market.py
+++ b/market.py
@@ -13,11 +13,12 @@ class Market:
13 trades = None 13 trades = None
14 balances = None 14 balances = None
15 15
16 def __init__(self, ccxt_instance, debug=False, user_id=None, report_path=None): 16 def __init__(self, ccxt_instance, args, user_id=None, report_path=None):
17 self.debug = debug 17 self.args = args
18 self.debug = args.debug
18 self.ccxt = ccxt_instance 19 self.ccxt = ccxt_instance
19 self.ccxt._market = self 20 self.ccxt._market = self
20 self.report = ReportStore(self) 21 self.report = ReportStore(self, verbose_print=(not args.quiet))
21 self.trades = TradeStore(self) 22 self.trades = TradeStore(self)
22 self.balances = BalanceStore(self) 23 self.balances = BalanceStore(self)
23 self.processor = Processor(self) 24 self.processor = Processor(self)
@@ -26,7 +27,7 @@ class Market:
26 self.report_path = report_path 27 self.report_path = report_path
27 28
28 @classmethod 29 @classmethod
29 def from_config(cls, config, debug=False, user_id=None, report_path=None): 30 def from_config(cls, config, args, user_id=None, report_path=None):
30 config["apiKey"] = config.pop("key", None) 31 config["apiKey"] = config.pop("key", None)
31 32
32 ccxt_instance = ccxt.poloniexE(config) 33 ccxt_instance = ccxt.poloniexE(config)
@@ -43,7 +44,7 @@ class Market:
43 ccxt_instance.session.request = request_wrap.__get__(ccxt_instance.session, 44 ccxt_instance.session.request = request_wrap.__get__(ccxt_instance.session,
44 ccxt_instance.session.__class__) 45 ccxt_instance.session.__class__)
45 46
46 return cls(ccxt_instance, debug=debug, user_id=user_id, report_path=report_path) 47 return cls(ccxt_instance, args, user_id=user_id, report_path=report_path)
47 48
48 def store_report(self): 49 def store_report(self):
49 self.report.merge(Portfolio.report) 50 self.report.merge(Portfolio.report)
diff --git a/test.py b/test.py
index 13bd332..3ee34c6 100644
--- a/test.py
+++ b/test.py
@@ -23,6 +23,9 @@ for test_type in limits:
23class WebMockTestCase(unittest.TestCase): 23class WebMockTestCase(unittest.TestCase):
24 import time 24 import time
25 25
26 def market_args(self, debug=False, quiet=False):
27 return type('Args', (object,), { "debug": debug, "quiet": quiet })()
28
26 def setUp(self): 29 def setUp(self):
27 super(WebMockTestCase, self).setUp() 30 super(WebMockTestCase, self).setUp()
28 self.wm = requests_mock.Mocker() 31 self.wm = requests_mock.Mocker()
@@ -1092,7 +1095,7 @@ class MarketTest(WebMockTestCase):
1092 self.ccxt = mock.Mock(spec=market.ccxt.poloniexE) 1095 self.ccxt = mock.Mock(spec=market.ccxt.poloniexE)
1093 1096
1094 def test_values(self): 1097 def test_values(self):
1095 m = market.Market(self.ccxt) 1098 m = market.Market(self.ccxt, self.market_args())
1096 1099
1097 self.assertEqual(self.ccxt, m.ccxt) 1100 self.assertEqual(self.ccxt, m.ccxt)
1098 self.assertFalse(m.debug) 1101 self.assertFalse(m.debug)
@@ -1104,19 +1107,27 @@ class MarketTest(WebMockTestCase):
1104 self.assertEqual(m, m.balances.market) 1107 self.assertEqual(m, m.balances.market)
1105 self.assertEqual(m, m.ccxt._market) 1108 self.assertEqual(m, m.ccxt._market)
1106 1109
1107 m = market.Market(self.ccxt, debug=True) 1110 m = market.Market(self.ccxt, self.market_args(debug=True))
1108 self.assertTrue(m.debug) 1111 self.assertTrue(m.debug)
1109 1112
1110 m = market.Market(self.ccxt, debug=False) 1113 m = market.Market(self.ccxt, self.market_args(debug=False))
1111 self.assertFalse(m.debug) 1114 self.assertFalse(m.debug)
1112 1115
1116 with mock.patch("market.ReportStore") as report_store:
1117 with self.subTest(quiet=False):
1118 m = market.Market(self.ccxt, self.market_args(quiet=False))
1119 report_store.assert_called_with(m, verbose_print=True)
1120 with self.subTest(quiet=True):
1121 m = market.Market(self.ccxt, self.market_args(quiet=True))
1122 report_store.assert_called_with(m, verbose_print=False)
1123
1113 @mock.patch("market.ccxt") 1124 @mock.patch("market.ccxt")
1114 def test_from_config(self, ccxt): 1125 def test_from_config(self, ccxt):
1115 with mock.patch("market.ReportStore"): 1126 with mock.patch("market.ReportStore"):
1116 ccxt.poloniexE.return_value = self.ccxt 1127 ccxt.poloniexE.return_value = self.ccxt
1117 self.ccxt.session.request.return_value = "response" 1128 self.ccxt.session.request.return_value = "response"
1118 1129
1119 m = market.Market.from_config({"key": "key", "secred": "secret"}) 1130 m = market.Market.from_config({"key": "key", "secred": "secret"}, self.market_args())
1120 1131
1121 self.assertEqual(self.ccxt, m.ccxt) 1132 self.assertEqual(self.ccxt, m.ccxt)
1122 1133
@@ -1125,7 +1136,7 @@ class MarketTest(WebMockTestCase):
1125 m.report.log_http_request.assert_called_with('GET', 'URL', 'data', 1136 m.report.log_http_request.assert_called_with('GET', 'URL', 'data',
1126 'headers', 'response') 1137 'headers', 'response')
1127 1138
1128 m = market.Market.from_config({"key": "key", "secred": "secret"}, debug=True) 1139 m = market.Market.from_config({"key": "key", "secred": "secret"}, self.market_args(debug=True))
1129 self.assertEqual(True, m.debug) 1140 self.assertEqual(True, m.debug)
1130 1141
1131 def test_get_tickers(self): 1142 def test_get_tickers(self):
@@ -1134,7 +1145,7 @@ class MarketTest(WebMockTestCase):
1134 market.NotSupported 1145 market.NotSupported
1135 ] 1146 ]
1136 1147
1137 m = market.Market(self.ccxt) 1148 m = market.Market(self.ccxt, self.market_args())
1138 self.assertEqual("tickers", m.get_tickers()) 1149 self.assertEqual("tickers", m.get_tickers())
1139 self.assertEqual("tickers", m.get_tickers()) 1150 self.assertEqual("tickers", m.get_tickers())
1140 self.ccxt.fetch_tickers.assert_called_once() 1151 self.ccxt.fetch_tickers.assert_called_once()
@@ -1147,7 +1158,7 @@ class MarketTest(WebMockTestCase):
1147 "ETH/ETC": { "bid": 1, "ask": 3 }, 1158 "ETH/ETC": { "bid": 1, "ask": 3 },
1148 "XVG/ETH": { "bid": 10, "ask": 40 }, 1159 "XVG/ETH": { "bid": 10, "ask": 40 },
1149 } 1160 }
1150 m = market.Market(self.ccxt) 1161 m = market.Market(self.ccxt, self.market_args())
1151 1162
1152 ticker = m.get_ticker("ETH", "ETC") 1163 ticker = m.get_ticker("ETH", "ETC")
1153 self.assertEqual(1, ticker["bid"]) 1164 self.assertEqual(1, ticker["bid"])
@@ -1175,7 +1186,7 @@ class MarketTest(WebMockTestCase):
1175 market.ExchangeError("foo"), 1186 market.ExchangeError("foo"),
1176 ] 1187 ]
1177 1188
1178 m = market.Market(self.ccxt) 1189 m = market.Market(self.ccxt, self.market_args())
1179 1190
1180 ticker = m.get_ticker("ETH", "ETC") 1191 ticker = m.get_ticker("ETH", "ETC")
1181 self.ccxt.fetch_ticker.assert_called_with("ETH/ETC") 1192 self.ccxt.fetch_ticker.assert_called_with("ETH/ETC")
@@ -1195,7 +1206,7 @@ class MarketTest(WebMockTestCase):
1195 self.assertIsNone(ticker) 1206 self.assertIsNone(ticker)
1196 1207
1197 def test_fetch_fees(self): 1208 def test_fetch_fees(self):
1198 m = market.Market(self.ccxt) 1209 m = market.Market(self.ccxt, self.market_args())
1199 self.ccxt.fetch_fees.return_value = "Foo" 1210 self.ccxt.fetch_fees.return_value = "Foo"
1200 self.assertEqual("Foo", m.fetch_fees()) 1211 self.assertEqual("Foo", m.fetch_fees())
1201 self.ccxt.fetch_fees.assert_called_once() 1212 self.ccxt.fetch_fees.assert_called_once()
@@ -1222,7 +1233,7 @@ class MarketTest(WebMockTestCase):
1222 get_ticker.side_effect = _get_ticker 1233 get_ticker.side_effect = _get_ticker
1223 1234
1224 with mock.patch("market.ReportStore"): 1235 with mock.patch("market.ReportStore"):
1225 m = market.Market(self.ccxt) 1236 m = market.Market(self.ccxt, self.market_args())
1226 self.ccxt.fetch_all_balances.return_value = { 1237 self.ccxt.fetch_all_balances.return_value = {
1227 "USDT": { 1238 "USDT": {
1228 "exchange_free": D("10000.0"), 1239 "exchange_free": D("10000.0"),
@@ -1262,7 +1273,7 @@ class MarketTest(WebMockTestCase):
1262 (False, 12), (True, 12)]: 1273 (False, 12), (True, 12)]:
1263 with self.subTest(sleep=sleep, debug=debug), \ 1274 with self.subTest(sleep=sleep, debug=debug), \
1264 mock.patch("market.ReportStore"): 1275 mock.patch("market.ReportStore"):
1265 m = market.Market(self.ccxt, debug=debug) 1276 m = market.Market(self.ccxt, self.market_args(debug=debug))
1266 1277
1267 order_mock1 = mock.Mock() 1278 order_mock1 = mock.Mock()
1268 order_mock2 = mock.Mock() 1279 order_mock2 = mock.Mock()
@@ -1339,7 +1350,7 @@ class MarketTest(WebMockTestCase):
1339 for debug in [True, False]: 1350 for debug in [True, False]:
1340 with self.subTest(debug=debug),\ 1351 with self.subTest(debug=debug),\
1341 mock.patch("market.ReportStore"): 1352 mock.patch("market.ReportStore"):
1342 m = market.Market(self.ccxt, debug=debug) 1353 m = market.Market(self.ccxt, self.market_args(debug=debug))
1343 1354
1344 value_from = portfolio.Amount("BTC", "1.0") 1355 value_from = portfolio.Amount("BTC", "1.0")
1345 value_from.linked_to = portfolio.Amount("ETH", "10.0") 1356 value_from.linked_to = portfolio.Amount("ETH", "10.0")
@@ -1378,7 +1389,7 @@ class MarketTest(WebMockTestCase):
1378 def test_store_report(self): 1389 def test_store_report(self):
1379 1390
1380 file_open = mock.mock_open() 1391 file_open = mock.mock_open()
1381 m = market.Market(self.ccxt, user_id=1) 1392 m = market.Market(self.ccxt, self.market_args(), user_id=1)
1382 with self.subTest(file=None),\ 1393 with self.subTest(file=None),\
1383 mock.patch.object(m, "report") as report,\ 1394 mock.patch.object(m, "report") as report,\
1384 mock.patch("market.open", file_open): 1395 mock.patch("market.open", file_open):
@@ -1388,7 +1399,7 @@ class MarketTest(WebMockTestCase):
1388 1399
1389 report.reset_mock() 1400 report.reset_mock()
1390 file_open = mock.mock_open() 1401 file_open = mock.mock_open()
1391 m = market.Market(self.ccxt, report_path="present", user_id=1) 1402 m = market.Market(self.ccxt, self.market_args(), report_path="present", user_id=1)
1392 with self.subTest(file="present"),\ 1403 with self.subTest(file="present"),\
1393 mock.patch("market.open", file_open),\ 1404 mock.patch("market.open", file_open),\
1394 mock.patch.object(m, "report") as report,\ 1405 mock.patch.object(m, "report") as report,\
@@ -1409,7 +1420,7 @@ class MarketTest(WebMockTestCase):
1409 1420
1410 report.reset_mock() 1421 report.reset_mock()
1411 1422
1412 m = market.Market(self.ccxt, report_path="error", user_id=1) 1423 m = market.Market(self.ccxt, self.market_args(), report_path="error", user_id=1)
1413 with self.subTest(file="error"),\ 1424 with self.subTest(file="error"),\
1414 mock.patch("market.open") as file_open,\ 1425 mock.patch("market.open") as file_open,\
1415 mock.patch.object(m, "report") as report,\ 1426 mock.patch.object(m, "report") as report,\
@@ -1422,7 +1433,7 @@ class MarketTest(WebMockTestCase):
1422 self.assertRegex(stdout_mock.getvalue(), "impossible to store report file: FileNotFoundError;") 1433 self.assertRegex(stdout_mock.getvalue(), "impossible to store report file: FileNotFoundError;")
1423 1434
1424 def test_print_orders(self): 1435 def test_print_orders(self):
1425 m = market.Market(self.ccxt) 1436 m = market.Market(self.ccxt, self.market_args())
1426 with mock.patch.object(m.report, "log_stage") as log_stage,\ 1437 with mock.patch.object(m.report, "log_stage") as log_stage,\
1427 mock.patch.object(m.balances, "fetch_balances") as fetch_balances,\ 1438 mock.patch.object(m.balances, "fetch_balances") as fetch_balances,\
1428 mock.patch.object(m, "prepare_trades") as prepare_trades,\ 1439 mock.patch.object(m, "prepare_trades") as prepare_trades,\
@@ -1436,7 +1447,7 @@ class MarketTest(WebMockTestCase):
1436 prepare_orders.assert_called_with(compute_value="average") 1447 prepare_orders.assert_called_with(compute_value="average")
1437 1448
1438 def test_print_balances(self): 1449 def test_print_balances(self):
1439 m = market.Market(self.ccxt) 1450 m = market.Market(self.ccxt, self.market_args())
1440 1451
1441 with mock.patch.object(m.balances, "in_currency") as in_currency,\ 1452 with mock.patch.object(m.balances, "in_currency") as in_currency,\
1442 mock.patch.object(m.report, "log_stage") as log_stage,\ 1453 mock.patch.object(m.report, "log_stage") as log_stage,\
@@ -1461,7 +1472,7 @@ class MarketTest(WebMockTestCase):
1461 @mock.patch("market.ReportStore.log_error") 1472 @mock.patch("market.ReportStore.log_error")
1462 @mock.patch("market.Market.store_report") 1473 @mock.patch("market.Market.store_report")
1463 def test_process(self, store_report, log_error, process): 1474 def test_process(self, store_report, log_error, process):
1464 m = market.Market(self.ccxt) 1475 m = market.Market(self.ccxt, self.market_args())
1465 with self.subTest(before=False, after=False): 1476 with self.subTest(before=False, after=False):
1466 m.process(None) 1477 m.process(None)
1467 1478
@@ -3571,7 +3582,7 @@ class MainTest(WebMockTestCase):
3571 main.process("config", 1, "report_path", args_mock) 3582 main.process("config", 1, "report_path", args_mock)
3572 3583
3573 market_mock.from_config.assert_has_calls([ 3584 market_mock.from_config.assert_has_calls([
3574 mock.call("config", debug="debug", user_id=1, report_path="report_path"), 3585 mock.call("config", args_mock, user_id=1, report_path="report_path"),
3575 mock.call().process("action", before="before", after="after"), 3586 mock.call().process("action", before="before", after="after"),
3576 ]) 3587 ])
3577 3588
@@ -3797,7 +3808,7 @@ class ProcessorTest(WebMockTestCase):
3797 3808
3798 def test_method_arguments(self): 3809 def test_method_arguments(self):
3799 ccxt = mock.Mock(spec=market.ccxt.poloniexE) 3810 ccxt = mock.Mock(spec=market.ccxt.poloniexE)
3800 m = market.Market(ccxt) 3811 m = market.Market(ccxt, self.market_args())
3801 3812
3802 processor = market.Processor(m) 3813 processor = market.Processor(m)
3803 3814