diff --git a/notebooks/optim_backtestingpy_sma_with_sl_tp.ipynb b/notebooks/optim_backtestingpy_sma_with_sl_tp.ipynb new file mode 100644 index 0000000..51e49bc --- /dev/null +++ b/notebooks/optim_backtestingpy_sma_with_sl_tp.ipynb @@ -0,0 +1,152 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "7712680a", + "metadata": {}, + "outputs": [], + "source": [ + "# %%\n", + "# filename: optim_backtestingpy_sma_with_sl_tp.ipynb\n", + "\n", + "# --- 1. Imports and Setup ---\n", + "import numpy as np\n", + "import pandas as pd\n", + "import pandas_ta as ta\n", + "from backtesting import Backtest, Strategy\n", + "from backtesting.lib import crossover\n", + "from backtesting.test import EURUSD\n", + "\n", + "# --- 2. Load Sample Data ---\n", + "print(\"Loading built-in EURUSD sample data...\")\n", + "data = EURUSD.copy()\n", + "print(\"Data loaded successfully.\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0fd6f9be", + "metadata": {}, + "outputs": [], + "source": [ + "# %%\n", + "# --- 3. The Parameterized Strategy with SL/TP ---\n", + "\n", + "class SmaCrossSLTP(Strategy):\n", + " # --- Parameters for Optimization ---\n", + " fast_period = 10\n", + " slow_period = 40\n", + "\n", + " # New parameters for Stop-Loss and Take-Profit (as percentages)\n", + " # Note: We express them as decimals, e.g., 1.5% SL is 0.015\n", + " sl_percent = 1.5\n", + " tp_percent = 3.0\n", + "\n", + " def init(self):\n", + " # Calculate indicators internally for optimization\n", + " self.fast_sma = self.I(ta.sma, pd.Series(self.data.Close), length=self.fast_period)\n", + " self.slow_sma = self.I(ta.sma, pd.Series(self.data.Close), length=self.slow_period)\n", + "\n", + " def next(self):\n", + " # Define SL and TP prices based on the current close\n", + " sl_price = self.data.Close[-1] * (1 - self.sl_percent / 100)\n", + " tp_price = self.data.Close[-1] * (1 + self.tp_percent / 100)\n", + "\n", + " # Entry logic\n", + " if crossover(self.fast_sma, self.slow_sma):\n", + " if not self.position:\n", + " # When buying, provide the sl and tp prices\n", + " self.buy(sl=sl_price, tp=tp_price)\n", + "\n", + " # The exit signal from the crossover is still valid\n", + " elif crossover(self.slow_sma, self.fast_sma):\n", + " self.position.close()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9572ae93", + "metadata": {}, + "outputs": [], + "source": [ + "# %%\n", + "# --- 4. Running the Optimization (FINAL, DEFINITIVE VERSION) ---\n", + "print(\"\\n--- Starting Grid Search Optimization with SL/TP ---\")\n", + "\n", + "bt = Backtest(data, SmaCrossSLTP, cash=10000, commission=.002)\n", + "\n", + "# Helper function to generate a range of floats\n", + "def frange(start, stop, step):\n", + " return np.arange(start, stop, step).tolist()\n", + "\n", + "# CORRECTED: The optimize() method with return_heatmap=True returns a TUPLE\n", + "# containing (stats_series, heatmap_data). We unpack this tuple into two variables.\n", + "stats, heatmap = bt.optimize(\n", + " fast_period=range(10, 31, 10),\n", + " slow_period=range(40, 61, 10),\n", + " sl_percent=frange(0.5, 2.1, 0.5),\n", + " tp_percent=frange(2.0, 5.1, 1.0),\n", + "\n", + " maximize='SQN',\n", + " constraint=lambda p: p.fast_period < p.slow_period,\n", + " return_heatmap=True # This is crucial for getting the tuple back\n", + ")\n", + "\n", + "print(\"\\n--- Optimization Results ---\")\n", + "print(\"Best stats found:\")\n", + "# The 'stats' variable now correctly holds the results Series\n", + "print(stats)\n", + "\n", + "print(\"\\nBest parameters found:\")\n", + "# The strategy object is an attribute of the stats Series\n", + "print(stats._strategy)\n", + "\n", + "# The 'heatmap' variable now correctly holds the heatmap data for the next cell" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b7cac03e", + "metadata": {}, + "outputs": [], + "source": [ + "# %%\n", + "# --- 5. Visualizing the Best Run and Heatmaps ---\n", + "from backtesting.lib import plot_heatmaps\n", + "\n", + "print(\"\\n--- Plotting the Best Strategy Run ---\")\n", + "# The .plot() method will automatically show the SL/TP levels on the chart\n", + "bt.plot()\n", + "\n", + "print(\"\\n--- Plotting Optimization Heatmap ---\")\n", + "# This will generate a heatmap for each pair of optimized parameters\n", + "plot_heatmaps(heatmap, agg='mean')" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "strategy-optimizer_env_bck", + "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.12.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}