def load_trades(args: Namespace, pair: str,
                timerange: TimeRange) -> pd.DataFrame:
    trades: pd.DataFrame = pd.DataFrame()
    if args.db_url:
        persistence.init(_CONF)
        columns = [
            "pair", "profit", "open_time", "close_time", "open_rate",
            "close_rate", "duration"
        ]

        for x in Trade.query.all():
            print("date: {}".format(x.open_date))

        trades = pd.DataFrame(
            [(t.pair, t.calc_profit(), t.open_date.replace(tzinfo=timeZone),
              t.close_date.replace(tzinfo=timeZone) if t.close_date else None,
              t.open_rate, t.close_rate, t.close_date.timestamp() -
              t.open_date.timestamp() if t.close_date else None)
             for t in Trade.query.filter(Trade.pair.is_(pair)).all()],
            columns=columns)

    elif args.exportfilename:

        file = Path(args.exportfilename)
        if file.exists():
            load_backtest_data(file)

        else:
            trades = pd.DataFrame([], columns=BT_DATA_COLUMNS)

    return trades
Example #2
0
def test_load_backtest_data_old_format(testdatadir, mocker):

    filename = testdatadir / "backtest-result_test222.json"
    mocker.patch('freqtrade.data.btanalysis.load_backtest_stats',
                 return_value=[])

    with pytest.raises(
            OperationalException,
            match=
            r"Backtest-results with only trades data are no longer supported."
    ):
        load_backtest_data(filename)
Example #3
0
def test_load_backtest_data():

    filename = make_testdata_path(None) / "backtest-result_test.json"
    bt_data = load_backtest_data(filename)
    assert isinstance(bt_data, DataFrame)
    assert list(bt_data.columns) == BT_DATA_COLUMNS + ["profitabs"]
    assert len(bt_data) == 179

    # Test loading from string (must yield same result)
    bt_data2 = load_backtest_data(str(filename))
    assert bt_data.equals(bt_data2)

    with pytest.raises(ValueError, match=r"File .* does not exist\."):
        load_backtest_data(str("filename") + "nofile")
Example #4
0
def test_load_backtest_data_old_format(testdatadir):

    filename = testdatadir / "backtest-result_test.json"
    bt_data = load_backtest_data(filename)
    assert isinstance(bt_data, DataFrame)
    assert list(bt_data.columns
                ) == BT_DATA_COLUMNS_OLD + ['profit_abs', 'profit_ratio']
    assert len(bt_data) == 179

    # Test loading from string (must yield same result)
    bt_data2 = load_backtest_data(str(filename))
    assert bt_data.equals(bt_data2)

    with pytest.raises(ValueError, match=r"File .* does not exist\."):
        load_backtest_data(str("filename") + "nofile")
Example #5
0
def test_generate_profit_graph():
    filename = history.make_testdata_path(None) / "backtest-result_test.json"
    trades = load_backtest_data(filename)
    timerange = Arguments.parse_timerange("20180110-20180112")
    pairs = ["POWR/BTC", "XLM/BTC"]

    tickers = history.load_data(datadir=None,
                                pairs=pairs,
                                ticker_interval='5m',
                                timerange=timerange)
    trades = trades[trades['pair'].isin(pairs)]

    fig = generate_profit_graph(pairs, tickers, trades)
    assert isinstance(fig, go.Figure)

    assert fig.layout.title.text == "Profit plot"
    figure = fig.layout.figure
    assert len(figure.data) == 4

    avgclose = find_trace_in_fig_data(figure.data, "Avg close price")
    assert isinstance(avgclose, go.Scattergl)

    profit = find_trace_in_fig_data(figure.data, "Profit")
    assert isinstance(profit, go.Scattergl)

    for pair in pairs:
        profit_pair = find_trace_in_fig_data(figure.data, f"Profit {pair}")
        assert isinstance(profit_pair, go.Scattergl)
def test_add_profit(testdatadir):
    filename = testdatadir / "backtest-result_test.json"
    bt_data = load_backtest_data(filename)
    timerange = TimeRange.parse_timerange("20180110-20180112")

    df = history.load_pair_history(pair="TRX/BTC",
                                   ticker_interval='5m',
                                   datadir=testdatadir,
                                   timerange=timerange)
    fig = generate_empty_figure()

    cum_profits = create_cum_profit(df.set_index('date'),
                                    bt_data[bt_data["pair"] == 'TRX/BTC'],
                                    "cum_profits",
                                    timeframe="5m")

    fig1 = add_profit(fig,
                      row=2,
                      data=cum_profits,
                      column='cum_profits',
                      name='Profits')
    figure = fig1.layout.figure
    profits = find_trace_in_fig_data(figure.data, "Profits")
    assert isinstance(profits, go.Scatter)
    assert profits.yaxis == "y2"
