From c2bb873267b55f2ed46d9c165512f74164ea5c51 Mon Sep 17 00:00:00 2001 From: Dane Isburgh Date: Sat, 10 Feb 2024 19:04:08 -0500 Subject: [PATCH] chore: add multiple options historical test notebook --- .../multiple-options-historical-test.ipynb | 1746 +++++++++++++++++ 1 file changed, 1746 insertions(+) create mode 100644 notebooks/multiple-options-historical-test.ipynb diff --git a/notebooks/multiple-options-historical-test.ipynb b/notebooks/multiple-options-historical-test.ipynb new file mode 100644 index 0000000..3397f2f --- /dev/null +++ b/notebooks/multiple-options-historical-test.ipynb @@ -0,0 +1,1746 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "563c124a", + "metadata": { + "_cell_guid": "b1076dfc-b9ad-4769-8c92-a6c4dae69d19", + "_uuid": "8f2839f25d086af736a60e9eeb907d3b93b6e0e5", + "papermill": { + "duration": 0.037344, + "end_time": "2023-02-27T05:31:50.171956", + "exception": false, + "start_time": "2023-02-27T05:31:50.134612", + "status": "completed" + }, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "data/spy-options-data-2020-2022/spy_2020_2022.csv\n", + "data/qqq-options-data-2020-2022/qqq_2020_2022.csv\n" + ] + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import os\n", + "import pandas as pd\n", + "import pandas_ta as ta\n", + "\n", + "%matplotlib widget\n", + "pd.options.display.max_columns = 100\n", + "pd.options.display.max_rows = 100\n", + "\n", + "product_data = {\n", + " \"SPY\": {\n", + " \"directory_path\": \"data/spy-options-data-2020-2022\",\n", + " \"df_raw\": None,\n", + " \"df_final\": None,\n", + " \"df_option_history\": None,\n", + " },\n", + " \"QQQ\": {\n", + " \"directory_path\": \"data/qqq-options-data-2020-2022\",\n", + " \"df_raw\": None,\n", + " \"df_final\": None,\n", + " \"df_option_history\": None,\n", + " },\n", + "}\n", + "\n", + "for product_id in product_data.keys():\n", + " dfs = []\n", + "\n", + " for dirname, _, filenames in os.walk(product_data[product_id][\"directory_path\"]):\n", + " for filename in filenames:\n", + " data_path = os.path.join(dirname, filename)\n", + " print(data_path)\n", + " dfs.append(pd.read_csv(data_path, low_memory=False))\n", + "\n", + " df_raw = pd.concat(dfs)\n", + " columns = df_raw.columns\n", + " columns = [s.replace(\"[\", \"\") for s in columns]\n", + " columns = [s.replace(\"]\", \"\") for s in columns]\n", + " columns = [s.replace(\" \", \"\") for s in columns]\n", + " df_raw.columns = columns\n", + "\n", + " product_data[product_id][\"df_raw\"] = df_raw" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "4e199f2c", + "metadata": { + "papermill": { + "duration": 10.257179, + "end_time": "2023-02-27T05:32:14.035264", + "exception": false, + "start_time": "2023-02-27T05:32:03.778085", + "status": "completed" + }, + "tags": [] + }, + "outputs": [], + "source": [ + "for product_id in product_data.keys():\n", + " df_raw = product_data[product_id][\"df_raw\"]\n", + " date_columns = [\"QUOTE_READTIME\", \"QUOTE_DATE\", \"EXPIRE_DATE\"]\n", + " numeric_cols = df_raw.columns.to_list()\n", + " numeric_cols.remove(\"QUOTE_READTIME\")\n", + " numeric_cols.remove(\"QUOTE_DATE\")\n", + " numeric_cols.remove(\"EXPIRE_DATE\")\n", + "\n", + " df_numeric = df_raw.drop(columns=date_columns)\n", + "\n", + " for i in numeric_cols:\n", + " df_numeric[i] = pd.to_numeric(df_numeric[i], errors=\"coerce\")\n", + "\n", + " df_final = df_numeric.drop(columns=[\"C_SIZE\", \"P_SIZE\"])\n", + " product_data[product_id][\"df_final\"] = df_final" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "7aa6169d-117f-4b6b-8ff7-668533d80d7a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Retrieving historical ETF fear and greed index\n", + "Retrieving historical ETF fear and greed index\n" + ] + } + ], + "source": [ + "for product_id in product_data.keys():\n", + " df_final = product_data[product_id][\"df_final\"]\n", + " df_option_history = df_final.copy()\n", + "\n", + " df_option_history[\"EXPIRE_UNIX\"] = pd.to_datetime(df_option_history.EXPIRE_UNIX, unit=\"s\", utc=True)\n", + " df_option_history[\"QUOTE_UNIXTIME\"] = pd.to_datetime(df_option_history.QUOTE_UNIXTIME, unit=\"s\", utc=True).apply(\n", + " lambda x: pd.Timestamp(x).round(freq=\"D\")\n", + " )\n", + "\n", + " df_option_history.set_index(pd.DatetimeIndex(df_option_history.QUOTE_UNIXTIME), inplace=True)\n", + " df_option_history.drop(columns=[\"QUOTE_UNIXTIME\"], inplace=True)\n", + " df_option_history.sort_index(inplace=True)\n", + "\n", + " df_option_history[\"UNDERLYING_PRODUCT_ID\"] = product_id\n", + " df_option_history[\"OPTION_ID\"] = (\n", + " df_option_history[\"UNDERLYING_PRODUCT_ID\"]\n", + " + df_option_history[\"EXPIRE_UNIX\"].astype(str)\n", + " + df_option_history[\"STRIKE\"].astype(str)\n", + " )\n", + " df_option_history[\"OPTION_ID\"] = df_option_history[\"OPTION_ID\"].apply(lambda x: hash(x))\n", + "\n", + " def get_df_cnn_fear_greed_index():\n", + " print(\"Retrieving historical ETF fear and greed index\")\n", + " import json\n", + "\n", + " with open(\"cnn_fear_greed_index_data.json\") as f:\n", + " cnn_fear_greed_index_data = json.load(f)\n", + "\n", + " df_fear_greed_index = pd.DataFrame(\n", + " data=cnn_fear_greed_index_data[\"data\"][\"c:50108\"][\"series\"][0], columns=[\"x\", \"y\"]\n", + " )\n", + " df_fear_greed_index.set_index(\n", + " pd.DatetimeIndex([pd.Timestamp(x, unit=\"s\", tz=\"UTC\") for x in df_fear_greed_index.x]),\n", + " inplace=True,\n", + " )\n", + " df_fear_greed_index.rename(columns={\"y\": \"fear_greed_index\"}, inplace=True)\n", + " df_fear_greed_index[\"fear_greed_index\"] = df_fear_greed_index.fear_greed_index.astype(float).round()\n", + " return df_fear_greed_index\n", + "\n", + " df_fear_greed_index = get_df_cnn_fear_greed_index()\n", + " df_option_history = df_option_history.join(df_fear_greed_index, how=\"inner\")\n", + "\n", + " df_history = df_option_history.groupby(df_option_history.index).first()[[\"UNDERLYING_LAST\", \"fear_greed_index\"]]\n", + " # df_history = df_option_history.groupby(df_option_history.index).first()[[\"UNDERLYING_LAST\"]]\n", + " df_history.rename(columns={\"UNDERLYING_LAST\": \"close\"}, inplace=True)\n", + "\n", + " CustomStrategy = ta.Strategy(\n", + " name=\"RSI\",\n", + " ta=[\n", + " {\"kind\": \"rsi\", \"length\": 14},\n", + " ],\n", + " )\n", + " df_history.ta.strategy(CustomStrategy)\n", + "\n", + " for column in [\"close\", \"fear_greed_index\", \"RSI_14\"]:\n", + " for days in [14]:\n", + " periods = days\n", + " df_history[f\"{column}_min_{days}\"] = df_history[column].rolling(window=periods, min_periods=periods).min()\n", + " df_history[f\"{column}_max_{days}\"] = df_history[column].rolling(window=periods, min_periods=periods).max()\n", + "\n", + " # df_option_history = df_option_history.join(df_history, how=\"inner\")\n", + " df_option_history = df_option_history.join(df_history.drop(columns=[\"fear_greed_index\"]), how=\"inner\")\n", + " df_option_history[\"index\"] = df_option_history.index\n", + " df_option_history.sort_values(by=[\"index\", \"EXPIRE_UNIX\", \"DTE\", \"STRIKE_DISTANCE_PCT\"], inplace=True)\n", + "\n", + " product_data[product_id][\"df_option_history\"] = df_option_history" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "094e8869-7d66-4c91-b590-a1e00c9d5a92", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
QUOTE_TIME_HOURSUNDERLYING_LASTEXPIRE_UNIXDTEC_DELTAC_GAMMAC_VEGAC_THETAC_RHOC_IVC_VOLUMEC_LASTC_BIDC_ASKSTRIKEP_BIDP_ASKP_LASTP_DELTAP_GAMMAP_VEGAP_THETAP_RHOP_IVP_VOLUMESTRIKE_DISTANCESTRIKE_DISTANCE_PCTUNDERLYING_PRODUCT_IDOPTION_IDxfear_greed_indexcloseRSI_14close_min_14close_max_14fear_greed_index_min_14fear_greed_index_max_14RSI_14_min_14RSI_14_max_14index
2021-05-18 00:00:00+00:0016.0324.442021-05-17 20:00:00+00:000.01.000000.000000.00000-0.000350.00694NaNNaN0.350.340.44324.00.030.070.04-0.185850.542610.03924-0.05014-0.000940.03353NaN0.40.001QQQ-85783055652344111722021-05-1835.0324.44NaNNaNNaNNaNNaNNaNNaN2021-05-18 00:00:00+00:00
2021-05-18 00:00:00+00:0016.0324.442021-05-17 20:00:00+00:000.00.098260.400270.02551-0.020060.000690.03015NaN0.020.010.04325.00.610.760.79-0.747890.380480.04665-0.12534-0.004330.05740NaN0.60.002QQQ-39122519409114326382021-05-1835.0324.44NaNNaNNaNNaNNaNNaNNaN2021-05-18 00:00:00+00:00
2021-05-18 00:00:00+00:0016.0324.442021-05-17 20:00:00+00:000.00.030290.083120.01023-0.01026-0.000030.05774NaN0.030.020.02326.01.561.711.84-0.875220.146380.02973-0.08046-0.004730.09216481.01.60.005QQQ-7967741117193267682021-05-1835.0324.44NaNNaNNaNNaNNaNNaNNaN2021-05-18 00:00:00+00:00
2021-05-18 00:00:00+00:0016.0324.442021-05-17 20:00:00+00:000.01.000000.000000.00000-0.000170.00682NaNNaN2.382.262.42322.00.020.030.01-0.029430.051430.00999-0.01417-0.000160.08914NaN2.40.008QQQ-83050441595691294642021-05-1835.0324.44NaNNaNNaNNaNNaNNaNNaN2021-05-18 00:00:00+00:00
2021-05-18 00:00:00+00:0016.0324.442021-05-17 20:00:00+00:000.00.009530.017190.00381-0.00535-0.000390.10426NaN0.010.000.01328.03.543.704.03-0.927700.045730.02007-0.06009-0.003850.16061130.03.60.011QQQ-10704385775027523432021-05-1835.0324.44NaNNaNNaNNaNNaNNaNNaN2021-05-18 00:00:00+00:00
...........................................................................................................................
2022-12-31 00:00:00+00:0016.0382.442025-12-19 21:00:00+00:001085.00.105950.001501.19348-0.012041.051290.177702.05.710.5910.00630.0243.00250.500.00-1.000000.000000.000000.000000.00000NaNNaN247.60.647SPY-26020910600954015252022-12-3138.0382.4444.376002376.71401.9536.061.037.97203156.5454852022-12-31 00:00:00+00:00
2022-12-31 00:00:00+00:0016.0382.442025-12-19 21:00:00+00:001085.00.093920.001401.09723-0.010820.942070.17304NaN0.002.007.00635.0247.66257.500.00-0.894310.003070.72687-0.00434-0.203300.29557NaN252.60.660SPY-28729504153844011992022-12-3138.0382.4444.376002376.71401.9536.061.037.97203156.5454852022-12-31 00:00:00+00:00
2022-12-31 00:00:00+00:0016.0382.442025-12-19 21:00:00+00:001085.00.092790.001371.08956-0.011140.931990.17558NaN0.002.007.00640.0253.00262.500.00-0.885360.002980.78662-0.00524-1.787770.30289NaN257.60.673SPY-61626820960788522492022-12-3138.0382.4444.376002376.71401.9536.061.037.97203156.5454852022-12-31 00:00:00+00:00
2022-12-31 00:00:00+00:0016.0382.442025-12-19 21:00:00+00:001085.00.099380.001471.14502-0.011280.990680.182393.04.330.1210.00645.0258.00267.500.00-0.882640.002870.79928-0.00538-1.829850.30699NaN262.60.687SPY39373551876004158412022-12-3138.0382.4444.376002376.71401.9536.061.037.97203156.5454852022-12-31 00:00:00+00:00
2022-12-31 00:00:00+00:0016.0382.442025-12-19 21:00:00+00:001085.00.114330.001491.25917-0.013241.116890.195612.04.152.6010.00650.0262.75272.500.00-0.884670.002880.78257-0.00516-0.631950.31007NaN267.60.700SPY46086049513686750582022-12-3138.0382.4444.376002376.71401.9536.061.037.97203156.5454852022-12-31 00:00:00+00:00
\n", + "

2924028 rows × 40 columns

\n", + "
" + ], + "text/plain": [ + " QUOTE_TIME_HOURS UNDERLYING_LAST \\\n", + "2021-05-18 00:00:00+00:00 16.0 324.44 \n", + "2021-05-18 00:00:00+00:00 16.0 324.44 \n", + "2021-05-18 00:00:00+00:00 16.0 324.44 \n", + "2021-05-18 00:00:00+00:00 16.0 324.44 \n", + "2021-05-18 00:00:00+00:00 16.0 324.44 \n", + "... ... ... \n", + "2022-12-31 00:00:00+00:00 16.0 382.44 \n", + "2022-12-31 00:00:00+00:00 16.0 382.44 \n", + "2022-12-31 00:00:00+00:00 16.0 382.44 \n", + "2022-12-31 00:00:00+00:00 16.0 382.44 \n", + "2022-12-31 00:00:00+00:00 16.0 382.44 \n", + "\n", + " EXPIRE_UNIX DTE C_DELTA C_GAMMA \\\n", + "2021-05-18 00:00:00+00:00 2021-05-17 20:00:00+00:00 0.0 1.00000 0.00000 \n", + "2021-05-18 00:00:00+00:00 2021-05-17 20:00:00+00:00 0.0 0.09826 0.40027 \n", + "2021-05-18 00:00:00+00:00 2021-05-17 20:00:00+00:00 0.0 0.03029 0.08312 \n", + "2021-05-18 00:00:00+00:00 2021-05-17 20:00:00+00:00 0.0 1.00000 0.00000 \n", + "2021-05-18 00:00:00+00:00 2021-05-17 20:00:00+00:00 0.0 0.00953 0.01719 \n", + "... ... ... ... ... \n", + "2022-12-31 00:00:00+00:00 2025-12-19 21:00:00+00:00 1085.0 0.10595 0.00150 \n", + "2022-12-31 00:00:00+00:00 2025-12-19 21:00:00+00:00 1085.0 0.09392 0.00140 \n", + "2022-12-31 00:00:00+00:00 2025-12-19 21:00:00+00:00 1085.0 0.09279 0.00137 \n", + "2022-12-31 00:00:00+00:00 2025-12-19 21:00:00+00:00 1085.0 0.09938 0.00147 \n", + "2022-12-31 00:00:00+00:00 2025-12-19 21:00:00+00:00 1085.0 0.11433 0.00149 \n", + "\n", + " C_VEGA C_THETA C_RHO C_IV C_VOLUME \\\n", + "2021-05-18 00:00:00+00:00 0.00000 -0.00035 0.00694 NaN NaN \n", + "2021-05-18 00:00:00+00:00 0.02551 -0.02006 0.00069 0.03015 NaN \n", + "2021-05-18 00:00:00+00:00 0.01023 -0.01026 -0.00003 0.05774 NaN \n", + "2021-05-18 00:00:00+00:00 0.00000 -0.00017 0.00682 NaN NaN \n", + "2021-05-18 00:00:00+00:00 0.00381 -0.00535 -0.00039 0.10426 NaN \n", + "... ... ... ... ... ... \n", + "2022-12-31 00:00:00+00:00 1.19348 -0.01204 1.05129 0.17770 2.0 \n", + "2022-12-31 00:00:00+00:00 1.09723 -0.01082 0.94207 0.17304 NaN \n", + "2022-12-31 00:00:00+00:00 1.08956 -0.01114 0.93199 0.17558 NaN \n", + "2022-12-31 00:00:00+00:00 1.14502 -0.01128 0.99068 0.18239 3.0 \n", + "2022-12-31 00:00:00+00:00 1.25917 -0.01324 1.11689 0.19561 2.0 \n", + "\n", + " C_LAST C_BID C_ASK STRIKE P_BID P_ASK \\\n", + "2021-05-18 00:00:00+00:00 0.35 0.34 0.44 324.0 0.03 0.07 \n", + "2021-05-18 00:00:00+00:00 0.02 0.01 0.04 325.0 0.61 0.76 \n", + "2021-05-18 00:00:00+00:00 0.03 0.02 0.02 326.0 1.56 1.71 \n", + "2021-05-18 00:00:00+00:00 2.38 2.26 2.42 322.0 0.02 0.03 \n", + "2021-05-18 00:00:00+00:00 0.01 0.00 0.01 328.0 3.54 3.70 \n", + "... ... ... ... ... ... ... \n", + "2022-12-31 00:00:00+00:00 5.71 0.59 10.00 630.0 243.00 250.50 \n", + "2022-12-31 00:00:00+00:00 0.00 2.00 7.00 635.0 247.66 257.50 \n", + "2022-12-31 00:00:00+00:00 0.00 2.00 7.00 640.0 253.00 262.50 \n", + "2022-12-31 00:00:00+00:00 4.33 0.12 10.00 645.0 258.00 267.50 \n", + "2022-12-31 00:00:00+00:00 4.15 2.60 10.00 650.0 262.75 272.50 \n", + "\n", + " P_LAST P_DELTA P_GAMMA P_VEGA P_THETA \\\n", + "2021-05-18 00:00:00+00:00 0.04 -0.18585 0.54261 0.03924 -0.05014 \n", + "2021-05-18 00:00:00+00:00 0.79 -0.74789 0.38048 0.04665 -0.12534 \n", + "2021-05-18 00:00:00+00:00 1.84 -0.87522 0.14638 0.02973 -0.08046 \n", + "2021-05-18 00:00:00+00:00 0.01 -0.02943 0.05143 0.00999 -0.01417 \n", + "2021-05-18 00:00:00+00:00 4.03 -0.92770 0.04573 0.02007 -0.06009 \n", + "... ... ... ... ... ... \n", + "2022-12-31 00:00:00+00:00 0.00 -1.00000 0.00000 0.00000 0.00000 \n", + "2022-12-31 00:00:00+00:00 0.00 -0.89431 0.00307 0.72687 -0.00434 \n", + "2022-12-31 00:00:00+00:00 0.00 -0.88536 0.00298 0.78662 -0.00524 \n", + "2022-12-31 00:00:00+00:00 0.00 -0.88264 0.00287 0.79928 -0.00538 \n", + "2022-12-31 00:00:00+00:00 0.00 -0.88467 0.00288 0.78257 -0.00516 \n", + "\n", + " P_RHO P_IV P_VOLUME STRIKE_DISTANCE \\\n", + "2021-05-18 00:00:00+00:00 -0.00094 0.03353 NaN 0.4 \n", + "2021-05-18 00:00:00+00:00 -0.00433 0.05740 NaN 0.6 \n", + "2021-05-18 00:00:00+00:00 -0.00473 0.09216 481.0 1.6 \n", + "2021-05-18 00:00:00+00:00 -0.00016 0.08914 NaN 2.4 \n", + "2021-05-18 00:00:00+00:00 -0.00385 0.16061 130.0 3.6 \n", + "... ... ... ... ... \n", + "2022-12-31 00:00:00+00:00 0.00000 NaN NaN 247.6 \n", + "2022-12-31 00:00:00+00:00 -0.20330 0.29557 NaN 252.6 \n", + "2022-12-31 00:00:00+00:00 -1.78777 0.30289 NaN 257.6 \n", + "2022-12-31 00:00:00+00:00 -1.82985 0.30699 NaN 262.6 \n", + "2022-12-31 00:00:00+00:00 -0.63195 0.31007 NaN 267.6 \n", + "\n", + " STRIKE_DISTANCE_PCT UNDERLYING_PRODUCT_ID \\\n", + "2021-05-18 00:00:00+00:00 0.001 QQQ \n", + "2021-05-18 00:00:00+00:00 0.002 QQQ \n", + "2021-05-18 00:00:00+00:00 0.005 QQQ \n", + "2021-05-18 00:00:00+00:00 0.008 QQQ \n", + "2021-05-18 00:00:00+00:00 0.011 QQQ \n", + "... ... ... \n", + "2022-12-31 00:00:00+00:00 0.647 SPY \n", + "2022-12-31 00:00:00+00:00 0.660 SPY \n", + "2022-12-31 00:00:00+00:00 0.673 SPY \n", + "2022-12-31 00:00:00+00:00 0.687 SPY \n", + "2022-12-31 00:00:00+00:00 0.700 SPY \n", + "\n", + " OPTION_ID x fear_greed_index \\\n", + "2021-05-18 00:00:00+00:00 -8578305565234411172 2021-05-18 35.0 \n", + "2021-05-18 00:00:00+00:00 -3912251940911432638 2021-05-18 35.0 \n", + "2021-05-18 00:00:00+00:00 -796774111719326768 2021-05-18 35.0 \n", + "2021-05-18 00:00:00+00:00 -8305044159569129464 2021-05-18 35.0 \n", + "2021-05-18 00:00:00+00:00 -1070438577502752343 2021-05-18 35.0 \n", + "... ... ... ... \n", + "2022-12-31 00:00:00+00:00 -2602091060095401525 2022-12-31 38.0 \n", + "2022-12-31 00:00:00+00:00 -2872950415384401199 2022-12-31 38.0 \n", + "2022-12-31 00:00:00+00:00 -6162682096078852249 2022-12-31 38.0 \n", + "2022-12-31 00:00:00+00:00 3937355187600415841 2022-12-31 38.0 \n", + "2022-12-31 00:00:00+00:00 4608604951368675058 2022-12-31 38.0 \n", + "\n", + " close RSI_14 close_min_14 close_max_14 \\\n", + "2021-05-18 00:00:00+00:00 324.44 NaN NaN NaN \n", + "2021-05-18 00:00:00+00:00 324.44 NaN NaN NaN \n", + "2021-05-18 00:00:00+00:00 324.44 NaN NaN NaN \n", + "2021-05-18 00:00:00+00:00 324.44 NaN NaN NaN \n", + "2021-05-18 00:00:00+00:00 324.44 NaN NaN NaN \n", + "... ... ... ... ... \n", + "2022-12-31 00:00:00+00:00 382.44 44.376002 376.71 401.95 \n", + "2022-12-31 00:00:00+00:00 382.44 44.376002 376.71 401.95 \n", + "2022-12-31 00:00:00+00:00 382.44 44.376002 376.71 401.95 \n", + "2022-12-31 00:00:00+00:00 382.44 44.376002 376.71 401.95 \n", + "2022-12-31 00:00:00+00:00 382.44 44.376002 376.71 401.95 \n", + "\n", + " fear_greed_index_min_14 fear_greed_index_max_14 \\\n", + "2021-05-18 00:00:00+00:00 NaN NaN \n", + "2021-05-18 00:00:00+00:00 NaN NaN \n", + "2021-05-18 00:00:00+00:00 NaN NaN \n", + "2021-05-18 00:00:00+00:00 NaN NaN \n", + "2021-05-18 00:00:00+00:00 NaN NaN \n", + "... ... ... \n", + "2022-12-31 00:00:00+00:00 36.0 61.0 \n", + "2022-12-31 00:00:00+00:00 36.0 61.0 \n", + "2022-12-31 00:00:00+00:00 36.0 61.0 \n", + "2022-12-31 00:00:00+00:00 36.0 61.0 \n", + "2022-12-31 00:00:00+00:00 36.0 61.0 \n", + "\n", + " RSI_14_min_14 RSI_14_max_14 \\\n", + "2021-05-18 00:00:00+00:00 NaN NaN \n", + "2021-05-18 00:00:00+00:00 NaN NaN \n", + "2021-05-18 00:00:00+00:00 NaN NaN \n", + "2021-05-18 00:00:00+00:00 NaN NaN \n", + "2021-05-18 00:00:00+00:00 NaN NaN \n", + "... ... ... \n", + "2022-12-31 00:00:00+00:00 37.972031 56.545485 \n", + "2022-12-31 00:00:00+00:00 37.972031 56.545485 \n", + "2022-12-31 00:00:00+00:00 37.972031 56.545485 \n", + "2022-12-31 00:00:00+00:00 37.972031 56.545485 \n", + "2022-12-31 00:00:00+00:00 37.972031 56.545485 \n", + "\n", + " index \n", + "2021-05-18 00:00:00+00:00 2021-05-18 00:00:00+00:00 \n", + "2021-05-18 00:00:00+00:00 2021-05-18 00:00:00+00:00 \n", + "2021-05-18 00:00:00+00:00 2021-05-18 00:00:00+00:00 \n", + "2021-05-18 00:00:00+00:00 2021-05-18 00:00:00+00:00 \n", + "2021-05-18 00:00:00+00:00 2021-05-18 00:00:00+00:00 \n", + "... ... \n", + "2022-12-31 00:00:00+00:00 2022-12-31 00:00:00+00:00 \n", + "2022-12-31 00:00:00+00:00 2022-12-31 00:00:00+00:00 \n", + "2022-12-31 00:00:00+00:00 2022-12-31 00:00:00+00:00 \n", + "2022-12-31 00:00:00+00:00 2022-12-31 00:00:00+00:00 \n", + "2022-12-31 00:00:00+00:00 2022-12-31 00:00:00+00:00 \n", + "\n", + "[2924028 rows x 40 columns]" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df_option_history = pd.concat([product_data[product_id][\"df_option_history\"] for product_id in product_data.keys()])\n", + "df_option_history.sort_values(\n", + " by=[\"index\", \"UNDERLYING_PRODUCT_ID\", \"EXPIRE_UNIX\", \"DTE\", \"STRIKE_DISTANCE_PCT\"], inplace=True\n", + ")\n", + "df_option_history" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "6fa62b1c-0b12-475f-93b9-c9719d5d44a3", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
QUOTE_TIME_HOURSUNDERLYING_LASTDTEC_DELTAC_GAMMAC_VEGAC_THETAC_RHOC_IVC_VOLUMEC_LASTC_BIDC_ASKSTRIKEP_BIDP_ASKP_LASTP_DELTAP_GAMMAP_VEGAP_THETAP_RHOP_IVP_VOLUMESTRIKE_DISTANCESTRIKE_DISTANCE_PCTOPTION_IDfear_greed_indexcloseRSI_14close_min_14close_max_14fear_greed_index_min_14fear_greed_index_max_14RSI_14_min_14RSI_14_max_14
count2924028.02924028.02924028.02923915.02923915.02923915.02923915.02923915.02760678.02288147.02921862.02921862.02921862.02924028.02921864.02921864.02921864.02923915.02923915.02923915.02923915.02923915.02727843.02268486.02924028.02924028.02924028.02924028.02924028.02793236.02802474.02802474.02802474.02802474.02678509.02678509.0
mean16.0384.4283184189752138.021397469517720.5147727075171475-0.14266524726950.37393658445953426-0.0624486126580286740.53386450206657870.32184403888465085223.6717426808679627.45722131982963542.8209144921971543.63370481905037378.434966594027136.41209915998826637.2027906979928117.72762483811704-0.4751130797851511-1.3617365511890733-3.372096385903825-0.09526726047781825-0.5821601944003160.33483247641084907278.7348861751846770.20244983974160.1851790229094933-5.510601608850764e+1639.008525910148606384.428318418975251.6879211539061372.19830265686676397.410733830180125.548625964058952.212838370668240.7211163882641960.877541732984994
std0.056.07916429168577192.175843559954930.3861001036753277253.3353304625550211.6514934771307160.077405793036403957.7294011775726370.362497349418848542948.963353816754550.1136370942132259.909997400824760.562646345379925103.5777122129331255.34932942300104556.0445095983943135.349041771466650.383797454837477851480.3815675885251.6430643414218550.6985629638230251.34261674922944320.2803954621622832867.374699873000769.386643706476630.182967958393020135.322665503534296e+1816.5875101815231656.0791642916857712.34475441331096455.8309268817512254.1328044188928713.96914876232752414.34095858293043710.3461882867599459.91193022420065
min16.0260.050.00.0-433189.70517-2815.39969-7.16086-2878.27141-0.00050.00.00.00.025.00.00.00.0-1.0-2211829.9611-2199.50048-43.52167-36.5688-0.00050.00.00.0-9.223268179247174e+184.0260.0523.20999431509113260.05282.174.022.023.2099943150911342.18860128883254
25%16.0349.8616.00.068010.00050.0311-0.084070.010390.194010.00.010.770.92314.01.71.790.02-0.896250.000570.05015-0.08544-0.560050.209220.021.60.057-4.677348367868452e+1827.0349.8641.85144511620841339.57368.4717.041.032.6379242159138852.672438402454766
50%16.0390.1543.00.582570.00280.21219-0.042480.11430.251481.03.3317.4118.06379.013.6914.282.98-0.420470.002880.24047-0.04357-0.111670.276242.047.30.125-6.743361482311614e+1637.0390.1550.69687314399896377.94402.4221.052.038.47040362697090660.6994653162677
75%16.0432.88191.040.90210.006840.57939-0.010350.542510.330713.031.3260.1561.45440.045.2146.4919.42-0.075040.006760.62677-0.01672-0.007960.3766930.098.60.264.520398356603582e+1852.0432.8861.698535691456804420.84444.8933.064.047.0751440230802968.28616665486885
max16.0477.771096.01.02.26443147.328070.0263.7268241.39908282571.0444.2445.08446.284898.04451.194455.5359.210.0280.8988781.846370.00.012.17003265102.04469.310.4259.222556436732245e+1877.0477.7783.36208171663986464.72477.7763.077.072.827664802766583.36208171663986
\n", + "
" + ], + "text/plain": [ + " QUOTE_TIME_HOURS UNDERLYING_LAST DTE \\\n", + "count 2924028.0 2924028.0 2924028.0 \n", + "mean 16.0 384.4283184189752 138.02139746951772 \n", + "std 0.0 56.07916429168577 192.17584355995493 \n", + "min 16.0 260.05 0.0 \n", + "25% 16.0 349.86 16.0 \n", + "50% 16.0 390.15 43.0 \n", + "75% 16.0 432.88 191.04 \n", + "max 16.0 477.77 1096.0 \n", + "\n", + " C_DELTA C_GAMMA C_VEGA \\\n", + "count 2923915.0 2923915.0 2923915.0 \n", + "mean 0.5147727075171475 -0.1426652472695 0.37393658445953426 \n", + "std 0.3861001036753277 253.33533046255502 11.651493477130716 \n", + "min 0.0 -433189.70517 -2815.39969 \n", + "25% 0.06801 0.0005 0.0311 \n", + "50% 0.58257 0.0028 0.21219 \n", + "75% 0.9021 0.00684 0.57939 \n", + "max 1.0 2.26443 147.32807 \n", + "\n", + " C_THETA C_RHO C_IV \\\n", + "count 2923915.0 2923915.0 2760678.0 \n", + "mean -0.062448612658028674 0.5338645020665787 0.32184403888465085 \n", + "std 0.07740579303640395 7.729401177572637 0.36249734941884854 \n", + "min -7.16086 -2878.27141 -0.0005 \n", + "25% -0.08407 0.01039 0.19401 \n", + "50% -0.04248 0.1143 0.25148 \n", + "75% -0.01035 0.54251 0.3307 \n", + "max 0.0 263.72682 41.39908 \n", + "\n", + " C_VOLUME C_LAST C_BID \\\n", + "count 2288147.0 2921862.0 2921862.0 \n", + "mean 223.67174268086796 27.457221319829635 42.82091449219715 \n", + "std 2948.9633538167545 50.11363709421322 59.9099974008247 \n", + "min 0.0 0.0 0.0 \n", + "25% 0.0 0.01 0.77 \n", + "50% 1.0 3.33 17.41 \n", + "75% 13.0 31.32 60.15 \n", + "max 282571.0 444.2 445.08 \n", + "\n", + " C_ASK STRIKE P_BID \\\n", + "count 2921862.0 2924028.0 2921864.0 \n", + "mean 43.63370481905037 378.4349665940271 36.412099159988266 \n", + "std 60.562646345379925 103.57771221293312 55.349329423001045 \n", + "min 0.0 25.0 0.0 \n", + "25% 0.92 314.0 1.7 \n", + "50% 18.06 379.0 13.69 \n", + "75% 61.45 440.0 45.21 \n", + "max 446.28 4898.0 4451.19 \n", + "\n", + " P_ASK P_LAST P_DELTA \\\n", + "count 2921864.0 2921864.0 2923915.0 \n", + "mean 37.20279069799281 17.72762483811704 -0.4751130797851511 \n", + "std 56.04450959839431 35.34904177146665 0.38379745483747785 \n", + "min 0.0 0.0 -1.0 \n", + "25% 1.79 0.02 -0.89625 \n", + "50% 14.28 2.98 -0.42047 \n", + "75% 46.49 19.42 -0.07504 \n", + "max 4455.5 359.21 0.0 \n", + "\n", + " P_GAMMA P_VEGA P_THETA \\\n", + "count 2923915.0 2923915.0 2923915.0 \n", + "mean -1.3617365511890733 -3.372096385903825 -0.09526726047781825 \n", + "std 1480.38156758852 51.643064341421855 0.698562963823025 \n", + "min -2211829.9611 -2199.50048 -43.52167 \n", + "25% 0.00057 0.05015 -0.08544 \n", + "50% 0.00288 0.24047 -0.04357 \n", + "75% 0.00676 0.62677 -0.01672 \n", + "max 280.89887 81.84637 0.0 \n", + "\n", + " P_RHO P_IV P_VOLUME \\\n", + "count 2923915.0 2727843.0 2268486.0 \n", + "mean -0.582160194400316 0.33483247641084907 278.73488617518467 \n", + "std 1.3426167492294432 0.280395462162283 2867.3746998730007 \n", + "min -36.5688 -0.0005 0.0 \n", + "25% -0.56005 0.20922 0.0 \n", + "50% -0.11167 0.27624 2.0 \n", + "75% -0.00796 0.37669 30.0 \n", + "max 0.0 12.17003 265102.0 \n", + "\n", + " STRIKE_DISTANCE STRIKE_DISTANCE_PCT OPTION_ID \\\n", + "count 2924028.0 2924028.0 2924028.0 \n", + "mean 70.2024498397416 0.1851790229094933 -5.510601608850764e+16 \n", + "std 69.38664370647663 0.18296795839302013 5.322665503534296e+18 \n", + "min 0.0 0.0 -9.223268179247174e+18 \n", + "25% 21.6 0.057 -4.677348367868452e+18 \n", + "50% 47.3 0.125 -6.743361482311614e+16 \n", + "75% 98.6 0.26 4.520398356603582e+18 \n", + "max 4469.3 10.425 9.222556436732245e+18 \n", + "\n", + " fear_greed_index close RSI_14 \\\n", + "count 2924028.0 2924028.0 2793236.0 \n", + "mean 39.008525910148606 384.4283184189752 51.6879211539061 \n", + "std 16.58751018152316 56.07916429168577 12.344754413310964 \n", + "min 4.0 260.05 23.20999431509113 \n", + "25% 27.0 349.86 41.85144511620841 \n", + "50% 37.0 390.15 50.69687314399896 \n", + "75% 52.0 432.88 61.698535691456804 \n", + "max 77.0 477.77 83.36208171663986 \n", + "\n", + " close_min_14 close_max_14 fear_greed_index_min_14 \\\n", + "count 2802474.0 2802474.0 2802474.0 \n", + "mean 372.19830265686676 397.4107338301801 25.5486259640589 \n", + "std 55.83092688175122 54.13280441889287 13.969148762327524 \n", + "min 260.05 282.17 4.0 \n", + "25% 339.57 368.47 17.0 \n", + "50% 377.94 402.42 21.0 \n", + "75% 420.84 444.89 33.0 \n", + "max 464.72 477.77 63.0 \n", + "\n", + " fear_greed_index_max_14 RSI_14_min_14 RSI_14_max_14 \n", + "count 2802474.0 2678509.0 2678509.0 \n", + "mean 52.2128383706682 40.72111638826419 60.877541732984994 \n", + "std 14.340958582930437 10.346188286759945 9.91193022420065 \n", + "min 22.0 23.20999431509113 42.18860128883254 \n", + "25% 41.0 32.63792421591388 52.672438402454766 \n", + "50% 52.0 38.470403626970906 60.6994653162677 \n", + "75% 64.0 47.07514402308029 68.28616665486885 \n", + "max 77.0 72.8276648027665 83.36208171663986 " + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# for c in [\"UNDERLYING_LAST\", \"fear_greed_index\"]:\n", + "# df = df_option_history[[c]]\n", + "# df[\"date\"] = df.index\n", + "# df.drop_duplicates(subset=[\"date\", c]).plot(x=\"date\", y=c)\n", + "\n", + "df_option_history.describe().astype(str)" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "95a774ff-3056-460b-a80c-a39cac253015", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2021-06-10 QQQ $1027 1 buy call 2021-06-25 336.86 337.0 $486 3479158678833100675\n", + "2021-06-10 QQQ $117 2 buy call 2021-06-25 336.86 337.5 $454 -3598241872408703621\n", + "2021-06-11 SPY $0 3 buy call 2021-06-25 423.61 431.0 $58 -3094602456089219840\n", + "2021-06-16 QQQ $1305 2 sell call 2021-06-25 342.15 337.5 $653 -3598241872408703621\n", + "2021-06-16 QQQ $2685 1 sell call 2021-06-25 342.15 337.0 $691 3479158678833100675\n", + "2021-06-16 SPY $2782 0 sell call 2021-06-25 424.51 431.0 $49 -3094602456089219840\n", + "2021-07-07 QQQ $2275 1 buy put 2021-07-21 360.13 354.0 $253 1455647653561036424\n", + "2021-07-07 QQQ $1305 2 buy put 2021-07-23 360.13 360.0 $484 -2619219960940882630\n", + "2021-07-07 QQQ $414 3 buy put 2021-07-23 360.13 359.0 $445 -3008072389610402244\n", + "2021-07-07 SPY $-1 4 buy put 2021-07-21 432.88 427.0 $207 4274915379359932434\n", + "2021-07-09 QQQ $679 3 sell put 2021-07-21 358.79 354.0 $341 1455647653561036424\n", + "2021-07-09 QQQ $1820 2 sell put 2021-07-23 358.79 359.0 $571 -3008072389610402244\n", + "2021-07-09 QQQ $3035 1 sell put 2021-07-23 358.79 360.0 $608 -2619219960940882630\n", + "2021-07-09 SPY $3666 0 sell put 2021-07-21 430.87 427.0 $316 4274915379359932434\n", + "2021-07-15 QQQ $2570 1 buy put 2021-07-30 363.1 363.0 $547 7665537119925776718\n", + "2021-07-15 QQQ $1529 2 buy put 2021-07-30 363.1 362.5 $520 -4215429045744817303\n", + "2021-07-15 QQQ $344 3 buy put 2021-07-30 363.1 364.0 $592 4021412419915507109\n", + "2021-07-21 QQQ $1574 2 sell put 2021-07-30 358.78 362.5 $616 -4215429045744817303\n", + "2021-07-21 QQQ $2857 1 sell put 2021-07-30 358.78 363.0 $642 7665537119925776718\n", + "2021-07-21 QQQ $4264 0 sell put 2021-07-30 358.78 364.0 $704 4021412419915507109\n", + "2021-08-05 QQQ $3274 1 buy call 2021-08-20 367.34 367.0 $494 -2492154288151173285\n", + "2021-08-05 QQQ $2157 2 buy call 2021-08-20 367.34 366.0 $558 4029445948671140943\n", + "2021-08-05 QQQ $1402 3 buy call 2021-08-20 367.34 369.0 $377 7664081963786003086\n", + "2021-08-05 QQQ $168 4 buy call 2021-08-20 367.34 365.0 $616 -6352818614728215081\n", + "2021-08-06 SPY $29 5 buy call 2021-08-20 441.73 450.0 $69 -8845821036070862059\n", + "2021-08-13 QQQ $642 4 sell call 2021-08-20 367.58 367.0 $307 -2492154288151173285\n", + "2021-08-13 QQQ $1378 3 sell call 2021-08-20 367.58 366.0 $369 4029445948671140943\n", + "2021-08-13 QQQ $1775 2 sell call 2021-08-20 367.58 369.0 $199 7664081963786003086\n", + "2021-08-13 QQQ $2650 1 sell call 2021-08-20 367.58 365.0 $438 -6352818614728215081\n", + "2021-08-13 QQQ $1844 2 buy call 2021-08-27 367.58 368.0 $402 5701635151616173389\n", + "2021-08-13 QQQ $923 3 buy call 2021-08-27 367.58 367.0 $460 6833983001175984167\n", + "2021-08-13 QQQ $232 4 buy call 2021-08-27 367.58 369.0 $345 -29270181784786071\n", + "2021-08-13 SPY $42 5 buy call 2021-08-27 445.06 451.0 $94 -7049535863332786931\n", + "2021-08-17 QQQ $713 4 sell call 2021-08-27 368.97 369.0 $336 -29270181784786071\n", + "2021-08-17 QQQ $1508 3 sell call 2021-08-27 368.97 368.0 $398 5701635151616173389\n", + "2021-08-17 QQQ $2434 2 sell call 2021-08-27 368.97 367.0 $464 6833983001175984167\n", + "2021-08-17 SPY $2515 1 sell call 2021-08-20 447.06 450.0 $41 -8845821036070862059\n", + "2021-08-17 SPY $2716 0 sell call 2021-08-27 447.06 451.0 $101 -7049535863332786931\n", + "2021-08-18 QQQ $1539 1 buy put 2021-09-01 365.67 368.0 $588 5563668740461325759\n", + "2021-08-18 QQQ $527 2 buy put 2021-09-03 365.67 365.0 $505 -4896361780820862711\n", + "2021-08-18 SPY $14 3 buy put 2021-09-01 443.95 437.0 $256 -7241514007088948224\n", + "2021-08-20 QQQ $1337 2 sell put 2021-09-01 364.0 368.0 $662 5563668740461325759\n", + "2021-08-20 QQQ $2525 1 sell put 2021-09-03 364.0 365.0 $595 -4896361780820862711\n", + "2021-08-20 SPY $3384 0 sell put 2021-09-01 439.87 437.0 $430 -7241514007088948224\n", + "2021-08-27 QQQ $2661 1 buy call 2021-09-10 372.4 374.0 $361 -5581727436213367973\n", + "2021-08-27 QQQ $2041 2 buy call 2021-09-10 372.4 375.0 $309 5011091652458344542\n", + "2021-08-27 QQQ $1044 3 buy call 2021-09-15 372.4 373.0 $498 -3897788335741031678\n", + "2021-08-27 QQQ $283 4 buy call 2021-09-15 372.4 375.0 $380 -5607472823889186386\n", + "2021-08-27 SPY $29 5 buy call 2021-09-10 446.33 452.5 $126 6193195140520552914\n" + ] + }, + { + "ename": "KeyboardInterrupt", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[14], line 15\u001b[0m\n\u001b[1;32m 12\u001b[0m owned_options \u001b[38;5;241m=\u001b[39m []\n\u001b[1;32m 13\u001b[0m trade_data \u001b[38;5;241m=\u001b[39m []\n\u001b[0;32m---> 15\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m index, row \u001b[38;5;129;01min\u001b[39;00m df_option_history\u001b[38;5;241m.\u001b[39miterrows():\n\u001b[1;32m 16\u001b[0m expire_date \u001b[38;5;241m=\u001b[39m row\u001b[38;5;241m.\u001b[39mEXPIRE_UNIX\u001b[38;5;241m.\u001b[39mstrftime(\u001b[38;5;28mformat\u001b[39m\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m%\u001b[39m\u001b[38;5;124mY-\u001b[39m\u001b[38;5;124m%\u001b[39m\u001b[38;5;124mm-\u001b[39m\u001b[38;5;132;01m%d\u001b[39;00m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 17\u001b[0m index_date \u001b[38;5;241m=\u001b[39m index\u001b[38;5;241m.\u001b[39mstrftime(\u001b[38;5;28mformat\u001b[39m\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m%\u001b[39m\u001b[38;5;124mY-\u001b[39m\u001b[38;5;124m%\u001b[39m\u001b[38;5;124mm-\u001b[39m\u001b[38;5;132;01m%d\u001b[39;00m\u001b[38;5;124m\"\u001b[39m)\n", + "File \u001b[0;32m~/.local/lib/python3.10/site-packages/pandas/core/frame.py:1450\u001b[0m, in \u001b[0;36mDataFrame.iterrows\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 1448\u001b[0m using_cow \u001b[38;5;241m=\u001b[39m using_copy_on_write()\n\u001b[1;32m 1449\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m k, v \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mzip\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mindex, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mvalues):\n\u001b[0;32m-> 1450\u001b[0m s \u001b[38;5;241m=\u001b[39m \u001b[43mklass\u001b[49m\u001b[43m(\u001b[49m\u001b[43mv\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mindex\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcolumns\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mname\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mk\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241m.\u001b[39m__finalize__(\u001b[38;5;28mself\u001b[39m)\n\u001b[1;32m 1451\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m using_cow \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_mgr\u001b[38;5;241m.\u001b[39mis_single_block:\n\u001b[1;32m 1452\u001b[0m s\u001b[38;5;241m.\u001b[39m_mgr\u001b[38;5;241m.\u001b[39madd_references(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_mgr) \u001b[38;5;66;03m# type: ignore[arg-type]\u001b[39;00m\n", + "File \u001b[0;32m~/.local/lib/python3.10/site-packages/pandas/core/series.py:512\u001b[0m, in \u001b[0;36mSeries.__init__\u001b[0;34m(self, data, index, dtype, name, copy, fastpath)\u001b[0m\n\u001b[1;32m 510\u001b[0m data \u001b[38;5;241m=\u001b[39m data\u001b[38;5;241m.\u001b[39mcopy()\n\u001b[1;32m 511\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m--> 512\u001b[0m data \u001b[38;5;241m=\u001b[39m \u001b[43msanitize_array\u001b[49m\u001b[43m(\u001b[49m\u001b[43mdata\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mindex\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdtype\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcopy\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 514\u001b[0m manager \u001b[38;5;241m=\u001b[39m get_option(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmode.data_manager\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 515\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m manager \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mblock\u001b[39m\u001b[38;5;124m\"\u001b[39m:\n", + "File \u001b[0;32m~/.local/lib/python3.10/site-packages/pandas/core/construction.py:603\u001b[0m, in \u001b[0;36msanitize_array\u001b[0;34m(data, index, dtype, copy, allow_2d)\u001b[0m\n\u001b[1;32m 601\u001b[0m subarr \u001b[38;5;241m=\u001b[39m data\n\u001b[1;32m 602\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m data\u001b[38;5;241m.\u001b[39mdtype \u001b[38;5;241m==\u001b[39m \u001b[38;5;28mobject\u001b[39m:\n\u001b[0;32m--> 603\u001b[0m subarr \u001b[38;5;241m=\u001b[39m \u001b[43mmaybe_infer_to_datetimelike\u001b[49m\u001b[43m(\u001b[49m\u001b[43mdata\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 604\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m data\u001b[38;5;241m.\u001b[39mdtype\u001b[38;5;241m.\u001b[39mkind \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mU\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;129;01mand\u001b[39;00m using_pyarrow_string_dtype():\n\u001b[1;32m 605\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mpandas\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mcore\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01marrays\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mstring_\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m StringDtype\n", + "File \u001b[0;32m~/.local/lib/python3.10/site-packages/pandas/core/dtypes/cast.py:1180\u001b[0m, in \u001b[0;36mmaybe_infer_to_datetimelike\u001b[0;34m(value)\u001b[0m\n\u001b[1;32m 1175\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m value\n\u001b[1;32m 1177\u001b[0m \u001b[38;5;66;03m# error: Incompatible return value type (got \"Union[ExtensionArray,\u001b[39;00m\n\u001b[1;32m 1178\u001b[0m \u001b[38;5;66;03m# ndarray[Any, Any]]\", expected \"Union[ndarray[Any, Any], DatetimeArray,\u001b[39;00m\n\u001b[1;32m 1179\u001b[0m \u001b[38;5;66;03m# TimedeltaArray, PeriodArray, IntervalArray]\")\u001b[39;00m\n\u001b[0;32m-> 1180\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mlib\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mmaybe_convert_objects\u001b[49m\u001b[43m(\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;66;43;03m# type: ignore[return-value]\u001b[39;49;00m\n\u001b[1;32m 1181\u001b[0m \u001b[43m \u001b[49m\u001b[43mvalue\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1182\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;66;43;03m# Here we do not convert numeric dtypes, as if we wanted that,\u001b[39;49;00m\n\u001b[1;32m 1183\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;66;43;03m# numpy would have done it for us.\u001b[39;49;00m\n\u001b[1;32m 1184\u001b[0m \u001b[43m \u001b[49m\u001b[43mconvert_numeric\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 1185\u001b[0m \u001b[43m \u001b[49m\u001b[43mconvert_non_numeric\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mTrue\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 1186\u001b[0m \u001b[43m \u001b[49m\u001b[43mdtype_if_all_nat\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mnp\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdtype\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mM8[ns]\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1187\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32mlib.pyx:2519\u001b[0m, in \u001b[0;36mpandas._libs.lib.maybe_convert_objects\u001b[0;34m()\u001b[0m\n", + "File \u001b[0;32m~/.local/lib/python3.10/site-packages/numpy/core/numeric.py:274\u001b[0m, in \u001b[0;36mfull\u001b[0;34m(shape, fill_value, dtype, order, like)\u001b[0m\n\u001b[1;32m 270\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_full_dispatcher\u001b[39m(shape, fill_value, dtype\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m, order\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m, \u001b[38;5;241m*\u001b[39m, like\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m):\n\u001b[1;32m 271\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m(like,)\n\u001b[0;32m--> 274\u001b[0m \u001b[38;5;129m@set_array_function_like_doc\u001b[39m\n\u001b[1;32m 275\u001b[0m \u001b[38;5;129m@set_module\u001b[39m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mnumpy\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 276\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mfull\u001b[39m(shape, fill_value, dtype\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m, order\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mC\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;241m*\u001b[39m, like\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m):\n\u001b[1;32m 277\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 278\u001b[0m \u001b[38;5;124;03m Return a new array of given shape and type, filled with `fill_value`.\u001b[39;00m\n\u001b[1;32m 279\u001b[0m \n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 320\u001b[0m \n\u001b[1;32m 321\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[1;32m 322\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m like \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n", + "\u001b[0;31mKeyboardInterrupt\u001b[0m: " + ] + } + ], + "source": [ + "min_dte_buy = 14\n", + "min_dte_sell = int(min_dte_buy / 2)\n", + "min_volume = 100\n", + "max_strike_distance_pct = 0.02\n", + "contract_fee = 0.66\n", + "total_contracts = 2\n", + "\n", + "money = 2000\n", + "start_money = money\n", + "last_index = df_option_history.index.values[-1]\n", + "\n", + "owned_options = []\n", + "trade_data = []\n", + "\n", + "for index, row in df_option_history.iterrows():\n", + " expire_date = row.EXPIRE_UNIX.strftime(format=\"%Y-%m-%d\")\n", + " index_date = index.strftime(format=\"%Y-%m-%d\")\n", + " is_last_index = index.to_numpy() == last_index\n", + "\n", + " good_call_buy = row.fear_greed_index >= row.fear_greed_index_max_14 - 1\n", + " good_put_buy = row.fear_greed_index <= row.fear_greed_index_min_14 + 1\n", + "\n", + " call_bid_price = row.C_BID * 100\n", + " put_bid_price = row.P_BID * 100\n", + "\n", + " owned_options_not_sold = []\n", + "\n", + " for option in owned_options:\n", + " if option[\"OPTION_ID\"] == row.OPTION_ID:\n", + " if (\n", + " option[\"side\"] == \"call\"\n", + " and not np.isnan(row.C_BID)\n", + " and (\n", + " not good_call_buy\n", + " or row.DTE < min_dte_sell\n", + " or (option[\"DTE\"] - row.DTE) > min_dte_sell\n", + " or is_last_index\n", + " )\n", + " ):\n", + " money += (call_bid_price - contract_fee) * total_contracts\n", + " print(\n", + " f\"{index_date} {row.UNDERLYING_PRODUCT_ID} ${money:.0f} {len(owned_options)-1} sell call {expire_date} {row.UNDERLYING_LAST} {row.STRIKE} ${call_bid_price:.0f} {row.OPTION_ID}\"\n", + " )\n", + " trade_data.append(\n", + " {\n", + " \"date\": index_date,\n", + " \"money\": money,\n", + " \"side\": \"sell\",\n", + " \"price\": call_bid_price,\n", + " \"options\": len(owned_options) - 1,\n", + " }\n", + " )\n", + " elif (\n", + " option[\"side\"] == \"put\"\n", + " and not np.isnan(row.P_BID)\n", + " and (\n", + " not good_put_buy\n", + " or row.DTE < min_dte_sell\n", + " or (option[\"DTE\"] - row.DTE) > min_dte_sell\n", + " or is_last_index\n", + " )\n", + " ):\n", + " money += (put_bid_price - contract_fee) * total_contracts\n", + " print(\n", + " f\"{index_date} {row.UNDERLYING_PRODUCT_ID} ${money:.0f} {len(owned_options)-1} sell put {expire_date} {row.UNDERLYING_LAST} {row.STRIKE} ${put_bid_price:.0f} {row.OPTION_ID}\"\n", + " )\n", + " trade_data.append(\n", + " {\n", + " \"date\": index_date,\n", + " \"money\": money,\n", + " \"side\": \"sell\",\n", + " \"price\": put_bid_price,\n", + " \"options\": len(owned_options) - 1,\n", + " }\n", + " )\n", + " else:\n", + " owned_options_not_sold.append(option)\n", + " else:\n", + " owned_options_not_sold.append(option)\n", + "\n", + " owned_options = owned_options_not_sold\n", + "\n", + " max_buy_price = money / total_contracts\n", + " max_buy_amount = 10\n", + " call_ask_price = row.C_ASK * 100\n", + " put_ask_price = row.P_ASK * 100\n", + "\n", + " if not is_last_index and row.DTE > min_dte_buy and row.STRIKE_DISTANCE_PCT < max_strike_distance_pct:\n", + " if (\n", + " good_call_buy\n", + " and not np.isnan(row.C_ASK)\n", + " and row.C_VOLUME > min_volume\n", + " and call_ask_price <= max_buy_price\n", + " and money >= call_ask_price\n", + " and len([x for x in owned_options if x[\"OPTION_ID\"] == row.OPTION_ID]) == 0\n", + " # and len([x for x in owned_options if x[\"side\"] == \"call\" and x[\"purchase_date\"] == index_date]) <= max_buy_amount\n", + " # and row.UNDERLYING_LAST > row.STRIKE\n", + " ):\n", + " money -= (call_ask_price + contract_fee) * total_contracts\n", + " option_to_buy = row.to_dict()\n", + " option_to_buy[\"side\"] = \"call\"\n", + " option_to_buy[\"purchase_date\"] = index_date\n", + " owned_options.append(option_to_buy)\n", + " print(\n", + " f\"{index_date} {row.UNDERLYING_PRODUCT_ID} ${money:.0f} {len(owned_options)} buy call {expire_date} {row.UNDERLYING_LAST} {row.STRIKE} ${call_ask_price:.0f} {row.OPTION_ID}\"\n", + " )\n", + " trade_data.append(\n", + " {\n", + " \"date\": index_date,\n", + " \"money\": money,\n", + " \"side\": \"buy\",\n", + " \"price\": call_ask_price,\n", + " \"options\": len(owned_options),\n", + " }\n", + " )\n", + " elif (\n", + " good_put_buy\n", + " and not np.isnan(row.P_ASK)\n", + " and row.P_VOLUME > min_volume\n", + " and put_ask_price <= max_buy_price\n", + " and money >= put_ask_price\n", + " and len([x for x in owned_options if x[\"OPTION_ID\"] == row.OPTION_ID]) == 0\n", + " # and len([x for x in owned_options if x[\"side\"] == \"put\" and x[\"purchase_date\"] == index_date]) <= max_buy_amount\n", + " # and row.UNDERLYING_LAST < row.STRIKE\n", + " ):\n", + " money -= (put_ask_price + contract_fee) * total_contracts\n", + " option_to_buy = row.to_dict()\n", + " option_to_buy[\"side\"] = \"put\"\n", + " option_to_buy[\"purchase_date\"] = index_date\n", + " owned_options.append(option_to_buy)\n", + " print(\n", + " f\"{index_date} {row.UNDERLYING_PRODUCT_ID} ${money:.0f} {len(owned_options)} buy put {expire_date} {row.UNDERLYING_LAST} {row.STRIKE} ${put_ask_price:.0f} {row.OPTION_ID}\"\n", + " )\n", + " trade_data.append(\n", + " {\n", + " \"date\": index_date,\n", + " \"money\": money,\n", + " \"side\": \"buy\",\n", + " \"price\": put_ask_price,\n", + " \"options\": len(owned_options),\n", + " }\n", + " )\n", + "\n", + "print(f\"Start money: ${start_money:.2f}\")\n", + "print(f\"End money: ${money:.2f} ({(money-start_money)/start_money*100:.2f}%)\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6784b905-13d8-4f2d-9f51-724d5451ba14", + "metadata": {}, + "outputs": [], + "source": [ + "from matplotlib.pyplot import figure\n", + "\n", + "figure(figsize=(13, 4), dpi=80)\n", + "\n", + "df_trades = pd.DataFrame(trade_data)\n", + "\n", + "field_to_plot = \"money\"\n", + "# df_trades_plot = df_trades_plot.copy()\n", + "# df_trades_plot = df_trades.loc[(df_trades[\"side\"] == \"sell\")]\n", + "df_trades_plot = df_trades.loc[(df_trades[\"side\"] == \"sell\") & (df_trades[\"options\"] == 0)]\n", + "\n", + "# field_to_plot = \"options\"\n", + "# df_trades_plot = df_trades.groupby([\"date\"]).max(\"options\").reset_index()\n", + "\n", + "plt.clf()\n", + "plt.plot(pd.to_datetime(df_trades_plot[\"date\"]), df_trades_plot[field_to_plot])\n", + "plt.xlabel(\"date\")\n", + "plt.ylabel(field_to_plot)\n", + "plt.show()\n", + "df_trades.describe().astype(str)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9c86f9b9-1941-4b42-9d3b-46d512e775e9", + "metadata": {}, + "outputs": [], + "source": [ + "# SPY, max strike distance .05, fear and greed max+1/min-1, max purchase money / 10, max 10 options daily\n", + "# Options: 3304\n", + "# End money: $379182.36 (18859.12%)\n", + "\n", + "# SPY, max strike distance .02, fear and greed max+1/min-1, max purchase money / 10, max 10 options daily\n", + "# Options: 2966\n", + "# End money: $369782.44 (18389.12%)\n", + "\n", + "# SPY, max strike distance .02, fear and greed max+1/min-1, max purchase money, max 10 options daily\n", + "# Options: 3206\n", + "# End money: $427413.04 (21270.65%)\n", + "\n", + "# SPY, max strike distance .01, fear and greed max+1/min-1, max purchase money, max 50 options daily\n", + "# Options: 8828\n", + "# End money: $1249933.52 (62396.68%)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.10.12" + }, + "papermill": { + "default_parameters": {}, + "duration": 42.448071, + "end_time": "2023-02-27T05:32:21.988648", + "environment_variables": {}, + "exception": null, + "input_path": "__notebook__.ipynb", + "output_path": "__notebook__.ipynb", + "parameters": {}, + "start_time": "2023-02-27T05:31:39.540577", + "version": "2.4.0" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}