diff --git a/freqtrade/data/history.py b/freqtrade/data/history.py index cbae01152..46da37f3c 100644 --- a/freqtrade/data/history.py +++ b/freqtrade/data/history.py @@ -83,15 +83,15 @@ def store_tickerdata_file(datadir: Path, pair: str, def load_trades_file(datadir: Optional[Path], pair: str, - timerange: Optional[TimeRange] = None) -> Optional[list]: + timerange: Optional[TimeRange] = None) -> List[Dict]: """ Load a pair from file, either .json.gz or .json - :return: tickerlist or None if unsuccesful + :return: tickerlist or empty list if unsuccesful """ filename = pair_trades_filename(datadir, pair) tradesdata = misc.file_load_json(filename) if not tradesdata: - return None + return [] # TODO: trim trades based on timerange... ? return tradesdata @@ -329,6 +329,47 @@ def refresh_backtest_ohlcv_data(exchange: Exchange, pairs: List[str], timeframes return pairs_not_available +def download_trades_history(datadir: Optional[Path], + exchange: Optional[Exchange], + pair: str, + ticker_interval: str = '5m', + timerange: Optional[TimeRange] = None) -> bool: + + if not exchange: + raise OperationalException( + "Exchange needs to be initialized to download data") + try: + + since = timerange.startts * 1000 if timerange and timerange.starttype == 'date' else None + + trades = load_trades_file(datadir, pair) + + from_id = trades[-1]['id'] if trades else None + + logger.debug("Current Start: %s", trades[1]['datetime'] if trades else 'None') + logger.debug("Current End: %s", trades[-1]['datetime'] if trades else 'None') + + exchange.get_historic_trades(pair=pair, + since=since if since else + int(arrow.utcnow().shift(days=-30).float_timestamp) * 1000, + # until=xxx, + from_id=from_id, + ) + + store_trades_file(datadir, pair, trades) + + logger.debug("New Start: %s", trades[0]['datetime']) + logger.debug("New End: %s", trades[-1]['datetime']) + logger.info(f"New Amount of trades: {len(trades)}") + + except Exception as e: + logger.error( + f'Failed to download historic trades for pair: "{pair}". ' + f'Error: {e}' + ) + return False + + def get_timeframe(data: Dict[str, DataFrame]) -> Tuple[arrow.Arrow, arrow.Arrow]: """ Get the maximum timeframe for the given backtest data diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 945c06966..158dfee9e 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -791,6 +791,7 @@ class Exchange: :param pair: Pair to fetch trade data for :param since: Since as integer timestamp in milliseconds :param until: Until as integer timestamp in milliseconds + :param from_id: Download data starting with ID (if id is known). Ignores "since" if set. returns tuple: (pair, ticker_interval, ohlcv_list) """ try: @@ -880,14 +881,18 @@ class Exchange: Async over one pair, assuming we get `_ohlcv_candle_limit` candles per call. :param pair: Pair to download :param ticker_interval: Interval to get - :param since_ms: Timestamp in milliseconds to get history from + :param since: Timestamp in milliseconds to get history from + :param until: Timestamp in milliseconds. Defaults to current timestamp if not defined. :param from_id: Download data starting with ID (if id is known) :returns List of tickers """ - + if not until: + # Current milliseconds + until = ccxt.Exchange.milliseconds() if self._trades_pagination == 'time': return asyncio.get_event_loop().run_until_complete( self._async_get_trade_history(pair=pair, since=since, until=until)) + elif self._trades_pagination == 'id': # Use id-based trade-downloader return asyncio.get_event_loop().run_until_complete(