def test_generate_profit_graph(testdatadir):
    filename = testdatadir / "backtest-result_test.json"
    trades = load_backtest_data(filename)
    timerange = TimeRange.parse_timerange("20180110-20180112")
    pairs = ["TRX/BTC", "ADA/BTC"]

    tickers = history.load_data(datadir=testdatadir,
                                pairs=pairs,
                                ticker_interval='5m',
                                timerange=timerange)
    trades = trades[trades['pair'].isin(pairs)]

    fig = generate_profit_graph(pairs, tickers, trades, timeframe="5m")
    assert isinstance(fig, go.Figure)

    assert fig.layout.title.text == "Freqtrade Profit plot"
    assert fig.layout.yaxis.title.text == "Price"
    assert fig.layout.yaxis2.title.text == "Profit"
    assert fig.layout.yaxis3.title.text == "Profit"

    figure = fig.layout.figure
    assert len(figure.data) == 4

    avgclose = find_trace_in_fig_data(figure.data, "Avg close price")
    assert isinstance(avgclose, go.Scatter)

    profit = find_trace_in_fig_data(figure.data, "Profit")
    assert isinstance(profit, go.Scatter)

    for pair in pairs:
        profit_pair = find_trace_in_fig_data(figure.data, f"Profit {pair}")
        assert isinstance(profit_pair, go.Scatter)
Example #8
0
def test_create_cum_profit1(testdatadir):
    filename = testdatadir / "backtest-result_test.json"
    bt_data = load_backtest_data(filename)
    # Move close-time to "off" the candle, to make sure the logic still works
    bt_data.loc[:, 'close_date'] = bt_data.loc[:, 'close_date'] + DateOffset(
        seconds=20)
    timerange = TimeRange.parse_timerange("20180110-20180112")

    df = load_pair_history(pair="TRX/BTC",
                           timeframe='5m',
                           datadir=testdatadir,
                           timerange=timerange)

    cum_profits = create_cum_profit(df.set_index('date'),
                                    bt_data[bt_data["pair"] == 'TRX/BTC'],
                                    "cum_profits",
                                    timeframe="5m")
    assert "cum_profits" in cum_profits.columns
    assert cum_profits.iloc[0]['cum_profits'] == 0
    assert cum_profits.iloc[-1]['cum_profits'] == 0.0798005

    with pytest.raises(ValueError, match='Trade dataframe empty.'):
        create_cum_profit(df.set_index('date'),
                          bt_data[bt_data["pair"] == 'NOTAPAIR'],
                          "cum_profits",
                          timeframe="5m")
Example #9
0
def test_plot_trades(caplog):
    fig1 = generage_empty_figure()
    # nothing happens when no trades are available
    fig = plot_trades(fig1, None)
    assert fig == fig1
    assert log_has("No trades found.", caplog.record_tuples)
    pair = "ADA/BTC"
    filename = history.make_testdata_path(None) / "backtest-result_test.json"
    trades = load_backtest_data(filename)
    trades = trades.loc[trades['pair'] == pair]

    fig = plot_trades(fig, trades)
    figure = fig1.layout.figure

    # Check buys - color, should be in first graph, ...
    trade_buy = find_trace_in_fig_data(figure.data, "trade_buy")
    assert isinstance(trade_buy, go.Scatter)
    assert trade_buy.yaxis == 'y'
    assert len(trades) == len(trade_buy.x)
    assert trade_buy.marker.color == 'green'

    trade_sell = find_trace_in_fig_data(figure.data, "trade_sell")
    assert isinstance(trade_sell, go.Scatter)
    assert trade_sell.yaxis == 'y'
    assert len(trades) == len(trade_sell.x)
    assert trade_sell.marker.color == 'red'
