from ccxt import ExchangeError, NotSupported, RequestTimeout, InvalidNonce
import ccxt_wrapper as ccxt
import time
-import psycopg2
-import redis
+import dbs
from store import *
from cachetools.func import ttl_cache
from datetime import datetime
self.balances = BalanceStore(self)
self.processor = Processor(self)
- for key in ["user_id", "market_id", "pg_config", "redis_config"]:
+ for key in ["user_id", "market_id"]:
setattr(self, key, kwargs.get(key, None))
self.report.log_market(self.args)
date = datetime.datetime.now()
if self.args.report_path is not None:
self.store_file_report(date)
- if self.pg_config is not None and self.args.report_db:
+ if dbs.psql_connected() and self.args.report_db:
self.store_database_report(date)
- if self.redis_config is not None and self.args.report_redis:
+ if dbs.redis_connected() and self.args.report_redis:
self.store_redis_report(date)
def store_file_report(self, date):
try:
report_query = 'INSERT INTO reports("date", "market_config_id", "debug") VALUES (%s, %s, %s) RETURNING id;'
line_query = 'INSERT INTO report_lines("date", "report_id", "type", "payload") VALUES (%s, %s, %s, %s);'
- connection = psycopg2.connect(**self.pg_config)
- cursor = connection.cursor()
+ cursor = dbs.psql.cursor()
cursor.execute(report_query, (date, self.market_id, self.debug))
report_id = cursor.fetchone()[0]
for date, type_, payload in self.report.to_json_array():
cursor.execute(line_query, (date, report_id, type_, payload))
- connection.commit()
+ dbs.psql.commit()
cursor.close()
- connection.close()
except Exception as e:
print("impossible to store report to database: {}; {}".format(e.__class__.__name__, e))
def store_redis_report(self, date):
try:
- conn = redis.Redis(**self.redis_config)
for type_, log in self.report.to_json_redis():
key = "/cryptoportfolio/{}/{}/{}".format(self.market_id, date.isoformat(), type_)
- conn.set(key, log, ex=31*24*60*60)
+ dbs.redis.set(key, log, ex=31*24*60*60)
key = "/cryptoportfolio/{}/latest/{}".format(self.market_id, type_)
- conn.set(key, log)
+ dbs.redis.set(key, log)
+ key = "/cryptoportfolio/{}/latest/date".format(self.market_id)
+ dbs.redis.set(key, date.isoformat())
except Exception as e:
print("impossible to store report to redis: {}; {}".format(e.__class__.__name__, e))
elif after:
self.processor.process(action, steps="after")
except Exception as e:
- self.report.log_error("market_process", exception=e)
+ import traceback
+ self.report.log_error("market_process", exception=e, message=traceback.format_exc())
finally:
self.store_report()
if status == "error_disappeared":
self.report.log_error("follow_orders",
message="{} disappeared, recreating it".format(order))
- order.trade.prepare_order(
+ new_order = order.trade.prepare_order(
compute_value=order.trade.tick_actions_recreate(tick))
+ new_order.run()
+ self.report.log_order(order, tick, new_order=new_order)
self.report.log_stage("follow_orders_end")
def prepare_trades(self, base_currency="BTC", liquidity="medium",
- compute_value="average", repartition=None, only=None):
+ compute_value="average", repartition=None, only=None,
+ available_balance_only=False):
self.report.log_stage("prepare_trades",
base_currency=base_currency, liquidity=liquidity,
compute_value=compute_value, only=only,
- repartition=repartition)
+ repartition=repartition, available_balance_only=available_balance_only)
values_in_base = self.balances.in_currency(base_currency,
compute_value=compute_value)
- total_base_value = sum(values_in_base.values())
+ if available_balance_only:
+ balance = self.balances.all.get(base_currency)
+ if balance is None:
+ total_base_value = portfolio.Amount(base_currency, 0)
+ else:
+ total_base_value = balance.exchange_free + balance.margin_available
+ else:
+ total_base_value = sum(values_in_base.values())
new_repartition = self.balances.dispatch_assets(total_base_value,
liquidity=liquidity, repartition=repartition)
+ if available_balance_only:
+ for currency, amount in values_in_base.items():
+ if currency != base_currency:
+ new_repartition.setdefault(currency, portfolio.Amount(base_currency, 0))
+ new_repartition[currency] += amount
+
self.trades.compute_trades(values_in_base, new_repartition, only=only)
def print_tickers(self, base_currency="BTC"):
{
"name": "print_balances",
"number": 1,
- "fetch_balances": ["begin"],
+ "fetch_balances_begin": {
+ "log_tickers": True,
+ "add_usdt": True,
+ "add_portfolio": True
+ },
"print_tickers": { "base_currency": "BTC" },
}
],
"number": 2,
"before": False,
"after": True,
- "fetch_balances": ["begin"],
+ "fetch_balances_begin": {},
"prepare_trades": { "compute_value": "average" },
"prepare_orders": { "compute_value": "average" },
},
],
"sell_needed": [
{
- "name": "wait",
+ "name": "print_balances",
"number": 0,
+ "before": True,
+ "after": False,
+ "fetch_balances_begin": {
+ "checkpoint": "end",
+ "log_tickers": True,
+ "add_usdt": True,
+ "add_portfolio": True
+ },
+ },
+ {
+ "name": "wait",
+ "number": 1,
"before": False,
"after": True,
"wait_for_recent": {},
},
{
"name": "sell",
- "number": 1,
+ "number": 2,
"before": False,
"after": True,
- "fetch_balances": ["begin", "end"],
+ "fetch_balances_begin": {},
+ "fetch_balances_end": {},
"prepare_trades": {},
"prepare_orders": { "only": "dispose", "compute_value": "average" },
"run_orders": {},
},
{
"name": "buy",
- "number": 2,
+ "number": 3,
"before": False,
"after": True,
- "fetch_balances": ["begin", "end"],
- "prepare_trades": { "only": "acquire" },
+ "fetch_balances_begin": {},
+ "fetch_balances_end": {
+ "checkpoint": "begin",
+ "add_usdt": True,
+ "log_tickers": True
+ },
+ "prepare_trades": { "only": "acquire", "available_balance_only": True },
"prepare_orders": { "only": "acquire", "compute_value": "average" },
"move_balances": {},
"run_orders": {},
"number": 1,
"before": True,
"after": False,
- "fetch_balances": ["begin", "end"],
+ "fetch_balances_begin": {
+ "checkpoint": "end",
+ "log_tickers": True,
+ "add_usdt": True,
+ "add_portfolio": True
+ },
+ "fetch_balances_end": {},
"prepare_trades": { "repartition": { "base_currency": (1, "long") } },
"prepare_orders": { "compute_value": "average" },
"run_orders": {},
"number": 3,
"before": False,
"after": True,
- "fetch_balances": ["begin", "end"],
- "prepare_trades": {},
+ "fetch_balances_begin": {},
+ "fetch_balances_end": {
+ "checkpoint": "begin",
+ "add_usdt": True,
+ "log_tickers": True
+ },
+ "prepare_trades": { "available_balance_only": True },
"prepare_orders": { "compute_value": "average" },
"move_balances": {},
"run_orders": {},
def process_step(self, scenario_name, step, kwargs):
process_name = "process_{}__{}_{}".format(scenario_name, step["number"], step["name"])
self.market.report.log_stage("{}_begin".format(process_name))
- if "begin" in step.get("fetch_balances", []):
- self.market.balances.fetch_balances(tag="{}_begin".format(process_name))
+
+ if "fetch_balances_begin" in step:
+ self.market.balances.fetch_balances(tag="{}_begin".format(process_name),
+ **step["fetch_balances_begin"])
for action in self.ordered_actions:
if action in step:
self.run_action(action, step[action], kwargs)
- if "end" in step.get("fetch_balances", []):
- self.market.balances.fetch_balances(tag="{}_end".format(process_name))
+ if "fetch_balances_end" in step:
+ self.market.balances.fetch_balances(tag="{}_end".format(process_name),
+ **step["fetch_balances_end"])
+
self.market.report.log_stage("{}_end".format(process_name))
def method_arguments(self, action):