{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## Strategy debugging example\n", "\n", "Debugging a strategy can be time-consuming. FreqTrade offers helper functions to visualize raw data." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Setup" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Change directory\n", "# Modify this cell to insure that the output shows the correct path.\n", "import os\n", "from pathlib import Path\n", "\n", "# Define all paths relative to the project root shown in the cell output\n", "project_root = \"somedir/freqtrade\"\n", "i=0\n", "try:\n", " os.chdirdir(project_root)\n", " assert Path('LICENSE').is_file()\n", "except:\n", " while i<4 and (not Path('LICENSE').is_file()):\n", " os.chdir(Path(Path.cwd(), '../'))\n", " i+=1\n", " project_root = Path.cwd()\n", "print(Path.cwd())" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Customize these according to your needs.\n", "\n", "# Define some constants\n", "ticker_interval = \"5m\"\n", "# Name of the strategy class\n", "strategy_name = 'SampleStrategy'\n", "# Path to user data\n", "user_data_dir = 'user_data'\n", "# Location of the strategy\n", "strategy_location = Path(user_data_dir, 'strategies')\n", "# Location of the data\n", "data_location = Path(user_data_dir, 'data', 'binance')\n", "# Pair to analyze - Only use one pair here\n", "pair = \"BTC_USDT\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Load data using values set above\n", "from pathlib import Path\n", "from freqtrade.data.history import load_pair_history\n", "\n", "candles = load_pair_history(datadir=data_location,\n", " ticker_interval=ticker_interval,\n", " pair=pair)\n", "\n", "# Confirm success\n", "print(\"Loaded \" + str(len(candles)) + f\" rows of data for {pair} from {data_location}\")\n", "candles.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Load and run strategy\n", "* Rerun each time the strategy file is changed" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "# Load strategy using values set above\n", "from freqtrade.resolvers import StrategyResolver\n", "strategy = StrategyResolver({'strategy': strategy_name,\n", " 'user_data_dir': user_data_dir,\n", " 'strategy_path': strategy_location}).strategy\n", "\n", "# Generate buy/sell signals using strategy\n", "df = strategy.analyze_ticker(candles, {'pair': pair})\n", "df.tail()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Display the trade details\n", "\n", "* Note that using `data.head()` would also work, however most indicators have some \"startup\" data at the top of the dataframe.\n", "* Some possible problems\n", " * Columns with NaN values at the end of the dataframe\n", " * Columns used in `crossed*()` functions with completely different units\n", "* Comparison with full backtest\n", " * having 200 buy signals as output for one pair from `analyze_ticker()` does not necessarily mean that 200 trades will be made during backtesting.\n", " * 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. \n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Report results\n", "print(f\"Generated {df['buy'].sum()} buy signals\")\n", "data = df.set_index('date', drop=True)\n", "data.tail()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "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." ] } ], "metadata": { "file_extension": ".py", "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.3" }, "mimetype": "text/x-python", "name": "python", "npconvert_exporter": "python", "pygments_lexer": "ipython3", "toc": { "base_numbering": 1, "nav_menu": {}, "number_sections": true, "sideBar": true, "skip_h1_title": false, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": false, "toc_position": {}, "toc_section_display": true, "toc_window_display": false }, "varInspector": { "cols": { "lenName": 16, "lenType": 16, "lenVar": 40 }, "kernels_config": { "python": { "delete_cmd_postfix": "", "delete_cmd_prefix": "del ", "library": "var_list.py", "varRefreshCmd": "print(var_dic_list())" }, "r": { "delete_cmd_postfix": ") ", "delete_cmd_prefix": "rm(", "library": "var_list.r", "varRefreshCmd": "cat(var_dic_list()) " } }, "types_to_exclude": [ "module", "function", "builtin_function_or_method", "instance", "_Feature" ], "window_display": false }, "version": 3 }, "nbformat": 4, "nbformat_minor": 2 }