X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=portfolio.py;h=69e37557fd9cd355fbdccabcd1fb993fbf9adef1;hb=83c698c925db9dcb2d347c2a625de88d85cfeb21;hp=65fdc6cf1a7b5bbb52bf60630112d5fb4e1b7243;hpb=186f7d816a6bfc4fbf64027c3d7ecea10b97db38;p=perso%2FImmae%2FProjets%2FCryptomonnaies%2FCryptoportfolio%2FTrader.git diff --git a/portfolio.py b/portfolio.py index 65fdc6c..69e3755 100644 --- a/portfolio.py +++ b/portfolio.py @@ -1,87 +1,10 @@ -import time -from datetime import datetime, timedelta +from datetime import datetime from decimal import Decimal as D, ROUND_DOWN -from json import JSONDecodeError -from simplejson.errors import JSONDecodeError as SimpleJSONDecodeError from ccxt import ExchangeError, InsufficientFunds, ExchangeNotAvailable, InvalidOrder, OrderNotCached, OrderNotFound from retry import retry -import requests # FIXME: correctly handle web call timeouts -class Portfolio: - URL = "https://cryptoportfolio.io/wp-content/uploads/portfolio/json/cryptoportfolio.json" - liquidities = {} - data = None - last_date = None - - @classmethod - def wait_for_recent(cls, market, delta=4): - cls.repartition(market, refetch=True) - while cls.last_date is None or datetime.now() - cls.last_date > timedelta(delta): - time.sleep(30) - market.report.print_log("Attempt to fetch up-to-date cryptoportfolio") - cls.repartition(market, refetch=True) - - @classmethod - def repartition(cls, market, liquidity="medium", refetch=False): - cls.parse_cryptoportfolio(market, refetch=refetch) - liquidities = cls.liquidities[liquidity] - return liquidities[cls.last_date] - - @classmethod - def get_cryptoportfolio(cls, market): - try: - r = requests.get(cls.URL) - market.report.log_http_request(r.request.method, - r.request.url, r.request.body, r.request.headers, r) - except Exception as e: - market.report.log_error("get_cryptoportfolio", exception=e) - return - try: - cls.data = r.json(parse_int=D, parse_float=D) - except (JSONDecodeError, SimpleJSONDecodeError): - cls.data = None - - @classmethod - def parse_cryptoportfolio(cls, market, refetch=False): - if refetch or cls.data is None: - cls.get_cryptoportfolio(market) - - def filter_weights(weight_hash): - if weight_hash[1][0] == 0: - return False - if weight_hash[0] == "_row": - return False - return True - - def clean_weights(i): - def clean_weights_(h): - if h[0].endswith("s"): - return [h[0][0:-1], (h[1][i], "short")] - else: - return [h[0], (h[1][i], "long")] - return clean_weights_ - - def parse_weights(portfolio_hash): - weights_hash = portfolio_hash["weights"] - weights = {} - for i in range(len(weights_hash["_row"])): - date = datetime.strptime(weights_hash["_row"][i], "%Y-%m-%d") - weights[date] = dict(filter( - filter_weights, - map(clean_weights(i), weights_hash.items()))) - return weights - - high_liquidity = parse_weights(cls.data["portfolio_1"]) - medium_liquidity = parse_weights(cls.data["portfolio_2"]) - - cls.liquidities = { - "medium": medium_liquidity, - "high": high_liquidity, - } - cls.last_date = max(max(medium_liquidity.keys()), max(high_liquidity.keys())) - class Computation: computations = { "default": lambda x, y: x[y], @@ -550,7 +473,7 @@ class Order: @property def finished(self): - return self.status == "closed" or self.status == "canceled" or self.status == "error" + return self.status.startswith("closed") or self.status == "canceled" or self.status == "error" @retry(InsufficientFunds) def run(self): @@ -594,15 +517,13 @@ class Order: # other states are "closed" and "canceled" if not self.finished: self.fetch() - if self.finished: - self.mark_finished_order() return self.status def mark_finished_order(self): - if self.market.debug: + if self.status.startswith("closed") and self.market.debug: self.market.report.log_debug_action("Mark {} as finished".format(self)) return - if self.status == "closed": + if self.status.startswith("closed"): if self.trade_type == "short" and self.action == "buy" and self.close_if_possible: self.market.ccxt.close_margin_position(self.amount.currency, self.base_currency) @@ -621,6 +542,7 @@ class Order: self.fetch_mouvements() + self.mark_finished_order() # FIXME: consider open order with dust remaining as closed def dust_amount_remaining(self):