Example #10
0
def analyse_and_plot_pairs(config: Dict[str, Any]):
    """
    From arguments provided in cli:
    -Initialise backtest env
    -Get tickers data
    -Generate Dafaframes populated with indicators and signals
    -Load trades excecuted on same periods
    -Generate Plotly plot objects
    -Generate plot files
    :return: None
    """
    exchange = ExchangeResolver(config.get('exchange', {}).get('name'), config).exchange

    strategy = StrategyResolver(config).strategy
    if "pairs" in config:
        pairs = config["pairs"].split(',')
    else:
        pairs = config["exchange"]["pair_whitelist"]

    # Set timerange to use
    timerange = Arguments.parse_timerange(config["timerange"])
    ticker_interval = strategy.ticker_interval

    tickers = history.load_data(
        datadir=Path(str(config.get("datadir"))),
        pairs=pairs,
        ticker_interval=config['ticker_interval'],
        refresh_pairs=config.get('refresh_pairs', False),
        timerange=timerange,
        exchange=exchange,
        live=config.get("live", False),
    )

    pair_counter = 0
    for pair, data in tickers.items():
        pair_counter += 1
        logger.info("analyse pair %s", pair)
        tickers = {}
        tickers[pair] = data
        dataframe = generate_dataframe(strategy, tickers, pair)
        if config["trade_source"] == "DB":
            trades = load_trades_from_db(config["db_url"])
        elif config["trade_source"] == "file":
            trades = load_backtest_data(Path(config["exportfilename"]))

        trades = trades.loc[trades['pair'] == pair]
        trades = extract_trades_of_period(dataframe, trades)

        fig = generate_graph(
            pair=pair,
            data=dataframe,
            trades=trades,
            indicators1=config["indicators1"].split(","),
            indicators2=config["indicators2"].split(",")
        )

        generate_plot_file(fig, pair, ticker_interval)

    logger.info('End of ploting process %s plots generated', pair_counter)
Example #11
0
def test_analyze_trade_parallelism(default_conf, mocker, testdatadir):
    filename = testdatadir / "backtest-result_test.json"
    bt_data = load_backtest_data(filename)

    res = analyze_trade_parallelism(bt_data, "5m")
    assert isinstance(res, DataFrame)
    assert 'open_trades' in res.columns
    assert res['open_trades'].max() == 3
    assert res['open_trades'].min() == 0
Example #12
0
def test_generate_profit_graph(testdatadir):
    filename = testdatadir / "backtest_results/backtest-result_new.json"
    trades = load_backtest_data(filename)
    timerange = TimeRange.parse_timerange("20180110-20180112")
    pairs = ["TRX/BTC", "XLM/BTC"]
    trades = trades[
        trades['close_date'] < pd.Timestamp('2018-01-12', tz='UTC')]

    data = history.load_data(datadir=testdatadir,
                             pairs=pairs,
                             timeframe='5m',
                             timerange=timerange)

    trades = trades[trades['pair'].isin(pairs)]

    fig = generate_profit_graph(pairs,
                                data,
                                trades,
                                timeframe="5m",
                                stake_currency='BTC')
    assert isinstance(fig, go.Figure)

    assert fig.layout.title.text == "Freqtrade Profit plot"
    assert fig.layout.yaxis.title.text == "Price"
    assert fig.layout.yaxis2.title.text == "Profit BTC"
    assert fig.layout.yaxis3.title.text == "Profit BTC"

    figure = fig.layout.figure
    assert len(figure.data) == 7

    avgclose = find_trace_in_fig_data(figure.data, "Avg close price")
    assert isinstance(avgclose, go.Scatter)

    profit = find_trace_in_fig_data(figure.data, "Profit")
    assert isinstance(profit, go.Scatter)
    drawdown = find_trace_in_fig_data(figure.data, "Max drawdown 35.69%")
    assert isinstance(drawdown, go.Scatter)
    parallel = find_trace_in_fig_data(figure.data, "Parallel trades")
    assert isinstance(parallel, go.Scatter)

    underwater = find_trace_in_fig_data(figure.data, "Underwater Plot")
    assert isinstance(underwater, go.Scatter)

    for pair in pairs:
        profit_pair = find_trace_in_fig_data(figure.data, f"Profit {pair}")
        assert isinstance(profit_pair, go.Scatter)

    with pytest.raises(OperationalException, match=r"No trades found.*"):
        # Pair cannot be empty - so it's an empty dataframe.
        generate_profit_graph(pairs,
                              data,
                              trades.loc[trades['pair'].isnull()],
                              timeframe="5m",
                              stake_currency='BTC')
Example #13
0
def test_calculate_csum(testdatadir):
    filename = testdatadir / "backtest-result_test.json"
    bt_data = load_backtest_data(filename)
    csum_min, csum_max = calculate_csum(bt_data)

    assert isinstance(csum_min, float)
    assert isinstance(csum_max, float)
    assert csum_min < 0.01
    assert csum_max > 0.02

    with pytest.raises(ValueError, match='Trade dataframe empty.'):
        csum_min, csum_max = calculate_csum(DataFrame())
