aboutsummaryrefslogtreecommitdiff
path: root/market.py
diff options
context:
space:
mode:
authorIsmaël Bouya <ismael.bouya@normalesup.org>2018-04-21 00:43:24 +0200
committerIsmaël Bouya <ismael.bouya@normalesup.org>2018-04-21 00:43:24 +0200
commite8b0c21d62d72d955c21cb3047951433b1655745 (patch)
tree1191b8438f1f7d52aa7ef736ec2def0595e311d0 /market.py
parentbd559095622e4f654a54cf5054f77d9ebb42341b (diff)
parentc5ca26b83ca9f120fb39f1e61265216342f8a4db (diff)
downloadTrader-e8b0c21d62d72d955c21cb3047951433b1655745.tar.gz
Trader-e8b0c21d62d72d955c21cb3047951433b1655745.tar.zst
Trader-e8b0c21d62d72d955c21cb3047951433b1655745.zip
Merge branch 'dev'v1.3
Diffstat (limited to 'market.py')
-rw-r--r--market.py68
1 files changed, 42 insertions, 26 deletions
diff --git a/market.py b/market.py
index 7a37cf6..ce0c48c 100644
--- a/market.py
+++ b/market.py
@@ -2,6 +2,7 @@ from ccxt import ExchangeError, NotSupported, RequestTimeout, InvalidNonce
2import ccxt_wrapper as ccxt 2import ccxt_wrapper as ccxt
3import time 3import time
4import psycopg2 4import psycopg2
5import redis
5from store import * 6from store import *
6from cachetools.func import ttl_cache 7from cachetools.func import ttl_cache
7from datetime import datetime 8from 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 []