diff --git a/project-templates/python/alternative-data-universe-eodhdupcomingdividends/research.ipynb b/project-templates/python/alternative-data-universe-eodhdupcomingdividends/research.ipynb new file mode 100644 index 0000000000..085685bd23 --- /dev/null +++ b/project-templates/python/alternative-data-universe-eodhdupcomingdividends/research.ipynb @@ -0,0 +1,663 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "a1b2c3d4", + "metadata": {}, + "source": [ + "![QuantConnect Logo](https://cdn.quantconnect.com/web/i/icon.png)\n", + "
" + ] + }, + { + "cell_type": "markdown", + "id": "e5f6a7b8", + "metadata": {}, + "source": [ + "## EODHD Upcoming Dividends Research\n", + "\n", + "This notebook measures ex-dividend returns, calculated as the change from the dividend day's opening price to the next trading day's opening price." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c9d0e1f2", + "metadata": {}, + "outputs": [], + "source": [ + "qb = QuantBook()\n", + "# Anchor the research clock to the start of 2026.\n", + "qb.set_start_date(2026, 1, 1)\n", + "# Daily bars will have an end_time that matches the following midnight.\n", + "qb.settings.daily_precise_end_time = False\n", + "# Add the data feed.\n", + "ipo_data = qb.add_data(EODHDUpcomingDividends, \"IPOS\")" + ] + }, + { + "cell_type": "markdown", + "id": "a3b4c5d6", + "metadata": {}, + "source": [ + "### Build a Upcoming Dividends Universe\n", + "\n", + "Select US Equities going ex-dividend soon with a meaningful payout, then inspect the returned universe history." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "e7f8a9b0", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Shape: (10712, 6)\n", + "Columns: ['declarationdate', 'dividend', 'dividenddate', 'paymentdate', 'reportdate', 'value']\n" + ] + }, + { + "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", + "
declarationdatedividenddividenddatepaymentdatereportdatevalue
symboltime
AMDY YBXWWTRDGGH12025-05-012025-10-150.952025-10-162025-10-172025-10-160.95
APD R735QTJ8XC9X2025-01-022024-11-211.772025-01-022025-02-102025-01-021.77
2025-03-252025-01-221.792025-04-012025-05-122025-04-011.79
2025-03-262025-01-221.792025-04-012025-05-122025-04-011.79
2025-03-272025-01-221.792025-04-012025-05-122025-04-011.79
\n", + "
" + ], + "text/plain": [ + " declarationdate dividend dividenddate \\\n", + "symbol time \n", + "AMDY YBXWWTRDGGH1 2025-05-01 2025-10-15 0.95 2025-10-16 \n", + "APD R735QTJ8XC9X 2025-01-02 2024-11-21 1.77 2025-01-02 \n", + " 2025-03-25 2025-01-22 1.79 2025-04-01 \n", + " 2025-03-26 2025-01-22 1.79 2025-04-01 \n", + " 2025-03-27 2025-01-22 1.79 2025-04-01 \n", + "\n", + " paymentdate reportdate value \n", + "symbol time \n", + "AMDY YBXWWTRDGGH1 2025-05-01 2025-10-17 2025-10-16 0.95 \n", + "APD R735QTJ8XC9X 2025-01-02 2025-02-10 2025-01-02 1.77 \n", + " 2025-03-25 2025-05-12 2025-04-01 1.79 \n", + " 2025-03-26 2025-05-12 2025-04-01 1.79 \n", + " 2025-03-27 2025-05-12 2025-04-01 1.79 " + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Pull the dataset history.\n", + "universe_history = qb.history(EODHDUpcomingDividends, qb.time - timedelta(365), qb.time)\n", + "# Filter EODHDUpcomingDividends dataframe.\n", + "universe_history = universe_history[\n", + " universe_history['dividenddate'].notna() &\n", + " (universe_history['dividend'] > 0.75)\n", + "]\n", + "# Print the returned shape and columns.\n", + "print(f\"Shape: {universe_history.shape}\")\n", + "print(f\"Columns: {list(universe_history.columns)}\")\n", + "universe_history.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "538668d8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Dividend events: 2174\n" + ] + }, + { + "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", + "
dividend
dividenddatesymbol
2025-01-02APD R735QTJ8XC9X1.77
ESS R735QTJ8XC9X2.45
FRT R735QTJ8XC9X1.10
CPO R735QTJ8XC9X0.80
NDSN R735QTJ8XC9X0.78
\n", + "
" + ], + "text/plain": [ + " dividend\n", + "dividenddate symbol \n", + "2025-01-02 APD R735QTJ8XC9X 1.77\n", + " ESS R735QTJ8XC9X 2.45\n", + " FRT R735QTJ8XC9X 1.10\n", + " CPO R735QTJ8XC9X 0.80\n", + " NDSN R735QTJ8XC9X 0.78" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Take one row per dividend event across all names.\n", + "dividend_events = universe_history.reset_index().groupby(['dividenddate', 'symbol']).agg(dividend=('dividend', 'first'))\n", + "print(f\"Dividend events: {len(dividend_events)}\")\n", + "dividend_events.head()" + ] + }, + { + "cell_type": "markdown", + "id": "c1d2e3f4", + "metadata": {}, + "source": [ + "### Universe Diagnostics\n", + "\n", + "Check how many assets pass the filter each day and summarize the factors." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a5b6c7d8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Universe days: 364\n", + "Mean universe size per day: 29.4\n", + "\n", + "count 10712.000\n", + "mean 8.195\n", + "std 274.311\n", + "min 0.750\n", + "25% 0.880\n", + "50% 1.071\n", + "75% 1.580\n", + "max 11593.900\n", + "Name: dividend, dtype: object\n" + ] + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "https://s3.amazonaws.com/research.quantconnect.com/images/5ea32e88-3927-4e93-8822-6457459cbfc2.png?AWSAccessKeyId=AKIAY3TRDSUSL3ZLVGGZ&Signature=gzPc3CjZaVfmq7jq1eB6hFRSua8%3D&Expires=1781305028" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Count how many names pass the filter each day.\n", + "universe_size = universe_history.groupby(level=1).size()\n", + "print(f\"Universe days: {len(universe_size)}\")\n", + "# Keep the unique list of selected symbols.\n", + "unique_assets = list(universe_history.index.unique(0))\n", + "print(f\"Mean universe size per day: {universe_size.mean():.1f}\")\n", + "print('')\n", + "print(universe_history.dividend.describe().map('{:0.3f}'.format))\n", + "universe_size.plot(title='Daily Universe Size', ylabel='Universe Size');" + ] + }, + { + "cell_type": "markdown", + "id": "e9f0a1b2", + "metadata": {}, + "source": [ + "### Daily Universe Prices\n", + "\n", + "Fetch daily price history for every symbol that appears in the universe." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "c3d4e5f6", + "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", + "
closehighlowopenvolume
symboltime
AMDY YBXWWTRDGGH12025-01-0318.00818518.30208717.83896818.204120157277.0
2025-01-0418.56036418.56036418.13287018.168495209319.0
2025-01-0718.95223419.05892918.80973618.934422400169.0
2025-01-0818.70286219.18379318.63179219.094732426225.0
2025-01-0917.93042018.46428217.69110218.464282730426.0
.....................
UBEW YWV5WCLHZM912025-12-2533.33941533.59987533.16107633.5998751077.0
2025-12-2733.36718233.65051533.35511333.650515810.0
2025-12-3033.51472533.79040933.31962533.72679011857.0
2025-12-3133.81721433.98975033.35355633.3535563807.0
2026-01-0133.56655433.79040933.56655433.790409701.0
\n", + "

188859 rows × 5 columns

\n", + "
" + ], + "text/plain": [ + " close high low open \\\n", + "symbol time \n", + "AMDY YBXWWTRDGGH1 2025-01-03 18.008185 18.302087 17.838968 18.204120 \n", + " 2025-01-04 18.560364 18.560364 18.132870 18.168495 \n", + " 2025-01-07 18.952234 19.058929 18.809736 18.934422 \n", + " 2025-01-08 18.702862 19.183793 18.631792 19.094732 \n", + " 2025-01-09 17.930420 18.464282 17.691102 18.464282 \n", + "... ... ... ... ... \n", + "UBEW YWV5WCLHZM91 2025-12-25 33.339415 33.599875 33.161076 33.599875 \n", + " 2025-12-27 33.367182 33.650515 33.355113 33.650515 \n", + " 2025-12-30 33.514725 33.790409 33.319625 33.726790 \n", + " 2025-12-31 33.817214 33.989750 33.353556 33.353556 \n", + " 2026-01-01 33.566554 33.790409 33.566554 33.790409 \n", + "\n", + " volume \n", + "symbol time \n", + "AMDY YBXWWTRDGGH1 2025-01-03 157277.0 \n", + " 2025-01-04 209319.0 \n", + " 2025-01-07 400169.0 \n", + " 2025-01-08 426225.0 \n", + " 2025-01-09 730426.0 \n", + "... ... \n", + "UBEW YWV5WCLHZM91 2025-12-25 1077.0 \n", + " 2025-12-27 810.0 \n", + " 2025-12-30 11857.0 \n", + " 2025-12-31 3807.0 \n", + " 2026-01-01 701.0 \n", + "\n", + "[188859 rows x 5 columns]" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Fetch daily price history for every name.\n", + "symbols = list(universe_history.index.unique(0))\n", + "# Start one day before the earliest dividend date.\n", + "start_time = universe_history['dividenddate'].min() - timedelta(1)\n", + "history = qb.history(symbols, start_time, qb.time, Resolution.DAILY)\n", + "history" + ] + }, + { + "cell_type": "markdown", + "id": "a7b8c9d0", + "metadata": {}, + "source": [ + "### Ex-Dividend Returns\n", + "\n", + "Take each name's open-to-open return across its dividend date, one row per dividend." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "3d56c7cd", + "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", + "
dividenddividendreturn
dividenddatesymbol
2025-01-02APD R735QTJ8XC9X1.77-0.015405
ESS R735QTJ8XC9X2.45-0.008817
FRT R735QTJ8XC9X1.10-0.012475
CPO R735QTJ8XC9X0.80-0.005250
NDSN R735QTJ8XC9X0.78-0.024331
\n", + "
" + ], + "text/plain": [ + " dividend dividendreturn\n", + "dividenddate symbol \n", + "2025-01-02 APD R735QTJ8XC9X 1.77 -0.015405\n", + " ESS R735QTJ8XC9X 2.45 -0.008817\n", + " FRT R735QTJ8XC9X 1.10 -0.012475\n", + " CPO R735QTJ8XC9X 0.80 -0.005250\n", + " NDSN R735QTJ8XC9X 0.78 -0.024331" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Join each dividend event to its open-to-open return across the ex-date.\n", + "dataset = dividend_events.join(\n", + " history.open.unstack(level=0).sort_index().pct_change(1, fill_method=None).shift(-1).rename(index=lambda t: t - timedelta(1))\n", + " .stack().rename_axis(['dividenddate', 'symbol']).rename('dividendreturn'), how='inner'\n", + ")\n", + "dataset.dropna().head()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Foundation-Py-Default", + "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.11.14" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/project-templates/python/alternative-data-universe-eodhdupcomingipos/research.ipynb b/project-templates/python/alternative-data-universe-eodhdupcomingipos/research.ipynb new file mode 100644 index 0000000000..6774a650eb --- /dev/null +++ b/project-templates/python/alternative-data-universe-eodhdupcomingipos/research.ipynb @@ -0,0 +1,699 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "a1b2c3d4", + "metadata": {}, + "source": [ + "![QuantConnect Logo](https://cdn.quantconnect.com/web/i/icon.png)\n", + "
" + ] + }, + { + "cell_type": "markdown", + "id": "e5f6a7b8", + "metadata": {}, + "source": [ + "## EODHD Upcoming IPOs Research\n", + "\n", + "This notebook measures IPO first-day returns, calculated as the change from the IPO day's opening price to the next trading day's opening price." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "c9d0e1f2", + "metadata": {}, + "outputs": [], + "source": [ + "qb = QuantBook()\n", + "# Anchor the research clock to the start of 2026.\n", + "qb.set_start_date(2026, 1, 1)\n", + "# Daily bars will have an end_time that matches the following midnight.\n", + "qb.settings.daily_precise_end_time = False\n", + "# Add the data feed.\n", + "ipo_data = qb.add_data(EODHDUpcomingIPOs, \"IPOS\")" + ] + }, + { + "cell_type": "markdown", + "id": "a3b4c5d6", + "metadata": {}, + "source": [ + "### Build a Upcoming IPOs Universe\n", + "\n", + "Select confirmed non-penny upcoming IPOs, then inspect the returned universe history." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "4c79a468", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Shape: (496, 10)\n", + "Columns: ['amendeddate', 'dealtype', 'exchange', 'filingdate', 'highestprice', 'ipodate', 'lowestprice', 'name', 'offerprice', 'shares']\n" + ] + }, + { + "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", + "
amendeddatedealtypeexchangefilingdatehighestpriceipodatelowestpricenameofferpriceshares
symboltime
MCW YOTOGV1VHT2D2025-01-02NaTExpectedNASDAQNaT17.02025-01-0215.0Mister Car Wash Inc. Common Stock15.0NaN
HCAI YPR5O1HM3GIT2025-01-292025-02-05Expected2025-02-056.02025-02-054.0Huachen AI Parking Management Technology Holdi...NaN1500000.0
2025-01-302025-02-05Expected2025-02-056.02025-02-054.0Huachen AI Parking Management Technology Holdi...NaN1500000.0
2025-01-312025-02-05Expected2025-02-056.02025-02-054.0Huachen AI Parking Management Technology Holdi...NaN1500000.0
2025-02-012025-02-05Expected2025-02-056.02025-02-054.0Huachen AI Parking Management Technology Holdi...NaN1500000.0
\n", + "
" + ], + "text/plain": [ + " amendeddate dealtype exchange filingdate \\\n", + "symbol time \n", + "MCW YOTOGV1VHT2D 2025-01-02 NaT Expected NASDAQ NaT \n", + "HCAI YPR5O1HM3GIT 2025-01-29 2025-02-05 Expected 2025-02-05 \n", + " 2025-01-30 2025-02-05 Expected 2025-02-05 \n", + " 2025-01-31 2025-02-05 Expected 2025-02-05 \n", + " 2025-02-01 2025-02-05 Expected 2025-02-05 \n", + "\n", + " highestprice ipodate lowestprice \\\n", + "symbol time \n", + "MCW YOTOGV1VHT2D 2025-01-02 17.0 2025-01-02 15.0 \n", + "HCAI YPR5O1HM3GIT 2025-01-29 6.0 2025-02-05 4.0 \n", + " 2025-01-30 6.0 2025-02-05 4.0 \n", + " 2025-01-31 6.0 2025-02-05 4.0 \n", + " 2025-02-01 6.0 2025-02-05 4.0 \n", + "\n", + " name \\\n", + "symbol time \n", + "MCW YOTOGV1VHT2D 2025-01-02 Mister Car Wash Inc. Common Stock \n", + "HCAI YPR5O1HM3GIT 2025-01-29 Huachen AI Parking Management Technology Holdi... \n", + " 2025-01-30 Huachen AI Parking Management Technology Holdi... \n", + " 2025-01-31 Huachen AI Parking Management Technology Holdi... \n", + " 2025-02-01 Huachen AI Parking Management Technology Holdi... \n", + "\n", + " offerprice shares \n", + "symbol time \n", + "MCW YOTOGV1VHT2D 2025-01-02 15.0 NaN \n", + "HCAI YPR5O1HM3GIT 2025-01-29 NaN 1500000.0 \n", + " 2025-01-30 NaN 1500000.0 \n", + " 2025-01-31 NaN 1500000.0 \n", + " 2025-02-01 NaN 1500000.0 " + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Pull the dataset history.\n", + "universe_history = qb.history(EODHDUpcomingIPOs, qb.time - timedelta(365), qb.time)\n", + "# Define target price columns.\n", + "price_cols = ['lowestprice', 'highestprice', 'offerprice']\n", + "# Filter EODHDUpcomingIPOs dataframe.\n", + "universe_history = universe_history[\n", + " universe_history['ipodate'].notna() &\n", + " universe_history['dealtype'].isin([EODHD.DealType.EXPECTED, EODHD.DealType.PRICED]) &\n", + " (universe_history[price_cols].min(axis=1) > 1)\n", + "]\n", + "# Print the returned shape and columns.\n", + "print(f\"Shape: {universe_history.shape}\")\n", + "print(f\"Columns: {list(universe_history.columns)}\")\n", + "universe_history.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "a4e60128", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "IPO listings: 72\n" + ] + }, + { + "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", + "
name
ipodatesymbol
2025-01-02MCW YOTOGV1VHT2DMister Car Wash Inc. Common Stock
2025-02-05HCAI YPR5O1HM3GITHuachen AI Parking Management Technology Holdi...
2025-04-01TOPW YR9B96LWAYCLTop Win International Limited Ordinary Shares
WTF YR9B96LWAYCLWaton Financial Ltd
2025-04-02SMA YRAAP9Z2DPIDSmartStop Self Storage REIT Inc.
\n", + "
" + ], + "text/plain": [ + " name\n", + "ipodate symbol \n", + "2025-01-02 MCW YOTOGV1VHT2D Mister Car Wash Inc. Common Stock\n", + "2025-02-05 HCAI YPR5O1HM3GIT Huachen AI Parking Management Technology Holdi...\n", + "2025-04-01 TOPW YR9B96LWAYCL Top Win International Limited Ordinary Shares\n", + " WTF YR9B96LWAYCL Waton Financial Ltd\n", + "2025-04-02 SMA YRAAP9Z2DPID SmartStop Self Storage REIT Inc." + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Take one row per IPO listing.\n", + "ipo_events = universe_history.reset_index().groupby(['ipodate', 'symbol']).agg(name=('name', 'first'))\n", + "print(f\"IPO listings: {len(ipo_events)}\")\n", + "ipo_events.head()" + ] + }, + { + "cell_type": "markdown", + "id": "c1d2e3f4", + "metadata": {}, + "source": [ + "### Universe Diagnostics\n", + "\n", + "Check how many assets pass the filter each day and summarize the factors." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "a5b6c7d8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Universe days: 163\n", + "Mean universe size per day: 3.0\n" + ] + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "https://s3.amazonaws.com/research.quantconnect.com/images/582123b7-c5be-430f-9fe6-64c3dcc15ab1.png?AWSAccessKeyId=AKIAY3TRDSUSL3ZLVGGZ&Signature=1cUuOqXNRvSc08tg0%2Bn8G7wlXis%3D&Expires=1781309254" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Count how many symbols pass the filter each day.\n", + "universe_size = universe_history.groupby(level=1).size()\n", + "print(f\"Universe days: {len(universe_size)}\")\n", + "# Keep the unique list of selected symbols.\n", + "unique_assets = list(universe_history.index.unique(0))\n", + "print(f\"Mean universe size per day: {universe_size.mean():.1f}\")\n", + "universe_size.plot(title='Daily Universe Size', ylabel='Universe Size');" + ] + }, + { + "cell_type": "markdown", + "id": "e9f0a1b2", + "metadata": {}, + "source": [ + "### Daily Universe Prices\n", + "\n", + "Fetch daily price history for every symbol that appears in the universe." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "c3d4e5f6", + "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", + "
closehighlowopenvolume
symboltime
MCW YOTOGV1VHT2D2025-01-037.2807.72367.1957.6101012598.0
2025-01-047.1007.30007.0507.300496291.0
2025-01-077.1107.25007.0607.235515718.0
2025-01-087.0707.24406.9707.130631353.0
2025-01-097.0357.17006.8407.170628007.0
.....................
SVAQU YYFADOG4CMED2025-12-259.9409.95009.9409.950259777.0
2025-12-279.9409.96509.9409.940424407.0
2025-12-309.9509.95509.9409.9501060180.0
2025-12-319.9409.95009.9409.95019321.0
2026-01-019.9459.95009.9359.950104851.0
\n", + "

4770 rows × 5 columns

\n", + "
" + ], + "text/plain": [ + " close high low open volume\n", + "symbol time \n", + "MCW YOTOGV1VHT2D 2025-01-03 7.280 7.7236 7.195 7.610 1012598.0\n", + " 2025-01-04 7.100 7.3000 7.050 7.300 496291.0\n", + " 2025-01-07 7.110 7.2500 7.060 7.235 515718.0\n", + " 2025-01-08 7.070 7.2440 6.970 7.130 631353.0\n", + " 2025-01-09 7.035 7.1700 6.840 7.170 628007.0\n", + "... ... ... ... ... ...\n", + "SVAQU YYFADOG4CMED 2025-12-25 9.940 9.9500 9.940 9.950 259777.0\n", + " 2025-12-27 9.940 9.9650 9.940 9.940 424407.0\n", + " 2025-12-30 9.950 9.9550 9.940 9.950 1060180.0\n", + " 2025-12-31 9.940 9.9500 9.940 9.950 19321.0\n", + " 2026-01-01 9.945 9.9500 9.935 9.950 104851.0\n", + "\n", + "[4770 rows x 5 columns]" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Fetch daily price history for every listing.\n", + "symbols = list(universe_history.index.unique(0))\n", + "# Start one day before the earliest listing.\n", + "start_time = universe_history['ipodate'].min() - timedelta(1)\n", + "history = qb.history(symbols, start_time, qb.time, Resolution.DAILY)\n", + "history" + ] + }, + { + "cell_type": "markdown", + "id": "27ba5e25", + "metadata": {}, + "source": [ + "### IPO First-Day Returns\n", + "\n", + "Take each listing's open-to-open return across its IPO date, one row per IPO." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "da85ca71", + "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", + "
namefirstdayreturn
ipodatesymbol
2025-01-02MCW YOTOGV1VHT2DMister Car Wash Inc. Common Stock-0.040736
2025-02-05HCAI YPR5O1HM3GITHuachen AI Parking Management Technology Holdi...-0.148064
2025-04-01WTF YR9B96LWAYCLWaton Financial Ltd2.601399
2025-04-02SMA YRAAP9Z2DPIDSmartStop Self Storage REIT Inc.-0.012346
2025-05-21AACIU YSMJLUWC4ODHArmada Acquisition Corp. II - Units0.000000
\n", + "
" + ], + "text/plain": [ + " name \\\n", + "ipodate symbol \n", + "2025-01-02 MCW YOTOGV1VHT2D Mister Car Wash Inc. Common Stock \n", + "2025-02-05 HCAI YPR5O1HM3GIT Huachen AI Parking Management Technology Holdi... \n", + "2025-04-01 WTF YR9B96LWAYCL Waton Financial Ltd \n", + "2025-04-02 SMA YRAAP9Z2DPID SmartStop Self Storage REIT Inc. \n", + "2025-05-21 AACIU YSMJLUWC4ODH Armada Acquisition Corp. II - Units \n", + "\n", + " firstdayreturn \n", + "ipodate symbol \n", + "2025-01-02 MCW YOTOGV1VHT2D -0.040736 \n", + "2025-02-05 HCAI YPR5O1HM3GIT -0.148064 \n", + "2025-04-01 WTF YR9B96LWAYCL 2.601399 \n", + "2025-04-02 SMA YRAAP9Z2DPID -0.012346 \n", + "2025-05-21 AACIU YSMJLUWC4ODH 0.000000 " + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Join each listing to its open-to-open return across the IPO date.\n", + "dataset = ipo_events.join(\n", + " history.open.unstack(level=0).sort_index().pct_change(1, fill_method=None).shift(-1).rename(index=lambda t: t - timedelta(1))\n", + " .stack().rename_axis(['ipodate', 'symbol']).rename('firstdayreturn'), how='inner'\n", + ")\n", + "dataset.dropna().head()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Foundation-Py-Default", + "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.11.14" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}