diff --git "a/notebooks/retention_metrics.ipynb" "b/notebooks/retention_metrics.ipynb" --- "a/notebooks/retention_metrics.ipynb" +++ "b/notebooks/retention_metrics.ipynb" @@ -12,6 +12,13 @@ "import gc" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, { "cell_type": "markdown", "metadata": {}, @@ -21,7 +28,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 40, "metadata": {}, "outputs": [], "source": [ @@ -30,7 +37,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 41, "metadata": {}, "outputs": [ { @@ -41,7 +48,7 @@ " dtype='object')" ] }, - "execution_count": 12, + "execution_count": 41, "metadata": {}, "output_type": "execute_result" } @@ -52,7 +59,58 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 42, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 42, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "retention_df.staking.value_counts" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": {}, + "outputs": [], + "source": [ + "retention_df[\"trader_type\"] = retention_df[\"staking\"].apply(\n", + " lambda x: \"non_Olas\" if x == \"non_Olas\" else \"Olas\"\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": {}, + "outputs": [], + "source": [ + "olas_data = retention_df.loc[retention_df[\"trader_type\"]==\"Olas\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 45, "metadata": {}, "outputs": [ { @@ -82,338 +140,261 @@ " request_date\n", " staking\n", " month_year_week\n", + " trader_type\n", " \n", " \n", " \n", " \n", - " 0\n", - " 0x721de88cee9be146c8f0c7ef1a4188bee36494d6\n", - " 2024-10-25 00:00:20+00:00\n", + " 2\n", + " 0x8fb970f4aff9b61e6b3bc5a8117b437b89c88711\n", + " 2024-11-13 00:04:25+00:00\n", " quickstart\n", - " 2024-10-25\n", + " 2024-11-13\n", " non_staking\n", - " Oct-25-2024\n", + " Nov-13-2024\n", + " Olas\n", " \n", " \n", - " 1\n", - " 0x8a1d5f22b5a3bea34697b85e7b4ad894bf9ee36a\n", - " 2024-10-25 00:00:25+00:00\n", - " quickstart\n", - " 2024-10-25\n", - " non_staking\n", - " Oct-25-2024\n", + " 3\n", + " 0x1fe2b09de07475b1027b0c73a5bf52693b31a52e\n", + " 2024-11-13 00:05:10+00:00\n", + " pearl\n", + " 2024-11-13\n", + " pearl\n", + " Nov-13-2024\n", + " Olas\n", " \n", " \n", - " 2\n", - " 0xf839eaf4b42eadd917b46d7b6da0dd0e1fd6f684\n", - " 2024-10-25 00:00:55+00:00\n", - " quickstart\n", - " 2024-10-25\n", - " non_staking\n", - " Oct-25-2024\n", + " 6\n", + " 0x1fe2b09de07475b1027b0c73a5bf52693b31a52e\n", + " 2024-11-13 00:08:05+00:00\n", + " pearl\n", + " 2024-11-13\n", + " pearl\n", + " Nov-13-2024\n", + " Olas\n", " \n", " \n", - " 3\n", - " 0x01274796ce41aa8e8312e05a427ffb4b0d2148f6\n", - " 2024-10-25 00:00:55+00:00\n", - " quickstart\n", - " 2024-10-25\n", - " non_staking\n", - " Oct-25-2024\n", + " 10\n", + " 0xd71b78ce490776a8f0cad6876ea79bc190f7bcce\n", + " 2024-11-13 00:19:45+00:00\n", + " pearl\n", + " 2024-11-13\n", + " pearl\n", + " Nov-13-2024\n", + " Olas\n", " \n", " \n", - " 4\n", - " 0xc20678890f94d0162593c46fe5da67d9a4b7a6fb\n", - " 2024-10-25 00:01:05+00:00\n", + " 11\n", + " 0x6f40dbf1f102d47248802a423c0cd117ac4a3781\n", + " 2024-11-13 00:27:30+00:00\n", " quickstart\n", - " 2024-10-25\n", + " 2024-11-13\n", " non_staking\n", - " Oct-25-2024\n", + " Nov-13-2024\n", + " Olas\n", " \n", " \n", "\n", "" ], "text/plain": [ - " trader_address request_time \\\n", - "0 0x721de88cee9be146c8f0c7ef1a4188bee36494d6 2024-10-25 00:00:20+00:00 \n", - "1 0x8a1d5f22b5a3bea34697b85e7b4ad894bf9ee36a 2024-10-25 00:00:25+00:00 \n", - "2 0xf839eaf4b42eadd917b46d7b6da0dd0e1fd6f684 2024-10-25 00:00:55+00:00 \n", - "3 0x01274796ce41aa8e8312e05a427ffb4b0d2148f6 2024-10-25 00:00:55+00:00 \n", - "4 0xc20678890f94d0162593c46fe5da67d9a4b7a6fb 2024-10-25 00:01:05+00:00 \n", + " trader_address request_time \\\n", + "2 0x8fb970f4aff9b61e6b3bc5a8117b437b89c88711 2024-11-13 00:04:25+00:00 \n", + "3 0x1fe2b09de07475b1027b0c73a5bf52693b31a52e 2024-11-13 00:05:10+00:00 \n", + "6 0x1fe2b09de07475b1027b0c73a5bf52693b31a52e 2024-11-13 00:08:05+00:00 \n", + "10 0xd71b78ce490776a8f0cad6876ea79bc190f7bcce 2024-11-13 00:19:45+00:00 \n", + "11 0x6f40dbf1f102d47248802a423c0cd117ac4a3781 2024-11-13 00:27:30+00:00 \n", "\n", - " market_creator request_date staking month_year_week \n", - "0 quickstart 2024-10-25 non_staking Oct-25-2024 \n", - "1 quickstart 2024-10-25 non_staking Oct-25-2024 \n", - "2 quickstart 2024-10-25 non_staking Oct-25-2024 \n", - "3 quickstart 2024-10-25 non_staking Oct-25-2024 \n", - "4 quickstart 2024-10-25 non_staking Oct-25-2024 " + " market_creator request_date staking month_year_week trader_type \n", + "2 quickstart 2024-11-13 non_staking Nov-13-2024 Olas \n", + "3 pearl 2024-11-13 pearl Nov-13-2024 Olas \n", + "6 pearl 2024-11-13 pearl Nov-13-2024 Olas \n", + "10 pearl 2024-11-13 pearl Nov-13-2024 Olas \n", + "11 quickstart 2024-11-13 non_staking Nov-13-2024 Olas " ] }, - "execution_count": 13, + "execution_count": 45, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "retention_df.head()" + "olas_data.head()" ] }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 47, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "staking\n", - "non_Olas 764956\n", - "non_staking 275246\n", - "pearl 56487\n", - "quickstart 48511\n", - "Name: count, dtype: int64" + "" ] }, - "execution_count": 14, + "execution_count": 47, "metadata": {}, "output_type": "execute_result" + }, + { + "data": { + "image/png": "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1rhy5QrGjRuHrKwsxMbGVtlvaWkpLCws8N5772Hz5s3VjiEjI0MtM+XRjGBN6H3ZLYkEB7euAcDsUSKqX+amJnjjnffrrH9moNKT0GqJETs7Oxw8eBBeXl74/PPPsXHjRiQnJ2P37t0YN24cLl68qNVgbt68CYVCgaSkJPTq1Qv5+flwdHTE+vXr8corrwAAzp49C29vb6SkpKBr166V9qNSqXDmzBkkJCSobR82bBg8PT0hlUqxdevWCjNrVbl8+TI8PDxw/Pjxx87gbdq0Ca+//jru3r2rlvhRldGjRyMvLw9bt25V256YmIjevXvj1q1bsLW11WicRUVFauv3FRQUQKlUYt6yL/U6O/VhzFQlIkPC7FeqjKZLjGg1PVNSUiK+D/fbb79hwIABAIBWrVrh+vXr2nQJAOJjSHt7ewAPZtlKSkoQGBgotmnVqhVcXV2RkpJSbT/lfZSLjo7GxYsXxff66kr5DdckgNNEhw4d4OLigueff16cfazK/PnzIZfLxY9SqayVMRAREZHu0SqIa9OmDVatWoX9+/djz5494rIiWVlZcHBw0GogZWVliIiIQPfu3dG2bVsAQHZ2NkxNTSvMRDk5OVX5btiBAwewceNGhIaGitvOnz+PKVOmICYmptaCq8r8/fff+Oijj9TOrS0XFxesWrUKmzdvxubNm6FUKuHv749jx45VeczUqVORn58vfq5evfrE4yAiIiLdpFUQ98knn+Crr76Cv78/hg8fjmeeeQYAsH37dnTu3FmrgahUKqSlpWHDhg1aHQ8AaWlpGDhwIKKiohAUFATgwftnI0aMwJw5c/D0009Xety6detgbW0tfvbv31/jcxcUFODFF19E69atMXv2bHF7mzZtxH779euncX9eXl5455134OPjg27duuG7775Dt27dsGTJkiqPMTMzg42NjdqHiIiIDJNW01L+/v74+++/UVBQADu7/71kHhoaCktLyxr3FxYWhh07dmDfvn1o3ry5uN3Z2RnFxcXIy8tTm43LycmBs7OzWh/p6eno06cPQkNDMWPGDHH77du3ceTIERw/flxMdCgrK4MgCDA2Nsbu3bsxYMAAdOnSRTymWbNmNRr/7du30bdvX8hkMsTFxcHExETct2vXLpSUlAAALJ7wvbTOnTvj999/r/Fxep/Y8LCHkhzqAhMniAxLQ5bN0oSjnayh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6QnWTiUiqkcvvPACTp48iYyMDFhZWanty8vLg62tLTIzMxEeHo74+HgYGRmhb9+++OKLL+Dk5AQAGD16NPLy8tRm0SIiIpCamorExEQAgL+/P9q3bw9zc3OsXr0apqamGDduHGbPng0AcHd3x5UrV8Tj3dzccPny5bq8dCKqZXycSkRUT3Jzc/HLL79ApVJVCOAAwNbWFmVlZRg4cCByc3ORlJSEPXv24OLFixg6dGiNz7d27VpYWVnh0KFDWLhwIT788EPs2bMHAHD48GEAQHR0NK5fvy5+JyL9wcepRET15MKFCxAEAa1ataqyTXx8PE6dOoVLly5BqVQCAL7//nu0adMGhw8fhq+vr8bna9++PaKiogAAnp6e+PLLLxEfH4/nn38ejo6OAB4Ejs7Ozk9wVUTUUDgTR0RUTzR5e+XMmTNQKpViAAcArVu3hq2tLc6cOVOj87Vv317tu4uLC27cuFGjPohIdzGIIyKqJ56enpBIJE+cvGBkZFQhICwpKanQzsTERO27RCJBWVnZE52biHQHgzgionpib2+P4OBgLF++HHfv3q2wPy8vD97e3rh69SquXr0qbk9PT0deXh5at24NAHB0dMT169fVjk1NTa3xeExMTFBaWlrj44hINzCIIyKqR8uXL0dpaSk6d+6MzZs34/z58zhz5gw+//xz+Pn5ITAwEO3atcNrr72GY8eO4Y8//sDIkSPx3HPP4dlnnwUABAQE4MiRI/j+++9x/vx5REVFIS0trcZjcXd3R3x8PLKzs3Hr1q3avlQiqmMM4oiI6lGLFi1w7Ngx9O7dGxMmTEDbtm3x/PPPIz4+HitXroREIsG2bdtgZ2eHXr16ITAwEC1atMDGjRvFPoKDgzFz5kx88MEH8PX1xe3btzFy5Mgaj2Xx4sXYs2cPlEolOnbsWJuXSUT1gOvEEREREekhzsQRERER6SEGcURERER6iEEcERERkR5iEEdERESkhxjEEREREekhBnFEREREeohBHBEREZEeYhBHREREpIcYxBERERHpIQZxRERERHqIQRwRERGRHvo/s22I/I1Ra7IAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" } ], "source": [ - "retention_df.staking.value_counts()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Join the two datasets" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [], - "source": [ - "# read trades dataset\n", - "traders_df = pd.read_parquet(\"../data/all_trades_profitability.parquet\")\n", - "unknown_df = pd.read_parquet(\"../data/unknown_traders.parquet\")\n" + "sns.histplot(olas_data, y=\"request_date\", hue=\"market_creator\")" ] }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 29, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "staking\n", - "non_Olas 56266\n", - "non_staking 20954\n", - "pearl 6084\n", - "quickstart 3975\n", - "Name: count, dtype: int64" + "Index(['trader_address', 'request_time', 'market_creator', 'request_date',\n", + " 'staking', 'month_year_week'],\n", + " dtype='object')" ] }, - "execution_count": 25, + "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "traders_df.staking.value_counts()" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [], - "source": [ - "traders_df[\"trader_type\"] = traders_df[\"staking\"].apply(\n", - " lambda x: \"non_Olas\" if x == \"non_Olas\" else \"Olas\"\n", - ")" + "retention_df.columns" ] }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 35, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "trader_type\n", - "non_Olas 56266\n", - "Olas 31013\n", - "Name: count, dtype: int64" + "" ] }, - "execution_count": 30, + "execution_count": 35, "metadata": {}, "output_type": "execute_result" + }, + { + "data": { + "image/png": "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FxcXnD59Gl27dsW8efNaoyYiIiIiugeHzol7/vnn8dFHH7V0LURERETURA6dE/ef//wHa9euxb/+9S8MGTKkzuO23n///RYpjoiIiIjq51CIy83NxeDBgwEAX3/9td02PnaLiIiIqPU5FOL279/f0nUQERERUTM4dE4cEREREcmLIY6IiIhIgRz6OZWUxZJ3HDdLS+Qug4hI0SquFwMA8vPz4evrC6PRKHNF1NmphBBC7iKoddhsNuj1ernLICLqcDQaD5w7l88gR62i9vvbarVCp9M12I9H4jqBgc8kQB8YKncZRESKp1arcau0CMfWLsT169cZ4khWDHGdgG9wbxhCB8ldBhFRh1Ba6Cp3CUQAeGEDERERkSIxxBEREREpEEMcERERkQIxxBEREREpEEMcERERkQIxxBEREREpEEMcERERkQIxxBEREREpEEMcERERkQIxxBEREREpEEMcERERkQLx2amdgCXvOG6WlshdBhFRq3Px0EKj92nVfdiKL7fq+ERNxRDXCeR/tk7uEoiI2ogKgGj1vWg0HvD19W31/RA1hiGuExj4TAL0gaFyl0FE1KpuXC1ETtpipKamwmQyteq+fH19YTQaW3UfRPfCENcJ+Ab3hiF0kNxlEBG1qtIuHgAAk8mEwYMHy1wNUeuT9cKG5ORkDB06FFqtFgaDARMmTEBBQYFdn9u3b8NsNsPHxweenp6Ii4tDScmP53edOnUKkydPRlBQEDQaDUwmE5YtW9bgPg8fPgy1Wo1Bgwbds7709HTExMTAx8cHKpUKOTk5dfqsXr0ao0aNgk6ng0qlQllZ2T3HbWrNH374IUwmEzQaDfr06YP169ffc2wiIiLqHGQNcZmZmTCbzTh69CgyMjJQVVWFmJgYVFRUSH1mz56NnTt3YvPmzcjMzERRUREmTpwobc/OzobBYEBqairy8vIwb948zJ07F8uXL6+zv7KyMkydOhVRUVFNqq+iogIjR47E4sWLG+xz8+ZNjB49Gm+99VaT592UmleuXIm5c+diwYIFyMvLw8KFC2E2m7Fz584m74eIiIg6LpUQovXPAG2ia9euwWAwIDMzExEREbBarfDz80NaWhp+/etfAwDOnTsHk8mErKwsDB8+vN5xzGYz8vPzsW/fPrv2Z599FqGhoXB2dsa2bdvqPbJWn8uXLyMkJAQnT55s8AjegQMH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/P73vxddu3YVHh4e4umnnxbFxcXS9qSkpHrHCA4ObnC/SUlJ4sEHH7xnfSkpKfWOnZSUJIQQYv/+/Q3O4dKlS42OferUKTFy5Ejh5uYmAgMDxTvvvGO3/dKlS/WO+9hjj92z7lpWq1UAEJmZmU3+DBEREcmr9vvbarU22q9d3SeOWlbtfWYOHTqEkSNHyl0OERERNYEi7xNHraOmpkbuEoiIiKiFMcQRERERKRBDHBEREZECMcQRERERKRBDHBEREZECMcQRERERKRBDHBEREZECMcQRERERKRBDHBEREZECMcQRERERKRBDHBEREZECMcQRERERKRBDHBEREZECMcQRERERKRBDXCfg5MT/zURERB0Nv907gZqaGrlLICIiohbGEEdERESkQAxxRERERArEEEdERESkQAxxRERERArEEEdERESkQAxxRERERArEEEdERESkQAxxRERERArEEEdERESkQAxxRERERArEEEdERESkQAxxRERERArEEEdERESkQAxxnYCTE/83ExERdTT8du8Eampq5C6BiIiIWhhDHBEREZECMcQRERERKRBDHBEREZECMcQRERERKRBDHBEREZECMcQRERERKRBDHBEREZECMcQRERERKRBDHBEREZECMcQRERERKRBDHBEREZECMcQRERERKRBDXCfg5MT/zURERB0Nv907gZqaGrlLICIiohbGEEdERESkQAxxRERERAoka4hLTk7G0KFDodVqYTAYMGHCBBQUFNj1uX37NsxmM3x8fODp6Ym4uDiUlJRI20+dOoXJkycjKCgIGo0GJpMJy5Yta3Cfhw8fhlqtxqBBg+5ZX3p6OmJiYuDj4wOVSoWcnBy77aWlpYiPj0efPn2g0WhgNBrx6quvwmq13nPs06dP49FHH4W7uzuCgoLw7rvv2m1ft24dVCqV3cvd3f2e4xIREVHnIGuIy8zMhNlsxtGjR5GRkYGqqirExMSgoqJC6jN79mzs3LkTmzdvRmZmJoqKijBx4kRpe3Z2NgwGA1JTU5GXl4d58+Zh7ty5WL58eZ39lZWVYerUqYiKimpSfRUVFRg5ciQWL15c7/aioiIUFRXhz3/+M3Jzc7Fu3Trs3r0bM2bMaHRcm82GmJgYBAcHIzs7G0uWLMGCBQuwevVqu346nQ7FxcXS69tvv21S3URERNQJiHbk6tWrAoDI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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" } ], "source": [ - "traders_df.trader_type.value_counts()" + "import seaborn as sns\n", + "\n", + "sns.histplot(retention_df, y=\"request_date\")" ] }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 30, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "staking\n", - "non_Olas 1654\n", - "Name: count, dtype: int64" + "Timestamp('2024-10-25 00:00:20+0000', tz='UTC')" ] }, - "execution_count": 26, + "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "unknown_df.staking.value_counts()" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [], - "source": [ - "unknown_df[\"trader_type\"] = \"unclassified\"" + "min(retention_df.request_time)" ] }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 31, "metadata": {}, "outputs": [], "source": [ - "all_traders = pd.concat([traders_df, unknown_df], ignore_index=True)" + "from datetime import datetime\n", + "cutoff_date1 = \"2024-11-13\"\n", + "timestamp1 = pd.Timestamp(\n", + "datetime.strptime(cutoff_date1, \"%Y-%m-%d\")\n", + ").tz_localize(\"UTC\")" ] }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 32, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "trader_type\n", - "non_Olas 56266\n", - "Olas 31013\n", - "unclassified 1654\n", - "Name: count, dtype: int64" + "Timestamp('2024-11-13 00:00:15+0000', tz='UTC')" ] }, - "execution_count": 31, + "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "all_traders.trader_type.value_counts()" + "retention_df = retention_df.loc[retention_df[\"request_time\"]>=timestamp1]\n", + "min(retention_df.request_time)" ] }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 34, "metadata": {}, "outputs": [ { - "name": "stderr", - "output_type": "stream", - "text": [ - "/var/folders/gp/02mb1d514ng739czlxw1lhh00000gn/T/ipykernel_51242/2488528526.py:5: UserWarning: Converting to PeriodArray/Index representation will drop timezone information.\n", - " all_traders[\"creation_timestamp\"].dt.to_period(\"W\").dt.strftime(\"%b-%d-%Y\")\n" - ] + "data": { + "text/plain": [ + "Index(['trader_address', 'request_time', 'market_creator', 'request_date',\n", + " 'staking', 'month_year_week'],\n", + " dtype='object')" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ - "# First, create week numbers from timestamps\n", - "all_traders[\"creation_timestamp\"] = pd.to_datetime(all_traders[\"creation_timestamp\"])\n", - "all_traders = all_traders.sort_values(by=\"creation_timestamp\", ascending=True)\n", - "all_traders[\"month_year_week\"] = (\n", - "all_traders[\"creation_timestamp\"].dt.to_period(\"W\").dt.strftime(\"%b-%d-%Y\")\n", - ")" + "retention_df.columns" ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": 33, "metadata": {}, + "outputs": [], "source": [ - "# WoW Retention" + "retention_df.to_parquet(\"../data/retention_activity.parquet\", index=False)" ] }, { "cell_type": "code", - "execution_count": 33, - "metadata": {}, - "outputs": [], - "source": [ - "def calculate_wow_retention_by_type(df):\n", - " # Get unique traders per week and type\n", - " weekly_traders = df.groupby(['month_year_week', 'trader_type'])['trader_address'].nunique().reset_index()\n", - " weekly_traders = weekly_traders.sort_values(['trader_type', 'month_year_week'])\n", - " \n", - " # Calculate retention\n", - " retention = []\n", - " # Iterate through each trader type\n", - " for trader_type in weekly_traders['trader_type'].unique():\n", - " type_data = weekly_traders[weekly_traders['trader_type'] == trader_type]\n", - " \n", - " # Calculate retention for each week within this trader type\n", - " for i in range(1, len(type_data)):\n", - " current_week = type_data.iloc[i]['month_year_week']\n", - " previous_week = type_data.iloc[i-1]['month_year_week']\n", - " \n", - " # Get traders in both weeks for this type\n", - " current_traders = set(df[\n", - " (df['month_year_week'] == current_week) & \n", - " (df['trader_type'] == trader_type)\n", - " ]['trader_address'])\n", - " \n", - " previous_traders = set(df[\n", - " (df['month_year_week'] == previous_week) & \n", - " (df['trader_type'] == trader_type)\n", - " ]['trader_address'])\n", - " \n", - " retained = len(current_traders.intersection(previous_traders))\n", - " retention_rate = (retained / len(previous_traders)) * 100 if len(previous_traders) > 0 else 0\n", - " \n", - " retention.append({\n", - " 'trader_type': trader_type,\n", - " 'week': current_week,\n", - " 'retained_traders': retained,\n", - " 'previous_traders': len(previous_traders),\n", - " 'retention_rate': round(retention_rate, 2)\n", - " })\n", - " \n", - " return pd.DataFrame(retention)" - ] - }, - { - "cell_type": "code", - "execution_count": 34, - "metadata": {}, - "outputs": [], - "source": [ - "wow_retention = calculate_wow_retention_by_type(all_traders)" - ] - }, - { - "cell_type": "code", - "execution_count": 35, + "execution_count": 13, "metadata": {}, "outputs": [ { @@ -437,212 +418,573 @@ " \n", " \n", " \n", - " trader_type\n", - " week\n", - " retained_traders\n", - " previous_traders\n", - " retention_rate\n", + " trader_address\n", + " request_time\n", + " market_creator\n", + " request_date\n", + " staking\n", + " month_year_week\n", " \n", " \n", " \n", " \n", " 0\n", - " Olas\n", - " Dec-08-2024\n", - " 93\n", - " 98\n", - " 94.90\n", + " 0x721de88cee9be146c8f0c7ef1a4188bee36494d6\n", + " 2024-10-25 00:00:20+00:00\n", + " quickstart\n", + " 2024-10-25\n", + " non_staking\n", + " Oct-25-2024\n", " \n", " \n", " 1\n", - " Olas\n", - " Dec-15-2024\n", - " 187\n", - " 207\n", - " 90.34\n", + " 0x8a1d5f22b5a3bea34697b85e7b4ad894bf9ee36a\n", + " 2024-10-25 00:00:25+00:00\n", + " quickstart\n", + " 2024-10-25\n", + " non_staking\n", + " Oct-25-2024\n", " \n", " \n", " 2\n", - " Olas\n", - " Dec-22-2024\n", - " 186\n", - " 213\n", - " 87.32\n", + " 0xf839eaf4b42eadd917b46d7b6da0dd0e1fd6f684\n", + " 2024-10-25 00:00:55+00:00\n", + " quickstart\n", + " 2024-10-25\n", + " non_staking\n", + " Oct-25-2024\n", " \n", " \n", " 3\n", - " Olas\n", - " Dec-29-2024\n", - " 143\n", - " 203\n", - " 70.44\n", + " 0x01274796ce41aa8e8312e05a427ffb4b0d2148f6\n", + " 2024-10-25 00:00:55+00:00\n", + " quickstart\n", + " 2024-10-25\n", + " non_staking\n", + " Oct-25-2024\n", " \n", " \n", " 4\n", - " Olas\n", - " Jan-05-2025\n", - " 117\n", - " 148\n", - " 79.05\n", + " 0xc20678890f94d0162593c46fe5da67d9a4b7a6fb\n", + " 2024-10-25 00:01:05+00:00\n", + " quickstart\n", + " 2024-10-25\n", + " non_staking\n", + " Oct-25-2024\n", " \n", " \n", "\n", "" ], "text/plain": [ - " trader_type week retained_traders previous_traders retention_rate\n", - "0 Olas Dec-08-2024 93 98 94.90\n", - "1 Olas Dec-15-2024 187 207 90.34\n", - "2 Olas Dec-22-2024 186 213 87.32\n", - "3 Olas Dec-29-2024 143 203 70.44\n", - "4 Olas Jan-05-2025 117 148 79.05" + " trader_address request_time \\\n", + "0 0x721de88cee9be146c8f0c7ef1a4188bee36494d6 2024-10-25 00:00:20+00:00 \n", + "1 0x8a1d5f22b5a3bea34697b85e7b4ad894bf9ee36a 2024-10-25 00:00:25+00:00 \n", + "2 0xf839eaf4b42eadd917b46d7b6da0dd0e1fd6f684 2024-10-25 00:00:55+00:00 \n", + "3 0x01274796ce41aa8e8312e05a427ffb4b0d2148f6 2024-10-25 00:00:55+00:00 \n", + "4 0xc20678890f94d0162593c46fe5da67d9a4b7a6fb 2024-10-25 00:01:05+00:00 \n", + "\n", + " market_creator request_date staking month_year_week \n", + "0 quickstart 2024-10-25 non_staking Oct-25-2024 \n", + "1 quickstart 2024-10-25 non_staking Oct-25-2024 \n", + "2 quickstart 2024-10-25 non_staking Oct-25-2024 \n", + "3 quickstart 2024-10-25 non_staking Oct-25-2024 \n", + "4 quickstart 2024-10-25 non_staking Oct-25-2024 " ] }, - "execution_count": 35, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "wow_retention.head()" + "retention_df.head()" ] }, { "cell_type": "code", - "execution_count": 39, + "execution_count": 14, "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", - "
trader_typeweekretained_tradersprevious_tradersretention_rate
9non_Olas2024-12-08154154100.00
10non_Olas2024-12-1530132492.90
11non_Olas2024-12-2231032196.57
12non_Olas2024-12-2931234191.50
13non_Olas2025-01-0530432693.25
14non_Olas2025-01-1224633373.87
15non_Olas2024-11-105125120.32
16non_Olas2024-11-179010090.00
17non_Olas2024-11-2415118183.43
\n", - "
" - ], "text/plain": [ - " trader_type week retained_traders previous_traders retention_rate\n", - "9 non_Olas 2024-12-08 154 154 100.00\n", - "10 non_Olas 2024-12-15 301 324 92.90\n", - "11 non_Olas 2024-12-22 310 321 96.57\n", - "12 non_Olas 2024-12-29 312 341 91.50\n", - "13 non_Olas 2025-01-05 304 326 93.25\n", - "14 non_Olas 2025-01-12 246 333 73.87\n", - "15 non_Olas 2024-11-10 51 251 20.32\n", - "16 non_Olas 2024-11-17 90 100 90.00\n", - "17 non_Olas 2024-11-24 151 181 83.43" + "staking\n", + "non_Olas 764956\n", + "non_staking 275246\n", + "pearl 56487\n", + "quickstart 48511\n", + "Name: count, dtype: int64" ] }, - "execution_count": 39, + "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "non_olas = wow_retention.loc[wow_retention[\"trader_type\"]==\"non_Olas\"]\n", - "non_olas" + "retention_df.staking.value_counts()" ] }, { - "cell_type": "code", - "execution_count": 47, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Join the two datasets" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": {}, + "outputs": [], + "source": [ + "# read trades dataset\n", + "traders_df = pd.read_parquet(\"../data/all_trades_profitability.parquet\")\n", + "unknown_df = pd.read_parquet(\"../data/unknown_traders.parquet\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "staking\n", + "non_Olas 56266\n", + "non_staking 20954\n", + "pearl 6084\n", + "quickstart 3975\n", + "Name: count, dtype: int64" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "traders_df.staking.value_counts()" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [], + "source": [ + "traders_df[\"trader_type\"] = traders_df[\"staking\"].apply(\n", + " lambda x: \"non_Olas\" if x == \"non_Olas\" else \"Olas\"\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "trader_type\n", + "non_Olas 56266\n", + "Olas 31013\n", + "Name: count, dtype: int64" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "traders_df.trader_type.value_counts()" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "staking\n", + "non_Olas 1654\n", + "Name: count, dtype: int64" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "unknown_df.staking.value_counts()" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [], + "source": [ + "unknown_df[\"trader_type\"] = \"unclassified\"" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [], + "source": [ + "all_traders = pd.concat([traders_df, unknown_df], ignore_index=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "trader_type\n", + "non_Olas 56266\n", + "Olas 31013\n", + "unclassified 1654\n", + "Name: count, dtype: int64" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "all_traders.trader_type.value_counts()" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/var/folders/gp/02mb1d514ng739czlxw1lhh00000gn/T/ipykernel_51242/2488528526.py:5: UserWarning: Converting to PeriodArray/Index representation will drop timezone information.\n", + " all_traders[\"creation_timestamp\"].dt.to_period(\"W\").dt.strftime(\"%b-%d-%Y\")\n" + ] + } + ], + "source": [ + "# First, create week numbers from timestamps\n", + "all_traders[\"creation_timestamp\"] = pd.to_datetime(all_traders[\"creation_timestamp\"])\n", + "all_traders = all_traders.sort_values(by=\"creation_timestamp\", ascending=True)\n", + "all_traders[\"month_year_week\"] = (\n", + "all_traders[\"creation_timestamp\"].dt.to_period(\"W\").dt.strftime(\"%b-%d-%Y\")\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# WoW Retention" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [], + "source": [ + "def calculate_wow_retention_by_type(df):\n", + " # Get unique traders per week and type\n", + " weekly_traders = df.groupby(['month_year_week', 'trader_type'])['trader_address'].nunique().reset_index()\n", + " weekly_traders = weekly_traders.sort_values(['trader_type', 'month_year_week'])\n", + " \n", + " # Calculate retention\n", + " retention = []\n", + " # Iterate through each trader type\n", + " for trader_type in weekly_traders['trader_type'].unique():\n", + " type_data = weekly_traders[weekly_traders['trader_type'] == trader_type]\n", + " \n", + " # Calculate retention for each week within this trader type\n", + " for i in range(1, len(type_data)):\n", + " current_week = type_data.iloc[i]['month_year_week']\n", + " previous_week = type_data.iloc[i-1]['month_year_week']\n", + " \n", + " # Get traders in both weeks for this type\n", + " current_traders = set(df[\n", + " (df['month_year_week'] == current_week) & \n", + " (df['trader_type'] == trader_type)\n", + " ]['trader_address'])\n", + " \n", + " previous_traders = set(df[\n", + " (df['month_year_week'] == previous_week) & \n", + " (df['trader_type'] == trader_type)\n", + " ]['trader_address'])\n", + " \n", + " retained = len(current_traders.intersection(previous_traders))\n", + " retention_rate = (retained / len(previous_traders)) * 100 if len(previous_traders) > 0 else 0\n", + " \n", + " retention.append({\n", + " 'trader_type': trader_type,\n", + " 'week': current_week,\n", + " 'retained_traders': retained,\n", + " 'previous_traders': len(previous_traders),\n", + " 'retention_rate': round(retention_rate, 2)\n", + " })\n", + " \n", + " return pd.DataFrame(retention)" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [], + "source": [ + "wow_retention = calculate_wow_retention_by_type(all_traders)" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "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", + "
trader_typeweekretained_tradersprevious_tradersretention_rate
0OlasDec-08-2024939894.90
1OlasDec-15-202418720790.34
2OlasDec-22-202418621387.32
3OlasDec-29-202414320370.44
4OlasJan-05-202511714879.05
\n", + "
" + ], + "text/plain": [ + " trader_type week retained_traders previous_traders retention_rate\n", + "0 Olas Dec-08-2024 93 98 94.90\n", + "1 Olas Dec-15-2024 187 207 90.34\n", + "2 Olas Dec-22-2024 186 213 87.32\n", + "3 Olas Dec-29-2024 143 203 70.44\n", + "4 Olas Jan-05-2025 117 148 79.05" + ] + }, + "execution_count": 35, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "wow_retention.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "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", + "
trader_typeweekretained_tradersprevious_tradersretention_rate
9non_Olas2024-12-08154154100.00
10non_Olas2024-12-1530132492.90
11non_Olas2024-12-2231032196.57
12non_Olas2024-12-2931234191.50
13non_Olas2025-01-0530432693.25
14non_Olas2025-01-1224633373.87
15non_Olas2024-11-105125120.32
16non_Olas2024-11-179010090.00
17non_Olas2024-11-2415118183.43
\n", + "
" + ], + "text/plain": [ + " trader_type week retained_traders previous_traders retention_rate\n", + "9 non_Olas 2024-12-08 154 154 100.00\n", + "10 non_Olas 2024-12-15 301 324 92.90\n", + "11 non_Olas 2024-12-22 310 321 96.57\n", + "12 non_Olas 2024-12-29 312 341 91.50\n", + "13 non_Olas 2025-01-05 304 326 93.25\n", + "14 non_Olas 2025-01-12 246 333 73.87\n", + "15 non_Olas 2024-11-10 51 251 20.32\n", + "16 non_Olas 2024-11-17 90 100 90.00\n", + "17 non_Olas 2024-11-24 151 181 83.43" + ] + }, + "execution_count": 39, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "non_olas = wow_retention.loc[wow_retention[\"trader_type\"]==\"non_Olas\"]\n", + "non_olas" + ] + }, + { + "cell_type": "code", + "execution_count": 47, "metadata": {}, "outputs": [], "source": [ @@ -1686,79 +2028,693 @@ } }, "metadata": {}, - "output_type": "display_data" + "output_type": "display_data" + } + ], + "source": [ + "# Create and show the plot\n", + "fig = plot_wow_retention_by_type(wow_retention)\n", + "fig.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Cohort retention" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "metadata": {}, + "outputs": [], + "source": [ + "def calculate_cohort_retention(\n", + " df: pd.DataFrame, market_creator: str, trader_type: str\n", + ") -> pd.DataFrame:\n", + " df_filtered = df.loc[\n", + " (df[\"market_creator\"] == market_creator) & (df[\"trader_type\"] == trader_type)\n", + " ]\n", + " # Get first week for each trader\n", + " first_trades = (\n", + " df_filtered.groupby(\"trader_address\")\n", + " .agg({\"creation_timestamp\": \"min\", \"month_year_week\": \"first\"})\n", + " .reset_index()\n", + " )\n", + " first_trades.columns = [\"trader_address\", \"first_trade\", \"cohort_week\"]\n", + "\n", + " # Get ordered list of unique weeks - converting to datetime for proper sorting\n", + " all_weeks = df_filtered[\"month_year_week\"].unique()\n", + " weeks_datetime = pd.to_datetime(all_weeks)\n", + " sorted_weeks_idx = weeks_datetime.argsort()\n", + " all_weeks = all_weeks[sorted_weeks_idx]\n", + " print(f\"all_weeks={all_weeks}\")\n", + "\n", + " # Create mapping from week string to numeric index\n", + " week_to_number = {week: idx for idx, week in enumerate(all_weeks)}\n", + "\n", + " # Merge back to get all activities\n", + " cohort_data = pd.merge(\n", + " df_filtered,\n", + " first_trades[[\"trader_address\", \"cohort_week\"]],\n", + " on=\"trader_address\",\n", + " )\n", + " print(cohort_data.tail())\n", + " print(cohort_data.cohort_week.value_counts())\n", + "\n", + " # Calculate week number since first activity\n", + " cohort_data[\"cohort_number\"] = cohort_data[\"cohort_week\"].map(week_to_number)\n", + " cohort_data[\"activity_number\"] = cohort_data[\"month_year_week\"].map(week_to_number)\n", + " cohort_data[\"week_number\"] = (\n", + " cohort_data[\"activity_number\"] - cohort_data[\"cohort_number\"]\n", + " )\n", + "\n", + " # Calculate retention by cohort\n", + " cohort_sizes = cohort_data.groupby(\"cohort_week\")[\"trader_address\"].nunique()\n", + " print(\"COHORT SIZES\")\n", + " print(cohort_sizes)\n", + " retention_matrix = cohort_data.groupby([\"cohort_week\", \"week_number\"])[\n", + " \"trader_address\"\n", + " ].nunique()\n", + " retention_matrix = retention_matrix.unstack(fill_value=0)\n", + "\n", + " # Convert to percentages\n", + " retention_matrix = retention_matrix.div(cohort_sizes, axis=0) * 100\n", + "\n", + " # Sort index (cohort_week) chronologically\n", + " retention_matrix.index = pd.to_datetime(retention_matrix.index)\n", + " retention_matrix = retention_matrix.sort_index()\n", + "\n", + " return retention_matrix.round(2)" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "metadata": {}, + "outputs": [], + "source": [ + "def prepare_retention_dataset(\n", + " retention_df: pd.DataFrame, unknown_df: pd.DataFrame\n", + ") -> pd.DataFrame:\n", + "\n", + " retention_df[\"trader_type\"] = retention_df[\"staking\"].apply(\n", + " lambda x: \"non_Olas\" if x == \"non_Olas\" else \"Olas\"\n", + " )\n", + " retention_df.rename(columns={\"request_time\": \"creation_timestamp\"}, inplace=True)\n", + " retention_df = retention_df[\n", + " [\"trader_type\", \"market_creator\", \"trader_address\", \"creation_timestamp\"]\n", + " ]\n", + " unknown_df[\"trader_type\"] = \"unclassified\"\n", + " unknown_df = unknown_df[\n", + " [\"trader_type\", \"market_creator\", \"trader_address\", \"creation_timestamp\"]\n", + " ]\n", + " all_traders = pd.concat([retention_df, unknown_df], ignore_index=True)\n", + "\n", + " all_traders[\"creation_timestamp\"] = pd.to_datetime(\n", + " all_traders[\"creation_timestamp\"]\n", + " )\n", + " all_traders = all_traders.sort_values(by=\"creation_timestamp\", ascending=True)\n", + " all_traders[\"month_year_week\"] = (\n", + " all_traders[\"creation_timestamp\"].dt.to_period(\"W\").dt.strftime(\"%b-%d-%Y\")\n", + " )\n", + " return all_traders" + ] + }, + { + "cell_type": "code", + "execution_count": 80, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/var/folders/gp/02mb1d514ng739czlxw1lhh00000gn/T/ipykernel_51242/2945974734.py:23: UserWarning: Converting to PeriodArray/Index representation will drop timezone information.\n", + " all_traders[\"creation_timestamp\"].dt.to_period(\"W\").dt.strftime(\"%b-%d-%Y\")\n" + ] + } + ], + "source": [ + "all_traders = prepare_retention_dataset(retention_df=retention_df, unknown_df=unknown_df)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 81, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "all_weeks=['Nov-17-2024' 'Nov-24-2024' 'Dec-01-2024' 'Dec-08-2024' 'Dec-15-2024'\n", + " 'Dec-22-2024' 'Dec-29-2024' 'Jan-05-2025' 'Jan-12-2025' 'Jan-19-2025']\n", + " trader_type market_creator trader_address \\\n", + "50119 Olas pearl 0xcaa568047b0ae065b5cf5d29b875e31afe0ab70e \n", + "50120 Olas pearl 0xcaa568047b0ae065b5cf5d29b875e31afe0ab70e \n", + "50121 Olas pearl 0x5fc7213135962250147030c5dd30b84a80f2ad1e \n", + "50122 Olas pearl 0xe715cc8f264ab48f75bb1b5c11d7dbaf949d73c5 \n", + "50123 Olas pearl 0xe715cc8f264ab48f75bb1b5c11d7dbaf949d73c5 \n", + "\n", + " creation_timestamp month_year_week cohort_week \n", + "50119 2025-01-14 12:34:00+00:00 Jan-19-2025 Dec-08-2024 \n", + "50120 2025-01-14 12:36:35+00:00 Jan-19-2025 Dec-08-2024 \n", + "50121 2025-01-14 13:18:10+00:00 Jan-19-2025 Nov-17-2024 \n", + "50122 2025-01-14 13:21:10+00:00 Jan-19-2025 Nov-17-2024 \n", + "50123 2025-01-14 13:22:55+00:00 Jan-19-2025 Nov-17-2024 \n", + "cohort_week\n", + "Nov-17-2024 46407\n", + "Nov-24-2024 1802\n", + "Dec-01-2024 848\n", + "Dec-08-2024 578\n", + "Dec-15-2024 429\n", + "Jan-19-2025 46\n", + "Dec-22-2024 7\n", + "Dec-29-2024 7\n", + "Name: count, dtype: int64\n", + "COHORT SIZES\n", + "cohort_week\n", + "Dec-01-2024 7\n", + "Dec-08-2024 6\n", + "Dec-15-2024 10\n", + "Dec-22-2024 2\n", + "Dec-29-2024 1\n", + "Jan-19-2025 1\n", + "Nov-17-2024 143\n", + "Nov-24-2024 6\n", + "Name: trader_address, dtype: int64\n" + ] + } + ], + "source": [ + "olas_cohort_pearl = calculate_cohort_retention(df=all_traders, market_creator=\"pearl\", trader_type=\"Olas\")" + ] + }, + { + "cell_type": "code", + "execution_count": 72, + "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", + "
week_number0123456789
cohort_week
2024-12-08100.083.3366.6766.6733.3350.050.00.00.00.0
2024-12-15100.040.0030.0030.0020.000.00.00.00.00.0
2024-12-22100.00.000.000.000.000.00.00.00.00.0
2024-12-29100.00.000.000.000.000.00.00.00.00.0
2025-01-19100.00.000.000.000.000.00.00.00.00.0
\n", + "
" + ], + "text/plain": [ + "week_number 0 1 2 3 4 5 6 7 8 9\n", + "cohort_week \n", + "2024-12-08 100.0 83.33 66.67 66.67 33.33 50.0 50.0 0.0 0.0 0.0\n", + "2024-12-15 100.0 40.00 30.00 30.00 20.00 0.0 0.0 0.0 0.0 0.0\n", + "2024-12-22 100.0 0.00 0.00 0.00 0.00 0.0 0.0 0.0 0.0 0.0\n", + "2024-12-29 100.0 0.00 0.00 0.00 0.00 0.0 0.0 0.0 0.0 0.0\n", + "2025-01-19 100.0 0.00 0.00 0.00 0.00 0.0 0.0 0.0 0.0 0.0" + ] + }, + "execution_count": 72, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "olas_cohort_pearl.tail()" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Index([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype='int64', name='week_number')" + ] + }, + "execution_count": 54, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "olas_cohort_pearl.columns" + ] + }, + { + "cell_type": "code", + "execution_count": 82, + "metadata": {}, + "outputs": [], + "source": [ + "olas_data.rename(columns={\"request_time\": \"creation_timestamp\"}, inplace=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 83, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/var/folders/gp/02mb1d514ng739czlxw1lhh00000gn/T/ipykernel_51242/1537996894.py:3: UserWarning: Converting to PeriodArray/Index representation will drop timezone information.\n", + " olas_data[\"creation_timestamp\"].dt.to_period(\"W\").dt.strftime(\"%b-%d-%Y\")\n" + ] + } + ], + "source": [ + "olas_data = olas_data.sort_values(by=\"creation_timestamp\", ascending=True)\n", + "olas_data[\"month_year_week\"] = (\n", + " olas_data[\"creation_timestamp\"].dt.to_period(\"W\").dt.strftime(\"%b-%d-%Y\")\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 84, + "metadata": {}, + "outputs": [], + "source": [ + "first_trades = (\n", + " olas_data.groupby(\"trader_address\")\n", + " .agg({\"creation_timestamp\": \"min\", \"month_year_week\": \"first\"})\n", + " .reset_index()\n", + " )\n", + "first_trades.columns = [\"trader_address\", \"first_trade\", \"cohort_week\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 67, + "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", + "
trader_addressfirst_tradecohort_week
00x006f70b4e3c3a3648f31ec16b2e7106fc58166f22024-11-20 07:26:35+00:00Nov-24-2024
10x00897abcbbefe4f558956b7a9d1b7819677e4d902024-11-13 10:21:25+00:00Nov-17-2024
20x01274796ce41aa8e8312e05a427ffb4b0d2148f62024-11-13 10:13:05+00:00Nov-17-2024
30x01c72d0743a22b70d73c76c5e16ba7524e20e0c02024-11-13 19:27:15+00:00Nov-17-2024
40x0244169d0fe1014b9e71f71070099d9c2364af282024-11-16 06:06:20+00:00Nov-17-2024
............
2680xfaa64c148c32af3552413438ec78599bffbd077a2024-11-13 03:23:00+00:00Nov-17-2024
2690xfab01f48385de3ffea00f9bf9f27c888e4802d172024-11-13 12:22:50+00:00Nov-17-2024
2700xfe16926cefc4db4a7496bfc3e961445228fbbf392024-12-15 12:47:10+00:00Dec-15-2024
2710xfe2c8e93ce30d1c961831d8e4d120a307aedbe722024-11-13 11:44:40+00:00Nov-17-2024
2720xfe94203ab2c1c22fe8585cbebf865f7b69eb70272024-11-13 00:46:35+00:00Nov-17-2024
\n", + "

273 rows × 3 columns

\n", + "
" + ], + "text/plain": [ + " trader_address first_trade \\\n", + "0 0x006f70b4e3c3a3648f31ec16b2e7106fc58166f2 2024-11-20 07:26:35+00:00 \n", + "1 0x00897abcbbefe4f558956b7a9d1b7819677e4d90 2024-11-13 10:21:25+00:00 \n", + "2 0x01274796ce41aa8e8312e05a427ffb4b0d2148f6 2024-11-13 10:13:05+00:00 \n", + "3 0x01c72d0743a22b70d73c76c5e16ba7524e20e0c0 2024-11-13 19:27:15+00:00 \n", + "4 0x0244169d0fe1014b9e71f71070099d9c2364af28 2024-11-16 06:06:20+00:00 \n", + ".. ... ... \n", + "268 0xfaa64c148c32af3552413438ec78599bffbd077a 2024-11-13 03:23:00+00:00 \n", + "269 0xfab01f48385de3ffea00f9bf9f27c888e4802d17 2024-11-13 12:22:50+00:00 \n", + "270 0xfe16926cefc4db4a7496bfc3e961445228fbbf39 2024-12-15 12:47:10+00:00 \n", + "271 0xfe2c8e93ce30d1c961831d8e4d120a307aedbe72 2024-11-13 11:44:40+00:00 \n", + "272 0xfe94203ab2c1c22fe8585cbebf865f7b69eb7027 2024-11-13 00:46:35+00:00 \n", + "\n", + " cohort_week \n", + "0 Nov-24-2024 \n", + "1 Nov-17-2024 \n", + "2 Nov-17-2024 \n", + "3 Nov-17-2024 \n", + "4 Nov-17-2024 \n", + ".. ... \n", + "268 Nov-17-2024 \n", + "269 Nov-17-2024 \n", + "270 Dec-15-2024 \n", + "271 Nov-17-2024 \n", + "272 Nov-17-2024 \n", + "\n", + "[273 rows x 3 columns]" + ] + }, + "execution_count": 67, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ - "# Create and show the plot\n", - "fig = plot_wow_retention_by_type(wow_retention)\n", - "fig.show()" + "first_trades" ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": 85, "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array(['Nov-17-2024', 'Nov-24-2024', 'Dec-01-2024', 'Dec-08-2024',\n", + " 'Dec-15-2024', 'Dec-22-2024', 'Dec-29-2024', 'Jan-05-2025',\n", + " 'Jan-12-2025', 'Jan-19-2025'], dtype=object)" + ] + }, + "execution_count": 85, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "# Cohort retention" + "all_weeks = olas_data[\"month_year_week\"].unique()\n", + "all_weeks" ] }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 86, "metadata": {}, "outputs": [], "source": [ - "def calculate_cohort_retention(df, max_weeks=12):\n", - " # Get first week for each trader\n", - " first_trades = (\n", - " df.groupby(\"trader_address\")\n", - " .agg({\"creation_timestamp\": \"min\", \"month_year_week\": \"first\"})\n", - " .reset_index()\n", - " )\n", - " first_trades.columns = [\"trader_address\", \"first_trade\", \"cohort_week\"]\n", - "\n", - " # Get ordered list of unique weeks - converting to datetime for proper sorting\n", - " all_weeks = df[\"month_year_week\"].unique()\n", - " weeks_datetime = pd.to_datetime(all_weeks)\n", - " sorted_weeks_idx = weeks_datetime.argsort()\n", - " all_weeks = all_weeks[sorted_weeks_idx]\n", - "\n", - " # Create mapping from week string to numeric index\n", - " week_to_number = {week: idx for idx, week in enumerate(all_weeks)}\n", + "all_weeks = olas_data[\"month_year_week\"].unique()\n", + "weeks_datetime = pd.to_datetime(all_weeks)\n", + "sorted_weeks_idx = weeks_datetime.argsort()\n", + "all_weeks = all_weeks[sorted_weeks_idx]" + ] + }, + { + "cell_type": "code", + "execution_count": 70, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array(['Nov-17-2024', 'Nov-24-2024', 'Dec-01-2024', 'Dec-08-2024',\n", + " 'Dec-15-2024', 'Dec-22-2024', 'Dec-29-2024', 'Jan-05-2025',\n", + " 'Jan-12-2025', 'Jan-19-2025'], dtype=object)" + ] + }, + "execution_count": 70, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "all_weeks" + ] + }, + { + "cell_type": "code", + "execution_count": 87, + "metadata": {}, + "outputs": [], + "source": [ + "# Create mapping from week string to numeric index\n", + "week_to_number = {week: idx for idx, week in enumerate(all_weeks)}\n", "\n", - " # Merge back to get all activities\n", - " cohort_data = pd.merge(\n", - " df, first_trades[[\"trader_address\", \"cohort_week\"]], on=\"trader_address\"\n", - " )\n", + "# Merge back to get all activities\n", + "cohort_data = pd.merge(\n", + " olas_data,\n", + " first_trades[[\"trader_address\", \"cohort_week\"]],\n", + " on=\"trader_address\",\n", + ")\n", "\n", - " # Calculate week number since first activity\n", - " cohort_data[\"cohort_number\"] = cohort_data[\"cohort_week\"].map(week_to_number)\n", - " cohort_data[\"activity_number\"] = cohort_data[\"month_year_week\"].map(week_to_number)\n", - " cohort_data[\"week_number\"] = (\n", - " cohort_data[\"activity_number\"] - cohort_data[\"cohort_number\"]\n", - " )\n", + "# Calculate week number since first activity\n", + "cohort_data[\"cohort_number\"] = cohort_data[\"cohort_week\"].map(week_to_number)\n", + "cohort_data[\"activity_number\"] = cohort_data[\"month_year_week\"].map(week_to_number)\n", + "cohort_data[\"week_number\"] = (\n", + " cohort_data[\"activity_number\"] - cohort_data[\"cohort_number\"]\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 88, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "cohort_week\n", + "Dec-01-2024 10\n", + "Dec-08-2024 12\n", + "Dec-15-2024 10\n", + "Dec-22-2024 2\n", + "Dec-29-2024 1\n", + "Jan-05-2025 1\n", + "Jan-19-2025 1\n", + "Nov-17-2024 220\n", + "Nov-24-2024 16\n", + "Name: trader_address, dtype: int64\n" + ] + } + ], + "source": [ + "cohort_sizes = cohort_data.groupby(\"cohort_week\")[\"trader_address\"].nunique()\n", "\n", - " # Calculate retention by cohort\n", - " cohort_sizes = cohort_data.groupby(\"cohort_week\")[\"trader_address\"].nunique()\n", + "print(cohort_sizes)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ " retention_matrix = cohort_data.groupby([\"cohort_week\", \"week_number\"])[\n", " \"trader_address\"\n", " ].nunique()\n", - " retention_matrix = retention_matrix.unstack(fill_value=0)\n", - "\n", - " # Convert to percentages\n", - " retention_matrix = retention_matrix.div(cohort_sizes, axis=0) * 100\n", - "\n", - " # Sort index (cohort_week) chronologically\n", - " retention_matrix.index = pd.to_datetime(retention_matrix.index)\n", - " retention_matrix = retention_matrix.sort_index()\n", - "\n", - " # Limit to max_weeks if specified\n", - " if max_weeks is not None and max_weeks < retention_matrix.shape[1]:\n", - " retention_matrix = retention_matrix.iloc[:, :max_weeks]\n", - "\n", - " return retention_matrix.round(2)" + " retention_matrix = retention_matrix.unstack(fill_value=0)" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, { "cell_type": "code", "execution_count": 54,