freqtrade_origin/docs/data-analysis.md

110 lines
3.6 KiB
Markdown
Raw Normal View History

2019-06-22 14:18:22 +00:00
# Analyzing bot data
2019-08-07 02:35:14 +00:00
You can analyze the results of backtests and trading history easily using Jupyter notebooks. A sample notebook is located at `user_data/notebooks/analysis_example.ipynb`. For usage instructions, see [jupyter.org](https://jupyter.org/documentation).
2019-06-22 14:18:22 +00:00
2019-08-09 15:53:29 +00:00
*Pro tip - Don't forget to start a jupyter notbook server from within your conda or venv environment or use [nb_conda_kernels](https://github.com/Anaconda-Platform/nb_conda_kernels)*
2019-08-09 02:09:15 +00:00
## Example snippets
### Load backtest results into a pandas dataframe
```python
2019-08-09 21:06:19 +00:00
from freqtrade.data.btanalysis import load_backtest_data
2019-08-09 02:09:15 +00:00
# Load backtest results
df = load_backtest_data("user_data/backtest_data/backtest-result.json")
# Show value-counts per pair
df.groupby("pair")["sell_reason"].value_counts()
```
### Load live trading results into a pandas dataframe
``` python
2019-08-09 21:06:19 +00:00
from freqtrade.data.btanalysis import load_trades_from_db
2019-08-09 02:09:15 +00:00
# Fetch trades from database
df = load_trades_from_db("sqlite:///tradesv3.sqlite")
# Display results
df.groupby("pair")["sell_reason"].value_counts()
```
2019-08-07 02:35:14 +00:00
## Strategy debugging example
2019-06-22 14:18:22 +00:00
2019-08-07 02:35:14 +00:00
Debugging a strategy can be time-consuming. FreqTrade offers helper functions to visualize raw data.
2019-06-22 14:18:22 +00:00
2019-08-09 02:09:15 +00:00
### Import requirements and define variables used in analyses
```python
2019-08-07 02:35:14 +00:00
# Imports
from pathlib import Path
2019-08-07 02:35:14 +00:00
import os
from freqtrade.data.history import load_pair_history
from freqtrade.resolvers import StrategyResolver
# Define some constants
2019-08-09 21:06:19 +00:00
ticker_interval = "5m"
# Name of the strategy class
2019-08-09 21:06:19 +00:00
strategy_name = 'AwesomeStrategy'
2019-08-07 02:35:14 +00:00
# Path to user data
user_data_dir = 'user_data'
# Location of the strategy
strategy_location = Path(user_data_dir, 'strategies')
# Location of the data
data_location = Path(user_data_dir, 'data', 'binance')
2019-08-07 02:35:14 +00:00
# Pair to analyze
# Only use one pair here
2019-08-07 02:35:14 +00:00
pair = "BTC_USDT"
```
2019-08-07 02:35:14 +00:00
### Load exchange data
2019-08-07 02:35:14 +00:00
```python
# Load data using values set above
bt_data = load_pair_history(datadir=Path(data_location),
2019-08-07 02:35:14 +00:00
ticker_interval=ticker_interval,
pair=pair)
2019-08-07 02:35:14 +00:00
# Confirm success
print("Loaded " + str(len(bt_data)) + f" rows of data for {pair} from {data_location}")
```
2019-08-07 02:35:14 +00:00
### Load and run strategy
2019-08-07 02:35:14 +00:00
* Rerun each time the strategy file is changed
```python
# Load strategy using values set above
strategy = StrategyResolver({'strategy': strategy_name,
'user_data_dir': user_data_dir,
'strategy_path': strategy_location}).strategy
2019-08-09 02:09:15 +00:00
# Generate buy/sell signals using strategy
df = strategy.analyze_ticker(bt_data, {'pair': pair})
```
2019-08-09 02:09:15 +00:00
### Display the trade details
2019-08-09 02:09:15 +00:00
* Note that using `data.head()` would also work, however most indicators have some "startup" data at the top of the dataframe.
2019-06-22 14:18:22 +00:00
2019-08-09 02:09:15 +00:00
#### Some possible problems
2019-06-22 14:18:22 +00:00
2019-08-09 02:09:15 +00:00
* Columns with NaN values at the end of the dataframe
* Columns used in `crossed*()` functions with completely different units
2019-06-22 14:18:22 +00:00
2019-08-09 02:09:15 +00:00
#### Comparison with full backtest
2019-06-22 14:18:22 +00:00
2019-08-09 02:09:15 +00:00
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.
```python
# Report results
print(f"Generated {df['buy'].sum()} buy signals")
data = df.set_index('date', drop=True)
data.tail()
2019-06-22 14:18:22 +00:00
```
2019-06-24 15:20:41 +00:00
Feel free to submit an issue or Pull Request enhancing this document if you would like to share ideas on how to best analyze the data.