{ "cells": [ { "cell_type": "code", "execution_count": null, "id": "a9834d4d", "metadata": {}, "outputs": [], "source": [ "# -*- coding: utf-8 -*-\n", "\"\"\"\n", "Stationarity Test for BTC/ETH Spread\n", "\n", "This notebook:\n", "1. Loads BTCUSDT and ETHUSDT close prices\n", "2. Computes ratio and difference series\n", "3. Plots raw series, rolling means, and residuals\n", "4. Runs stationarity tests (ADF & KPSS)\n", "\"\"\"\n", "\n", "import pandas as pd\n", "import plotly.graph_objects as go\n", "from statsmodels.tsa.stattools import adfuller, kpss\n", "\n", "# ======================================\n", "# Load Data\n", "# ======================================\n", "btc = pd.read_csv(r'C:\\Users\\amirs\\OneDrive\\Desktop\\myAlgoCode\\detector\\BTCUSDT_1m_1000d.csv')\n", "eth = pd.read_csv(r'C:\\Users\\amirs\\OneDrive\\Desktop\\myAlgoCode\\detector\\ETHUSDT_1m_1000d.csv')\n", "\n", "btc_price = btc['close']\n", "eth_price = eth['close']\n", "\n", "# ======================================\n", "# Helper: Stationarity Tests\n", "# ======================================\n", "def run_stationarity_tests(series, name=\"Series\", sample_step=10):\n", " \"\"\"\n", " Run KPSS and ADF tests on a given series.\n", " Subsamples the series for ADF to avoid memory issues.\n", " \"\"\"\n", " series = series.dropna()\n", "\n", " print(f\"\\n=== {name} ===\")\n", "\n", " # KPSS Test\n", " print(\"\\n--- KPSS Test ---\")\n", " kpss_result = kpss(series, regression='c', nlags=\"auto\")\n", " print(f\"Statistic : {kpss_result[0]:.4f}\")\n", " print(f\"p-value : {kpss_result[1]:.4f}\")\n", " print(f\"Lags Used : {kpss_result[2]}\")\n", " print(\"Critical Values:\")\n", " for key, value in kpss_result[3].items():\n", " print(f\" {key} : {value:.4f}\")\n", " print(\"=> Stationary\" if kpss_result[1] > 0.05 else \"=> Non-stationary\")\n", "\n", " # ADF Test\n", " print(\"\\n--- Augmented Dickey-Fuller Test ---\")\n", " adf_result = adfuller(series[::sample_step])\n", " print(f\"ADF Statistic : {adf_result[0]:.4f}\")\n", " print(f\"p-value : {adf_result[1]:.4f}\")\n", " print(f\"Lags Used : {adf_result[2]}\")\n", " print(f\"Observations : {adf_result[3]}\")\n", " print(\"Critical Values:\")\n", " for key, value in adf_result[4].items():\n", " print(f\" {key} : {value:.4f}\")\n", " print(\"=> Stationary\" if adf_result[1] < 0.05 else \"=> Non-stationary\")\n", "\n", "\n", "# ======================================\n", "# Ratio Series (BTC/ETH)\n", "# ======================================\n", "z_ratio = btc_price / eth_price\n", "rolling_mean_ratio = z_ratio.rolling(60*24).mean()\n", "ratio_resid = z_ratio - rolling_mean_ratio\n", "\n", "# Plot ratio & rolling mean\n", "fig = go.Figure()\n", "fig.add_trace(go.Scatter(y=z_ratio, mode=\"lines\", name=\"BTC/ETH Ratio\", line=dict(color=\"green\")))\n", "fig.add_trace(go.Scatter(y=rolling_mean_ratio, mode=\"lines\", name=\"Rolling Mean (1d)\", line=dict(color=\"red\")))\n", "fig.update_layout(title=\"BTC/ETH Ratio with Rolling Mean\", template=\"plotly\")\n", "fig.show()\n", "\n", "# Plot residuals\n", "fig = go.Figure()\n", "fig.add_trace(go.Scatter(y=ratio_resid, mode=\"lines\", name=\"Residuals\", line=dict(color=\"blue\")))\n", "fig.update_layout(title=\"BTC/ETH Ratio Residuals\", template=\"plotly\")\n", "fig.show()\n", "\n", "# Run tests\n", "run_stationarity_tests(ratio_resid, name=\"BTC/ETH Ratio Residuals\")\n", "\n", "# ======================================\n", "# Difference Series (BTC - ETH)\n", "# ======================================\n", "z_diff = btc_price - eth_price\n", "rolling_mean_diff = z_diff.rolling(60*24).mean()\n", "diff_resid = z_diff - rolling_mean_diff\n", "diff_resid_mean = diff_resid.rolling(60*24*30).mean() # 30-day rolling mean of residuals\n", "\n", "# Plot diff residuals\n", "fig = go.Figure()\n", "fig.add_trace(go.Scatter(y=diff_resid, mode=\"lines\", name=\"Residuals\", line=dict(color=\"green\")))\n", "fig.add_trace(go.Scatter(y=diff_resid_mean, mode=\"lines\", name=\"Rolling Mean (30d)\", line=dict(color=\"red\")))\n", "fig.update_layout(title=\"BTC-ETH Difference Residuals\", template=\"plotly\")\n", "fig.show()\n", "\n", "# Run tests\n", "run_stationarity_tests(diff_resid, name=\"BTC-ETH Difference Residuals\")\n" ] } ], "metadata": { "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 5 }