Skip to content

Instantly share code, notes, and snippets.

@iangow
Last active December 21, 2023 02:21
Show Gist options
  • Save iangow/1bf5304053046f876abbabe42fc06a22 to your computer and use it in GitHub Desktop.
Save iangow/1bf5304053046f876abbabe42fc06a22 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "42231e76-0148-4820-a8b3-811200cb0585",
"metadata": {},
"outputs": [],
"source": [
"import ibis\n",
"ibis.options.interactive = True"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "59241356-9f5e-4468-8ce8-ba900b0e97f5",
"metadata": {},
"outputs": [],
"source": [
"con = ibis.postgres.connect()"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "76fba4e6-6b60-4320-89a3-bfe472a1d0dd",
"metadata": {},
"outputs": [],
"source": [
"dsf = con.table(\"dsf\", schema=\"crsp\")\n",
"stocknames = con.table(\"stocknames\", schema=\"crsp\")"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "91492346-38d3-44dc-a08f-9c84e18d2c69",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"102905313"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dsf.count().to_pandas()"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "50385bbf-863b-4f91-9c30-dc20d3f53b9c",
"metadata": {},
"outputs": [],
"source": [
"from ibis import udf\n",
"\n",
"@udf.scalar.builtin\n",
"def date_part(field, source) -> int:\n",
" ..."
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "97034579-b6eb-4604-9c99-301c76021775",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>year</th>\n",
" <th>n</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>2022</td>\n",
" <td>2390746</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>2021</td>\n",
" <td>2186792</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>2020</td>\n",
" <td>1948470</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>2019</td>\n",
" <td>1911581</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>2018</td>\n",
" <td>1869102</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>93</th>\n",
" <td>1929</td>\n",
" <td>201537</td>\n",
" </tr>\n",
" <tr>\n",
" <th>94</th>\n",
" <td>1928</td>\n",
" <td>180698</td>\n",
" </tr>\n",
" <tr>\n",
" <th>95</th>\n",
" <td>1927</td>\n",
" <td>172364</td>\n",
" </tr>\n",
" <tr>\n",
" <th>96</th>\n",
" <td>1926</td>\n",
" <td>160937</td>\n",
" </tr>\n",
" <tr>\n",
" <th>97</th>\n",
" <td>1925</td>\n",
" <td>509</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>98 rows × 2 columns</p>\n",
"</div>"
],
"text/plain": [
" year n\n",
"0 2022 2390746\n",
"1 2021 2186792\n",
"2 2020 1948470\n",
"3 2019 1911581\n",
"4 2018 1869102\n",
".. ... ...\n",
"93 1929 201537\n",
"94 1928 180698\n",
"95 1927 172364\n",
"96 1926 160937\n",
"97 1925 509\n",
"\n",
"[98 rows x 2 columns]"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dsf. \\\n",
" mutate(year=date_part(\"year\", dsf.date)). \\\n",
" group_by(\"year\"). \\\n",
" aggregate(n=dsf.count()). \\\n",
" order_by([ibis.desc(\"year\")]). \\\n",
" to_pandas()"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "688967e6-dc6c-440e-935f-5d3ece336653",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>permno</th>\n",
" <th>date</th>\n",
" <th>ret</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>10000</td>\n",
" <td>1986-01-07</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>10015</td>\n",
" <td>1986-01-07</td>\n",
" <td>0.000000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>10031</td>\n",
" <td>1986-01-07</td>\n",
" <td>0.000000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>10057</td>\n",
" <td>1986-01-07</td>\n",
" <td>0.026549</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>10065</td>\n",
" <td>1986-01-07</td>\n",
" <td>0.006410</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6424</th>\n",
" <td>93252</td>\n",
" <td>1986-01-07</td>\n",
" <td>-0.019608</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6425</th>\n",
" <td>93279</td>\n",
" <td>1986-01-07</td>\n",
" <td>0.000000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6426</th>\n",
" <td>93287</td>\n",
" <td>1986-01-07</td>\n",
" <td>0.000000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6427</th>\n",
" <td>93308</td>\n",
" <td>1986-01-07</td>\n",
" <td>0.000000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6428</th>\n",
" <td>93316</td>\n",
" <td>1986-01-07</td>\n",
" <td>0.012987</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>6429 rows × 3 columns</p>\n",
"</div>"
],
"text/plain": [
" permno date ret\n",
"0 10000 1986-01-07 NaN\n",
"1 10015 1986-01-07 0.000000\n",
"2 10031 1986-01-07 0.000000\n",
"3 10057 1986-01-07 0.026549\n",
"4 10065 1986-01-07 0.006410\n",
"... ... ... ...\n",
"6424 93252 1986-01-07 -0.019608\n",
"6425 93279 1986-01-07 0.000000\n",
"6426 93287 1986-01-07 0.000000\n",
"6427 93308 1986-01-07 0.000000\n",
"6428 93316 1986-01-07 0.012987\n",
"\n",
"[6429 rows x 3 columns]"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dsf_subset = dsf. \\\n",
" filter(dsf.date == \"1986-01-07\"). \\\n",
" to_pandas()\n",
"\n",
"dsf_subset[[\"permno\", \"date\", \"ret\"]]"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "96ede439-9d72-4d43-9251-f781970af952",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"14593"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"@udf.scalar.builtin\n",
"def regexp_like(string, pattern) -> bool:\n",
" ...\n",
"\n",
"apple_permno = stocknames. \\\n",
" filter(regexp_like(stocknames.comnam, \"^APPLE COM\")). \\\n",
" select(\"permno\"). \\\n",
" to_pandas(). \\\n",
" permno[0]\n",
"\n",
"apple_permno"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "6eb9bc96-6424-4def-811b-bbf443e987bc",
"metadata": {},
"outputs": [],
"source": [
"@udf.scalar.builtin\n",
"def coalesce(x, y) -> float:\n",
" ...\n",
"\n",
"@udf.scalar.builtin\n",
"def exp(x) -> float:\n",
" ...\n",
"\n",
"@udf.scalar.builtin\n",
"def ln(x) -> float:\n",
" ...\n",
"\n",
"@ibis.udf.agg.builtin\n",
"def sum(x: float) -> float:\n",
" ..."
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "829e852d-a964-481e-a527-aa2f0164ebe9",
"metadata": {},
"outputs": [],
"source": [
"log_rets = dsf. \\\n",
" filter(dsf.permno == apple_permno). \\\n",
" mutate(log_ret = ln(1 + coalesce(dsf.ret, 0)))\n",
"\n",
"w = ibis.window(group_by=\"permno\", following=0)\n",
"plot_data = log_rets. \\\n",
" mutate(sum_ret = exp(log_rets.log_ret.sum().over(w))). \\\n",
" select(\"permno\", \"date\", \"ret\", \"sum_ret\"). \\\n",
" to_pandas()"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "24f97573-c2b7-4fbf-9c4b-349e168268eb",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[<matplotlib.lines.Line2D at 0x163109c90>]"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"import matplotlib.pyplot as plt\n",
"plt.plot(plot_data.date, plot_data.sum_ret)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a07ad212-1acf-4abf-a473-7c1f78e7c1fc",
"metadata": {},
"outputs": [],
"source": []
}
],
"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.11.3"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
@iangow
Copy link
Author

iangow commented Dec 21, 2023

Equivalent code using dplyr with parquet files can be found here.

@iangow
Copy link
Author

iangow commented Dec 21, 2023

iangow@Ians-MacBook-Pro git % time quarto render ibis_test_postgres.ipynb --to html --execute

Starting python3 kernel...Done

Executing 'ibis_test_postgres.ipynb'
  Cell 1/12...Done
  Cell 2/12...Done
  Cell 3/12...Done
  Cell 4/12...Done
  Cell 5/12...Done
  Cell 6/12...Done
  Cell 7/12...Done
  Cell 8/12...Done
  Cell 9/12...Done
  Cell 10/12...Done
  Cell 11/12...Done
  Cell 12/12...Done

pandoc 
  to: html
  output-file: ibis_test_postgres.html
  standalone: true
  section-divs: true
  html-math-method: mathjax
  wrap: none
  default-image-extension: png
  
metadata
  document-css: false
  link-citations: true
  date-format: long
  lang: en
  
Output created: ibis_test_postgres.html

quarto render ibis_test_postgres.ipynb --to html --execute  1.54s user 0.20s system 15% cpu 11.557 total

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment