Strategy analysis example¶

Debugging a strategy can be time-consuming. Freqtrade offers helper functions to visualize raw data. The following assumes you work with SampleStrategy, data for 5m timeframe from Binance and have downloaded them into the data directory in the default location.

Setup¶

from pathlib import Path

# Customize these according to your needs.

# Initialize empty configuration object
config = Configuration.from_files([])
# Optionally, use existing configuration file
# config = Configuration.from_files(["config.json"])

# Define some constants
config["timeframe"] = "5m"
# Name of the strategy class
config["strategy"] = "SampleStrategy"
# Location of the data
data_location = Path(config['user_data_dir'], 'data', 'binance')
# Pair to analyze - Only use one pair here
pair = "BTC_USDT"
# Load data using values set above

timeframe=config["timeframe"],
pair=pair)

# Confirm success
print("Loaded " + str(len(candles)) + f" rows of data for {pair} from {data_location}")

• Rerun each time the strategy file is changed
# Load strategy using values set above

# Generate buy/sell signals using strategy
df = strategy.analyze_ticker(candles, {'pair': pair})
df.tail()

• Note that using data.head() would also work, however most indicators have some "startup" data at the top of the dataframe.
• Some possible problems * Columns with NaN values at the end of the dataframe * Columns used in crossed*() functions with completely different units
• Comparison with full backtest * having 200 buy signals as output for one pair from analyze_ticker() does not necessarily mean that 200 trades will be made during backtesting. * Assuming you use only one condition such as, df['rsi'] < 30 as buy condition, this will generate multiple "buy" signals for each pair in sequence (until rsi returns > 29). The bot will only buy on the first of these signals (and also only if a trade-slot ("max_open_trades") is still available), or on one of the middle signals, as soon as a "slot" becomes available.
# Report results
data = df.set_index('date', drop=False)
data.tail()

Load existing objects into a Jupyter notebook¶

The following cells assume that you have already generated data using the cli.
They will allow you to drill deeper into your results, and perform analysis which otherwise would make the output very difficult to digest due to information overload.

Load backtest results to pandas dataframe¶

Analyze a trades dataframe (also used below for plotting)

# if backtest_dir points to a directory, it'll automatically load the last backtest file.
backtest_dir = config["user_data_dir"] / "backtest_results"
# backtest_dir can also point to a specific file
# backtest_dir = config["user_data_dir"] / "backtest_results/backtest-result-2020-07-01_20-04-22.json"
# You can get the full backtest statistics by using the following command.
# This contains all information used to generate the backtest result.

strategy = 'SampleStrategy'
# All statistics are available per strategy, so if --strategy-list was used during backtest, this will be reflected here as well.
# Example usages:
print(stats['strategy'][strategy]['results_per_pair'])
# Get pairlist used for this backtest
print(stats['strategy'][strategy]['pairlist'])
# Get market change (average change of all pairs from start to end of the backtest period)
print(stats['strategy'][strategy]['market_change'])
# Maximum drawdown ()
print(stats['strategy'][strategy]['max_drawdown'])
# Maximum drawdown start and end
print(stats['strategy'][strategy]['drawdown_start'])
print(stats['strategy'][strategy]['drawdown_end'])

# Get strategy comparison (only relevant if multiple strategies were compared)
print(stats['strategy_comparison'])

# Show value-counts per pair

# Display results

This can be useful to find the best max_open_trades parameter, when used with backtesting in conjunction with --disable-max-market-positions.

analyze_trade_parallelism() returns a timeseries dataframe with an "open_trades" column, specifying the number of open trades for each candle.

# Analyze the above

Plot results¶

Freqtrade offers interactive plotting capabilities based on plotly.

# Limit graph period to keep plotly quick and reactive

# Filter trades to one pair

data_red = data['2019-06-01':'2019-06-10']
# Generate candlestick graph
graph = generate_candlestick_graph(pair=pair,
data=data_red,