Example #14
0
def test_calculate_max_drawdown(testdatadir):
    filename = testdatadir / "backtest-result_test.json"
    bt_data = load_backtest_data(filename)
    drawdown, h, low = calculate_max_drawdown(bt_data)
    assert isinstance(drawdown, float)
    assert pytest.approx(drawdown) == 0.21142322
    assert isinstance(h, Timestamp)
    assert isinstance(low, Timestamp)
    assert h == Timestamp('2018-01-24 14:25:00', tz='UTC')
    assert low == Timestamp('2018-01-30 04:45:00', tz='UTC')
    with pytest.raises(ValueError, match='Trade dataframe empty.'):
        drawdown, h, low = calculate_max_drawdown(DataFrame())
Example #15
0
def test_create_cum_profit():
    filename = make_testdata_path(None) / "backtest-result_test.json"
    bt_data = load_backtest_data(filename)
    timerange = TimeRange.parse_timerange("20180110-20180112")

    df = load_pair_history(pair="POWR/BTC", ticker_interval='5m',
                           datadir=None, timerange=timerange)

    cum_profits = create_cum_profit(df.set_index('date'),
                                    bt_data[bt_data["pair"] == 'POWR/BTC'],
                                    "cum_profits")
    assert "cum_profits" in cum_profits.columns
    assert cum_profits.iloc[0]['cum_profits'] == 0
    assert cum_profits.iloc[-1]['cum_profits'] == 0.0798005
def test_generate_trading_stats(testdatadir):
    filename = testdatadir / "backtest-result_new.json"
    bt_data = load_backtest_data(filename)
    res = generate_trading_stats(bt_data)
    assert isinstance(res, dict)
    assert res['winner_holding_avg'] == timedelta(seconds=1440)
    assert res['loser_holding_avg'] == timedelta(days=1, seconds=21420)
    assert 'wins' in res
    assert 'losses' in res
    assert 'draws' in res

    # Select empty dataframe!
    res = generate_trading_stats(bt_data.loc[bt_data['open_date'] == '2000-01-01', :])
    assert res['wins'] == 0
    assert res['losses'] == 0
Example #17
0
def test_generate_periodic_breakdown_stats(testdatadir):
    filename = testdatadir / "backtest_results/backtest-result_new.json"
    bt_data = load_backtest_data(filename).to_dict(orient='records')

    res = generate_periodic_breakdown_stats(bt_data, 'day')
    assert isinstance(res, list)
    assert len(res) == 21
    day = res[0]
    assert 'date' in day
    assert 'draws' in day
    assert 'loses' in day
    assert 'wins' in day
    assert 'profit_abs' in day

    # Select empty dataframe!
    res = generate_periodic_breakdown_stats([], 'day')
    assert res == []
Example #18
0
def test_create_cum_profit(testdatadir):
    filename = testdatadir / "backtest-result_test.json"
    bt_data = load_backtest_data(filename)
    timerange = TimeRange.parse_timerange("20180110-20180112")

    df = load_pair_history(pair="TRX/BTC",
                           timeframe='5m',
                           datadir=testdatadir,
                           timerange=timerange)

    cum_profits = create_cum_profit(df.set_index('date'),
                                    bt_data[bt_data["pair"] == 'TRX/BTC'],
                                    "cum_profits",
                                    timeframe="5m")
    assert "cum_profits" in cum_profits.columns
    assert cum_profits.iloc[0]['cum_profits'] == 0
    assert cum_profits.iloc[-1]['cum_profits'] == 0.0798005
def test_generate_daily_stats(testdatadir):

    filename = testdatadir / "backtest-result_new.json"
    bt_data = load_backtest_data(filename)
    res = generate_daily_stats(bt_data)
    assert isinstance(res, dict)
    assert round(res['backtest_best_day'], 4) == 0.1796
    assert round(res['backtest_worst_day'], 4) == -0.1468
    assert res['winning_days'] == 14
    assert res['draw_days'] == 4
    assert res['losing_days'] == 3

    # Select empty dataframe!
    res = generate_daily_stats(bt_data.loc[bt_data['open_date'] == '2000-01-01', :])
    assert isinstance(res, dict)
    assert round(res['backtest_best_day'], 4) == 0.0
    assert res['winning_days'] == 0
    assert res['draw_days'] == 0
    assert res['losing_days'] == 0
