Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
210 changes: 210 additions & 0 deletions notebooks/strat_supertrend_initial_backtest.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "247ae640",
"metadata": {},
"outputs": [],
"source": [
"# %%\n",
"# filename: strat_supertrend_initial_backtest.ipynb\n",
"\n",
"# --- 1. Imports and Setup ---\n",
"import os\n",
"\n",
"import pandas as pd\n",
"import pandas_ta as ta # noqa: F401\n",
"import plotly.graph_objects as go\n",
"import vectorbt as vbt"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7486f4f9",
"metadata": {},
"outputs": [],
"source": [
"# %%\n",
"# --- 2. Configuration and Data Loading ---\n",
"\n",
"# --- Path Configuration ---\n",
"project_root = os.path.abspath(os.path.join(os.getcwd(), \"..\"))\n",
"data_dir = os.path.join(project_root, \"data\", \"parquet\")\n",
"# Make sure this filename matches the file you copied into the data/parquet directory\n",
"DATA_FILENAME = \"EURUSD_M15_2024-09-14_to_2025-09-14.parquet\"\n",
"file_path = os.path.join(data_dir, DATA_FILENAME)\n",
"\n",
"# --- Strategy Parameters ---\n",
"SUPERTREND_PERIOD = 7\n",
"SUPERTREND_MULTIPLIER = 3.0\n",
"\n",
"# --- Data Loading ---\n",
"print(f\"Loading data from: {file_path}\")\n",
"try:\n",
" price_data = pd.read_parquet(file_path)\n",
" price_data.set_index('Time', inplace=True)\n",
" print(\"Data loaded successfully and index set.\")\n",
"except FileNotFoundError:\n",
" print(f\"ERROR: File not found at '{file_path}'.\")\n",
" # Stop execution if data is not found\n",
" exit()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ed3dcc21",
"metadata": {},
"outputs": [],
"source": [
"# %%\n",
"# --- 3. Indicator Calculation ---\n",
"print(f\"Calculating Supertrend with period={SUPERTREND_PERIOD} and multiplier={SUPERTREND_MULTIPLIER}...\")\n",
"\n",
"# Use pandas-ta to calculate the Supertrend indicator\n",
"# It conveniently returns multiple columns, including the trend direction and the line itself.\n",
"price_data.ta.supertrend(\n",
" length=SUPERTREND_PERIOD,\n",
" multiplier=SUPERTREND_MULTIPLIER,\n",
" append=True\n",
")\n",
"\n",
"# For clarity, let's rename the supertrend line column\n",
"# The default name is SUPERT_7_3.0\n",
"supertrend_col_name = f\"SUPERT_{SUPERTREND_PERIOD}_{SUPERTREND_MULTIPLIER}\"\n",
"price_data.rename(columns={supertrend_col_name: 'supertrend_line'}, inplace=True)\n",
"\n",
"print(\"Supertrend calculation complete.\")\n",
"print(price_data.tail())"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "778fdcaa",
"metadata": {},
"outputs": [],
"source": [
"# %%\n",
"# --- 4. Strategy Logic & Signal Generation ---\n",
"print(\"Generating trading signals...\")\n",
"\n",
"# The signal is when the Close price crosses the Supertrend line.\n",
"# We use vectorbt's built-in signal functions for this.\n",
"entries = price_data['Close'].vbt.crossed_above(price_data['supertrend_line'])\n",
"exits = price_data['Close'].vbt.crossed_below(price_data['supertrend_line'])"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "895de355",
"metadata": {},
"outputs": [],
"source": [
"# %%\n",
"# --- 5. Backtesting and Analysis ---\n",
"print(\"Running backtest with vectorbt...\")\n",
"\n",
"# Create the portfolio from the generated signals\n",
"portfolio = vbt.Portfolio.from_signals(\n",
" price_data['Close'],\n",
" entries,\n",
" exits,\n",
" freq='15min', # Set the frequency of the data (15 minutes)\n",
" init_cash=10000,\n",
" fees=0.0001, # Example fee: 0.01%\n",
" slippage=0.0001 # Example slippage: 0.01%\n",
")\n",
"\n",
"# Print the performance statistics\n",
"print(\"\\n--- Backtest Results ---\")\n",
"print(portfolio.stats())"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "04ff5766",
"metadata": {},
"outputs": [],
"source": [
"# %%\n",
"# --- 6. Visualization (Optimized and Corrected) ---\n",
"print(\"\\nGenerating plot...\")\n",
"\n",
"# --- Performance Optimization for Plotting ---\n",
"# To avoid browser slowdowns, we will only plot the last 3 months of data.\n",
"# We use the modern `.loc` slicing method instead of the deprecated `.last()`.\n",
"print(\"Selecting the last 3 months of data for visualization...\")\n",
"end_date = price_data.index[-1]\n",
"start_date_plot = end_date - pd.DateOffset(months=3)\n",
"plot_data = price_data.loc[start_date_plot:]\n",
"\n",
"# --- Re-run Backtest on the Sliced Data for Clean Plotting ---\n",
"# This is the most robust way to get a portfolio object that matches the plot data.\n",
"# It's extremely fast, so there's no significant performance cost.\n",
"print(\"Running a quick backtest on the sliced data for plotting...\")\n",
"plot_entries = entries.loc[plot_data.index]\n",
"plot_exits = exits.loc[plot_data.index]\n",
"\n",
"plot_portfolio = vbt.Portfolio.from_signals(\n",
" plot_data['Close'],\n",
" plot_entries,\n",
" plot_exits,\n",
" freq='15min', # Use the corrected frequency string\n",
" init_cash=10000,\n",
" fees=0.0001,\n",
" slippage=0.0001\n",
")\n",
"\n",
"# --- Layered Plotting ---\n",
"# Step 1: Create the base candlestick chart from the SLICED data\n",
"fig = plot_data.vbt.ohlc.plot(\n",
" title_text=f'Supertrend Strategy on {DATA_FILENAME} (Last 3 Months)',\n",
" template='plotly_dark'\n",
")\n",
"\n",
"# Step 2: Add the Supertrend line from the SLICED data\n",
"fig.add_trace(\n",
" go.Scatter(\n",
" x=plot_data.index,\n",
" y=plot_data['supertrend_line'],\n",
" mode='lines',\n",
" name='Supertrend Line',\n",
" line=dict(color='yellow', width=1.5)\n",
" )\n",
")\n",
"\n",
"# Step 3: Add the trade markers from the NEWLY created plot_portfolio\n",
"plot_portfolio.trades.plot(fig=fig)\n",
"\n",
"# Step 4: Show the final, combined figure\n",
"fig.show()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "strategy-optimizer_env",
"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
}