diff options
author | Ismaël Bouya <ismael.bouya@normalesup.org> | 2018-04-21 00:43:24 +0200 |
---|---|---|
committer | Ismaël Bouya <ismael.bouya@normalesup.org> | 2018-04-21 00:43:24 +0200 |
commit | e8b0c21d62d72d955c21cb3047951433b1655745 (patch) | |
tree | 1191b8438f1f7d52aa7ef736ec2def0595e311d0 /market.py | |
parent | bd559095622e4f654a54cf5054f77d9ebb42341b (diff) | |
parent | c5ca26b83ca9f120fb39f1e61265216342f8a4db (diff) | |
download | Trader-e8b0c21d62d72d955c21cb3047951433b1655745.tar.gz Trader-e8b0c21d62d72d955c21cb3047951433b1655745.tar.zst Trader-e8b0c21d62d72d955c21cb3047951433b1655745.zip |
Merge branch 'dev'v1.3
Diffstat (limited to 'market.py')
-rw-r--r-- | market.py | 68 |
1 files changed, 42 insertions, 26 deletions
@@ -2,6 +2,7 @@ from ccxt import ExchangeError, NotSupported, RequestTimeout, InvalidNonce | |||
2 | import ccxt_wrapper as ccxt | 2 | import ccxt_wrapper as ccxt |
3 | import time | 3 | import time |
4 | import psycopg2 | 4 | import psycopg2 |
5 | import redis | ||
5 | from store import * | 6 | from store import * |
6 | from cachetools.func import ttl_cache | 7 | from cachetools.func import ttl_cache |
7 | from datetime import datetime | 8 | from datetime import datetime |
@@ -26,7 +27,7 @@ class Market: | |||
26 | self.balances = BalanceStore(self) | 27 | self.balances = BalanceStore(self) |
27 | self.processor = Processor(self) | 28 | self.processor = Processor(self) |
28 | 29 | ||
29 | for key in ["user_id", "market_id", "pg_config"]: | 30 | for key in ["user_id", "market_id", "pg_config", "redis_config"]: |
30 | setattr(self, key, kwargs.get(key, None)) | 31 | setattr(self, key, kwargs.get(key, None)) |
31 | 32 | ||
32 | self.report.log_market(self.args) | 33 | self.report.log_market(self.args) |
@@ -46,6 +47,8 @@ class Market: | |||
46 | self.store_file_report(date) | 47 | self.store_file_report(date) |
47 | if self.pg_config is not None and self.args.report_db: | 48 | if self.pg_config is not None and self.args.report_db: |
48 | self.store_database_report(date) | 49 | self.store_database_report(date) |
50 | if self.redis_config is not None and self.args.report_redis: | ||
51 | self.store_redis_report(date) | ||
49 | 52 | ||
50 | def store_file_report(self, date): | 53 | def store_file_report(self, date): |
51 | try: | 54 | try: |
@@ -74,19 +77,26 @@ class Market: | |||
74 | except Exception as e: | 77 | except Exception as e: |
75 | print("impossible to store report to database: {}; {}".format(e.__class__.__name__, e)) | 78 | print("impossible to store report to database: {}; {}".format(e.__class__.__name__, e)) |
76 | 79 | ||
80 | def store_redis_report(self, date): | ||
81 | try: | ||
82 | conn = redis.Redis(**self.redis_config) | ||
83 | for type_, log in self.report.to_json_redis(): | ||
84 | key = "/cryptoportfolio/{}/{}/{}".format(self.market_id, date.isoformat(), type_) | ||
85 | conn.set(key, log, ex=31*24*60*60) | ||
86 | key = "/cryptoportfolio/{}/latest/{}".format(self.market_id, type_) | ||
87 | conn.set(key, log) | ||
88 | except Exception as e: | ||
89 | print("impossible to store report to redis: {}; {}".format(e.__class__.__name__, e)) | ||
90 | |||
77 | def process(self, actions, before=False, after=False): | 91 | def process(self, actions, before=False, after=False): |
78 | try: | 92 | try: |
79 | if len(actions or []) == 0: | 93 | for action in actions: |
80 | if before: | 94 | if bool(before) is bool(after): |
81 | self.processor.process("sell_all", steps="before") | 95 | self.processor.process(action, steps="all") |
82 | if after: | 96 | elif before: |
83 | self.processor.process("sell_all", steps="after") | 97 | self.processor.process(action, steps="before") |
84 | else: | 98 | elif after: |
85 | for action in actions: | 99 | self.processor.process(action, steps="after") |
86 | if hasattr(self, action): | ||
87 | getattr(self, action)() | ||
88 | else: | ||
89 | self.report.log_error("market_process", message="Unknown action {}".format(action)) | ||
90 | except Exception as e: | 100 | except Exception as e: |
91 | self.report.log_error("market_process", exception=e) | 101 | self.report.log_error("market_process", exception=e) |
92 | finally: | 102 | finally: |
@@ -212,16 +222,7 @@ class Market: | |||
212 | liquidity=liquidity, repartition=repartition) | 222 | liquidity=liquidity, repartition=repartition) |
213 | self.trades.compute_trades(values_in_base, new_repartition, only=only) | 223 | self.trades.compute_trades(values_in_base, new_repartition, only=only) |
214 | 224 | ||
215 | # Helpers | 225 | def print_tickers(self, base_currency="BTC"): |
216 | def print_orders(self, base_currency="BTC"): | ||
217 | self.report.log_stage("print_orders") | ||
218 | self.balances.fetch_balances(tag="print_orders") | ||
219 | self.prepare_trades(base_currency=base_currency, compute_value="average") | ||
220 | self.trades.prepare_orders(compute_value="average") | ||
221 | |||
222 | def print_balances(self, base_currency="BTC"): | ||
223 | self.report.log_stage("print_balances") | ||
224 | self.balances.fetch_balances() | ||
225 | if base_currency is not None: | 226 | if base_currency is not None: |
226 | self.report.print_log("total:") | 227 | self.report.print_log("total:") |
227 | self.report.print_log(sum(self.balances.in_currency(base_currency).values())) | 228 | self.report.print_log(sum(self.balances.in_currency(base_currency).values())) |
@@ -237,12 +238,20 @@ class Processor: | |||
237 | "wait_for_recent": {}, | 238 | "wait_for_recent": {}, |
238 | }, | 239 | }, |
239 | ], | 240 | ], |
241 | "print_balances": [ | ||
242 | { | ||
243 | "name": "print_balances", | ||
244 | "number": 1, | ||
245 | "fetch_balances": ["begin"], | ||
246 | "print_tickers": { "base_currency": "BTC" }, | ||
247 | } | ||
248 | ], | ||
240 | "print_orders": [ | 249 | "print_orders": [ |
241 | { | 250 | { |
242 | "name": "wait", | 251 | "name": "wait", |
243 | "number": 1, | 252 | "number": 1, |
244 | "before": False, | 253 | "before": True, |
245 | "after": True, | 254 | "after": False, |
246 | "wait_for_recent": {}, | 255 | "wait_for_recent": {}, |
247 | }, | 256 | }, |
248 | { | 257 | { |
@@ -328,7 +337,7 @@ class Processor: | |||
328 | ordered_actions = [ | 337 | ordered_actions = [ |
329 | "wait_for_recent", "prepare_trades", "prepare_orders", | 338 | "wait_for_recent", "prepare_trades", "prepare_orders", |
330 | "move_balances", "run_orders", "follow_orders", | 339 | "move_balances", "run_orders", "follow_orders", |
331 | "close_trades"] | 340 | "close_trades", "print_tickers"] |
332 | 341 | ||
333 | def __init__(self, market): | 342 | def __init__(self, market): |
334 | self.market = market | 343 | self.market = market |
@@ -337,7 +346,7 @@ class Processor: | |||
337 | if step == "all": | 346 | if step == "all": |
338 | return scenario | 347 | return scenario |
339 | elif step == "before" or step == "after": | 348 | elif step == "before" or step == "after": |
340 | return list(filter(lambda x: step in x and x[step], scenario)) | 349 | return list(filter(lambda x: x.get(step, False), scenario)) |
341 | elif type(step) == int: | 350 | elif type(step) == int: |
342 | return [scenario[step-1]] | 351 | return [scenario[step-1]] |
343 | elif type(step) == str: | 352 | elif type(step) == str: |
@@ -345,7 +354,12 @@ class Processor: | |||
345 | else: | 354 | else: |
346 | raise TypeError("Unknown step {}".format(step)) | 355 | raise TypeError("Unknown step {}".format(step)) |
347 | 356 | ||
357 | def can_process(self, scenario_name): | ||
358 | return scenario_name in self.scenarios | ||
359 | |||
348 | def process(self, scenario_name, steps="all", **kwargs): | 360 | def process(self, scenario_name, steps="all", **kwargs): |
361 | if not self.can_process(scenario_name): | ||
362 | raise TypeError("Unknown scenario {}".format(scenario_name)) | ||
349 | scenario = self.scenarios[scenario_name] | 363 | scenario = self.scenarios[scenario_name] |
350 | selected_steps = [] | 364 | selected_steps = [] |
351 | 365 | ||
@@ -388,6 +402,8 @@ class Processor: | |||
388 | method = self.market.follow_orders | 402 | method = self.market.follow_orders |
389 | elif action == "close_trades": | 403 | elif action == "close_trades": |
390 | method = self.market.trades.close_trades | 404 | method = self.market.trades.close_trades |
405 | elif action == "print_tickers": | ||
406 | method = self.market.print_tickers | ||
391 | 407 | ||
392 | signature = inspect.getfullargspec(method) | 408 | signature = inspect.getfullargspec(method) |
393 | defaults = signature.defaults or [] | 409 | defaults = signature.defaults or [] |