Example #20
0
def test_calculate_max_drawdown(testdatadir):
    filename = testdatadir / "backtest-result_new.json"
    bt_data = load_backtest_data(filename)
    _, hdate, lowdate, hval, lval, drawdown = calculate_max_drawdown(
        bt_data, value_col="profit_abs")
    assert isinstance(drawdown, float)
    assert pytest.approx(drawdown) == 0.12071099
    assert isinstance(hdate, Timestamp)
    assert isinstance(lowdate, Timestamp)
    assert isinstance(hval, float)
    assert isinstance(lval, float)
    assert hdate == Timestamp('2018-01-25 01:30:00', tz='UTC')
    assert lowdate == Timestamp('2018-01-25 03:50:00', tz='UTC')

    underwater = calculate_underwater(bt_data)
    assert isinstance(underwater, DataFrame)

    with pytest.raises(ValueError, match='Trade dataframe empty.'):
        calculate_max_drawdown(DataFrame())

    with pytest.raises(ValueError, match='Trade dataframe empty.'):
        calculate_underwater(DataFrame())
def test_plot_trades(testdatadir, caplog):
    fig1 = generate_empty_figure()
    # nothing happens when no trades are available
    fig = plot_trades(fig1, None)
    assert fig == fig1
    assert log_has("No trades found.", caplog)
    pair = "ADA/BTC"
    filename = testdatadir / "backtest-result_test.json"
    trades = load_backtest_data(filename)
    trades = trades.loc[trades['pair'] == pair]

    fig = plot_trades(fig, trades)
    figure = fig1.layout.figure

    # Check buys - color, should be in first graph, ...
    trade_buy = find_trace_in_fig_data(figure.data, 'Trade buy')
    assert isinstance(trade_buy, go.Scatter)
    assert trade_buy.yaxis == 'y'
    assert len(trades) == len(trade_buy.x)
    assert trade_buy.marker.color == 'cyan'
    assert trade_buy.marker.symbol == 'circle-open'
    assert trade_buy.text[0] == '4.0%, roi, 15 min'

    trade_sell = find_trace_in_fig_data(figure.data, 'Sell - Profit')
    assert isinstance(trade_sell, go.Scatter)
    assert trade_sell.yaxis == 'y'
    assert len(trades.loc[trades['profit_percent'] > 0]) == len(trade_sell.x)
    assert trade_sell.marker.color == 'green'
    assert trade_sell.marker.symbol == 'square-open'
    assert trade_sell.text[0] == '4.0%, roi, 15 min'

    trade_sell_loss = find_trace_in_fig_data(figure.data, 'Sell - Loss')
    assert isinstance(trade_sell_loss, go.Scatter)
    assert trade_sell_loss.yaxis == 'y'
    assert len(trades.loc[trades['profit_percent'] <= 0]) == len(
        trade_sell_loss.x)
    assert trade_sell_loss.marker.color == 'red'
    assert trade_sell_loss.marker.symbol == 'square-open'
    assert trade_sell_loss.text[5] == '-10.4%, stop_loss, 720 min'
Example #22
0
def test_load_backtest_data_new_format(testdatadir):

    filename = testdatadir / "backtest-result_new.json"
    bt_data = load_backtest_data(filename)
    assert isinstance(bt_data, DataFrame)
    assert set(bt_data.columns) == set(BT_DATA_COLUMNS_MID)
    assert len(bt_data) == 179

    # Test loading from string (must yield same result)
    bt_data2 = load_backtest_data(str(filename))
    assert bt_data.equals(bt_data2)

    # Test loading from folder (must yield same result)
    bt_data3 = load_backtest_data(testdatadir)
    assert bt_data.equals(bt_data3)

    with pytest.raises(ValueError, match=r"File .* does not exist\."):
        load_backtest_data(str("filename") + "nofile")

    with pytest.raises(ValueError, match=r"Unknown dataformat."):
        load_backtest_data(testdatadir / LAST_BT_RESULT_FN)
Example #23
0
def test_load_backtest_data_multi(testdatadir):

    filename = testdatadir / "backtest-result_multistrat.json"
    for strategy in ('DefaultStrategy', 'TestStrategy'):
        bt_data = load_backtest_data(filename, strategy=strategy)
        assert isinstance(bt_data, DataFrame)
        assert set(bt_data.columns) == set(BT_DATA_COLUMNS_MID)
        assert len(bt_data) == 179

        # Test loading from string (must yield same result)
        bt_data2 = load_backtest_data(str(filename), strategy=strategy)
        assert bt_data.equals(bt_data2)

    with pytest.raises(
            ValueError,
            match=r"Strategy XYZ not available in the backtest result\."):
        load_backtest_data(filename, strategy='XYZ')

    with pytest.raises(
            ValueError,
            match=r"Detected backtest result with more than one strategy.*"):
        load_backtest_data(filename)