Example #1
0
def test_today_to_timestamp():
    assert jh.today_to_timestamp(
    ) == arrow.utcnow().floor('day').int_timestamp * 1000
Example #2
0
def load_required_candles(exchange: str, symbol: str, start_date_str: str,
                          finish_date_str: str):
    """
    loads initial candles that required before executing strategies.
    210 for the biggest timeframe and more for the rest
    """
    start_date = jh.arrow_to_timestamp(arrow.get(start_date_str, 'YYYY-MM-DD'))
    finish_date = jh.arrow_to_timestamp(
        arrow.get(finish_date_str, 'YYYY-MM-DD')) - 60000

    # validate
    if start_date == finish_date:
        raise ValueError('start_date and finish_date cannot be the same.')
    if start_date > finish_date:
        raise ValueError('start_date cannot be bigger than finish_date.')
    if finish_date > arrow.utcnow().int_timestamp * 1000:
        raise ValueError('Can\'t backtest the future!')

    max_timeframe = jh.max_timeframe(config['app']['considering_timeframes'])
    short_candles_count = jh.get_config(
        'env.data.warmup_candles_num',
        210) * jh.timeframe_to_one_minutes(max_timeframe)
    pre_finish_date = start_date - 60_000
    pre_start_date = pre_finish_date - short_candles_count * 60_000
    # make sure starting from the beginning of the day instead
    pre_start_date = jh.timestamp_to_arrow(pre_start_date).floor(
        'day').int_timestamp * 1000
    # update candles_count to count from the beginning of the day instead
    short_candles_count = int((pre_finish_date - pre_start_date) / 60_000)

    key = jh.key(exchange, symbol)
    cache_key = '{}-{}-{}'.format(jh.timestamp_to_date(pre_start_date),
                                  jh.timestamp_to_date(pre_finish_date), key)
    cached_value = cache.get_value(cache_key)

    # if cache exists
    if cached_value:
        candles_tuple = cached_value
    # not cached, get and cache for later calls in the next 5 minutes
    else:
        # fetch from database
        candles_tuple = tuple(
            Candle.select(Candle.timestamp, Candle.open, Candle.close,
                          Candle.high, Candle.low, Candle.volume).where(
                              Candle.timestamp.between(pre_start_date,
                                                       pre_finish_date),
                              Candle.exchange == exchange,
                              Candle.symbol == symbol).order_by(
                                  Candle.timestamp.asc()).tuples())

        # cache it for near future calls
        cache.set_value(cache_key,
                        candles_tuple,
                        expire_seconds=60 * 60 * 24 * 7)

    candles = np.array(candles_tuple)

    if len(candles) < short_candles_count + 1:
        first_existing_candle = tuple(
            Candle.select(Candle.timestamp).where(
                Candle.exchange == exchange, Candle.symbol == symbol).order_by(
                    Candle.timestamp.asc()).limit(1).tuples())

        if not len(first_existing_candle):
            raise CandleNotFoundInDatabase(
                'No candle for {} {} is present in the database. Try importing candles.'
                .format(exchange, symbol))

        first_existing_candle = first_existing_candle[0][0]

        last_existing_candle = tuple(
            Candle.select(Candle.timestamp).where(
                Candle.exchange == exchange, Candle.symbol == symbol).order_by(
                    Candle.timestamp.desc()).limit(1).tuples())[0][0]

        first_backtestable_timestamp = first_existing_candle + (
            pre_finish_date - pre_start_date) + (60_000 * 1440)

        # if first backtestable timestamp is in the future, that means we have some but not enough candles
        if first_backtestable_timestamp > jh.today_to_timestamp():
            raise CandleNotFoundInDatabase(
                'Not enough candle for {} {} is present in the database. Jesse requires "210 * biggest_timeframe" warm-up candles. '
                'Try importing more candles from an earlier date.'.format(
                    exchange, symbol))

        raise CandleNotFoundInDatabase(
            'Not enough candles for {} {} exists to run backtest from {} => {}. \n'
            'First available date is {}\n'
            'Last available date is {}'.format(
                exchange,
                symbol,
                start_date_str,
                finish_date_str,
                jh.timestamp_to_date(first_backtestable_timestamp),
                jh.timestamp_to_date(last_existing_candle),
            ))

    return candles