{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Sliding Fit Strategy Visualization Notebook\n", "\n", "This notebook is specifically designed for the SlidingFitStrategy, which uses a sliding window approach.\n", "It re-trains the model every minute and shows how cointegration, model parameters, and trading signals evolve over time.\n", "You can visualize the dynamic nature of the sliding window and how the relationship between instruments changes." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 🎯 Key Features:\n", "\n", "1. **Interactive Configuration**: \n", " - Easy switching between CRYPTO and EQUITY configurations\n", " - Simple parameter adjustment for thresholds and training periods\n", "\n", "2. **Single Pair Focus**: \n", " - Instead of running multiple pairs, focuses on one pair at a time\n", " - Allows deep analysis of the relationship between two instruments\n", "\n", "3. **Step-by-Step Visualization**:\n", " - **Raw price data**: Individual prices, normalized comparison, and price ratios\n", " - **Training analysis**: Cointegration testing and VECM model fitting\n", " - **Dis-equilibrium visualization**: Both raw and scaled dis-equilibrium with threshold lines\n", " - **Strategy execution**: Trading signal generation and visualization\n", " - **Prediction analysis**: Actual vs predicted prices with trading signals overlaid\n", "\n", "4. **Rich Analytics**:\n", " - Cointegration status and VECM model details\n", " - Statistical summaries for all stages\n", " - Threshold crossing analysis\n", " - Trading signal breakdown\n", "\n", "5. **Interactive Experimentation**:\n", " - Easy parameter modification\n", " - Re-run capabilities for different configurations\n", " - Support for both StaticFitStrategy and SlidingFitStrategy\n", "\n", "### 🚀 How to Use:\n", "\n", "1. **Start Jupyter**:\n", " ```bash\n", " cd src/notebooks\n", " jupyter notebook pairs_trading_visualization.ipynb\n", " ```\n", "\n", "2. **Customize Your Analysis**:\n", " - Change `SYMBOL_A` and `SYMBOL_B` to your desired trading pair\n", " - Switch between `CRYPTO_CONFIG` and `EQT_CONFIG`\n", " - Choose your strategy (StaticFitStrategy or SlidingFitStrategy)\n", " - Adjust thresholds and parameters as needed\n", "\n", "3. **Run and Visualize**:\n", " - Execute cells step by step to see the analysis unfold\n", " - Rich matplotlib visualizations show relationships and signals\n", " - Comprehensive summary at the end\n", "\n", "The notebook provides exactly what you requested - a way to visualize the relationship between two instruments and their scaled dis-equilibrium, with all the stages of your pairs trading strategy clearly displayed and analyzed.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Setup and Imports" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "# Trading Parameters Configuration\n", "# Specify your configuration file, trading symbols and date here\n", "\n", "# Configuration file selection\n", "CONFIG_FILE = \"equity\" # Options: \"equity\", \"crypto\", or custom filename (without .cfg extension)\n", "\n", "# Trading pair symbols\n", "SYMBOL_A = \"COIN\" # Change this to your desired symbol A\n", "SYMBOL_B = \"MSTR\" # Change this to your desired symbol B\n", "\n", "# Date for data file selection (format: YYYYMMDD)\n", "TRADING_DATE = \"20250605\" # Change this to your desired date\n", "\n" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Setup complete!\n" ] } ], "source": [ "import sys\n", "import os\n", "sys.path.append('..')\n", "\n", "import pandas as pd\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "import seaborn as sns\n", "from typing import Dict, List, Optional\n", "from IPython.display import clear_output\n", "\n", "# Import our modules\n", "from strategies import SlidingFitStrategy, PairState\n", "from tools.data_loader import load_market_data\n", "from tools.trading_pair import TradingPair\n", "from results import BacktestResult\n", "\n", "# Set plotting style\n", "plt.style.use('seaborn-v0_8')\n", "sns.set_palette(\"husl\")\n", "plt.rcParams['figure.figsize'] = (15, 10)\n", "\n", "print(\"Setup complete!\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Configuration" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "# Load Configuration from Configuration Files using HJSON\n", "import hjson\n", "import os\n", "\n", "def load_config_from_file(config_type=\"equity\"):\n", " \"\"\"Load configuration from configuration files using HJSON\"\"\"\n", " config_file = f\"../../configuration/{config_type}.cfg\"\n", " \n", " try:\n", " with open(config_file, 'r') as f:\n", " # HJSON handles comments, trailing commas, and other human-friendly features\n", " config = hjson.load(f)\n", " \n", " # Convert relative paths to absolute paths from notebook perspective\n", " if 'data_directory' in config:\n", " data_dir = config['data_directory']\n", " if data_dir.startswith('./'):\n", " # Convert relative path to absolute path from notebook's perspective\n", " config['data_directory'] = os.path.abspath(f\"../../{data_dir[2:]}\")\n", " \n", " return config\n", " \n", " except FileNotFoundError:\n", " print(f\"Configuration file not found: {config_file}\")\n", " return None\n", " except hjson.HjsonDecodeError as e:\n", " print(f\"HJSON parsing error in {config_file}: {e}\")\n", " return None\n", " except Exception as e:\n", " print(f\"Unexpected error loading config from {config_file}: {e}\")\n", " return None\n", "\n" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Trading Parameters:\n", " Configuration: equity\n", " Symbol A: COIN\n", " Symbol B: MSTR\n", " Trading Date: 20250605\n", "\n", "Loading equity configuration using HJSON...\n", "✓ Successfully loaded EQUITY configuration\n", " Data directory: /home/oleg/develop/pairs_trading/data/equity\n", " Database table: md_1min_bars\n", " Exchange: ALPACA\n", " Training window: 120 minutes\n", " Open threshold: 2\n", " Close threshold: 1\n", "\n", "Data Configuration:\n", " Data File: 20250605.mktdata.ohlcv.db\n", " Security Type: EQUITY\n", " ✓ Data file found: /home/oleg/develop/pairs_trading/data/equity/20250605.mktdata.ohlcv.db\n" ] } ], "source": [ "print(f\"Trading Parameters:\")\n", "print(f\" Configuration: {CONFIG_FILE}\")\n", "print(f\" Symbol A: {SYMBOL_A}\")\n", "print(f\" Symbol B: {SYMBOL_B}\")\n", "print(f\" Trading Date: {TRADING_DATE}\")\n", "\n", "# Load the specified configuration\n", "print(f\"\\nLoading {CONFIG_FILE} configuration using HJSON...\")\n", "CONFIG = load_config_from_file(CONFIG_FILE)\n", "\n", "if CONFIG:\n", " print(f\"✓ Successfully loaded {CONFIG['security_type']} configuration\")\n", " print(f\" Data directory: {CONFIG['data_directory']}\")\n", " print(f\" Database table: {CONFIG['db_table_name']}\")\n", " print(f\" Exchange: {CONFIG['exchange_id']}\")\n", " print(f\" Training window: {CONFIG['training_minutes']} minutes\")\n", " print(f\" Open threshold: {CONFIG['dis-equilibrium_open_trshld']}\")\n", " print(f\" Close threshold: {CONFIG['dis-equilibrium_close_trshld']}\")\n", " \n", " # Automatically construct data file name based on date and config type\n", " # if CONFIG['security_type'] == \"CRYPTO\":\n", " DATA_FILE = f\"{TRADING_DATE}.mktdata.ohlcv.db\"\n", " # elif CONFIG['security_type'] == \"EQUITY\":\n", " # DATA_FILE = f\"{TRADING_DATE}.alpaca_sim_md.db\"\n", " # else:\n", " # DATA_FILE = f\"{TRADING_DATE}.mktdata.db\" # Default fallback\n", "\n", " # Update CONFIG with the specific data file and instruments\n", " CONFIG[\"datafiles\"] = [DATA_FILE]\n", " CONFIG[\"instruments\"] = [SYMBOL_A, SYMBOL_B]\n", " \n", " print(f\"\\nData Configuration:\")\n", " print(f\" Data File: {DATA_FILE}\")\n", " print(f\" Security Type: {CONFIG['security_type']}\")\n", " \n", " # Verify data file exists\n", " import os\n", " data_file_path = f\"{CONFIG['data_directory']}/{DATA_FILE}\"\n", " if os.path.exists(data_file_path):\n", " print(f\" ✓ Data file found: {data_file_path}\")\n", " else:\n", " print(f\" ⚠Data file not found: {data_file_path}\")\n", " print(f\" Please check if the date and file exist in the data directory\")\n", " \n", " # List available files in the data directory\n", " try:\n", " data_dir = CONFIG['data_directory']\n", " if os.path.exists(data_dir):\n", " available_files = [f for f in os.listdir(data_dir) if f.endswith('.db')]\n", " print(f\" Available files in {data_dir}:\")\n", " for file in sorted(available_files)[:5]: # Show first 5 files\n", " print(f\" - {file}\")\n", " if len(available_files) > 5:\n", " print(f\" ... and {len(available_files)-5} more files\")\n", " except Exception as e:\n", " print(f\" Could not list files in data directory: {e}\")\n", "else:\n", " print(\"⚠Failed to load configuration. Please check the configuration file.\")\n", " print(\"Available configuration files:\")\n", " config_dir = \"../../configuration\"\n", " if os.path.exists(config_dir):\n", " config_files = [f for f in os.listdir(config_dir) if f.endswith('.cfg')]\n", " for file in config_files:\n", " print(f\" - {file}\")\n", " else:\n", " print(f\" Configuration directory not found: {config_dir}\")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Select Trading Pair and Initialize Strategy" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Strategy Initialization:\n", " Selected pair: COIN & MSTR\n", " Data file: 20250605.mktdata.ohlcv.db\n", " Strategy: SlidingFitStrategy\n", "\n", "Strategy characteristics:\n", " - Sliding window training every minute\n", " - Dynamic cointegration testing\n", " - State-based position management\n", " - Continuous model re-training\n" ] } ], "source": [ "# Initialize Strategy\n", "# Trading pair and data file are now defined in the previous cell\n", "\n", "# Initialize SlidingFitStrategy\n", "STRATEGY = SlidingFitStrategy()\n", "\n", "print(f\"Strategy Initialization:\")\n", "print(f\" Selected pair: {SYMBOL_A} & {SYMBOL_B}\")\n", "print(f\" Data file: {DATA_FILE}\")\n", "print(f\" Strategy: {type(STRATEGY).__name__}\")\n", "print(f\"\\nStrategy characteristics:\")\n", "print(f\" - Sliding window training every minute\")\n", "print(f\" - Dynamic cointegration testing\")\n", "print(f\" - State-based position management\")\n", "print(f\" - Continuous model re-training\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Load and Prepare Market Data" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Loading data from: /home/oleg/develop/pairs_trading/data/equity/20250605.mktdata.ohlcv.db\n", "Loaded 782 rows of market data\n", "Symbols in data: ['COIN' 'MSTR']\n", "Time range: 2025-06-05 13:30:00 to 2025-06-05 20:00:00\n", "\n", "Created trading pair: COIN & MSTR\n", "Market data shape: (391, 3)\n", "Column names: ['close_COIN', 'close_MSTR']\n", "\n", "Sliding window analysis:\n", " Training window size: 120 minutes\n", " Maximum iterations: 271\n", " Total analysis time: ~271 minutes\n", "\n", "Sample data:\n" ] }, { "data": { "text/html": [ "
| \n", " | tstamp | \n", "close_COIN | \n", "close_MSTR | \n", "
|---|---|---|---|
| 0 | \n", "2025-06-05 13:30:00 | \n", "263.380 | \n", "384.7700 | \n", "
| 1 | \n", "2025-06-05 13:31:00 | \n", "265.385 | \n", "382.7806 | \n", "
| 2 | \n", "2025-06-05 13:32:00 | \n", "263.735 | \n", "379.8300 | \n", "
| 3 | \n", "2025-06-05 13:33:00 | \n", "264.250 | \n", "380.0400 | \n", "
| 4 | \n", "2025-06-05 13:34:00 | \n", "262.230 | \n", "379.6400 | \n", "