예제 #1
0
 def test_time_to_index(self):
     self.assertEqual(aux.time_to_index(aux.get_data_from_file("BTC-SRN",interval='10m'),
                                                     ['01-03-2018','04-03-2018']),
                                                         (33568, 33998))
     self.assertEqual(aux.time_to_index(aux.get_data_from_file("BTC-SRN",interval='10m'),
                                                     ['01-03-2018 00:00','04-03-2018']),
                                                         (33568, 33998))
예제 #2
0
def backtest_market(entry_funcs, exit_funcs, interval, _date, smas, emas,
                    from_file, to_file, plot, exchange, db_client, log_level,
                    market):
    '''
    Backtests strategies for a specific market.

    Args:
        entry_funcs(list): list of entry functions to test.
        exit_funcs(list): list of entry functions to test.
        interval(string): time between measures.
        _date(list): init and end point to backtest.
        smas(list): list of SMA values to use.
        emas(list): list of EMA values to use.
        to_file(bool): plot to file.
        from_file(bool): get data from file.
        plot(bool): plot data.
        markets(string): list with markets to backtest or empty to test all available markets.

    Returns:
        float: returns backtests profit & loss value for applied strategies.
    '''

    date = [0, 0]

    total = 0

    #market = check_market_name(market)
    #global cached
    is_cached = False

    entry_points_x = []
    entry_points_y = []

    exit_points_x = []
    exit_points_y = []

    full_log = '[Market analysis]: ' + market + '\n'

    if from_file:
        try:
            data = get_data_from_file(market, interval=interval)
        except Exception as e:
            log(str(e), 0, log_level)
            log('[ERROR] Can\'t find ' + market + ' in files.', 0, log_level)
            return 0

        data_init = data

        if isinstance(_date[0], str):
            date[0], date[1] = time_to_index(data, _date)
        else:
            date = _date

        if date[1] == 0:
            data = data[date[0]:]
        else:
            data = data[date[0]:date[1]]

    else:
        if market in cached and \
           cached[market]['interval'] == interval and \
           cached[market]['init_date'] == _date[0] and \
           cached[market]['end_date'] == _date[1]:
            # Check if cached data is the same as you want.
            data = cached[market]['data']
            cached[market]['last'] = 2
            is_cached = True
        else:
            try:
                data = get_historical_data(market,
                                           interval=interval,
                                           init_date=_date[0],
                                           end_date=_date[1],
                                           exchange=exchange)
                date[0], date[1] = 0, len(data)
            except Exception as e:
                log(str(e), 0, log_level)
                log('[ERROR] Can\'t find ' + market + ' in BD.', 0, log_level)
                return 0
            #continue

        data_init = data

    aux_buy = False
    buy_price = 0
    high_price = 0

    #    # Test for volume.
    #    if data.BaseVolume.mean() < 20:
    #        log(full_log, 1, log_level)
    #        del data
    #        del data_init
    #        return 0

    #Tests several functions.
    for i in range(len(data) - 110):
        if not aux_buy:
            if is_time_to_buy(data[i:i + 110], entry_funcs, smas, emas):

                buy_price = data_init.Ask.iloc[i + 109 + date[0]]
                high_price = buy_price

                entry_points_x.append(i + 109)
                entry_points_y.append(data_init.Ask.iloc[i + 109 + date[0]])

                if exit_funcs:
                    aux_buy = True

                full_log += str(data_init.time.iloc[i + 109 + date[0]]) + \
                    ' [BUY] @ ' + str(data_init.Ask.iloc[i + 109 + date[0]]) + '\n'

        else:
            # Used for trailing stop loss.
            if data_init.Last.iloc[i + 109 + date[0]] > high_price:
                high_price = data_init.Last.iloc[i + 109 + date[0]]

            if is_time_to_exit(data[i:i + 110],
                               exit_funcs,
                               smas,
                               emas,
                               stop=0,
                               bought_at=buy_price,
                               max_price=high_price):

                exit_points_x.append(i + 109)
                exit_points_y.append(data_init.Bid.iloc[i + 109 + date[0]])

                aux_buy = False

                total += round(
                    ((data_init.Bid.iloc[i + 109 + date[0]] - buy_price) /
                     buy_price) * 100, 2)

                full_log += str(data_init.time.iloc[i + 109 + date[0]]) + \
                    ' [SELL]@ ' + str(data_init.Bid.iloc[i + 109 + date[0]]) + '\n'

                full_log += '[P&L] > ' + str(total) + '%.' + '\n'

    del data_init

    # Use plot_data for just a few markets. If you try to run plot_data for several markets,
    # computer can start run really slow.
    try:
        if plot:
            plot_data(data,
                      name=market,
                      date=[0, 0],
                      smas=smas,
                      emas=None,
                      entry_points=(entry_points_x, entry_points_y),
                      exit_points=(exit_points_x, exit_points_y),
                      show_smas=True,
                      show_emas=True,
                      show_bbands=False,
                      to_file=to_file)

    except Exception as e:
        log("[ERROR] Ploting data: " + str(e), 0, log_level)

    if not is_cached:
        cached[market] = {
            'interval': interval,
            'init_date': _date[0],
            'end_date': _date[1],
            'data': data,
            'last': 2
        }

    #if len(exit_points_x):
    #    log(market + ' > ' + str(total), log_level)

    log('[' + market + '][TOTAL]> ' + str(total) + '%.', 0, log_level)

    log(full_log, 1, log_level)

    if isnan(total):
        log("[ERROR] Total is isnan", 0, log_level)
        return 0

    return total