4473 lines
317 KiB
Plaintext
4473 lines
317 KiB
Plaintext
{
|
||
"cells": [
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 51,
|
||
"id": "338730e2-a6de-4d4f-b438-efe3feb139ab",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"import pandas as pd\n",
|
||
"import numpy as np\n",
|
||
"import plotly.graph_objects as go\n",
|
||
"import matplotlib.pyplot as plt"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 52,
|
||
"id": "cfd11919-0941-400e-a516-72871881f733",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"/tmp/ipykernel_1311/1940519970.py:1: DtypeWarning:\n",
|
||
"\n",
|
||
"Columns (1,2,3,4) have mixed types. Specify dtype option on import or set low_memory=False.\n",
|
||
"\n",
|
||
"/tmp/ipykernel_1311/1940519970.py:2: DtypeWarning:\n",
|
||
"\n",
|
||
"Columns (1,2,3,4) have mixed types. Specify dtype option on import or set low_memory=False.\n",
|
||
"\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"stocks=pd.read_csv('stocks.csv')\n",
|
||
"flows = pd.read_csv('flows.csv')"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 53,
|
||
"id": "b99e3402-fe26-4f4e-8c1c-5f07847bce94",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"/tmp/ipykernel_1311/3613746644.py:1: DtypeWarning:\n",
|
||
"\n",
|
||
"Columns (1) have mixed types. Specify dtype option on import or set low_memory=False.\n",
|
||
"\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"merged = pd.read_csv('merged.csv')"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 54,
|
||
"id": "34e5a815-7269-4312-bfe6-e2cd12595e57",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# 1. Prepare stock dataset ISIN-by-ISIN\n",
|
||
"stocks_isin = stocks[[\n",
|
||
" \"Registrar Account - ID\",\n",
|
||
" \"Product - Isin\",\n",
|
||
" \"Centralisation Date\",\n",
|
||
" \"Quantity - AUM\"\n",
|
||
"]].copy()\n",
|
||
"\n",
|
||
"stocks_isin[\"Centralisation Date\"] = pd.to_datetime(stocks_isin[\"Centralisation Date\"])\n",
|
||
"\n",
|
||
"stocks_isin = stocks_isin.sort_values(\n",
|
||
" [\"Registrar Account - ID\", \"Product - Isin\", \"Centralisation Date\"]\n",
|
||
")\n",
|
||
"\n",
|
||
"# 2. Prepare flows dataset ISIN-by-ISIN\n",
|
||
"flows_isin = flows[[\n",
|
||
" \"Registrar Account - ID\",\n",
|
||
" \"Product - Isin\",\n",
|
||
" \"Centralisation Date\",\n",
|
||
" \"Quantity - NetFlows\"\n",
|
||
"]].copy()\n",
|
||
"\n",
|
||
"flows_isin[\"Centralisation Date\"] = pd.to_datetime(flows_isin[\"Centralisation Date\"])\n",
|
||
"\n",
|
||
"flows_isin = (\n",
|
||
" flows_isin\n",
|
||
" .groupby(\n",
|
||
" [\"Registrar Account - ID\", \"Product - Isin\", \"Centralisation Date\"]\n",
|
||
" )[\"Quantity - NetFlows\"]\n",
|
||
" .sum()\n",
|
||
" .reset_index()\n",
|
||
")\n",
|
||
"\n",
|
||
"# 3. Merge stocks & flows ISIN-by-ISIN\n",
|
||
"merged_isin = stocks_isin.merge(\n",
|
||
" flows_isin,\n",
|
||
" on=[\"Registrar Account - ID\", \"Product - Isin\", \"Centralisation Date\"],\n",
|
||
" how=\"left\"\n",
|
||
")\n",
|
||
"\n",
|
||
"merged_isin[\"Quantity - NetFlows\"] = merged_isin[\"Quantity - NetFlows\"].fillna(0)\n",
|
||
"\n",
|
||
"# 4. Compute expected stock per ISIN for each account\n",
|
||
"merged_isin[\"prev_stock\"] = (\n",
|
||
" merged_isin\n",
|
||
" .groupby([\"Registrar Account - ID\", \"Product - Isin\"])[\"Quantity - AUM\"]\n",
|
||
" .shift(1)\n",
|
||
")\n",
|
||
"\n",
|
||
"merged_isin[\"prev_netflows\"] = (\n",
|
||
" merged_isin\n",
|
||
" .groupby([\"Registrar Account - ID\", \"Product - Isin\"])[\"Quantity - NetFlows\"]\n",
|
||
" .shift(1)\n",
|
||
" .fillna(0)\n",
|
||
")\n",
|
||
"\n",
|
||
"merged_isin[\"expected_stock\"] = (\n",
|
||
" merged_isin[\"prev_stock\"] + merged_isin[\"prev_netflows\"]\n",
|
||
")\n",
|
||
"\n",
|
||
"# 5. Detect ruptures ISIN-by-ISIN (no aggregation)\n",
|
||
"TOL = 1e-6\n",
|
||
"\n",
|
||
"merged_isin[\"gap\"] = (\n",
|
||
" merged_isin[\"Quantity - AUM\"] - merged_isin[\"expected_stock\"]\n",
|
||
")\n",
|
||
"\n",
|
||
"merged_isin[\"rupture_flag\"] = (\n",
|
||
" merged_isin[\"prev_stock\"].notna()\n",
|
||
" & (merged_isin[\"gap\"].abs() > TOL)\n",
|
||
")\n",
|
||
"\n",
|
||
"# 6. Summarize ruptures per (Account, ISIN)\n",
|
||
"rupture_isin_summary = (\n",
|
||
" merged_isin\n",
|
||
" .groupby([\"Registrar Account - ID\", \"Product - Isin\"])\n",
|
||
" .agg(\n",
|
||
" n_ruptures=(\"rupture_flag\", \"sum\"),\n",
|
||
" obs=(\"rupture_flag\", \"count\"),\n",
|
||
" rupture_ratio=(\"rupture_flag\", \"mean\"),\n",
|
||
" max_gap=(\"gap\", lambda x: x.abs().max())\n",
|
||
" )\n",
|
||
" .reset_index()\n",
|
||
")\n",
|
||
"\n",
|
||
"# Sort by worst ISIN trajectories\n",
|
||
"rupture_isin_summary = rupture_isin_summary.sort_values(\n",
|
||
" \"rupture_ratio\",\n",
|
||
" ascending=False\n",
|
||
")"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "16213cb2-07d8-4e82-b9bb-252554ec47b9",
|
||
"metadata": {},
|
||
"source": [
|
||
"# Détection des ruptures"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 55,
|
||
"id": "78c3db70-e0b6-4de2-92ca-e29cf5bf6bd1",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# ============================================================\n",
|
||
"# AUM–FLOW CONSISTENCY & RUPTURE DETECTION (FINAL VERSION)\n",
|
||
"# ============================================================\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"# 1. Keep relevant columns\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"stocks_clean = stocks[[\n",
|
||
" \"Registrar Account - ID\",\n",
|
||
" \"Product - Isin\",\n",
|
||
" \"Centralisation Date\",\n",
|
||
" \"Quantity - AUM\"\n",
|
||
"]].copy()\n",
|
||
"\n",
|
||
"flows_clean = flows[[\n",
|
||
" \"Registrar Account - ID\",\n",
|
||
" \"Product - Isin\",\n",
|
||
" \"Centralisation Date\",\n",
|
||
" \"Quantity - NetFlows\"\n",
|
||
"]].copy()\n",
|
||
"\n",
|
||
"\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"# 2. Date formatting\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"stocks_clean[\"Centralisation Date\"] = pd.to_datetime(stocks_clean[\"Centralisation Date\"])\n",
|
||
"flows_clean[\"Centralisation Date\"] = pd.to_datetime(flows_clean[\"Centralisation Date\"])\n",
|
||
"\n",
|
||
"\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"# 3. Aggregate flows per day\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"flows_clean = (\n",
|
||
" flows_clean\n",
|
||
" .groupby(\n",
|
||
" [\"Registrar Account - ID\", \"Product - Isin\", \"Centralisation Date\"],\n",
|
||
" as_index=False\n",
|
||
" )[\"Quantity - NetFlows\"]\n",
|
||
" .sum()\n",
|
||
")\n",
|
||
"\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"# 4. Merge stocks and flows\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"df = stocks_clean.merge(\n",
|
||
" flows_clean,\n",
|
||
" on=[\"Registrar Account - ID\", \"Product - Isin\", \"Centralisation Date\"],\n",
|
||
" how=\"left\"\n",
|
||
")\n",
|
||
"\n",
|
||
"df[\"Quantity - NetFlows\"] = df[\"Quantity - NetFlows\"].fillna(0)\n",
|
||
"\n",
|
||
"\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"# 5. Sort and compute expected stock\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"df = df.sort_values(\n",
|
||
" [\"Registrar Account - ID\", \"Product - Isin\", \"Centralisation Date\"]\n",
|
||
")\n",
|
||
"\n",
|
||
"df[\"prev_stock\"] = df.groupby(\n",
|
||
" [\"Registrar Account - ID\", \"Product - Isin\"]\n",
|
||
")[\"Quantity - AUM\"].shift(1)\n",
|
||
"\n",
|
||
"df[\"prev_flows\"] = df.groupby(\n",
|
||
" [\"Registrar Account - ID\", \"Product - Isin\"]\n",
|
||
")[\"Quantity - NetFlows\"].shift(1).fillna(0)\n",
|
||
"\n",
|
||
"df[\"expected_stock\"] = df[\"prev_stock\"] + df[\"prev_flows\"]\n",
|
||
"\n",
|
||
"\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"# 6. Compute gaps\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"df[\"gap\"] = df[\"Quantity - AUM\"] - df[\"expected_stock\"]\n",
|
||
"df[\"gap_abs\"] = df[\"gap\"].abs()\n",
|
||
"df[\"gap_rel\"] = df[\"gap_abs\"] / df[\"expected_stock\"].abs().clip(lower=1)\n",
|
||
"\n",
|
||
"\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"# 7. Detect ruptures (economic rule)\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"TAU_ABS = 10.0 # minimum absolute gap (shares)\n",
|
||
"TAU_REL = 0.005 # minimum relative gap (0.5%)\n",
|
||
"\n",
|
||
"df[\"rupture_flag\"] = (\n",
|
||
" df[\"prev_stock\"].notna()\n",
|
||
" & (df[\"gap_abs\"] > TAU_ABS)\n",
|
||
" & (df[\"gap_rel\"] > TAU_REL)\n",
|
||
")\n",
|
||
"\n",
|
||
"\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"# 8. Remove end-of-sample false positives (edge effects)\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"last_date = df[\"Centralisation Date\"].max()\n",
|
||
"\n",
|
||
"df[\"rupture_flag\"] = np.where(\n",
|
||
" (df[\"rupture_flag\"]) & (df[\"Centralisation Date\"] == last_date),\n",
|
||
" False,\n",
|
||
" df[\"rupture_flag\"]\n",
|
||
")\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 56,
|
||
"id": "a9783dc1-e225-4142-8b6f-6f9e620b4b3d",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# ------------------------------------------------------------\n",
|
||
"# 9. ISIN-level summary (AFTER CLEANING)\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"rupture_isin_summary = (\n",
|
||
" df.groupby([\"Registrar Account - ID\", \"Product - Isin\"])\n",
|
||
" .agg(\n",
|
||
" n_ruptures=(\"rupture_flag\", \"sum\"),\n",
|
||
" total_obs=(\"rupture_flag\", \"count\"),\n",
|
||
" rupture_ratio=(\"rupture_flag\", \"mean\"),\n",
|
||
" max_gap=(\"gap_abs\", \"max\")\n",
|
||
" )\n",
|
||
" .reset_index()\n",
|
||
")\n",
|
||
"\n",
|
||
"\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"# 10. Account-level summary (AFTER CLEANING)\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"rupture_summary = (\n",
|
||
" df.groupby(\"Registrar Account - ID\")\n",
|
||
" .agg(\n",
|
||
" n_ruptures=(\"rupture_flag\", \"sum\"),\n",
|
||
" total_obs=(\"rupture_flag\", \"count\"),\n",
|
||
" rupture_ratio=(\"rupture_flag\", \"mean\"),\n",
|
||
" max_gap=(\"gap_abs\", \"max\")\n",
|
||
" )\n",
|
||
" .reset_index()\n",
|
||
")\n",
|
||
"\n",
|
||
"\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"# 11. Outputs\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"df.to_csv(\"aum_flow_gaps.csv\", index=False)\n",
|
||
"rupture_isin_summary.to_csv(\"rupture_isin_summary.csv\", index=False)\n",
|
||
"rupture_summary.to_csv(\"rupture_summary.csv\", index=False)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 57,
|
||
"id": "f5b62558-c27a-4428-a193-8b97e0ce6b6a",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"application/vnd.plotly.v1+json": {
|
||
"config": {
|
||
"plotlyServerURL": "https://plot.ly"
|
||
},
|
||
"data": [
|
||
{
|
||
"hole": 0.45,
|
||
"hoverinfo": "label+percent",
|
||
"labels": [
|
||
"Clean / quasi-clean (≤1%)",
|
||
"Moderate (1–10%)",
|
||
"High (10–30%)",
|
||
"Severe (>30%)"
|
||
],
|
||
"textinfo": "percent",
|
||
"type": "pie",
|
||
"values": {
|
||
"bdata": "AAAAAACASEAAAAAAAIBBQAAAAAAAAChAZmZmZmZmEEA=",
|
||
"dtype": "f8"
|
||
}
|
||
}
|
||
],
|
||
"layout": {
|
||
"legend": {
|
||
"orientation": "h",
|
||
"title": {
|
||
"text": "Rupture ratio"
|
||
},
|
||
"x": 0.5,
|
||
"xanchor": "center",
|
||
"y": -0.15,
|
||
"yanchor": "top"
|
||
},
|
||
"template": {
|
||
"data": {
|
||
"bar": [
|
||
{
|
||
"error_x": {
|
||
"color": "#2a3f5f"
|
||
},
|
||
"error_y": {
|
||
"color": "#2a3f5f"
|
||
},
|
||
"marker": {
|
||
"line": {
|
||
"color": "#E5ECF6",
|
||
"width": 0.5
|
||
},
|
||
"pattern": {
|
||
"fillmode": "overlay",
|
||
"size": 10,
|
||
"solidity": 0.2
|
||
}
|
||
},
|
||
"type": "bar"
|
||
}
|
||
],
|
||
"barpolar": [
|
||
{
|
||
"marker": {
|
||
"line": {
|
||
"color": "#E5ECF6",
|
||
"width": 0.5
|
||
},
|
||
"pattern": {
|
||
"fillmode": "overlay",
|
||
"size": 10,
|
||
"solidity": 0.2
|
||
}
|
||
},
|
||
"type": "barpolar"
|
||
}
|
||
],
|
||
"carpet": [
|
||
{
|
||
"aaxis": {
|
||
"endlinecolor": "#2a3f5f",
|
||
"gridcolor": "white",
|
||
"linecolor": "white",
|
||
"minorgridcolor": "white",
|
||
"startlinecolor": "#2a3f5f"
|
||
},
|
||
"baxis": {
|
||
"endlinecolor": "#2a3f5f",
|
||
"gridcolor": "white",
|
||
"linecolor": "white",
|
||
"minorgridcolor": "white",
|
||
"startlinecolor": "#2a3f5f"
|
||
},
|
||
"type": "carpet"
|
||
}
|
||
],
|
||
"choropleth": [
|
||
{
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
},
|
||
"type": "choropleth"
|
||
}
|
||
],
|
||
"contour": [
|
||
{
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
},
|
||
"colorscale": [
|
||
[
|
||
0,
|
||
"#0d0887"
|
||
],
|
||
[
|
||
0.1111111111111111,
|
||
"#46039f"
|
||
],
|
||
[
|
||
0.2222222222222222,
|
||
"#7201a8"
|
||
],
|
||
[
|
||
0.3333333333333333,
|
||
"#9c179e"
|
||
],
|
||
[
|
||
0.4444444444444444,
|
||
"#bd3786"
|
||
],
|
||
[
|
||
0.5555555555555556,
|
||
"#d8576b"
|
||
],
|
||
[
|
||
0.6666666666666666,
|
||
"#ed7953"
|
||
],
|
||
[
|
||
0.7777777777777778,
|
||
"#fb9f3a"
|
||
],
|
||
[
|
||
0.8888888888888888,
|
||
"#fdca26"
|
||
],
|
||
[
|
||
1,
|
||
"#f0f921"
|
||
]
|
||
],
|
||
"type": "contour"
|
||
}
|
||
],
|
||
"contourcarpet": [
|
||
{
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
},
|
||
"type": "contourcarpet"
|
||
}
|
||
],
|
||
"heatmap": [
|
||
{
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
},
|
||
"colorscale": [
|
||
[
|
||
0,
|
||
"#0d0887"
|
||
],
|
||
[
|
||
0.1111111111111111,
|
||
"#46039f"
|
||
],
|
||
[
|
||
0.2222222222222222,
|
||
"#7201a8"
|
||
],
|
||
[
|
||
0.3333333333333333,
|
||
"#9c179e"
|
||
],
|
||
[
|
||
0.4444444444444444,
|
||
"#bd3786"
|
||
],
|
||
[
|
||
0.5555555555555556,
|
||
"#d8576b"
|
||
],
|
||
[
|
||
0.6666666666666666,
|
||
"#ed7953"
|
||
],
|
||
[
|
||
0.7777777777777778,
|
||
"#fb9f3a"
|
||
],
|
||
[
|
||
0.8888888888888888,
|
||
"#fdca26"
|
||
],
|
||
[
|
||
1,
|
||
"#f0f921"
|
||
]
|
||
],
|
||
"type": "heatmap"
|
||
}
|
||
],
|
||
"histogram": [
|
||
{
|
||
"marker": {
|
||
"pattern": {
|
||
"fillmode": "overlay",
|
||
"size": 10,
|
||
"solidity": 0.2
|
||
}
|
||
},
|
||
"type": "histogram"
|
||
}
|
||
],
|
||
"histogram2d": [
|
||
{
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
},
|
||
"colorscale": [
|
||
[
|
||
0,
|
||
"#0d0887"
|
||
],
|
||
[
|
||
0.1111111111111111,
|
||
"#46039f"
|
||
],
|
||
[
|
||
0.2222222222222222,
|
||
"#7201a8"
|
||
],
|
||
[
|
||
0.3333333333333333,
|
||
"#9c179e"
|
||
],
|
||
[
|
||
0.4444444444444444,
|
||
"#bd3786"
|
||
],
|
||
[
|
||
0.5555555555555556,
|
||
"#d8576b"
|
||
],
|
||
[
|
||
0.6666666666666666,
|
||
"#ed7953"
|
||
],
|
||
[
|
||
0.7777777777777778,
|
||
"#fb9f3a"
|
||
],
|
||
[
|
||
0.8888888888888888,
|
||
"#fdca26"
|
||
],
|
||
[
|
||
1,
|
||
"#f0f921"
|
||
]
|
||
],
|
||
"type": "histogram2d"
|
||
}
|
||
],
|
||
"histogram2dcontour": [
|
||
{
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
},
|
||
"colorscale": [
|
||
[
|
||
0,
|
||
"#0d0887"
|
||
],
|
||
[
|
||
0.1111111111111111,
|
||
"#46039f"
|
||
],
|
||
[
|
||
0.2222222222222222,
|
||
"#7201a8"
|
||
],
|
||
[
|
||
0.3333333333333333,
|
||
"#9c179e"
|
||
],
|
||
[
|
||
0.4444444444444444,
|
||
"#bd3786"
|
||
],
|
||
[
|
||
0.5555555555555556,
|
||
"#d8576b"
|
||
],
|
||
[
|
||
0.6666666666666666,
|
||
"#ed7953"
|
||
],
|
||
[
|
||
0.7777777777777778,
|
||
"#fb9f3a"
|
||
],
|
||
[
|
||
0.8888888888888888,
|
||
"#fdca26"
|
||
],
|
||
[
|
||
1,
|
||
"#f0f921"
|
||
]
|
||
],
|
||
"type": "histogram2dcontour"
|
||
}
|
||
],
|
||
"mesh3d": [
|
||
{
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
},
|
||
"type": "mesh3d"
|
||
}
|
||
],
|
||
"parcoords": [
|
||
{
|
||
"line": {
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
}
|
||
},
|
||
"type": "parcoords"
|
||
}
|
||
],
|
||
"pie": [
|
||
{
|
||
"automargin": true,
|
||
"type": "pie"
|
||
}
|
||
],
|
||
"scatter": [
|
||
{
|
||
"fillpattern": {
|
||
"fillmode": "overlay",
|
||
"size": 10,
|
||
"solidity": 0.2
|
||
},
|
||
"type": "scatter"
|
||
}
|
||
],
|
||
"scatter3d": [
|
||
{
|
||
"line": {
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
}
|
||
},
|
||
"marker": {
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
}
|
||
},
|
||
"type": "scatter3d"
|
||
}
|
||
],
|
||
"scattercarpet": [
|
||
{
|
||
"marker": {
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
}
|
||
},
|
||
"type": "scattercarpet"
|
||
}
|
||
],
|
||
"scattergeo": [
|
||
{
|
||
"marker": {
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
}
|
||
},
|
||
"type": "scattergeo"
|
||
}
|
||
],
|
||
"scattergl": [
|
||
{
|
||
"marker": {
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
}
|
||
},
|
||
"type": "scattergl"
|
||
}
|
||
],
|
||
"scattermap": [
|
||
{
|
||
"marker": {
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
}
|
||
},
|
||
"type": "scattermap"
|
||
}
|
||
],
|
||
"scattermapbox": [
|
||
{
|
||
"marker": {
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
}
|
||
},
|
||
"type": "scattermapbox"
|
||
}
|
||
],
|
||
"scatterpolar": [
|
||
{
|
||
"marker": {
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
}
|
||
},
|
||
"type": "scatterpolar"
|
||
}
|
||
],
|
||
"scatterpolargl": [
|
||
{
|
||
"marker": {
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
}
|
||
},
|
||
"type": "scatterpolargl"
|
||
}
|
||
],
|
||
"scatterternary": [
|
||
{
|
||
"marker": {
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
}
|
||
},
|
||
"type": "scatterternary"
|
||
}
|
||
],
|
||
"surface": [
|
||
{
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
},
|
||
"colorscale": [
|
||
[
|
||
0,
|
||
"#0d0887"
|
||
],
|
||
[
|
||
0.1111111111111111,
|
||
"#46039f"
|
||
],
|
||
[
|
||
0.2222222222222222,
|
||
"#7201a8"
|
||
],
|
||
[
|
||
0.3333333333333333,
|
||
"#9c179e"
|
||
],
|
||
[
|
||
0.4444444444444444,
|
||
"#bd3786"
|
||
],
|
||
[
|
||
0.5555555555555556,
|
||
"#d8576b"
|
||
],
|
||
[
|
||
0.6666666666666666,
|
||
"#ed7953"
|
||
],
|
||
[
|
||
0.7777777777777778,
|
||
"#fb9f3a"
|
||
],
|
||
[
|
||
0.8888888888888888,
|
||
"#fdca26"
|
||
],
|
||
[
|
||
1,
|
||
"#f0f921"
|
||
]
|
||
],
|
||
"type": "surface"
|
||
}
|
||
],
|
||
"table": [
|
||
{
|
||
"cells": {
|
||
"fill": {
|
||
"color": "#EBF0F8"
|
||
},
|
||
"line": {
|
||
"color": "white"
|
||
}
|
||
},
|
||
"header": {
|
||
"fill": {
|
||
"color": "#C8D4E3"
|
||
},
|
||
"line": {
|
||
"color": "white"
|
||
}
|
||
},
|
||
"type": "table"
|
||
}
|
||
]
|
||
},
|
||
"layout": {
|
||
"annotationdefaults": {
|
||
"arrowcolor": "#2a3f5f",
|
||
"arrowhead": 0,
|
||
"arrowwidth": 1
|
||
},
|
||
"autotypenumbers": "strict",
|
||
"coloraxis": {
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
}
|
||
},
|
||
"colorscale": {
|
||
"diverging": [
|
||
[
|
||
0,
|
||
"#8e0152"
|
||
],
|
||
[
|
||
0.1,
|
||
"#c51b7d"
|
||
],
|
||
[
|
||
0.2,
|
||
"#de77ae"
|
||
],
|
||
[
|
||
0.3,
|
||
"#f1b6da"
|
||
],
|
||
[
|
||
0.4,
|
||
"#fde0ef"
|
||
],
|
||
[
|
||
0.5,
|
||
"#f7f7f7"
|
||
],
|
||
[
|
||
0.6,
|
||
"#e6f5d0"
|
||
],
|
||
[
|
||
0.7,
|
||
"#b8e186"
|
||
],
|
||
[
|
||
0.8,
|
||
"#7fbc41"
|
||
],
|
||
[
|
||
0.9,
|
||
"#4d9221"
|
||
],
|
||
[
|
||
1,
|
||
"#276419"
|
||
]
|
||
],
|
||
"sequential": [
|
||
[
|
||
0,
|
||
"#0d0887"
|
||
],
|
||
[
|
||
0.1111111111111111,
|
||
"#46039f"
|
||
],
|
||
[
|
||
0.2222222222222222,
|
||
"#7201a8"
|
||
],
|
||
[
|
||
0.3333333333333333,
|
||
"#9c179e"
|
||
],
|
||
[
|
||
0.4444444444444444,
|
||
"#bd3786"
|
||
],
|
||
[
|
||
0.5555555555555556,
|
||
"#d8576b"
|
||
],
|
||
[
|
||
0.6666666666666666,
|
||
"#ed7953"
|
||
],
|
||
[
|
||
0.7777777777777778,
|
||
"#fb9f3a"
|
||
],
|
||
[
|
||
0.8888888888888888,
|
||
"#fdca26"
|
||
],
|
||
[
|
||
1,
|
||
"#f0f921"
|
||
]
|
||
],
|
||
"sequentialminus": [
|
||
[
|
||
0,
|
||
"#0d0887"
|
||
],
|
||
[
|
||
0.1111111111111111,
|
||
"#46039f"
|
||
],
|
||
[
|
||
0.2222222222222222,
|
||
"#7201a8"
|
||
],
|
||
[
|
||
0.3333333333333333,
|
||
"#9c179e"
|
||
],
|
||
[
|
||
0.4444444444444444,
|
||
"#bd3786"
|
||
],
|
||
[
|
||
0.5555555555555556,
|
||
"#d8576b"
|
||
],
|
||
[
|
||
0.6666666666666666,
|
||
"#ed7953"
|
||
],
|
||
[
|
||
0.7777777777777778,
|
||
"#fb9f3a"
|
||
],
|
||
[
|
||
0.8888888888888888,
|
||
"#fdca26"
|
||
],
|
||
[
|
||
1,
|
||
"#f0f921"
|
||
]
|
||
]
|
||
},
|
||
"colorway": [
|
||
"#636efa",
|
||
"#EF553B",
|
||
"#00cc96",
|
||
"#ab63fa",
|
||
"#FFA15A",
|
||
"#19d3f3",
|
||
"#FF6692",
|
||
"#B6E880",
|
||
"#FF97FF",
|
||
"#FECB52"
|
||
],
|
||
"font": {
|
||
"color": "#2a3f5f"
|
||
},
|
||
"geo": {
|
||
"bgcolor": "white",
|
||
"lakecolor": "white",
|
||
"landcolor": "#E5ECF6",
|
||
"showlakes": true,
|
||
"showland": true,
|
||
"subunitcolor": "white"
|
||
},
|
||
"hoverlabel": {
|
||
"align": "left"
|
||
},
|
||
"hovermode": "closest",
|
||
"mapbox": {
|
||
"style": "light"
|
||
},
|
||
"paper_bgcolor": "white",
|
||
"plot_bgcolor": "#E5ECF6",
|
||
"polar": {
|
||
"angularaxis": {
|
||
"gridcolor": "white",
|
||
"linecolor": "white",
|
||
"ticks": ""
|
||
},
|
||
"bgcolor": "#E5ECF6",
|
||
"radialaxis": {
|
||
"gridcolor": "white",
|
||
"linecolor": "white",
|
||
"ticks": ""
|
||
}
|
||
},
|
||
"scene": {
|
||
"xaxis": {
|
||
"backgroundcolor": "#E5ECF6",
|
||
"gridcolor": "white",
|
||
"gridwidth": 2,
|
||
"linecolor": "white",
|
||
"showbackground": true,
|
||
"ticks": "",
|
||
"zerolinecolor": "white"
|
||
},
|
||
"yaxis": {
|
||
"backgroundcolor": "#E5ECF6",
|
||
"gridcolor": "white",
|
||
"gridwidth": 2,
|
||
"linecolor": "white",
|
||
"showbackground": true,
|
||
"ticks": "",
|
||
"zerolinecolor": "white"
|
||
},
|
||
"zaxis": {
|
||
"backgroundcolor": "#E5ECF6",
|
||
"gridcolor": "white",
|
||
"gridwidth": 2,
|
||
"linecolor": "white",
|
||
"showbackground": true,
|
||
"ticks": "",
|
||
"zerolinecolor": "white"
|
||
}
|
||
},
|
||
"shapedefaults": {
|
||
"line": {
|
||
"color": "#2a3f5f"
|
||
}
|
||
},
|
||
"ternary": {
|
||
"aaxis": {
|
||
"gridcolor": "white",
|
||
"linecolor": "white",
|
||
"ticks": ""
|
||
},
|
||
"baxis": {
|
||
"gridcolor": "white",
|
||
"linecolor": "white",
|
||
"ticks": ""
|
||
},
|
||
"bgcolor": "#E5ECF6",
|
||
"caxis": {
|
||
"gridcolor": "white",
|
||
"linecolor": "white",
|
||
"ticks": ""
|
||
}
|
||
},
|
||
"title": {
|
||
"x": 0.05
|
||
},
|
||
"xaxis": {
|
||
"automargin": true,
|
||
"gridcolor": "white",
|
||
"linecolor": "white",
|
||
"ticks": "",
|
||
"title": {
|
||
"standoff": 15
|
||
},
|
||
"zerolinecolor": "white",
|
||
"zerolinewidth": 2
|
||
},
|
||
"yaxis": {
|
||
"automargin": true,
|
||
"gridcolor": "white",
|
||
"linecolor": "white",
|
||
"ticks": "",
|
||
"title": {
|
||
"standoff": 15
|
||
},
|
||
"zerolinecolor": "white",
|
||
"zerolinewidth": 2
|
||
}
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"image/png": "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"
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
}
|
||
],
|
||
"source": [
|
||
"# Base\n",
|
||
"rs = rupture_summary.copy()\n",
|
||
"\n",
|
||
"# Classes simplifiées\n",
|
||
"bins = [0, 0.01, 0.10, 0.30, 1.01]\n",
|
||
"labels = [\n",
|
||
" \"Clean / quasi-clean (≤1%)\",\n",
|
||
" \"Moderate (1–10%)\",\n",
|
||
" \"High (10–30%)\",\n",
|
||
" \"Severe (>30%)\"\n",
|
||
"]\n",
|
||
"\n",
|
||
"rs[\"rupture_class\"] = pd.cut(\n",
|
||
" rs[\"rupture_ratio\"],\n",
|
||
" bins=bins,\n",
|
||
" labels=labels,\n",
|
||
" include_lowest=True\n",
|
||
")\n",
|
||
"\n",
|
||
"# Distribution en %\n",
|
||
"dist = (\n",
|
||
" rs[\"rupture_class\"]\n",
|
||
" .value_counts(normalize=True)\n",
|
||
" .sort_index()\n",
|
||
" * 100\n",
|
||
").round(1)\n",
|
||
"\n",
|
||
"# Donut chart\n",
|
||
"fig = go.Figure(\n",
|
||
" data=[go.Pie(\n",
|
||
" labels=dist.index,\n",
|
||
" values=dist.values,\n",
|
||
" hole=0.45,\n",
|
||
" textinfo=\"percent\",\n",
|
||
" hoverinfo=\"label+percent\"\n",
|
||
" )]\n",
|
||
")\n",
|
||
"\n",
|
||
"fig.update_layout(\n",
|
||
" legend=dict(\n",
|
||
" orientation=\"h\", # horizontale\n",
|
||
" yanchor=\"top\",\n",
|
||
" y=-0.15, # en dessous du graphe\n",
|
||
" xanchor=\"center\",\n",
|
||
" x=0.5\n",
|
||
" ),\n",
|
||
" legend_title_text=\"Rupture ratio\"\n",
|
||
")\n",
|
||
"\n",
|
||
"fig.show()\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "e52cd650-df05-490d-af59-e66c058f955d",
|
||
"metadata": {},
|
||
"source": [
|
||
"## AUM–FLOW CONSISTENCY & DISCONTINUITY DETECTION"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 58,
|
||
"id": "a7efe494-f5fa-43f8-8446-942fc2d3bd4c",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Detection threshold epsilon (trimmed 99th percentile): 40.03%\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"# ------------------------------------------------------------\n",
|
||
"# 1. Keep relevant columns\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"stocks_clean = stocks[\n",
|
||
" [\"Registrar Account - ID\", \"Product - Isin\", \"Centralisation Date\", \"Quantity - AUM\"]\n",
|
||
"].copy()\n",
|
||
"\n",
|
||
"flows_clean = flows[\n",
|
||
" [\"Registrar Account - ID\", \"Product - Isin\", \"Centralisation Date\", \"Quantity - NetFlows\"]\n",
|
||
"].copy()\n",
|
||
"\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"# 2. Date formatting\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"stocks_clean[\"Centralisation Date\"] = pd.to_datetime(stocks_clean[\"Centralisation Date\"])\n",
|
||
"flows_clean[\"Centralisation Date\"] = pd.to_datetime(flows_clean[\"Centralisation Date\"])\n",
|
||
"\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"# 3. Aggregate flows per day\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"flows_clean = (\n",
|
||
" flows_clean\n",
|
||
" .groupby(\n",
|
||
" [\"Registrar Account - ID\", \"Product - Isin\", \"Centralisation Date\"],\n",
|
||
" as_index=False\n",
|
||
" )[\"Quantity - NetFlows\"]\n",
|
||
" .sum()\n",
|
||
")\n",
|
||
"\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"# 4. Merge stocks and flows\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"df = stocks_clean.merge(\n",
|
||
" flows_clean,\n",
|
||
" on=[\"Registrar Account - ID\", \"Product - Isin\", \"Centralisation Date\"],\n",
|
||
" how=\"left\"\n",
|
||
")\n",
|
||
"\n",
|
||
"df[\"Quantity - NetFlows\"] = df[\"Quantity - NetFlows\"].fillna(0)\n",
|
||
"\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"# 5. Sort and reconstruct expected stock\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"df = df.sort_values(\n",
|
||
" [\"Registrar Account - ID\", \"Product - Isin\", \"Centralisation Date\"]\n",
|
||
")\n",
|
||
"\n",
|
||
"df[\"prev_stock\"] = (\n",
|
||
" df.groupby([\"Registrar Account - ID\", \"Product - Isin\"])\n",
|
||
" [\"Quantity - AUM\"]\n",
|
||
" .shift(1)\n",
|
||
")\n",
|
||
"\n",
|
||
"df[\"prev_flows\"] = (\n",
|
||
" df.groupby([\"Registrar Account - ID\", \"Product - Isin\"])\n",
|
||
" [\"Quantity - NetFlows\"]\n",
|
||
" .shift(1)\n",
|
||
" .fillna(0)\n",
|
||
")\n",
|
||
"\n",
|
||
"df[\"expected_stock\"] = df[\"prev_stock\"] + df[\"prev_flows\"]\n",
|
||
"\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"# 6. Compute accounting gaps\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"df[\"gap\"] = df[\"Quantity - AUM\"] - df[\"expected_stock\"]\n",
|
||
"df[\"gap_abs\"] = df[\"gap\"].abs()\n",
|
||
"\n",
|
||
"# Relative gap normalised by previous stock\n",
|
||
"df[\"gap_rel\"] = (\n",
|
||
" df[\"gap_abs\"] /\n",
|
||
" df[\"prev_stock\"].abs().replace(0, np.nan)\n",
|
||
")\n",
|
||
"\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"# 7. Calibration sample (valid regime)\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"valid_gaps = df.loc[\n",
|
||
" df[\"gap_rel\"].notna() & (df[\"prev_stock\"] > 0),\n",
|
||
" \"gap_rel\"\n",
|
||
"]\n",
|
||
"\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"# 8. Robust, data-driven threshold (epsilon)\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"# Step 1 — trim extreme breaks to avoid calibrating on resets\n",
|
||
"gap_rel_trimmed = valid_gaps[\n",
|
||
" valid_gaps <= valid_gaps.quantile(0.90)\n",
|
||
"]\n",
|
||
"\n",
|
||
"# Step 2 — define epsilon on the upper tail of the trimmed distribution\n",
|
||
"EPSILON = gap_rel_trimmed.quantile(0.99)\n",
|
||
"\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"# 9. Detect discontinuities (diagnostic rule)\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"df[\"rupture_flag\"] = (\n",
|
||
" df[\"prev_stock\"].notna()\n",
|
||
" & (df[\"prev_stock\"] > 0)\n",
|
||
" & (df[\"gap_rel\"] > EPSILON)\n",
|
||
")\n",
|
||
"\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"# 10. Remove end-of-sample edge effects\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"last_date = df[\"Centralisation Date\"].max()\n",
|
||
"\n",
|
||
"df.loc[\n",
|
||
" (df[\"rupture_flag\"]) &\n",
|
||
" (df[\"Centralisation Date\"] == last_date),\n",
|
||
" \"rupture_flag\"\n",
|
||
"] = False\n",
|
||
"\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"# 11. ISIN-level summary\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"rupture_isin_summary = (\n",
|
||
" df.groupby([\"Registrar Account - ID\", \"Product - Isin\"])\n",
|
||
" .agg(\n",
|
||
" n_ruptures=(\"rupture_flag\", \"sum\"),\n",
|
||
" total_obs=(\"rupture_flag\", \"count\"),\n",
|
||
" rupture_ratio=(\"rupture_flag\", \"mean\"),\n",
|
||
" max_gap_abs=(\"gap_abs\", \"max\"),\n",
|
||
" max_gap_rel=(\"gap_rel\", \"max\")\n",
|
||
" )\n",
|
||
" .reset_index()\n",
|
||
")\n",
|
||
"\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"# 12. Account-level summary\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"rupture_summary = (\n",
|
||
" df.groupby(\"Registrar Account - ID\")\n",
|
||
" .agg(\n",
|
||
" n_ruptures=(\"rupture_flag\", \"sum\"),\n",
|
||
" total_obs=(\"rupture_flag\", \"count\"),\n",
|
||
" rupture_ratio=(\"rupture_flag\", \"mean\"),\n",
|
||
" max_gap_abs=(\"gap_abs\", \"max\"),\n",
|
||
" max_gap_rel=(\"gap_rel\", \"max\")\n",
|
||
" )\n",
|
||
" .reset_index()\n",
|
||
")\n",
|
||
"\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"# 13. Outputs\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"df.to_csv(\"aum_flow_gaps.csv\", index=False)\n",
|
||
"rupture_isin_summary.to_csv(\"rupture_isin_summary.csv\", index=False)\n",
|
||
"rupture_summary.to_csv(\"rupture_summary.csv\", index=False)\n",
|
||
"\n",
|
||
"print(f\"Detection threshold epsilon (trimmed 99th percentile): {EPSILON:.2%}\")\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 59,
|
||
"id": "d7454212-1493-4715-a436-c331931f92fa",
|
||
"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>Registrar Account - ID</th>\n",
|
||
" <th>Product - Isin</th>\n",
|
||
" <th>n_ruptures</th>\n",
|
||
" <th>total_obs</th>\n",
|
||
" <th>rupture_ratio</th>\n",
|
||
" <th>max_gap_abs</th>\n",
|
||
" <th>max_gap_rel</th>\n",
|
||
" </tr>\n",
|
||
" </thead>\n",
|
||
" <tbody>\n",
|
||
" <tr>\n",
|
||
" <th>59545</th>\n",
|
||
" <td>200127410</td>\n",
|
||
" <td>FR0010135103</td>\n",
|
||
" <td>384</td>\n",
|
||
" <td>436</td>\n",
|
||
" <td>0.880734</td>\n",
|
||
" <td>295985.42</td>\n",
|
||
" <td>3371.158214</td>\n",
|
||
" </tr>\n",
|
||
" </tbody>\n",
|
||
"</table>\n",
|
||
"</div>"
|
||
],
|
||
"text/plain": [
|
||
" Registrar Account - ID Product - Isin n_ruptures total_obs \\\n",
|
||
"59545 200127410 FR0010135103 384 436 \n",
|
||
"\n",
|
||
" rupture_ratio max_gap_abs max_gap_rel \n",
|
||
"59545 0.880734 295985.42 3371.158214 "
|
||
]
|
||
},
|
||
"execution_count": 59,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"rupture_isin_summary.sort_values(\"rupture_ratio\").head(1)\n",
|
||
"rupture_isin_summary.sort_values(\"rupture_ratio\", ascending=False).head(1)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 60,
|
||
"id": "b4040847-e0cf-4aa5-966c-d1fbf3935b7d",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"def plot_isin_evolution(df, account_id, isin, title_suffix=\"\"):\n",
|
||
" sub = df[\n",
|
||
" (df[\"Registrar Account - ID\"] == account_id) &\n",
|
||
" (df[\"Product - Isin\"] == isin)\n",
|
||
" ].copy()\n",
|
||
"\n",
|
||
" if sub.empty:\n",
|
||
" print(\"No data for this (account, ISIN).\")\n",
|
||
" return\n",
|
||
"\n",
|
||
" plt.figure(figsize=(10,4))\n",
|
||
"\n",
|
||
" # Stock observé\n",
|
||
" plt.plot(\n",
|
||
" sub[\"Centralisation Date\"],\n",
|
||
" sub[\"Quantity - AUM\"],\n",
|
||
" label=\"Observed stock\",\n",
|
||
" linewidth=2\n",
|
||
" )\n",
|
||
"\n",
|
||
" # Stock attendu\n",
|
||
" plt.plot(\n",
|
||
" sub[\"Centralisation Date\"],\n",
|
||
" sub[\"expected_stock\"],\n",
|
||
" label=\"Expected stock\",\n",
|
||
" linestyle=\"--\"\n",
|
||
" )\n",
|
||
"\n",
|
||
" # Ruptures\n",
|
||
" rupt = sub[sub[\"rupture_flag\"]]\n",
|
||
" plt.scatter(\n",
|
||
" rupt[\"Centralisation Date\"],\n",
|
||
" rupt[\"Quantity - AUM\"],\n",
|
||
" color=\"red\",\n",
|
||
" label=\"Rupture\",\n",
|
||
" zorder=5\n",
|
||
" )\n",
|
||
"\n",
|
||
" plt.title(f\"ISIN {isin} — Account {account_id} {title_suffix}\")\n",
|
||
" plt.xlabel(\"Date\")\n",
|
||
" plt.ylabel(\"AUM (shares)\")\n",
|
||
" plt.legend()\n",
|
||
" plt.grid(True)\n",
|
||
" plt.tight_layout()\n",
|
||
" plt.show()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 61,
|
||
"id": "e5d7a5ab-40bd-452d-a6ae-d56e220c592f",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"ename": "NameError",
|
||
"evalue": "name 'plot_isin_dynamics' is not defined",
|
||
"output_type": "error",
|
||
"traceback": [
|
||
"\u001b[31m---------------------------------------------------------------------------\u001b[39m",
|
||
"\u001b[31mNameError\u001b[39m Traceback (most recent call last)",
|
||
"\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[61]\u001b[39m\u001b[32m, line 63\u001b[39m\n\u001b[32m 58\u001b[39m plt.show()\n\u001b[32m 62\u001b[39m \u001b[38;5;28;01mfor\u001b[39;00m _, row \u001b[38;5;129;01min\u001b[39;00m sample_isin.iterrows():\n\u001b[32m---> \u001b[39m\u001b[32m63\u001b[39m \u001b[43mplot_isin_dynamics\u001b[49m(\n\u001b[32m 64\u001b[39m df,\n\u001b[32m 65\u001b[39m row[\u001b[33m\"\u001b[39m\u001b[33mRegistrar Account - ID\u001b[39m\u001b[33m\"\u001b[39m],\n\u001b[32m 66\u001b[39m row[\u001b[33m\"\u001b[39m\u001b[33mProduct - Isin\u001b[39m\u001b[33m\"\u001b[39m]\n\u001b[32m 67\u001b[39m )\n",
|
||
"\u001b[31mNameError\u001b[39m: name 'plot_isin_dynamics' is not defined"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"# Option B (alternative) : les plus sévères\n",
|
||
"# sample_isin = problematic_isin.sort_values(\n",
|
||
"# \"rupture_ratio\", ascending=False\n",
|
||
"# ).head(10)\n",
|
||
"\n",
|
||
"sample_isin = rupture_isin_summary.sort_values(\n",
|
||
" \"rupture_ratio\",\n",
|
||
" ascending=False\n",
|
||
").head(10)\n",
|
||
"\n",
|
||
"def plot_isin_dynamics_clean(df, account_id, isin):\n",
|
||
" sub = df[\n",
|
||
" (df[\"Registrar Account - ID\"] == account_id) &\n",
|
||
" (df[\"Product - Isin\"] == isin)\n",
|
||
" ].sort_values(\"Centralisation Date\")\n",
|
||
"\n",
|
||
" if sub.empty:\n",
|
||
" return\n",
|
||
"\n",
|
||
" fig, ax = plt.subplots(figsize=(7.5, 3))\n",
|
||
"\n",
|
||
" # AUM observé\n",
|
||
" ax.plot(\n",
|
||
" sub[\"Centralisation Date\"],\n",
|
||
" sub[\"Quantity - AUM\"],\n",
|
||
" label=\"Observed AUM\",\n",
|
||
" linewidth=2,\n",
|
||
" color=\"black\"\n",
|
||
" )\n",
|
||
"\n",
|
||
" # AUM attendu\n",
|
||
" ax.plot(\n",
|
||
" sub[\"Centralisation Date\"],\n",
|
||
" sub[\"expected_stock\"],\n",
|
||
" label=\"Flow-implied AUM\",\n",
|
||
" linestyle=\"--\",\n",
|
||
" linewidth=2,\n",
|
||
" color=\"grey\"\n",
|
||
" )\n",
|
||
"\n",
|
||
" # Ruptures\n",
|
||
" rupt = sub[sub[\"rupture_flag\"]]\n",
|
||
" ax.scatter(\n",
|
||
" rupt[\"Centralisation Date\"],\n",
|
||
" rupt[\"Quantity - AUM\"],\n",
|
||
" color=\"red\",\n",
|
||
" s=25,\n",
|
||
" zorder=5,\n",
|
||
" label=\"Discontinuity\"\n",
|
||
" )\n",
|
||
"\n",
|
||
" ax.set_title(f\"Account {account_id} — ISIN {isin}\", fontsize=11)\n",
|
||
" ax.set_xlabel(\"\")\n",
|
||
" ax.set_ylabel(\"AUM (shares)\")\n",
|
||
" ax.legend(loc=\"best\")\n",
|
||
"\n",
|
||
" plt.tight_layout()\n",
|
||
" plt.show()\n",
|
||
"\n",
|
||
"\n",
|
||
"\n",
|
||
"for _, row in sample_isin.iterrows():\n",
|
||
" plot_isin_dynamics(\n",
|
||
" df,\n",
|
||
" row[\"Registrar Account - ID\"],\n",
|
||
" row[\"Product - Isin\"]\n",
|
||
" )"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 28,
|
||
"id": "aef8ceb9-28a6-4908-ae24-a88d85b64309",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"ename": "KeyError",
|
||
"evalue": "\"Column(s) ['rupture_flag'] do not exist\"",
|
||
"output_type": "error",
|
||
"traceback": [
|
||
"\u001b[31m---------------------------------------------------------------------------\u001b[39m",
|
||
"\u001b[31mKeyError\u001b[39m Traceback (most recent call last)",
|
||
"\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[28]\u001b[39m\u001b[32m, line 6\u001b[39m\n\u001b[32m 1\u001b[39m \u001b[38;5;66;03m# ------------------------------------------------------------\u001b[39;00m\n\u001b[32m 2\u001b[39m \u001b[38;5;66;03m# 1. Aggregate rupture rate over time\u001b[39;00m\n\u001b[32m 3\u001b[39m \u001b[38;5;66;03m# ------------------------------------------------------------\u001b[39;00m\n\u001b[32m 4\u001b[39m time_stats = (\n\u001b[32m 5\u001b[39m \u001b[43mdf\u001b[49m\u001b[43m.\u001b[49m\u001b[43mgroupby\u001b[49m\u001b[43m(\u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mCentralisation Date\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[32m----> \u001b[39m\u001b[32m6\u001b[39m \u001b[43m \u001b[49m\u001b[43m.\u001b[49m\u001b[43magg\u001b[49m\u001b[43m(\u001b[49m\n\u001b[32m 7\u001b[39m \u001b[43m \u001b[49m\u001b[43mtotal_obs\u001b[49m\u001b[43m=\u001b[49m\u001b[43m(\u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mrupture_flag\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mcount\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[32m 8\u001b[39m \u001b[43m \u001b[49m\u001b[43mn_ruptures\u001b[49m\u001b[43m=\u001b[49m\u001b[43m(\u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mrupture_flag\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43msum\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[32m 9\u001b[39m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 10\u001b[39m .reset_index()\n\u001b[32m 11\u001b[39m )\n\u001b[32m 13\u001b[39m time_stats[\u001b[33m\"\u001b[39m\u001b[33mrupture_rate\u001b[39m\u001b[33m\"\u001b[39m] = (\n\u001b[32m 14\u001b[39m time_stats[\u001b[33m\"\u001b[39m\u001b[33mn_ruptures\u001b[39m\u001b[33m\"\u001b[39m] / time_stats[\u001b[33m\"\u001b[39m\u001b[33mtotal_obs\u001b[39m\u001b[33m\"\u001b[39m]\n\u001b[32m 15\u001b[39m )\n\u001b[32m 17\u001b[39m \u001b[38;5;66;03m# ------------------------------------------------------------\u001b[39;00m\n\u001b[32m 18\u001b[39m \u001b[38;5;66;03m# 2. Smooth (optional but recommended for readability)\u001b[39;00m\n\u001b[32m 19\u001b[39m \u001b[38;5;66;03m# ------------------------------------------------------------\u001b[39;00m\n",
|
||
"\u001b[36mFile \u001b[39m\u001b[32m/opt/python/lib/python3.13/site-packages/pandas/core/groupby/generic.py:1432\u001b[39m, in \u001b[36mDataFrameGroupBy.aggregate\u001b[39m\u001b[34m(self, func, engine, engine_kwargs, *args, **kwargs)\u001b[39m\n\u001b[32m 1429\u001b[39m kwargs[\u001b[33m\"\u001b[39m\u001b[33mengine_kwargs\u001b[39m\u001b[33m\"\u001b[39m] = engine_kwargs\n\u001b[32m 1431\u001b[39m op = GroupByApply(\u001b[38;5;28mself\u001b[39m, func, args=args, kwargs=kwargs)\n\u001b[32m-> \u001b[39m\u001b[32m1432\u001b[39m result = \u001b[43mop\u001b[49m\u001b[43m.\u001b[49m\u001b[43magg\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 1433\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m is_dict_like(func) \u001b[38;5;129;01mand\u001b[39;00m result \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[32m 1434\u001b[39m \u001b[38;5;66;03m# GH #52849\u001b[39;00m\n\u001b[32m 1435\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mself\u001b[39m.as_index \u001b[38;5;129;01mand\u001b[39;00m is_list_like(func):\n",
|
||
"\u001b[36mFile \u001b[39m\u001b[32m/opt/python/lib/python3.13/site-packages/pandas/core/apply.py:190\u001b[39m, in \u001b[36mApply.agg\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m 187\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m.apply_str()\n\u001b[32m 189\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m is_dict_like(func):\n\u001b[32m--> \u001b[39m\u001b[32m190\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43magg_dict_like\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 191\u001b[39m \u001b[38;5;28;01melif\u001b[39;00m is_list_like(func):\n\u001b[32m 192\u001b[39m \u001b[38;5;66;03m# we require a list, but not a 'str'\u001b[39;00m\n\u001b[32m 193\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m.agg_list_like()\n",
|
||
"\u001b[36mFile \u001b[39m\u001b[32m/opt/python/lib/python3.13/site-packages/pandas/core/apply.py:423\u001b[39m, in \u001b[36mApply.agg_dict_like\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m 415\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34magg_dict_like\u001b[39m(\u001b[38;5;28mself\u001b[39m) -> DataFrame | Series:\n\u001b[32m 416\u001b[39m \u001b[38;5;250m \u001b[39m\u001b[33;03m\"\"\"\u001b[39;00m\n\u001b[32m 417\u001b[39m \u001b[33;03m Compute aggregation in the case of a dict-like argument.\u001b[39;00m\n\u001b[32m 418\u001b[39m \n\u001b[32m (...)\u001b[39m\u001b[32m 421\u001b[39m \u001b[33;03m Result of aggregation.\u001b[39;00m\n\u001b[32m 422\u001b[39m \u001b[33;03m \"\"\"\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m423\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43magg_or_apply_dict_like\u001b[49m\u001b[43m(\u001b[49m\u001b[43mop_name\u001b[49m\u001b[43m=\u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43magg\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n",
|
||
"\u001b[36mFile \u001b[39m\u001b[32m/opt/python/lib/python3.13/site-packages/pandas/core/apply.py:1603\u001b[39m, in \u001b[36mGroupByApply.agg_or_apply_dict_like\u001b[39m\u001b[34m(self, op_name)\u001b[39m\n\u001b[32m 1598\u001b[39m kwargs.update({\u001b[33m\"\u001b[39m\u001b[33mengine\u001b[39m\u001b[33m\"\u001b[39m: engine, \u001b[33m\"\u001b[39m\u001b[33mengine_kwargs\u001b[39m\u001b[33m\"\u001b[39m: engine_kwargs})\n\u001b[32m 1600\u001b[39m \u001b[38;5;28;01mwith\u001b[39;00m com.temp_setattr(\n\u001b[32m 1601\u001b[39m obj, \u001b[33m\"\u001b[39m\u001b[33mas_index\u001b[39m\u001b[33m\"\u001b[39m, \u001b[38;5;28;01mTrue\u001b[39;00m, condition=\u001b[38;5;28mhasattr\u001b[39m(obj, \u001b[33m\"\u001b[39m\u001b[33mas_index\u001b[39m\u001b[33m\"\u001b[39m)\n\u001b[32m 1602\u001b[39m ):\n\u001b[32m-> \u001b[39m\u001b[32m1603\u001b[39m result_index, result_data = \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mcompute_dict_like\u001b[49m\u001b[43m(\u001b[49m\n\u001b[32m 1604\u001b[39m \u001b[43m \u001b[49m\u001b[43mop_name\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mselected_obj\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mselection\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mkwargs\u001b[49m\n\u001b[32m 1605\u001b[39m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 1606\u001b[39m result = \u001b[38;5;28mself\u001b[39m.wrap_results_dict_like(selected_obj, result_index, result_data)\n\u001b[32m 1607\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m result\n",
|
||
"\u001b[36mFile \u001b[39m\u001b[32m/opt/python/lib/python3.13/site-packages/pandas/core/apply.py:462\u001b[39m, in \u001b[36mApply.compute_dict_like\u001b[39m\u001b[34m(self, op_name, selected_obj, selection, kwargs)\u001b[39m\n\u001b[32m 460\u001b[39m is_groupby = \u001b[38;5;28misinstance\u001b[39m(obj, (DataFrameGroupBy, SeriesGroupBy))\n\u001b[32m 461\u001b[39m func = cast(AggFuncTypeDict, \u001b[38;5;28mself\u001b[39m.func)\n\u001b[32m--> \u001b[39m\u001b[32m462\u001b[39m func = \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mnormalize_dictlike_arg\u001b[49m\u001b[43m(\u001b[49m\u001b[43mop_name\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mselected_obj\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mfunc\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 464\u001b[39m is_non_unique_col = (\n\u001b[32m 465\u001b[39m selected_obj.ndim == \u001b[32m2\u001b[39m\n\u001b[32m 466\u001b[39m \u001b[38;5;129;01mand\u001b[39;00m selected_obj.columns.nunique() < \u001b[38;5;28mlen\u001b[39m(selected_obj.columns)\n\u001b[32m 467\u001b[39m )\n\u001b[32m 469\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m selected_obj.ndim == \u001b[32m1\u001b[39m:\n\u001b[32m 470\u001b[39m \u001b[38;5;66;03m# key only used for output\u001b[39;00m\n",
|
||
"\u001b[36mFile \u001b[39m\u001b[32m/opt/python/lib/python3.13/site-packages/pandas/core/apply.py:663\u001b[39m, in \u001b[36mApply.normalize_dictlike_arg\u001b[39m\u001b[34m(self, how, obj, func)\u001b[39m\n\u001b[32m 661\u001b[39m cols = Index(\u001b[38;5;28mlist\u001b[39m(func.keys())).difference(obj.columns, sort=\u001b[38;5;28;01mTrue\u001b[39;00m)\n\u001b[32m 662\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(cols) > \u001b[32m0\u001b[39m:\n\u001b[32m--> \u001b[39m\u001b[32m663\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mKeyError\u001b[39;00m(\u001b[33mf\u001b[39m\u001b[33m\"\u001b[39m\u001b[33mColumn(s) \u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28mlist\u001b[39m(cols)\u001b[38;5;132;01m}\u001b[39;00m\u001b[33m do not exist\u001b[39m\u001b[33m\"\u001b[39m)\n\u001b[32m 665\u001b[39m aggregator_types = (\u001b[38;5;28mlist\u001b[39m, \u001b[38;5;28mtuple\u001b[39m, \u001b[38;5;28mdict\u001b[39m)\n\u001b[32m 667\u001b[39m \u001b[38;5;66;03m# if we have a dict of any non-scalars\u001b[39;00m\n\u001b[32m 668\u001b[39m \u001b[38;5;66;03m# eg. {'A' : ['mean']}, normalize all to\u001b[39;00m\n\u001b[32m 669\u001b[39m \u001b[38;5;66;03m# be list-likes\u001b[39;00m\n\u001b[32m 670\u001b[39m \u001b[38;5;66;03m# Cannot use func.values() because arg may be a Series\u001b[39;00m\n",
|
||
"\u001b[31mKeyError\u001b[39m: \"Column(s) ['rupture_flag'] do not exist\""
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"# ------------------------------------------------------------\n",
|
||
"# 1. Aggregate rupture rate over time\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"time_stats = (\n",
|
||
" df.groupby(\"Centralisation Date\")\n",
|
||
" .agg(\n",
|
||
" total_obs=(\"rupture_flag\", \"count\"),\n",
|
||
" n_ruptures=(\"rupture_flag\", \"sum\")\n",
|
||
" )\n",
|
||
" .reset_index()\n",
|
||
")\n",
|
||
"\n",
|
||
"time_stats[\"rupture_rate\"] = (\n",
|
||
" time_stats[\"n_ruptures\"] / time_stats[\"total_obs\"]\n",
|
||
")\n",
|
||
"\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"# 2. Smooth (optional but recommended for readability)\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"time_stats[\"rupture_rate_ma\"] = (\n",
|
||
" time_stats[\"rupture_rate\"]\n",
|
||
" .rolling(window=6, center=True) # 6 periods ≈ half-year\n",
|
||
" .mean()\n",
|
||
")\n",
|
||
"\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"# 3. Professional plot\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"plt.figure(figsize=(12, 5))\n",
|
||
"\n",
|
||
"plt.plot(\n",
|
||
" time_stats[\"Centralisation Date\"],\n",
|
||
" time_stats[\"rupture_rate\"] * 100,\n",
|
||
" color=\"lightgray\",\n",
|
||
" linewidth=1,\n",
|
||
" alpha=0.6,\n",
|
||
" label=\"Monthly rupture rate\"\n",
|
||
")\n",
|
||
"\n",
|
||
"plt.plot(\n",
|
||
" time_stats[\"Centralisation Date\"],\n",
|
||
" time_stats[\"rupture_rate_ma\"] * 100,\n",
|
||
" color=\"#1f77b4\",\n",
|
||
" linewidth=2.5,\n",
|
||
" label=\"6-month moving average\"\n",
|
||
")\n",
|
||
"\n",
|
||
"plt.ylabel(\"Rupture rate (%)\")\n",
|
||
"plt.xlabel(\"Date\")\n",
|
||
"\n",
|
||
"plt.grid(True, linestyle=\"--\", alpha=0.4)\n",
|
||
"plt.legend(frameon=False)\n",
|
||
"\n",
|
||
"plt.tight_layout()\n",
|
||
"plt.show()\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 63,
|
||
"id": "6624939b-f079-4e02-9989-60462e9f5356",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"image/png": "iVBORw0KGgoAAAANSUhEUgAABKUAAAHqCAYAAADVi/1VAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjgsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvwVt1zgAAAAlwSFlzAAAPYQAAD2EBqD+naQABAABJREFUeJzsnXmcE+X9xz8zuZNNspvsAQvLIbcIiFwCKuAFHtT7pFXUetUDL7yq9WhrW+vtz1pbK1iLeFSxHlWrKKiIB8gth3LDwh45N3cy8/z+WGdIdpPdZDfZZJLv+/XixWYymTzP5PnOPM9nvgfHGGMgCIIgCIIgCIIgCIIgiB6Ez3cDCIIgCIIgCIIgCIIgiNKDRCmCIAiCIAiCIAiCIAiixyFRiiAIgiAIgiAIgiAIguhxSJQiCIIgCIIgCIIgCIIgehwSpQiCIAiCIAiCIAiCIIgeh0QpgiAIgiAIgiAIgiAIoschUYogCIIgCIIgCIIgCILocUiUIgiCIAiCIAiCIAiCIHocdb4bkGtEUUR9fT3MZjM4jst3cwiCIAiCIAiCIAiCIIoaxhhaWlpQW1sLnk/tD1X0olR9fT3q6ury3QyCIAiCIAiCIAiCIIiSYu/evejbt2/K94telDKbzQBaT4TFYslza4hcI4oi9u7di7q6ug7VWIIoVsgGiFKHbIAodcgGiFKGxj9R6hSSDXi9XtTV1cmaTCqKXpSSQvYsFguJUiWAKIowm82wWCx5N0KCyAdkA0SpQzZAlDpkA0QpQ+OfKHUK0QY6S6NUGK0kiCzBcRzKy8spfxhRspANEKUO2QBR6pANEKUMjX+i1FGiDRS9pxRRWkhGSBClCtkAUeqQDRClDtkAUcrQ+CdKHSXaAHlKEUWFKIpoaGiAKIr5bgpB5AWyAaLUIRsgSh2yAaKUofFPlDpKtAESpYiiIxgM5rsJBJFXyAaIUodsgCh1yAaIUobGP1HqKM0GSJQiCIIgCIIgCIIgCIIgehwSpQiCIAiCIAiCIAiCIIgeh0QpoqjgOA52u11R1QYIIpuQDRClDtkAUeqQDRClDI1/otRRog1Q9T2iqOA4DmazOd/NIIi8QTZAlDpkA0SpQzZAlDI0/olSR4k2QJ5SRFEhiiL279+vqGoDBJFNyAaIUodsgCh1yAaIUobGP1HqKNEGSJQiio5oNJrvJhBEXiEbIEodsgGi1CEbIEoZGv9EqaM0GyBRiiAIgiAIgiAIgsg5HMfhrbfeSvn+smXLwHEc3G53j7WJ6BpLly7FiBEjIAhCTr9n+vTpuOmmm3L6HYwxXHXVVbDZbOA4DmvXru2R7+1JMrWt5uZmVFdXY9++fbltGEiUIgiCIAiCIAiCKFrmzp0LjuNwzTXXtHvvuuuuA8dxmDt3bla/8/7778eRRx6Z1WMWAgsXLkR5eXm+m9Elst3222+/Hffccw9UKlVWjpdKNHnzzTfx29/+NivfkYoPPvgACxcuxLvvvosDBw7giCOOyOn3KYHKykpccskluO+++3L+XSRKEUUFx3GoqalRVLUBgsgmZANEqUM2QJQ6ZANEMurq6vDKK68gGAzK20KhEF5++WX069cvjy3LLsnGfyQSyWOLUpOtEKt89O+LL77A9u3bcc455+T8u2w2W84Td2/fvh29e/fGlClT0KtXL6jVyq0Hl817wGWXXYZFixbB6XRmoWWpIVGKKCo4joPBYKCJGFGykA0QpQ7ZAFHqkA0QyTjqqKNQV1eHN998U9725ptvol+/fhg7dmzCvuFwGDfeeCOqq6uh1+txzDHH4Ntvv5Xflzxali5divHjx8NoNGLKlCnYunUrgFaPnAceeADr1q0Dx3HgOA4LFy6UP9/c3IyzzjoLRqMRQ4YMwdtvv520zX6/HxaLBf/+978Ttr/11lswmUxoaWlp9xmO43DKKafghhtuwE033YTKykrMnDkTu3btksOyJNxuNziOw7JlyxL69d5772H06NHQ6/U4+uijsXHjRvn9yy67DB6PR+7X/fffL39v27DE8vJyud/S97/66quYNm0a9Ho9Fi1aBAB4/vnnMWLECOj1egwfPhx/+ctfkp4PienTp+P6669P6B8APPbYYxg1ahRMJhPq6urwq1/9Cj6fr9O2h8Nh3HbbbejTpw9MJhMmTZokn5NUvPLKKzjppJOg1+vlbdu3b8cZZ5yBmpoalJWVYcKECfj4448TPhcOh3HHHXegrq4OOp0OgwcPxj/+8Q/s2rULM2bMAABUVFQkeO/Fh9HdfffdmDRpUrv2jBkzBg8++KD8OpNzOnfuXNxwww3Ys2cPOI7DgAEDku7ncrlwySWXoKKiAkajEaeccgp++OEHAK3hf1VVVQlj9cgjj0Tv3r3l11988QV0Oh0CgQAYY7j//vvRr18/6HQ61NbW4sYbb0zZRgB49tlnMWjQIGi1WgwbNgwvvfRSwvscx+H555/H2WefDbvdjqFDh3bbtkaOHIna2losWbKkw7Z1FxKliKJCFEXs3r1bUdUGCCKbkA0QpQ7ZAFHqkA0Qqbj88suxYMEC+fULL7yAyy67rN1+t99+O9544w28+OKL+O677zB48GDMnDmznbfEr3/9azz66KNYtWoV1Go1Lr/8cgDABRdcgFtvvRUjR47EgQMHcODAAVxwwQXy5x544AGcf/75WL9+PU499VTMmTMnqSeGyWTChRdemNBmAFiwYAHOPffcpN4zoigiFArhxRdfhFarxYoVK/DXv/41o/M0f/58PProo/j2229RVVWF2bNnIxqNYsqUKXjiiSdgsVjkft12220ZHfvOO+/EvHnzsHnzZsycOROLFi3Cb37zG/z+97/H5s2b8dBDD+Hee+/Fiy++2OFxkvWP53k89dRT2LRpE1588UV88sknuP322wGgw7Zff/31WLlyJV555RWsX78e5513HmbNmiULLsn4/PPPMX78+IRtPp8Pp556KpYuXYo1a9Zg1qxZmD17Nvbs2SPvc8kll2Dx4sV46qmnsHnzZjz33HMoKytDXV0d3njjDQDA1q1bceDAATz55JPtvnfOnDn45ptvsH37dnnbpk2bsH79elx88cUAkPE5ffLJJ/Hggw+ib9++OHDgQIIAG8/cuXOxatUqvP3221i5ciUYYzj11FMRjUbBcRyOO+44WcxzuVzYvHkzgsEgtmzZAgBYvnw5JkyYAKPRiDfeeAOPP/44nnvuOfzwww946623MGrUqJTne8mSJZg3bx5uvfVWbNy4EVdffTUuu+wyfPrppwn7PfDAAzj33HPx/vvv45RTTsmKbU2cOBGff/55yrZlBVbkeDweBoB5PJ58N6XbhMNhFo1G892MgkYQBLZz504mCEK+m0IQeYFsgCh1yAaIUodsoOcRBIGFw+Ee/ZfJ73vppZeyM844gzU2NjKdTsd27drFdu3axfR6PWtqamJnnHEGu/TSSxljjPl8PqbRaNiiRYvkz0ciEVZbW8sefvhhxhhjn376KQPAPv74Y3mf9957jwFgwWCQMcbYfffdx8aMGdOuLQDYPffcI7/2+XwMAHv//fcTju1yuRhjjH399ddMpVKx+vp6xhhjDQ0NTK1Ws2XLlqX8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BcYYrr/+enn/JUuWYN68ebj11luxceNGXH311bjsssvw6aefJhz3gQcewPnnn4/169fj1FNPxZw5c+B0OlFXV4c33ngDALB161YcOHAATz75pPy5F198ESaTCV9//TUefvhhPPjgg/joo4867MMnn3yC+vp6fPbZZ3jsscdw33334fTTT0dFRQW+/vprXHPNNbj66quxb98+AK3z+ZkzZ6KiogLffvstXn/9dXz88cdyP0844QSUl5fL7QQAQRDw6quvYs6cOSnbsX37drz11lt499138e6772L58uX44x//KL9/yy23YMWKFXj77bfx0Ucf4fPPP8d3333XYd98Ph9OPfVULF26FGvWrMGsWbMwe/Zs7NmzBwAwZ84cfPPNNwnC4aZNm7B+/XpcfPHFAIBFixbhN7/5DX7/+99j8+bNeOihh3DvvffixRdfTPiuO++8E/PmzcPmzZsxc+ZMhEIhjBs3Du+99x42btyIq666Cr/4xS/wzTffZNSn66+/HitXrsQrr7yC9evX47zzzsOsWbPwww8/dNh3oohgRY7H42EAmMfjyXdTepxQKMT27dvHQqFQvpuSc0RRZPv372der5ft27ePCYLQ7WNK5y8SiaS1fzQaZfv27WM+n6/D/fx+P9u3bx8TRbHbbSSItgiCkDUbIAglQjZAlDpkAz2LJxhh3+x05OWfJ5jeHFWn0zGdTsfuuusu9t1337HnnnuO6fV6tnDhwg4/B4Ddc8898uuVK1cyAOwf//iHvG3x4sVMr9fLr6dMmcKuvPLKhOOcd9557NRTT015XJ/PxwCw999/nzHG2KeffsoAMJfLlXCcadOmsWOOOSZh24QJE9gdd9whv247/i+99FLWv3//BHsYNmwYO/bYY+XXsViMmUwmtnjxYsYYY3/7299YRUVFwpz+vffeYzzPs4MHDzLGGJs3bx47/vjj5fc//PBDptPp5DYvWLCAWa1W+f377ruPGY1G5vV65W3z589nkyZNYowx5vV6mUajYa+//rr8vtvtZkajkc2bN49lwsiRI9nTTz8tvx4zZgx78MEH5dd33XWX/L2MMTZo0CD28ssvJxzjt7/9LZs8eTJjjLGdO3cyAOyJJ57o9LtPO+00duutt6bdp927dzOVSsX279+fcJwTTjiB3XXXXWn2mIinkO4B6Wox6vzJYUSuiQ/h68hzpxiI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o2MMkNExBsjIOP5JL9rb2yHLMkpKSjR93kyKgVhzMXEv35MkKab/MiEhRcYjyzLa2tq4PpcMizFARscYIKNjDJCRcfyTXiSrppQeYyDupBQRERERERERESVGEARIkpTuZmQEc7wPuOuuu4b8+R133JFwY4iIiIiIiIiIshl339sv7qTUyy+/HHE7GAxix44dMJvNGD9+PJNSlHYOhyPdTSBKK8YAGR1jgIyOMUBGxvFPepDMpJTeYiDupNTq1asHHHO73bj00ktx9tlna9IookSJoojy8vJ0N4MobRgDZHSMATI6xgAZGcc/6UWyipDrMQY0qSmVn5+PxYsX45e//KUWT0eUMFmW0dnZyamQZFiMATI6xgAZHWOAjIzjn/QimYXO9RYDmhU6d7lccLlcWj0dUUL0GIREWmIMkNExBsjoGANkZBz/pBdKUkrrsarHGIh7+d5DDz0UcVuWZTQ1NeGZZ57BySefrFnDiIiIiIiIiIiyDQud7xd3Uur++++PuC2KIsrKynDJJZfg1ltv1axhRERERERERETZRqkpJcty0upL6UXcSakdO3YM+jOfzzeixhBpITc3N91NIEorxgAZHWOAjI4xQEbG8U960DcppTW9xYAmNaX8fj/uu+8+jB07VounI0qYKIooLS2FKGpWLo1IVxgDZHSMATI6xgAZGcc/6UWyklJ6jIGYW+r3+3HrrbfioIMOwmGHHYZXXnkFAPDEE09g7NixuP/++3HTTTclq51EMZEkCa2trZAkKd1NIUoLxgAZHWOAjI4xQEbG8U96kayklB5jIOak1B133IE//OEPGDNmDHbu3Ilzzz0XV111FR544AHcd9992LlzJ/7nf/4nmW0lionH40l3E4jSijFARscYIKNjDJCRcfyTHiRz+Z7eYiDmmlIvvPACnn76aZxxxhn46quvMHPmTIRCIaxdu9bwhbmIiIiIiIiIiGKRzKSU3sQ8U2r37t2YO3cuAGD69Omw2Wy46aabmJAiIiIiIiIiIooRk1L7xZyUCofDsFqt6m2z2ay7qu6U/QRBQGFhIZOlZFiMATI6xgAZHWOAjIzjn/QiWUkpPcZAzMv3ZFnGpZdeCpvNBgDo6enBNddcg5ycnIj7vfTSS9q2kCgOShASGRVjgIyOMUBGxxggI+P4J71IdlJKT2JOSl1yySURt7///e9r3hiikZIk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LlUx4PV6IYqRHwEmkwlA719NiNJFqxjYsGEDFixYgEsuuQR33333gN8zf/78iOcAgLfffjuuOCJKhlTFAAA8++yzuOyyy/Dss8/i1FNPTU6HiOKUihjIz8/H+vXrsWbNGvW/a665BpMnT8aaNWswb9685HaSaAip+hw4/PDD0djYCI/Hox77+uuvIYpiRBIs6dJYZJ1ogGuvvVYuKCiQ33vvPbmpqUn9z+v1qve55ppr5NraWnn58uXyF198Ic+fP1+eP39+xPNs3bpVXr16tXz11VfLkyZNklevXi2vXr1a9vv9sizLcjgclg888ED5qKOOkr/88kv5iy++kOfNmyefcMIJKe0vUX+pioFly5bJgiDIixcvlr/++mt51apV8sKFC+W6urqI30WUalrEwPr16+WysjL5+9//fsRz7N27V73P9u3bZafTKf/sZz+TN23aJD/66KOyyWSSly5dmtL+EvWXqhj4+9//LpvNZvnRRx+NuE9nZ2dK+0vUX6pioD/uvkeZIlUx0NXVJY8ePVo+55xz5A0bNsgrVqyQJ06cKF955ZUp7S+TUpRRAET978knn1Tv4/P55Ouuu04uKiqSnU6nfPbZZ8tNTU0Rz3P00UdHfZ4dO3ao99mzZ4/8ne98R87NzZXLy8vlSy+9NO3bYRKlMgaeffZZec6cOXJOTo5cVlYmn3HGGfKmTZtS1FOi6LSIgTvvvDPqc9TV1UX8rnfffVeePXu2bLVa5XHjxkX8DqJ0SVUMDPY5cckll6Sus0RRpPJzoC8mpShTpDIGNm3aJB9//PGyw+GQR48eLS9atCjlf6AWZFmWRzDRioiIiIiIiIiIKG6sKUVERERERERERCnHpBQREREREREREaUck1JERERERERERJRyTEoREREREREREVHKMSlFREREREREREQpx6QUERERERERERGlHJNSRERERERERESUckxKERERERERERFRyjEpRUREREREREREKcekFBEREVESXXrppRAEAYIgwGKxoLy8HCeccAKeeOIJSJIU8/M89dRTKCwsTF5DiYiIiFKMSSkiIiKiJDvppJPQ1NSEnTt34o033sCCBQvw4x//GKeddhpCoVC6m0dERESUFkxKERERESWZzWZDRUUFqqurceCBB+IXv/gFXn31Vbzxxht46qmnAAD33XcfZsyYgZycHNTU1OC6666Dx+MBALz33nu47LLL4HK51FlXv/rVrwAAfr8fN998M6qrq5GTk4N58+bhvffeS09HiYiIiOLApBQRERFRGhx77LGYNWsWXnrpJQCAKIp46KGHsGHDBvz1r3/F8uXLccsttwAADjvsMDzwwAPIz89HU1MTmpqacPPNNwMAbrjhBqxcuRL//Oc/sW7dOpx77rk46aSTsHXr1rT1jYiIiCgWgizLcrobQURERJStLr30UnR2duKVV14Z8LMLLrgA69atw8aNGwf87F//+heuueYatLa2AuitKfWTn/wEnZ2d6n3q6+sxbtw41NfXo6qqSj1+/PHH45BDDsFvfvMbzftDREREpBVzuhtAREREZFSyLEMQBADAO++8gyVLlmDz5s1wu90IhULo6emB1+uF0+mM+vj169cjHA5j0qRJEcf9fj9KSkqS3n4iIiKikWBSioiIiChNNm3ahLFjx2Lnzp047bTTcO211+Luu+9GcXExPvzwQ1xxxRUIBAKDJqU8Hg9MJhNWrVoFk8kU8bPc3NxUdIGIiIgoYUxKEREREaXB8uXLsX79etx0001YtWoVJEnCvffeC1HsLfn5/PPPR9zfarUiHA5HHJszZw7C4TD27t2LI488MmVtJyIiItICk1JERERESeb3+9Hc3IxwOIyWlhYsXboUS5YswWmnnYaLL74YX331FYLBIB5++GGcfvrp+Oijj/DYY49FPMeYMWPg8XiwbNkyzJo1C06nE5MmTcJFF12Eiy++GPfeey/mzJmDffv2YdmyZZg5cyZOPfXUNPWYiIiIaHjcfY+IiIgoyZYuXYrKykqMGTMGJ510Et5991089NBDePXVV2EymTBr1izcd999+O1vf4vp06fj73//O5YsWRLxHIcddhiuueYanH/++SgrK8M999wDAHjyySdx8cUX46c//SkmT56Ms846C59//jlqa2vT0VUiIiKimHH3PSIiIiIiIiIiSjnOlCIiIiIiIiIiopRjUoqIiIiIiIiIiFKOSSkiIiIiIiIiIko5JqWIiIiIiIiIiCjlmJQiIiIiIiIiIqKUY1KKiIiIiIiIiIhSjkkpIiIiIiIiIiJKOSaliIiIiIiIiIgo5ZiUIiIiIiIiIiKilGNSioiIiIiIiIiIUo5JKSIiIiIiIiIiSjkmpYiIiIiIiIiIKOX+P9VflpAbY9AqAAAAAElFTkSuQmCC",
|
||
"text/plain": [
|
||
"<Figure size 1200x500 with 1 Axes>"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
}
|
||
],
|
||
"source": [
|
||
"# ------------------------------------------------------------\n",
|
||
"# 1. Aggregate rupture rate over time\n",
|
||
"# CORRECTED: denominator = only observations with active flows\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"\n",
|
||
"# Active observations = at least one non-zero flow at this date\n",
|
||
"active_obs = df[df[\"Quantity - NetFlows\"] != 0]\n",
|
||
"\n",
|
||
"time_stats = (\n",
|
||
" active_obs\n",
|
||
" .groupby(\"Centralisation Date\")\n",
|
||
" .agg(\n",
|
||
" total_obs=(\"rupture_flag\", \"count\"), # only active flow observations\n",
|
||
" n_ruptures=(\"rupture_flag\", \"sum\")\n",
|
||
" )\n",
|
||
" .reset_index()\n",
|
||
")\n",
|
||
"\n",
|
||
"time_stats[\"rupture_rate\"] = (\n",
|
||
" time_stats[\"n_ruptures\"] / time_stats[\"total_obs\"]\n",
|
||
")\n",
|
||
"\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"# 2. Smooth (6-month moving average)\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"time_stats[\"rupture_rate_ma\"] = (\n",
|
||
" time_stats[\"rupture_rate\"]\n",
|
||
" .rolling(window=6, center=True)\n",
|
||
" .mean()\n",
|
||
")\n",
|
||
"\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"# 3. Plot\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"plt.figure(figsize=(12, 5))\n",
|
||
"\n",
|
||
"plt.plot(\n",
|
||
" time_stats[\"Centralisation Date\"],\n",
|
||
" time_stats[\"rupture_rate\"] * 100,\n",
|
||
" color=\"lightgray\",\n",
|
||
" linewidth=1,\n",
|
||
" alpha=0.6,\n",
|
||
" label=\"Monthly rupture rate (active flows only)\"\n",
|
||
")\n",
|
||
"\n",
|
||
"plt.plot(\n",
|
||
" time_stats[\"Centralisation Date\"],\n",
|
||
" time_stats[\"rupture_rate_ma\"] * 100,\n",
|
||
" color=\"#1f77b4\",\n",
|
||
" linewidth=2.5,\n",
|
||
" label=\"6-month moving average\"\n",
|
||
")\n",
|
||
"\n",
|
||
"plt.ylabel(\"Rupture rate (%)\")\n",
|
||
"plt.xlabel(\"Date\")\n",
|
||
"plt.grid(True, linestyle=\"--\", alpha=0.4)\n",
|
||
"plt.legend(frameon=False)\n",
|
||
"plt.tight_layout()\n",
|
||
"plt.show()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 14,
|
||
"id": "d6ee0c24-e14e-4c40-97d4-49879229790c",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"/tmp/ipykernel_1311/1047489516.py:6: FutureWarning:\n",
|
||
"\n",
|
||
"DataFrameGroupBy.apply operated on the grouping columns. This behavior is deprecated, and in a future version of pandas the grouping columns will be excluded from the operation. Either pass `include_groups=False` to exclude the groupings or explicitly select the grouping columns after groupby to silence this warning.\n",
|
||
"\n"
|
||
]
|
||
},
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"has_reset\n",
|
||
"True 64192\n",
|
||
"False 15545\n",
|
||
"Name: count, dtype: int64"
|
||
]
|
||
},
|
||
"execution_count": 14,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"EPS = 1e-6 # seuil numérique\n",
|
||
"\n",
|
||
"reset_candidates = (\n",
|
||
" df\n",
|
||
" .groupby([\"Registrar Account - ID\", \"Product - Isin\"])\n",
|
||
" .apply(\n",
|
||
" lambda g: (\n",
|
||
" (g[\"Quantity - AUM\"].abs() < EPS) &\n",
|
||
" (g[\"expected_stock\"].abs() < EPS)\n",
|
||
" ).any()\n",
|
||
" )\n",
|
||
" .reset_index(name=\"has_reset\")\n",
|
||
")\n",
|
||
"\n",
|
||
"reset_candidates[\"has_reset\"].value_counts()\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 47,
|
||
"id": "601f61b8-0115-431d-97de-6ec5a0f1d4f4",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
" Before repair After repair Repaired points\n",
|
||
"0 756392 22357 18440\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"/tmp/ipykernel_1311/3061846510.py:66: FutureWarning:\n",
|
||
"\n",
|
||
"DataFrameGroupBy.apply operated on the grouping columns. This behavior is deprecated, and in a future version of pandas the grouping columns will be excluded from the operation. Either pass `include_groups=False` to exclude the groupings or explicitly select the grouping columns after groupby to silence this warning.\n",
|
||
"\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"GAP_TOL = 1e-6\n",
|
||
"REL_GAP_THR = 0.05\n",
|
||
"MIN_PERSISTENCE = 3\n",
|
||
"\n",
|
||
"df = merged_isin.copy().sort_values(\n",
|
||
" [\"Registrar Account - ID\", \"Product - Isin\", \"Centralisation Date\"]\n",
|
||
")\n",
|
||
"\n",
|
||
"df[\"corrected_aum\"] = df[\"Quantity - AUM\"]\n",
|
||
"df[\"repair_flag\"] = False\n",
|
||
"\n",
|
||
"def repair_group(g):\n",
|
||
" g = g.copy()\n",
|
||
"\n",
|
||
" obs = g[\"Quantity - AUM\"].values\n",
|
||
" flows = g[\"Quantity - NetFlows\"].values\n",
|
||
"\n",
|
||
" corrected = obs.copy()\n",
|
||
"\n",
|
||
" # Initial expected path\n",
|
||
" expected = np.empty_like(obs)\n",
|
||
" expected[0] = np.nan\n",
|
||
"\n",
|
||
" for t in range(1, len(obs)):\n",
|
||
" expected[t] = corrected[t-1] + flows[t-1]\n",
|
||
"\n",
|
||
" gap = obs - expected\n",
|
||
" rel_gap = np.abs(gap) / np.maximum(np.abs(expected), 1.0)\n",
|
||
"\n",
|
||
" idx = None\n",
|
||
"\n",
|
||
" for i in range(1, len(obs) - MIN_PERSISTENCE):\n",
|
||
" if (\n",
|
||
" rel_gap[i] > REL_GAP_THR\n",
|
||
" and np.all(np.abs(gap[i:i+MIN_PERSISTENCE] - gap[i]) < GAP_TOL)\n",
|
||
" and np.all(np.abs(np.diff(flows[i:i+MIN_PERSISTENCE])) < GAP_TOL)\n",
|
||
" ):\n",
|
||
" idx = i\n",
|
||
" break\n",
|
||
"\n",
|
||
" if idx is None:\n",
|
||
" return g\n",
|
||
"\n",
|
||
" # Apply correction\n",
|
||
" shift = gap[idx]\n",
|
||
" corrected[idx:] = obs[idx:] - shift\n",
|
||
"\n",
|
||
" g.loc[g.index[idx]:, \"repair_flag\"] = True\n",
|
||
"\n",
|
||
" # Rebuild expected stock AFTER correction\n",
|
||
" expected_corr = np.empty_like(obs)\n",
|
||
" expected_corr[0] = np.nan\n",
|
||
"\n",
|
||
" for t in range(1, len(obs)):\n",
|
||
" expected_corr[t] = corrected[t-1] + flows[t-1]\n",
|
||
"\n",
|
||
" g[\"corrected_aum\"] = corrected\n",
|
||
" g[\"expected_stock_corr\"] = expected_corr\n",
|
||
"\n",
|
||
" return g\n",
|
||
"\n",
|
||
"\n",
|
||
"df = (\n",
|
||
" df\n",
|
||
" .groupby([\"Registrar Account - ID\", \"Product - Isin\"], group_keys=False)\n",
|
||
" .apply(repair_group)\n",
|
||
")\n",
|
||
"\n",
|
||
"# Recompute gaps & ruptures\n",
|
||
"df[\"gap_before\"] = df[\"Quantity - AUM\"] - df[\"expected_stock\"]\n",
|
||
"df[\"gap_after\"] = df[\"corrected_aum\"] - df[\"expected_stock_corr\"]\n",
|
||
"\n",
|
||
"df[\"rupture_before\"] = df[\"gap_before\"].abs() > GAP_TOL\n",
|
||
"df[\"rupture_after\"] = df[\"gap_after\"].abs() > GAP_TOL\n",
|
||
"\n",
|
||
"summary = pd.DataFrame({\n",
|
||
" \"Before repair\": [df[\"rupture_before\"].sum()],\n",
|
||
" \"After repair\": [df[\"rupture_after\"].sum()],\n",
|
||
" \"Repaired points\": [df[\"repair_flag\"].sum()]\n",
|
||
"})\n",
|
||
"\n",
|
||
"print(summary)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 30,
|
||
"id": "62583cfe-a6e7-4931-a63e-4273dca97ff7",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"ename": "NameError",
|
||
"evalue": "name 'df_final' is not defined",
|
||
"output_type": "error",
|
||
"traceback": [
|
||
"\u001b[31m---------------------------------------------------------------------------\u001b[39m",
|
||
"\u001b[31mNameError\u001b[39m Traceback (most recent call last)",
|
||
"\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[30]\u001b[39m\u001b[32m, line 4\u001b[39m\n\u001b[32m 1\u001b[39m \u001b[38;5;28;01mimport\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01mplotly\u001b[39;00m\u001b[34;01m.\u001b[39;00m\u001b[34;01mgraph_objects\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mas\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01mgo\u001b[39;00m\n\u001b[32m 2\u001b[39m \u001b[38;5;28;01mimport\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01mpandas\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mas\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01mpd\u001b[39;00m\n\u001b[32m----> \u001b[39m\u001b[32m4\u001b[39m df_final = \u001b[43mdf_final\u001b[49m.rename(columns={\n\u001b[32m 5\u001b[39m \u001b[33m\"\u001b[39m\u001b[33mQuantity - AUM\u001b[39m\u001b[33m\"\u001b[39m: \u001b[33m\"\u001b[39m\u001b[33maum_raw\u001b[39m\u001b[33m\"\u001b[39m,\n\u001b[32m 6\u001b[39m \u001b[33m\"\u001b[39m\u001b[33mcorrected_aum\u001b[39m\u001b[33m\"\u001b[39m: \u001b[33m\"\u001b[39m\u001b[33maum_repaired\u001b[39m\u001b[33m\"\u001b[39m,\n\u001b[32m 7\u001b[39m \u001b[33m\"\u001b[39m\u001b[33mQuantity - NetFlows\u001b[39m\u001b[33m\"\u001b[39m: \u001b[33m\"\u001b[39m\u001b[33mflows\u001b[39m\u001b[33m\"\u001b[39m,\n\u001b[32m 8\u001b[39m \u001b[33m\"\u001b[39m\u001b[33mexpected_stock\u001b[39m\u001b[33m\"\u001b[39m: \u001b[33m\"\u001b[39m\u001b[33mexpected_aum_raw\u001b[39m\u001b[33m\"\u001b[39m,\n\u001b[32m 9\u001b[39m \u001b[33m\"\u001b[39m\u001b[33mexpected_stock_corr\u001b[39m\u001b[33m\"\u001b[39m: \u001b[33m\"\u001b[39m\u001b[33mexpected_aum_repaired\u001b[39m\u001b[33m\"\u001b[39m\n\u001b[32m 10\u001b[39m })\n\u001b[32m 12\u001b[39m df[\u001b[33m\"\u001b[39m\u001b[33mgap_before\u001b[39m\u001b[33m\"\u001b[39m] = df[\u001b[33m\"\u001b[39m\u001b[33mQuantity - AUM\u001b[39m\u001b[33m\"\u001b[39m] - df[\u001b[33m\"\u001b[39m\u001b[33mexpected_stock\u001b[39m\u001b[33m\"\u001b[39m]\n\u001b[32m 13\u001b[39m df[\u001b[33m\"\u001b[39m\u001b[33mgap_after\u001b[39m\u001b[33m\"\u001b[39m] = df[\u001b[33m\"\u001b[39m\u001b[33mcorrected_aum\u001b[39m\u001b[33m\"\u001b[39m] - df[\u001b[33m\"\u001b[39m\u001b[33mexpected_stock_corr\u001b[39m\u001b[33m\"\u001b[39m]\n",
|
||
"\u001b[31mNameError\u001b[39m: name 'df_final' is not defined"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"import plotly.graph_objects as go\n",
|
||
"import pandas as pd\n",
|
||
"\n",
|
||
"# ============================================================\n",
|
||
"# Parameters (fixed epsilon)\n",
|
||
"# ============================================================\n",
|
||
"GAP_EPS = 100 # fixed tolerance for accounting identity\n",
|
||
"\n",
|
||
"# ============================================================\n",
|
||
"# 1. Define ruptures using a FIXED epsilon\n",
|
||
"# ============================================================\n",
|
||
"df = df.copy()\n",
|
||
"\n",
|
||
"df[\"rupture_before\"] = df[\"gap_before\"].abs() > GAP_EPS\n",
|
||
"df[\"rupture_after\"] = df[\"gap_after\"].abs() > GAP_EPS\n",
|
||
"\n",
|
||
"# ============================================================\n",
|
||
"# 2. Rupture ratios BEFORE repair\n",
|
||
"# ============================================================\n",
|
||
"rupture_summary_before = (\n",
|
||
" df\n",
|
||
" .groupby([\"Registrar Account - ID\", \"Product - Isin\"])\n",
|
||
" .agg(\n",
|
||
" n_obs=(\"rupture_before\", \"count\"),\n",
|
||
" n_ruptures=(\"rupture_before\", \"sum\")\n",
|
||
" )\n",
|
||
" .reset_index()\n",
|
||
")\n",
|
||
"\n",
|
||
"rupture_summary_before[\"rupture_ratio\"] = (\n",
|
||
" rupture_summary_before[\"n_ruptures\"] /\n",
|
||
" rupture_summary_before[\"n_obs\"]\n",
|
||
")\n",
|
||
"\n",
|
||
"# ============================================================\n",
|
||
"# 3. Rupture ratios AFTER repair\n",
|
||
"# ============================================================\n",
|
||
"rupture_summary_after = (\n",
|
||
" df\n",
|
||
" .groupby([\"Registrar Account - ID\", \"Product - Isin\"])\n",
|
||
" .agg(\n",
|
||
" n_obs=(\"rupture_after\", \"count\"),\n",
|
||
" n_ruptures=(\"rupture_after\", \"sum\")\n",
|
||
" )\n",
|
||
" .reset_index()\n",
|
||
")\n",
|
||
"\n",
|
||
"rupture_summary_after[\"rupture_ratio\"] = (\n",
|
||
" rupture_summary_after[\"n_ruptures\"] /\n",
|
||
" rupture_summary_after[\"n_obs\"]\n",
|
||
")\n",
|
||
"\n",
|
||
"# ============================================================\n",
|
||
"# 4. Rupture intensity classes (fixed bins)\n",
|
||
"# ============================================================\n",
|
||
"bins = [0.0, 0.01, 0.10, 0.30, 1.0]\n",
|
||
"labels = [\n",
|
||
" \"Clean / quasi-clean (≤1%)\",\n",
|
||
" \"Moderate (1–10%)\",\n",
|
||
" \"High (10–30%)\",\n",
|
||
" \"Severe (>30%)\"\n",
|
||
"]\n",
|
||
"\n",
|
||
"rupture_summary_before[\"rupture_class\"] = pd.cut(\n",
|
||
" rupture_summary_before[\"rupture_ratio\"],\n",
|
||
" bins=bins,\n",
|
||
" labels=labels,\n",
|
||
" include_lowest=True\n",
|
||
")\n",
|
||
"\n",
|
||
"rupture_summary_after[\"rupture_class\"] = pd.cut(\n",
|
||
" rupture_summary_after[\"rupture_ratio\"],\n",
|
||
" bins=bins,\n",
|
||
" labels=labels,\n",
|
||
" include_lowest=True\n",
|
||
")\n",
|
||
"\n",
|
||
"# ============================================================\n",
|
||
"# 5. Distribution (%)\n",
|
||
"# ============================================================\n",
|
||
"dist_before = (\n",
|
||
" rupture_summary_before[\"rupture_class\"]\n",
|
||
" .value_counts(normalize=True)\n",
|
||
" .sort_index()\n",
|
||
" * 100\n",
|
||
").round(1)\n",
|
||
"\n",
|
||
"dist_after = (\n",
|
||
" rupture_summary_after[\"rupture_class\"]\n",
|
||
" .value_counts(normalize=True)\n",
|
||
" .sort_index()\n",
|
||
" * 100\n",
|
||
").round(1)\n",
|
||
"\n",
|
||
"# ============================================================\n",
|
||
"# 6. Donut chart: BEFORE vs AFTER (fixed epsilon)\n",
|
||
"# ============================================================\n",
|
||
"fig = go.Figure()\n",
|
||
"\n",
|
||
"fig.add_trace(go.Pie(\n",
|
||
" labels=dist_before.index,\n",
|
||
" values=dist_before.values,\n",
|
||
" hole=0.45,\n",
|
||
" name=\"Before repair\",\n",
|
||
" domain=dict(x=[0.0, 0.48]),\n",
|
||
" textinfo=\"percent\",\n",
|
||
" hoverinfo=\"label+percent\"\n",
|
||
"))\n",
|
||
"\n",
|
||
"fig.add_trace(go.Pie(\n",
|
||
" labels=dist_after.index,\n",
|
||
" values=dist_after.values,\n",
|
||
" hole=0.45,\n",
|
||
" name=\"After repair\",\n",
|
||
" domain=dict(x=[0.52, 1.0]),\n",
|
||
" textinfo=\"percent\",\n",
|
||
" hoverinfo=\"label+percent\"\n",
|
||
"))\n",
|
||
"\n",
|
||
"fig.update_layout(\n",
|
||
" title=\"Distribution of AUM–flow rupture intensity before vs after repair (fixed ε)\",\n",
|
||
" annotations=[\n",
|
||
" dict(text=\"Before repair\", x=0.24, y=0.5, showarrow=False),\n",
|
||
" dict(text=\"After repair\", x=0.76, y=0.5, showarrow=False),\n",
|
||
" ],\n",
|
||
" legend=dict(\n",
|
||
" orientation=\"h\",\n",
|
||
" yanchor=\"top\",\n",
|
||
" y=-0.15,\n",
|
||
" xanchor=\"center\",\n",
|
||
" x=0.5\n",
|
||
" ),\n",
|
||
" legend_title_text=\"Rupture ratio\"\n",
|
||
")\n",
|
||
"\n",
|
||
"fig.show()\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 31,
|
||
"id": "70cf0a99-bd19-41a9-9574-88647fde09ca",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"ename": "KeyError",
|
||
"evalue": "\"['Quantity - AUM', 'corrected_aum', 'Quantity - NetFlows', 'expected_stock', 'expected_stock_corr', 'gap_before', 'gap_after'] not in index\"",
|
||
"output_type": "error",
|
||
"traceback": [
|
||
"\u001b[31m---------------------------------------------------------------------------\u001b[39m",
|
||
"\u001b[31mKeyError\u001b[39m Traceback (most recent call last)",
|
||
"\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[31]\u001b[39m\u001b[32m, line 10\u001b[39m\n\u001b[32m 5\u001b[39m df_final = df.copy()\n\u001b[32m 7\u001b[39m \u001b[38;5;66;03m# ------------------------------------------------------------\u001b[39;00m\n\u001b[32m 8\u001b[39m \u001b[38;5;66;03m# Core variables (before / after)\u001b[39;00m\n\u001b[32m 9\u001b[39m \u001b[38;5;66;03m# ------------------------------------------------------------\u001b[39;00m\n\u001b[32m---> \u001b[39m\u001b[32m10\u001b[39m df_final = \u001b[43mdf_final\u001b[49m\u001b[43m[\u001b[49m\u001b[43m[\u001b[49m\n\u001b[32m 11\u001b[39m \u001b[43m \u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mRegistrar Account - ID\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[32m 12\u001b[39m \u001b[43m \u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mProduct - Isin\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[32m 13\u001b[39m \u001b[43m \u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mCentralisation Date\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[32m 14\u001b[39m \u001b[43m \u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mQuantity - AUM\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[32m 15\u001b[39m \u001b[43m \u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mcorrected_aum\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[32m 16\u001b[39m \u001b[43m \u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mQuantity - NetFlows\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[32m 17\u001b[39m \u001b[43m \u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mexpected_stock\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[32m 18\u001b[39m \u001b[43m \u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mexpected_stock_corr\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[32m 19\u001b[39m \u001b[43m \u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mgap_before\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[32m 20\u001b[39m \u001b[43m \u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mgap_after\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[32m 21\u001b[39m \u001b[43m \u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mrepair_flag\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\n\u001b[32m 22\u001b[39m \u001b[43m]\u001b[49m\u001b[43m]\u001b[49m.rename(columns={\n\u001b[32m 23\u001b[39m \u001b[33m\"\u001b[39m\u001b[33mQuantity - AUM\u001b[39m\u001b[33m\"\u001b[39m: \u001b[33m\"\u001b[39m\u001b[33maum_raw\u001b[39m\u001b[33m\"\u001b[39m,\n\u001b[32m 24\u001b[39m \u001b[33m\"\u001b[39m\u001b[33mcorrected_aum\u001b[39m\u001b[33m\"\u001b[39m: \u001b[33m\"\u001b[39m\u001b[33maum_repaired\u001b[39m\u001b[33m\"\u001b[39m,\n\u001b[32m 25\u001b[39m \u001b[33m\"\u001b[39m\u001b[33mQuantity - NetFlows\u001b[39m\u001b[33m\"\u001b[39m: \u001b[33m\"\u001b[39m\u001b[33mflows\u001b[39m\u001b[33m\"\u001b[39m,\n\u001b[32m 26\u001b[39m \u001b[33m\"\u001b[39m\u001b[33mexpected_stock\u001b[39m\u001b[33m\"\u001b[39m: \u001b[33m\"\u001b[39m\u001b[33mexpected_aum_raw\u001b[39m\u001b[33m\"\u001b[39m,\n\u001b[32m 27\u001b[39m \u001b[33m\"\u001b[39m\u001b[33mexpected_stock_corr\u001b[39m\u001b[33m\"\u001b[39m: \u001b[33m\"\u001b[39m\u001b[33mexpected_aum_repaired\u001b[39m\u001b[33m\"\u001b[39m\n\u001b[32m 28\u001b[39m })\n\u001b[32m 30\u001b[39m \u001b[38;5;66;03m# ------------------------------------------------------------\u001b[39;00m\n\u001b[32m 31\u001b[39m \u001b[38;5;66;03m# Relative gaps\u001b[39;00m\n\u001b[32m 32\u001b[39m \u001b[38;5;66;03m# ------------------------------------------------------------\u001b[39;00m\n\u001b[32m 33\u001b[39m df_final[\u001b[33m\"\u001b[39m\u001b[33mgap_rel_before\u001b[39m\u001b[33m\"\u001b[39m] = (\n\u001b[32m 34\u001b[39m df_final[\u001b[33m\"\u001b[39m\u001b[33mgap_before\u001b[39m\u001b[33m\"\u001b[39m].abs() /\n\u001b[32m 35\u001b[39m df_final[\u001b[33m\"\u001b[39m\u001b[33mexpected_aum_raw\u001b[39m\u001b[33m\"\u001b[39m].abs().clip(lower=\u001b[32m1\u001b[39m)\n\u001b[32m 36\u001b[39m )\n",
|
||
"\u001b[36mFile \u001b[39m\u001b[32m/opt/python/lib/python3.13/site-packages/pandas/core/frame.py:4119\u001b[39m, in \u001b[36mDataFrame.__getitem__\u001b[39m\u001b[34m(self, key)\u001b[39m\n\u001b[32m 4117\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m is_iterator(key):\n\u001b[32m 4118\u001b[39m key = \u001b[38;5;28mlist\u001b[39m(key)\n\u001b[32m-> \u001b[39m\u001b[32m4119\u001b[39m indexer = \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mcolumns\u001b[49m\u001b[43m.\u001b[49m\u001b[43m_get_indexer_strict\u001b[49m\u001b[43m(\u001b[49m\u001b[43mkey\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mcolumns\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m)\u001b[49m[\u001b[32m1\u001b[39m]\n\u001b[32m 4121\u001b[39m \u001b[38;5;66;03m# take() does not accept boolean indexers\u001b[39;00m\n\u001b[32m 4122\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mgetattr\u001b[39m(indexer, \u001b[33m\"\u001b[39m\u001b[33mdtype\u001b[39m\u001b[33m\"\u001b[39m, \u001b[38;5;28;01mNone\u001b[39;00m) == \u001b[38;5;28mbool\u001b[39m:\n",
|
||
"\u001b[36mFile \u001b[39m\u001b[32m/opt/python/lib/python3.13/site-packages/pandas/core/indexes/base.py:6212\u001b[39m, in \u001b[36mIndex._get_indexer_strict\u001b[39m\u001b[34m(self, key, axis_name)\u001b[39m\n\u001b[32m 6209\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[32m 6210\u001b[39m keyarr, indexer, new_indexer = \u001b[38;5;28mself\u001b[39m._reindex_non_unique(keyarr)\n\u001b[32m-> \u001b[39m\u001b[32m6212\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m_raise_if_missing\u001b[49m\u001b[43m(\u001b[49m\u001b[43mkeyarr\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mindexer\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43maxis_name\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 6214\u001b[39m keyarr = \u001b[38;5;28mself\u001b[39m.take(indexer)\n\u001b[32m 6215\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(key, Index):\n\u001b[32m 6216\u001b[39m \u001b[38;5;66;03m# GH 42790 - Preserve name from an Index\u001b[39;00m\n",
|
||
"\u001b[36mFile \u001b[39m\u001b[32m/opt/python/lib/python3.13/site-packages/pandas/core/indexes/base.py:6264\u001b[39m, in \u001b[36mIndex._raise_if_missing\u001b[39m\u001b[34m(self, key, indexer, axis_name)\u001b[39m\n\u001b[32m 6261\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mKeyError\u001b[39;00m(\u001b[33mf\u001b[39m\u001b[33m\"\u001b[39m\u001b[33mNone of [\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mkey\u001b[38;5;132;01m}\u001b[39;00m\u001b[33m] are in the [\u001b[39m\u001b[38;5;132;01m{\u001b[39;00maxis_name\u001b[38;5;132;01m}\u001b[39;00m\u001b[33m]\u001b[39m\u001b[33m\"\u001b[39m)\n\u001b[32m 6263\u001b[39m not_found = \u001b[38;5;28mlist\u001b[39m(ensure_index(key)[missing_mask.nonzero()[\u001b[32m0\u001b[39m]].unique())\n\u001b[32m-> \u001b[39m\u001b[32m6264\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mKeyError\u001b[39;00m(\u001b[33mf\u001b[39m\u001b[33m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mnot_found\u001b[38;5;132;01m}\u001b[39;00m\u001b[33m not in index\u001b[39m\u001b[33m\"\u001b[39m)\n",
|
||
"\u001b[31mKeyError\u001b[39m: \"['Quantity - AUM', 'corrected_aum', 'Quantity - NetFlows', 'expected_stock', 'expected_stock_corr', 'gap_before', 'gap_after'] not in index\""
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"# ============================================================\n",
|
||
"# FINAL DATASETS AFTER REPAIR\n",
|
||
"# ============================================================\n",
|
||
"\n",
|
||
"df_final = df.copy()\n",
|
||
"\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"# Core variables (before / after)\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"df_final = df_final[[\n",
|
||
" \"Registrar Account - ID\",\n",
|
||
" \"Product - Isin\",\n",
|
||
" \"Centralisation Date\",\n",
|
||
" \"Quantity - AUM\",\n",
|
||
" \"corrected_aum\",\n",
|
||
" \"Quantity - NetFlows\",\n",
|
||
" \"expected_stock\",\n",
|
||
" \"expected_stock_corr\",\n",
|
||
" \"gap_before\",\n",
|
||
" \"gap_after\",\n",
|
||
" \"repair_flag\"\n",
|
||
"]].rename(columns={\n",
|
||
" \"Quantity - AUM\": \"aum_raw\",\n",
|
||
" \"corrected_aum\": \"aum_repaired\",\n",
|
||
" \"Quantity - NetFlows\": \"flows\",\n",
|
||
" \"expected_stock\": \"expected_aum_raw\",\n",
|
||
" \"expected_stock_corr\": \"expected_aum_repaired\"\n",
|
||
"})\n",
|
||
"\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"# Relative gaps\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"df_final[\"gap_rel_before\"] = (\n",
|
||
" df_final[\"gap_before\"].abs() /\n",
|
||
" df_final[\"expected_aum_raw\"].abs().clip(lower=1)\n",
|
||
")\n",
|
||
"\n",
|
||
"df_final[\"gap_rel_after\"] = (\n",
|
||
" df_final[\"gap_after\"].abs() /\n",
|
||
" df_final[\"expected_aum_repaired\"].abs().clip(lower=1)\n",
|
||
")\n",
|
||
"df_final.to_csv('df_repaired.csv')"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "befb2962-73fb-4cb8-b86e-3218ec103204",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# ============================================================\n",
|
||
"# TYPE 3 REPAIR — TEMPORARY RESET TO ZERO (ONE BLOCK)\n",
|
||
"# ============================================================\n",
|
||
"\n",
|
||
"df_type3 = df_repaired.copy()\n",
|
||
"df_type3 = df_type3.sort_values(\n",
|
||
" [\"Registrar Account - ID\", \"Product - Isin\", \"Centralisation Date\"]\n",
|
||
")\n",
|
||
"\n",
|
||
"# Create lead/lag variables\n",
|
||
"df_type3[\"aum_prev\"] = df_type3.groupby(\n",
|
||
" [\"Registrar Account - ID\", \"Product - Isin\"]\n",
|
||
")[\"Quantity - AUM\"].shift(1)\n",
|
||
"\n",
|
||
"df_type3[\"aum_next\"] = df_type3.groupby(\n",
|
||
" [\"Registrar Account - ID\", \"Product - Isin\"]\n",
|
||
")[\"Quantity - AUM\"].shift(-1)\n",
|
||
"\n",
|
||
"df_type3[\"flow_prev\"] = df_type3.groupby(\n",
|
||
" [\"Registrar Account - ID\", \"Product - Isin\"]\n",
|
||
")[\"Quantity - NetFlows\"].shift(1)\n",
|
||
"\n",
|
||
"df_type3[\"flow_next\"] = df_type3.groupby(\n",
|
||
" [\"Registrar Account - ID\", \"Product - Isin\"]\n",
|
||
")[\"Quantity - NetFlows\"].shift(-1)\n",
|
||
"\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"# Detection of temporary reset\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"df_type3[\"type3_flag\"] = (\n",
|
||
" (df_type3[\"Quantity - AUM\"] == 0)\n",
|
||
" & (df_type3[\"aum_prev\"] > 0)\n",
|
||
" & (df_type3[\"aum_next\"] == df_type3[\"aum_prev\"])\n",
|
||
" & (df_type3[\"flow_prev\"].fillna(0) == 0)\n",
|
||
" & (df_type3[\"Quantity - NetFlows\"] == 0)\n",
|
||
" & (df_type3[\"flow_next\"].fillna(0) == 0)\n",
|
||
")\n",
|
||
"\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"# Repair: smooth the glitch (replace 0 by previous stock)\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"df_type3.loc[df_type3[\"type3_flag\"], \"Quantity - AUM\"] = (\n",
|
||
" df_type3.loc[df_type3[\"type3_flag\"], \"aum_prev\"]\n",
|
||
")\n",
|
||
"\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"# Recompute temporal chain AFTER repair\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"df_type3[\"prev_stock\"] = df_type3.groupby(\n",
|
||
" [\"Registrar Account - ID\", \"Product - Isin\"]\n",
|
||
")[\"Quantity - AUM\"].shift(1)\n",
|
||
"\n",
|
||
"df_type3[\"prev_flows\"] = df_type3.groupby(\n",
|
||
" [\"Registrar Account - ID\", \"Product - Isin\"]\n",
|
||
")[\"Quantity - NetFlows\"].shift(1).fillna(0)\n",
|
||
"\n",
|
||
"df_type3[\"expected_stock\"] = (\n",
|
||
" df_type3[\"prev_stock\"] + df_type3[\"prev_flows\"]\n",
|
||
")\n",
|
||
"\n",
|
||
"df_type3[\"gap\"] = df_type3[\"Quantity - AUM\"] - df_type3[\"expected_stock\"]\n",
|
||
"df_type3[\"gap_abs\"] = df_type3[\"gap\"].abs()\n",
|
||
"df_type3[\"gap_rel\"] = (\n",
|
||
" df_type3[\"gap_abs\"] /\n",
|
||
" df_type3[\"expected_stock\"].abs().clip(lower=1)\n",
|
||
")\n",
|
||
"\n",
|
||
"df_type3[\"rupture_flag\"] = (\n",
|
||
" df_type3[\"prev_stock\"].notna()\n",
|
||
" & (df_type3[\"gap_abs\"] > TAU_ABS)\n",
|
||
" & (df_type3[\"gap_rel\"] > TAU_REL)\n",
|
||
")\n",
|
||
"\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"# Diagnostic output\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"n_type3 = df_type3[\"type3_flag\"].sum()\n",
|
||
"print(f\"Temporary reset glitches repaired (Type 3): {n_type3}\")\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "1fc44ed4-829f-4a8a-985a-31350bdbdf6d",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"import numpy as np\n",
|
||
"import pandas as pd\n",
|
||
"\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"# 1. Sélection des ISIN avec exactement 1 rupture\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"one_rupture_isin = rupture_isin_summary[\n",
|
||
" rupture_isin_summary[\"n_ruptures\"] == 1\n",
|
||
"][[\"Registrar Account - ID\", \"Product - Isin\"]].head(100)\n",
|
||
"\n",
|
||
"results = []\n",
|
||
"\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"# 2. Boucle de correction test\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"for _, row in one_rupture_isin.iterrows():\n",
|
||
" acc = row[\"Registrar Account - ID\"]\n",
|
||
" isin = row[\"Product - Isin\"]\n",
|
||
"\n",
|
||
" sub = df[\n",
|
||
" (df[\"Registrar Account - ID\"] == acc) &\n",
|
||
" (df[\"Product - Isin\"] == isin)\n",
|
||
" ].sort_values(\"Centralisation Date\").copy()\n",
|
||
"\n",
|
||
" # Localiser la rupture\n",
|
||
" rupture_idx = sub.index[sub[\"rupture_flag\"]]\n",
|
||
"\n",
|
||
" if sub.index.get_loc(rupture_idx[0]) > 1:\n",
|
||
" #print(sub[[\"Centralisation Date\", \"Quantity - AUM\", \"expected_stock\", \"gap\", \"rupture_flag\"]].head(100))\n",
|
||
" continue\n",
|
||
"\n",
|
||
" # Vérifier si la rupture est à la première date\n",
|
||
" first_idx = sub.index[0]\n",
|
||
" if rupture_idx[0] != first_idx:\n",
|
||
" continue\n",
|
||
"\n",
|
||
" # ----- Réparation : décaler expected_stock -----\n",
|
||
" sub[\"expected_stock_fixed\"] = sub[\"expected_stock\"].shift(-1)\n",
|
||
"\n",
|
||
" # Recalcul des gaps\n",
|
||
" sub[\"gap_fixed\"] = sub[\"Quantity - AUM\"] - sub[\"expected_stock_fixed\"]\n",
|
||
" sub[\"gap_abs_fixed\"] = sub[\"gap_fixed\"].abs()\n",
|
||
" sub[\"gap_rel_fixed\"] = sub[\"gap_abs_fixed\"] / sub[\"expected_stock_fixed\"].abs().clip(lower=1)\n",
|
||
"\n",
|
||
" # Recalcul rupture\n",
|
||
" sub[\"rupture_fixed\"] = (\n",
|
||
" sub[\"expected_stock_fixed\"].notna()\n",
|
||
" & (sub[\"gap_abs_fixed\"] > TAU_ABS)\n",
|
||
" & (sub[\"gap_rel_fixed\"] > TAU_REL)\n",
|
||
" )\n",
|
||
"\n",
|
||
" results.append({\n",
|
||
" \"Registrar Account - ID\": acc,\n",
|
||
" \"Product - Isin\": isin,\n",
|
||
" \"ruptures_before\": sub[\"rupture_flag\"].sum(),\n",
|
||
" \"ruptures_after\": sub[\"rupture_fixed\"].sum()\n",
|
||
" })\n",
|
||
"\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"# 3. Résultats agrégés\n",
|
||
"# ------------------------------------------------------------\n",
|
||
"repair_test = pd.DataFrame(results)\n",
|
||
"\n",
|
||
"summary = repair_test.groupby(\n",
|
||
" [\"ruptures_before\", \"ruptures_after\"]\n",
|
||
").size().reset_index(name=\"count\")\n",
|
||
"\n",
|
||
"repair_test, summary\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 50,
|
||
"id": "d85728ca-55ba-4266-b881-23536eee4ba3",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"ename": "KeyError",
|
||
"evalue": "\"['corrected_aum'] not in index\"",
|
||
"output_type": "error",
|
||
"traceback": [
|
||
"\u001b[31m---------------------------------------------------------------------------\u001b[39m",
|
||
"\u001b[31mKeyError\u001b[39m Traceback (most recent call last)",
|
||
"\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[50]\u001b[39m\u001b[32m, line 16\u001b[39m\n\u001b[32m 10\u001b[39m stocks_repaired[\u001b[33m\"\u001b[39m\u001b[33mCentralisation Date\u001b[39m\u001b[33m\"\u001b[39m] = pd.to_datetime(\n\u001b[32m 11\u001b[39m stocks_repaired[\u001b[33m\"\u001b[39m\u001b[33mCentralisation Date\u001b[39m\u001b[33m\"\u001b[39m]\n\u001b[32m 12\u001b[39m )\n\u001b[32m 14\u001b[39m \u001b[38;5;66;03m# 2. Build repair map\u001b[39;00m\n\u001b[32m 15\u001b[39m repair_map = (\n\u001b[32m---> \u001b[39m\u001b[32m16\u001b[39m \u001b[43mdf\u001b[49m\u001b[43m[\u001b[49m\u001b[43m[\u001b[49m\n\u001b[32m 17\u001b[39m \u001b[43m \u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mRegistrar Account - ID\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[32m 18\u001b[39m \u001b[43m \u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mProduct - Isin\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[32m 19\u001b[39m \u001b[43m \u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mCentralisation Date\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[32m 20\u001b[39m \u001b[43m \u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mcorrected_aum\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[32m 21\u001b[39m \u001b[43m \u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mrepair_flag\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\n\u001b[32m 22\u001b[39m \u001b[43m \u001b[49m\u001b[43m]\u001b[49m\u001b[43m]\u001b[49m\n\u001b[32m 23\u001b[39m .rename(columns={\u001b[33m\"\u001b[39m\u001b[33mcorrected_aum\u001b[39m\u001b[33m\"\u001b[39m: \u001b[33m\"\u001b[39m\u001b[33mQuantity - AUM repaired\u001b[39m\u001b[33m\"\u001b[39m})\n\u001b[32m 24\u001b[39m )\n\u001b[32m 26\u001b[39m \u001b[38;5;66;03m# 3. Merge repaired quantities\u001b[39;00m\n\u001b[32m 27\u001b[39m stocks_repaired = stocks_repaired.merge(\n\u001b[32m 28\u001b[39m repair_map,\n\u001b[32m 29\u001b[39m on=[\u001b[33m\"\u001b[39m\u001b[33mRegistrar Account - ID\u001b[39m\u001b[33m\"\u001b[39m, \u001b[33m\"\u001b[39m\u001b[33mProduct - Isin\u001b[39m\u001b[33m\"\u001b[39m, \u001b[33m\"\u001b[39m\u001b[33mCentralisation Date\u001b[39m\u001b[33m\"\u001b[39m],\n\u001b[32m 30\u001b[39m how=\u001b[33m\"\u001b[39m\u001b[33mleft\u001b[39m\u001b[33m\"\u001b[39m\n\u001b[32m 31\u001b[39m )\n",
|
||
"\u001b[36mFile \u001b[39m\u001b[32m/opt/python/lib/python3.13/site-packages/pandas/core/frame.py:4119\u001b[39m, in \u001b[36mDataFrame.__getitem__\u001b[39m\u001b[34m(self, key)\u001b[39m\n\u001b[32m 4117\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m is_iterator(key):\n\u001b[32m 4118\u001b[39m key = \u001b[38;5;28mlist\u001b[39m(key)\n\u001b[32m-> \u001b[39m\u001b[32m4119\u001b[39m indexer = \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mcolumns\u001b[49m\u001b[43m.\u001b[49m\u001b[43m_get_indexer_strict\u001b[49m\u001b[43m(\u001b[49m\u001b[43mkey\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mcolumns\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m)\u001b[49m[\u001b[32m1\u001b[39m]\n\u001b[32m 4121\u001b[39m \u001b[38;5;66;03m# take() does not accept boolean indexers\u001b[39;00m\n\u001b[32m 4122\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mgetattr\u001b[39m(indexer, \u001b[33m\"\u001b[39m\u001b[33mdtype\u001b[39m\u001b[33m\"\u001b[39m, \u001b[38;5;28;01mNone\u001b[39;00m) == \u001b[38;5;28mbool\u001b[39m:\n",
|
||
"\u001b[36mFile \u001b[39m\u001b[32m/opt/python/lib/python3.13/site-packages/pandas/core/indexes/base.py:6212\u001b[39m, in \u001b[36mIndex._get_indexer_strict\u001b[39m\u001b[34m(self, key, axis_name)\u001b[39m\n\u001b[32m 6209\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[32m 6210\u001b[39m keyarr, indexer, new_indexer = \u001b[38;5;28mself\u001b[39m._reindex_non_unique(keyarr)\n\u001b[32m-> \u001b[39m\u001b[32m6212\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m_raise_if_missing\u001b[49m\u001b[43m(\u001b[49m\u001b[43mkeyarr\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mindexer\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43maxis_name\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 6214\u001b[39m keyarr = \u001b[38;5;28mself\u001b[39m.take(indexer)\n\u001b[32m 6215\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(key, Index):\n\u001b[32m 6216\u001b[39m \u001b[38;5;66;03m# GH 42790 - Preserve name from an Index\u001b[39;00m\n",
|
||
"\u001b[36mFile \u001b[39m\u001b[32m/opt/python/lib/python3.13/site-packages/pandas/core/indexes/base.py:6264\u001b[39m, in \u001b[36mIndex._raise_if_missing\u001b[39m\u001b[34m(self, key, indexer, axis_name)\u001b[39m\n\u001b[32m 6261\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mKeyError\u001b[39;00m(\u001b[33mf\u001b[39m\u001b[33m\"\u001b[39m\u001b[33mNone of [\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mkey\u001b[38;5;132;01m}\u001b[39;00m\u001b[33m] are in the [\u001b[39m\u001b[38;5;132;01m{\u001b[39;00maxis_name\u001b[38;5;132;01m}\u001b[39;00m\u001b[33m]\u001b[39m\u001b[33m\"\u001b[39m)\n\u001b[32m 6263\u001b[39m not_found = \u001b[38;5;28mlist\u001b[39m(ensure_index(key)[missing_mask.nonzero()[\u001b[32m0\u001b[39m]].unique())\n\u001b[32m-> \u001b[39m\u001b[32m6264\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mKeyError\u001b[39;00m(\u001b[33mf\u001b[39m\u001b[33m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mnot_found\u001b[38;5;132;01m}\u001b[39;00m\u001b[33m not in index\u001b[39m\u001b[33m\"\u001b[39m)\n",
|
||
"\u001b[31mKeyError\u001b[39m: \"['corrected_aum'] not in index\""
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"import pandas as pd\n",
|
||
"import numpy as np\n",
|
||
"\n",
|
||
"# ============================================================\n",
|
||
"# Rebuild STOCKS dataset using repaired AUM quantities\n",
|
||
"# ============================================================\n",
|
||
"\n",
|
||
"# 1. Copy original stocks\n",
|
||
"stocks_repaired = stocks.copy()\n",
|
||
"stocks_repaired[\"Centralisation Date\"] = pd.to_datetime(\n",
|
||
" stocks_repaired[\"Centralisation Date\"]\n",
|
||
")\n",
|
||
"\n",
|
||
"# 2. Build repair map\n",
|
||
"repair_map = (\n",
|
||
" df[[\n",
|
||
" \"Registrar Account - ID\",\n",
|
||
" \"Product - Isin\",\n",
|
||
" \"Centralisation Date\",\n",
|
||
" \"corrected_aum\",\n",
|
||
" \"repair_flag\"\n",
|
||
" ]]\n",
|
||
" .rename(columns={\"corrected_aum\": \"Quantity - AUM repaired\"})\n",
|
||
")\n",
|
||
"\n",
|
||
"# 3. Merge repaired quantities\n",
|
||
"stocks_repaired = stocks_repaired.merge(\n",
|
||
" repair_map,\n",
|
||
" on=[\"Registrar Account - ID\", \"Product - Isin\", \"Centralisation Date\"],\n",
|
||
" how=\"left\"\n",
|
||
")\n",
|
||
"\n",
|
||
"# 4. Store original quantity\n",
|
||
"stocks_repaired[\"Quantity - AUM original\"] = stocks_repaired[\"Quantity - AUM\"]\n",
|
||
"\n",
|
||
"# 5. Replace Quantity - AUM where repaired\n",
|
||
"stocks_repaired[\"Quantity - AUM\"] = np.where(\n",
|
||
" stocks_repaired[\"repair_flag\"] == True,\n",
|
||
" stocks_repaired[\"Quantity - AUM repaired\"],\n",
|
||
" stocks_repaired[\"Quantity - AUM\"]\n",
|
||
")\n",
|
||
"\n",
|
||
"# 6. Recompute monetary values (unit value unchanged)\n",
|
||
"stocks_repaired[\"nav_ccy\"] = (\n",
|
||
" stocks_repaired[\"Value - AUM CCY\"] /\n",
|
||
" stocks_repaired[\"Quantity - AUM original\"]\n",
|
||
")\n",
|
||
"\n",
|
||
"stocks_repaired[\"nav_eur\"] = (\n",
|
||
" stocks_repaired[\"Value - AUM €\"] /\n",
|
||
" stocks_repaired[\"Quantity - AUM original\"]\n",
|
||
")\n",
|
||
"\n",
|
||
"stocks_repaired[\"Value - AUM CCY\"] = (\n",
|
||
" stocks_repaired[\"Quantity - AUM\"] *\n",
|
||
" stocks_repaired[\"nav_ccy\"]\n",
|
||
")\n",
|
||
"\n",
|
||
"stocks_repaired[\"Value - AUM €\"] = (\n",
|
||
" stocks_repaired[\"Quantity - AUM\"] *\n",
|
||
" stocks_repaired[\"nav_eur\"]\n",
|
||
")\n",
|
||
"\n",
|
||
"# 7. Cleanup helper columns\n",
|
||
"stocks_repaired = stocks_repaired.drop(\n",
|
||
" columns=[\n",
|
||
" \"Quantity - AUM repaired\",\n",
|
||
" \"Quantity - AUM original\",\n",
|
||
" \"nav_ccy\",\n",
|
||
" \"nav_eur\"\n",
|
||
" ]\n",
|
||
")\n",
|
||
"\n",
|
||
"# ============================================================\n",
|
||
"# Sanity checks (CORRECT WAY)\n",
|
||
"# ============================================================\n",
|
||
"\n",
|
||
"# Share of observations repaired\n",
|
||
"repair_share = stocks_repaired[\"repair_flag\"].mean()\n",
|
||
"\n",
|
||
"# Ensure only repaired points were modified\n",
|
||
"n_modified = stocks_repaired[\"repair_flag\"].sum()\n",
|
||
"\n",
|
||
"print(f\"Share of repaired observations: {repair_share:.4%}\")\n",
|
||
"print(f\"Number of repaired rows: {n_modified:,}\")\n",
|
||
"\n",
|
||
"stocks_repaired.to_csv('AUM_repaired.csv')"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "5f262605-49e8-4304-b11e-38c8bcfc6e3f",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"print(stocks[\"Registrar Account - ID\"].nunique())\n",
|
||
"print(df[\"Registrar Account - ID\"].nunique())"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "37e9b599-aa51-4e03-b23c-2dd24e77fe38",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"import pandas as pd\n",
|
||
"\n",
|
||
"df = pd.read_csv(\"AUM_repaired.csv\")\n",
|
||
"\n",
|
||
"print(df.columns)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 20,
|
||
"id": "5cfb4526-7435-4e4a-ae48-0a8d40e39d81",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"/tmp/ipykernel_1311/55327206.py:8: DtypeWarning:\n",
|
||
"\n",
|
||
"Columns (1,2,3,4) have mixed types. Specify dtype option on import or set low_memory=False.\n",
|
||
"\n",
|
||
"/tmp/ipykernel_1311/55327206.py:9: DtypeWarning:\n",
|
||
"\n",
|
||
"Columns (2,3,4,5) have mixed types. Specify dtype option on import or set low_memory=False.\n",
|
||
"\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Merged dataset size: (9033269, 6)\n",
|
||
"\n",
|
||
"NUMBER OF MODIFIED OBSERVATIONS: 2263602\n",
|
||
"Share modified: 25.06 %\n",
|
||
"\n",
|
||
"NEGATIVE AUM\n",
|
||
"Before repair: 34374\n",
|
||
"After repair : 36320\n",
|
||
"\n",
|
||
"RAW AUM DISTRIBUTION\n",
|
||
"count 9.033269e+06\n",
|
||
"mean 9.106935e+03\n",
|
||
"std 1.915018e+05\n",
|
||
"min -9.918641e+06\n",
|
||
"25% 0.000000e+00\n",
|
||
"50% 0.000000e+00\n",
|
||
"75% 3.091340e+02\n",
|
||
"max 4.256300e+07\n",
|
||
"Name: Quantity - AUM_raw, dtype: float64\n",
|
||
"\n",
|
||
"REPAIRED AUM DISTRIBUTION\n",
|
||
"count 9.033269e+06\n",
|
||
"mean 9.104329e+03\n",
|
||
"std 1.914988e+05\n",
|
||
"min -9.918641e+06\n",
|
||
"25% 0.000000e+00\n",
|
||
"50% 0.000000e+00\n",
|
||
"75% 3.088430e+02\n",
|
||
"max 4.256300e+07\n",
|
||
"Name: Quantity - AUM_repaired, dtype: float64\n",
|
||
"\n",
|
||
"TOTAL AUM\n",
|
||
"Raw total : 82265397351.45718\n",
|
||
"Repaired total : 82241848877.5126\n",
|
||
"\n",
|
||
"TOP 20 AUM CHANGES\n",
|
||
" Registrar Account - ID Product - Isin Centralisation Date \\\n",
|
||
"8532368 OFF DISTRIBUTION LU0992627611 2021-12-31 \n",
|
||
"8532369 OFF DISTRIBUTION LU0992627611 2021-12-31 \n",
|
||
"8532370 OFF DISTRIBUTION LU0992627611 2021-12-31 \n",
|
||
"8477988 OFF DISTRIBUTION LU0992627611 2021-12-31 \n",
|
||
"8477987 OFF DISTRIBUTION LU0992627611 2021-12-31 \n",
|
||
"8477986 OFF DISTRIBUTION LU0992627611 2021-12-31 \n",
|
||
"8477989 OFF DISTRIBUTION LU0992627611 2021-12-31 \n",
|
||
"8532371 OFF DISTRIBUTION LU0992627611 2021-12-31 \n",
|
||
"8477994 OFF DISTRIBUTION LU0992627611 2021-12-31 \n",
|
||
"8477996 OFF DISTRIBUTION LU0992627611 2021-12-31 \n",
|
||
"8477997 OFF DISTRIBUTION LU0992627611 2021-12-31 \n",
|
||
"8928641 OFF DISTRIBUTION LU0992627611 2021-12-31 \n",
|
||
"8928642 OFF DISTRIBUTION LU0992627611 2021-12-31 \n",
|
||
"8928643 OFF DISTRIBUTION LU0992627611 2021-12-31 \n",
|
||
"8928644 OFF DISTRIBUTION LU0992627611 2021-12-31 \n",
|
||
"8477995 OFF DISTRIBUTION LU0992627611 2021-12-31 \n",
|
||
"8532359 OFF DISTRIBUTION LU0992627611 2021-11-30 \n",
|
||
"8713983 OFF DISTRIBUTION LU0992627611 2021-11-30 \n",
|
||
"8713984 OFF DISTRIBUTION LU0992627611 2021-11-30 \n",
|
||
"8532357 OFF DISTRIBUTION LU0992627611 2021-11-30 \n",
|
||
"\n",
|
||
" Quantity - AUM_raw Quantity - AUM_repaired aum_diff \n",
|
||
"8532368 41251.971 5298781.613 5257529.642 \n",
|
||
"8532369 41251.971 5298781.613 5257529.642 \n",
|
||
"8532370 41251.971 5298781.613 5257529.642 \n",
|
||
"8477988 5298781.613 41251.971 -5257529.642 \n",
|
||
"8477987 5298781.613 41251.971 -5257529.642 \n",
|
||
"8477986 5298781.613 41251.971 -5257529.642 \n",
|
||
"8477989 5298781.613 41251.971 -5257529.642 \n",
|
||
"8532371 41251.971 5298781.613 5257529.642 \n",
|
||
"8477994 5298781.613 128141.894 -5170639.719 \n",
|
||
"8477996 5298781.613 128141.894 -5170639.719 \n",
|
||
"8477997 5298781.613 128141.894 -5170639.719 \n",
|
||
"8928641 128141.894 5298781.613 5170639.719 \n",
|
||
"8928642 128141.894 5298781.613 5170639.719 \n",
|
||
"8928643 128141.894 5298781.613 5170639.719 \n",
|
||
"8928644 128141.894 5298781.613 5170639.719 \n",
|
||
"8477995 5298781.613 128141.894 -5170639.719 \n",
|
||
"8532359 41251.971 5059704.980 5018453.009 \n",
|
||
"8713983 5059704.980 41251.971 -5018453.009 \n",
|
||
"8713984 5059704.980 41251.971 -5018453.009 \n",
|
||
"8532357 41251.971 5059704.980 5018453.009 \n",
|
||
"\n",
|
||
"ISIN WITH MOST MODIFICATIONS\n",
|
||
"Product - Isin\n",
|
||
"LU1623762769 0.535539\n",
|
||
"LU2490324410 0.525588\n",
|
||
"FR0013516044 0.524862\n",
|
||
"LU2931971050 0.500000\n",
|
||
"LU2931971217 0.500000\n",
|
||
"FR001400TVB3 0.500000\n",
|
||
"FR001400TU23 0.500000\n",
|
||
"FR00140139F6 0.500000\n",
|
||
"FR001400TVD9 0.500000\n",
|
||
"LU2931971134 0.500000\n",
|
||
"Name: aum_diff, dtype: float64\n",
|
||
"\n",
|
||
"REPAIR FLAG ERRORS: 2260454\n",
|
||
"\n",
|
||
"==============================\n",
|
||
"COMPARISON COMPLETED\n",
|
||
"==============================\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"import pandas as pd\n",
|
||
"import numpy as np\n",
|
||
"\n",
|
||
"# ============================================================\n",
|
||
"# LOAD DATA\n",
|
||
"# ============================================================\n",
|
||
"\n",
|
||
"aum_raw = pd.read_csv(\"stocks.csv\") # fichier original\n",
|
||
"aum_rep = pd.read_csv(\"AUM_repaired.csv\") # fichier réparé\n",
|
||
"\n",
|
||
"aum_raw[\"Centralisation Date\"] = pd.to_datetime(aum_raw[\"Centralisation Date\"])\n",
|
||
"aum_rep[\"Centralisation Date\"] = pd.to_datetime(aum_rep[\"Centralisation Date\"])\n",
|
||
"\n",
|
||
"\n",
|
||
"# ============================================================\n",
|
||
"# KEEP SAME KEYS\n",
|
||
"# ============================================================\n",
|
||
"\n",
|
||
"keys = [\n",
|
||
" \"Registrar Account - ID\",\n",
|
||
" \"Product - Isin\",\n",
|
||
" \"Centralisation Date\"\n",
|
||
"]\n",
|
||
"\n",
|
||
"aum_raw = aum_raw[keys + [\"Quantity - AUM\"]]\n",
|
||
"aum_rep = aum_rep[keys + [\"Quantity - AUM\", \"repair_flag\"]]\n",
|
||
"\n",
|
||
"\n",
|
||
"# ============================================================\n",
|
||
"# MERGE DATASETS\n",
|
||
"# ============================================================\n",
|
||
"\n",
|
||
"df = aum_raw.merge(\n",
|
||
" aum_rep,\n",
|
||
" on=keys,\n",
|
||
" how=\"inner\",\n",
|
||
" suffixes=(\"_raw\", \"_repaired\")\n",
|
||
")\n",
|
||
"\n",
|
||
"print(\"Merged dataset size:\", df.shape)\n",
|
||
"\n",
|
||
"\n",
|
||
"# ============================================================\n",
|
||
"# 1. HOW MANY VALUES CHANGED\n",
|
||
"# ============================================================\n",
|
||
"\n",
|
||
"df[\"aum_diff\"] = df[\"Quantity - AUM_repaired\"] - df[\"Quantity - AUM_raw\"]\n",
|
||
"\n",
|
||
"n_changed = (df[\"aum_diff\"] != 0).sum()\n",
|
||
"\n",
|
||
"print(\"\\nNUMBER OF MODIFIED OBSERVATIONS:\", n_changed)\n",
|
||
"print(\"Share modified:\", round(n_changed / len(df) * 100, 2), \"%\")\n",
|
||
"\n",
|
||
"\n",
|
||
"# ============================================================\n",
|
||
"# 2. NEGATIVE AUM BEFORE / AFTER\n",
|
||
"# ============================================================\n",
|
||
"\n",
|
||
"neg_before = (df[\"Quantity - AUM_raw\"] < 0).sum()\n",
|
||
"neg_after = (df[\"Quantity - AUM_repaired\"] < 0).sum()\n",
|
||
"\n",
|
||
"print(\"\\nNEGATIVE AUM\")\n",
|
||
"print(\"Before repair:\", neg_before)\n",
|
||
"print(\"After repair :\", neg_after)\n",
|
||
"\n",
|
||
"\n",
|
||
"# ============================================================\n",
|
||
"# 3. DISTRIBUTION COMPARISON\n",
|
||
"# ============================================================\n",
|
||
"\n",
|
||
"print(\"\\nRAW AUM DISTRIBUTION\")\n",
|
||
"print(df[\"Quantity - AUM_raw\"].describe())\n",
|
||
"\n",
|
||
"print(\"\\nREPAIRED AUM DISTRIBUTION\")\n",
|
||
"print(df[\"Quantity - AUM_repaired\"].describe())\n",
|
||
"\n",
|
||
"\n",
|
||
"# ============================================================\n",
|
||
"# 4. TOTAL AUM COMPARISON\n",
|
||
"# ============================================================\n",
|
||
"\n",
|
||
"print(\"\\nTOTAL AUM\")\n",
|
||
"\n",
|
||
"print(\"Raw total :\", df[\"Quantity - AUM_raw\"].sum())\n",
|
||
"print(\"Repaired total :\", df[\"Quantity - AUM_repaired\"].sum())\n",
|
||
"\n",
|
||
"\n",
|
||
"# ============================================================\n",
|
||
"# 5. LARGEST MODIFICATIONS\n",
|
||
"# ============================================================\n",
|
||
"\n",
|
||
"largest_changes = df.sort_values(\n",
|
||
" \"aum_diff\",\n",
|
||
" key=lambda x: x.abs(),\n",
|
||
" ascending=False\n",
|
||
").head(20)\n",
|
||
"\n",
|
||
"print(\"\\nTOP 20 AUM CHANGES\")\n",
|
||
"\n",
|
||
"print(\n",
|
||
" largest_changes[\n",
|
||
" [\n",
|
||
" \"Registrar Account - ID\",\n",
|
||
" \"Product - Isin\",\n",
|
||
" \"Centralisation Date\",\n",
|
||
" \"Quantity - AUM_raw\",\n",
|
||
" \"Quantity - AUM_repaired\",\n",
|
||
" \"aum_diff\"\n",
|
||
" ]\n",
|
||
" ]\n",
|
||
")\n",
|
||
"\n",
|
||
"\n",
|
||
"# ============================================================\n",
|
||
"# 6. WHICH ISIN WERE MOST MODIFIED\n",
|
||
"# ============================================================\n",
|
||
"\n",
|
||
"isin_changes = (\n",
|
||
" df.groupby(\"Product - Isin\")[\"aum_diff\"]\n",
|
||
" .apply(lambda x: (x != 0).mean())\n",
|
||
" .sort_values(ascending=False)\n",
|
||
" .head(10)\n",
|
||
")\n",
|
||
"\n",
|
||
"print(\"\\nISIN WITH MOST MODIFICATIONS\")\n",
|
||
"print(isin_changes)\n",
|
||
"\n",
|
||
"\n",
|
||
"# ============================================================\n",
|
||
"# 7. CHECK REPAIR FLAG CONSISTENCY\n",
|
||
"# ============================================================\n",
|
||
"\n",
|
||
"if \"repair_flag\" in df.columns:\n",
|
||
"\n",
|
||
" repair_flag_errors = (\n",
|
||
" (df[\"repair_flag\"] == False) &\n",
|
||
" (df[\"Quantity - AUM_raw\"] != df[\"Quantity - AUM_repaired\"])\n",
|
||
" ).sum()\n",
|
||
"\n",
|
||
" print(\"\\nREPAIR FLAG ERRORS:\", repair_flag_errors)\n",
|
||
"\n",
|
||
"\n",
|
||
"print(\"\\n==============================\")\n",
|
||
"print(\"COMPARISON COMPLETED\")\n",
|
||
"print(\"==============================\")"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 48,
|
||
"id": "976dd82c-5c16-44e6-aa5d-65d085714b25",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"/tmp/ipykernel_1311/1498669893.py:8: DtypeWarning:\n",
|
||
"\n",
|
||
"Columns (2,3,4,5) have mixed types. Specify dtype option on import or set low_memory=False.\n",
|
||
"\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"import pandas as pd\n",
|
||
"import numpy as np\n",
|
||
"import plotly.graph_objects as go\n",
|
||
"\n",
|
||
"# ============================================================\n",
|
||
"# 1. LOAD DATA\n",
|
||
"# ============================================================\n",
|
||
"aum = pd.read_csv(\"AUM_repaired.csv\")\n",
|
||
"\n",
|
||
"flows[\"Centralisation Date\"] = pd.to_datetime(flows[\"Centralisation Date\"])\n",
|
||
"aum[\"Centralisation Date\"] = pd.to_datetime(aum[\"Centralisation Date\"])"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 49,
|
||
"id": "66c011b5-aed1-428e-bd18-44d8d814c283",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"application/vnd.plotly.v1+json": {
|
||
"config": {
|
||
"plotlyServerURL": "https://plot.ly"
|
||
},
|
||
"data": [
|
||
{
|
||
"hole": 0.45,
|
||
"hoverinfo": "label+percent",
|
||
"labels": [
|
||
"Clean / quasi-clean (≤1%)",
|
||
"Moderate (1–10%)",
|
||
"High (10–30%)",
|
||
"Severe (>30%)"
|
||
],
|
||
"textinfo": "percent",
|
||
"type": "pie",
|
||
"values": {
|
||
"bdata": "mpmZmZlZR0BmZmZmZmY7QM3MzMzMzCpAAAAAAAAAKUA=",
|
||
"dtype": "f8"
|
||
}
|
||
}
|
||
],
|
||
"layout": {
|
||
"legend": {
|
||
"orientation": "h",
|
||
"title": {
|
||
"text": "Rupture ratio"
|
||
},
|
||
"x": 0.5,
|
||
"xanchor": "center",
|
||
"y": -0.15,
|
||
"yanchor": "top"
|
||
},
|
||
"template": {
|
||
"data": {
|
||
"bar": [
|
||
{
|
||
"error_x": {
|
||
"color": "#2a3f5f"
|
||
},
|
||
"error_y": {
|
||
"color": "#2a3f5f"
|
||
},
|
||
"marker": {
|
||
"line": {
|
||
"color": "#E5ECF6",
|
||
"width": 0.5
|
||
},
|
||
"pattern": {
|
||
"fillmode": "overlay",
|
||
"size": 10,
|
||
"solidity": 0.2
|
||
}
|
||
},
|
||
"type": "bar"
|
||
}
|
||
],
|
||
"barpolar": [
|
||
{
|
||
"marker": {
|
||
"line": {
|
||
"color": "#E5ECF6",
|
||
"width": 0.5
|
||
},
|
||
"pattern": {
|
||
"fillmode": "overlay",
|
||
"size": 10,
|
||
"solidity": 0.2
|
||
}
|
||
},
|
||
"type": "barpolar"
|
||
}
|
||
],
|
||
"carpet": [
|
||
{
|
||
"aaxis": {
|
||
"endlinecolor": "#2a3f5f",
|
||
"gridcolor": "white",
|
||
"linecolor": "white",
|
||
"minorgridcolor": "white",
|
||
"startlinecolor": "#2a3f5f"
|
||
},
|
||
"baxis": {
|
||
"endlinecolor": "#2a3f5f",
|
||
"gridcolor": "white",
|
||
"linecolor": "white",
|
||
"minorgridcolor": "white",
|
||
"startlinecolor": "#2a3f5f"
|
||
},
|
||
"type": "carpet"
|
||
}
|
||
],
|
||
"choropleth": [
|
||
{
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
},
|
||
"type": "choropleth"
|
||
}
|
||
],
|
||
"contour": [
|
||
{
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
},
|
||
"colorscale": [
|
||
[
|
||
0,
|
||
"#0d0887"
|
||
],
|
||
[
|
||
0.1111111111111111,
|
||
"#46039f"
|
||
],
|
||
[
|
||
0.2222222222222222,
|
||
"#7201a8"
|
||
],
|
||
[
|
||
0.3333333333333333,
|
||
"#9c179e"
|
||
],
|
||
[
|
||
0.4444444444444444,
|
||
"#bd3786"
|
||
],
|
||
[
|
||
0.5555555555555556,
|
||
"#d8576b"
|
||
],
|
||
[
|
||
0.6666666666666666,
|
||
"#ed7953"
|
||
],
|
||
[
|
||
0.7777777777777778,
|
||
"#fb9f3a"
|
||
],
|
||
[
|
||
0.8888888888888888,
|
||
"#fdca26"
|
||
],
|
||
[
|
||
1,
|
||
"#f0f921"
|
||
]
|
||
],
|
||
"type": "contour"
|
||
}
|
||
],
|
||
"contourcarpet": [
|
||
{
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
},
|
||
"type": "contourcarpet"
|
||
}
|
||
],
|
||
"heatmap": [
|
||
{
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
},
|
||
"colorscale": [
|
||
[
|
||
0,
|
||
"#0d0887"
|
||
],
|
||
[
|
||
0.1111111111111111,
|
||
"#46039f"
|
||
],
|
||
[
|
||
0.2222222222222222,
|
||
"#7201a8"
|
||
],
|
||
[
|
||
0.3333333333333333,
|
||
"#9c179e"
|
||
],
|
||
[
|
||
0.4444444444444444,
|
||
"#bd3786"
|
||
],
|
||
[
|
||
0.5555555555555556,
|
||
"#d8576b"
|
||
],
|
||
[
|
||
0.6666666666666666,
|
||
"#ed7953"
|
||
],
|
||
[
|
||
0.7777777777777778,
|
||
"#fb9f3a"
|
||
],
|
||
[
|
||
0.8888888888888888,
|
||
"#fdca26"
|
||
],
|
||
[
|
||
1,
|
||
"#f0f921"
|
||
]
|
||
],
|
||
"type": "heatmap"
|
||
}
|
||
],
|
||
"histogram": [
|
||
{
|
||
"marker": {
|
||
"pattern": {
|
||
"fillmode": "overlay",
|
||
"size": 10,
|
||
"solidity": 0.2
|
||
}
|
||
},
|
||
"type": "histogram"
|
||
}
|
||
],
|
||
"histogram2d": [
|
||
{
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
},
|
||
"colorscale": [
|
||
[
|
||
0,
|
||
"#0d0887"
|
||
],
|
||
[
|
||
0.1111111111111111,
|
||
"#46039f"
|
||
],
|
||
[
|
||
0.2222222222222222,
|
||
"#7201a8"
|
||
],
|
||
[
|
||
0.3333333333333333,
|
||
"#9c179e"
|
||
],
|
||
[
|
||
0.4444444444444444,
|
||
"#bd3786"
|
||
],
|
||
[
|
||
0.5555555555555556,
|
||
"#d8576b"
|
||
],
|
||
[
|
||
0.6666666666666666,
|
||
"#ed7953"
|
||
],
|
||
[
|
||
0.7777777777777778,
|
||
"#fb9f3a"
|
||
],
|
||
[
|
||
0.8888888888888888,
|
||
"#fdca26"
|
||
],
|
||
[
|
||
1,
|
||
"#f0f921"
|
||
]
|
||
],
|
||
"type": "histogram2d"
|
||
}
|
||
],
|
||
"histogram2dcontour": [
|
||
{
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
},
|
||
"colorscale": [
|
||
[
|
||
0,
|
||
"#0d0887"
|
||
],
|
||
[
|
||
0.1111111111111111,
|
||
"#46039f"
|
||
],
|
||
[
|
||
0.2222222222222222,
|
||
"#7201a8"
|
||
],
|
||
[
|
||
0.3333333333333333,
|
||
"#9c179e"
|
||
],
|
||
[
|
||
0.4444444444444444,
|
||
"#bd3786"
|
||
],
|
||
[
|
||
0.5555555555555556,
|
||
"#d8576b"
|
||
],
|
||
[
|
||
0.6666666666666666,
|
||
"#ed7953"
|
||
],
|
||
[
|
||
0.7777777777777778,
|
||
"#fb9f3a"
|
||
],
|
||
[
|
||
0.8888888888888888,
|
||
"#fdca26"
|
||
],
|
||
[
|
||
1,
|
||
"#f0f921"
|
||
]
|
||
],
|
||
"type": "histogram2dcontour"
|
||
}
|
||
],
|
||
"mesh3d": [
|
||
{
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
},
|
||
"type": "mesh3d"
|
||
}
|
||
],
|
||
"parcoords": [
|
||
{
|
||
"line": {
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
}
|
||
},
|
||
"type": "parcoords"
|
||
}
|
||
],
|
||
"pie": [
|
||
{
|
||
"automargin": true,
|
||
"type": "pie"
|
||
}
|
||
],
|
||
"scatter": [
|
||
{
|
||
"fillpattern": {
|
||
"fillmode": "overlay",
|
||
"size": 10,
|
||
"solidity": 0.2
|
||
},
|
||
"type": "scatter"
|
||
}
|
||
],
|
||
"scatter3d": [
|
||
{
|
||
"line": {
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
}
|
||
},
|
||
"marker": {
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
}
|
||
},
|
||
"type": "scatter3d"
|
||
}
|
||
],
|
||
"scattercarpet": [
|
||
{
|
||
"marker": {
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
}
|
||
},
|
||
"type": "scattercarpet"
|
||
}
|
||
],
|
||
"scattergeo": [
|
||
{
|
||
"marker": {
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
}
|
||
},
|
||
"type": "scattergeo"
|
||
}
|
||
],
|
||
"scattergl": [
|
||
{
|
||
"marker": {
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
}
|
||
},
|
||
"type": "scattergl"
|
||
}
|
||
],
|
||
"scattermap": [
|
||
{
|
||
"marker": {
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
}
|
||
},
|
||
"type": "scattermap"
|
||
}
|
||
],
|
||
"scattermapbox": [
|
||
{
|
||
"marker": {
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
}
|
||
},
|
||
"type": "scattermapbox"
|
||
}
|
||
],
|
||
"scatterpolar": [
|
||
{
|
||
"marker": {
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
}
|
||
},
|
||
"type": "scatterpolar"
|
||
}
|
||
],
|
||
"scatterpolargl": [
|
||
{
|
||
"marker": {
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
}
|
||
},
|
||
"type": "scatterpolargl"
|
||
}
|
||
],
|
||
"scatterternary": [
|
||
{
|
||
"marker": {
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
}
|
||
},
|
||
"type": "scatterternary"
|
||
}
|
||
],
|
||
"surface": [
|
||
{
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
},
|
||
"colorscale": [
|
||
[
|
||
0,
|
||
"#0d0887"
|
||
],
|
||
[
|
||
0.1111111111111111,
|
||
"#46039f"
|
||
],
|
||
[
|
||
0.2222222222222222,
|
||
"#7201a8"
|
||
],
|
||
[
|
||
0.3333333333333333,
|
||
"#9c179e"
|
||
],
|
||
[
|
||
0.4444444444444444,
|
||
"#bd3786"
|
||
],
|
||
[
|
||
0.5555555555555556,
|
||
"#d8576b"
|
||
],
|
||
[
|
||
0.6666666666666666,
|
||
"#ed7953"
|
||
],
|
||
[
|
||
0.7777777777777778,
|
||
"#fb9f3a"
|
||
],
|
||
[
|
||
0.8888888888888888,
|
||
"#fdca26"
|
||
],
|
||
[
|
||
1,
|
||
"#f0f921"
|
||
]
|
||
],
|
||
"type": "surface"
|
||
}
|
||
],
|
||
"table": [
|
||
{
|
||
"cells": {
|
||
"fill": {
|
||
"color": "#EBF0F8"
|
||
},
|
||
"line": {
|
||
"color": "white"
|
||
}
|
||
},
|
||
"header": {
|
||
"fill": {
|
||
"color": "#C8D4E3"
|
||
},
|
||
"line": {
|
||
"color": "white"
|
||
}
|
||
},
|
||
"type": "table"
|
||
}
|
||
]
|
||
},
|
||
"layout": {
|
||
"annotationdefaults": {
|
||
"arrowcolor": "#2a3f5f",
|
||
"arrowhead": 0,
|
||
"arrowwidth": 1
|
||
},
|
||
"autotypenumbers": "strict",
|
||
"coloraxis": {
|
||
"colorbar": {
|
||
"outlinewidth": 0,
|
||
"ticks": ""
|
||
}
|
||
},
|
||
"colorscale": {
|
||
"diverging": [
|
||
[
|
||
0,
|
||
"#8e0152"
|
||
],
|
||
[
|
||
0.1,
|
||
"#c51b7d"
|
||
],
|
||
[
|
||
0.2,
|
||
"#de77ae"
|
||
],
|
||
[
|
||
0.3,
|
||
"#f1b6da"
|
||
],
|
||
[
|
||
0.4,
|
||
"#fde0ef"
|
||
],
|
||
[
|
||
0.5,
|
||
"#f7f7f7"
|
||
],
|
||
[
|
||
0.6,
|
||
"#e6f5d0"
|
||
],
|
||
[
|
||
0.7,
|
||
"#b8e186"
|
||
],
|
||
[
|
||
0.8,
|
||
"#7fbc41"
|
||
],
|
||
[
|
||
0.9,
|
||
"#4d9221"
|
||
],
|
||
[
|
||
1,
|
||
"#276419"
|
||
]
|
||
],
|
||
"sequential": [
|
||
[
|
||
0,
|
||
"#0d0887"
|
||
],
|
||
[
|
||
0.1111111111111111,
|
||
"#46039f"
|
||
],
|
||
[
|
||
0.2222222222222222,
|
||
"#7201a8"
|
||
],
|
||
[
|
||
0.3333333333333333,
|
||
"#9c179e"
|
||
],
|
||
[
|
||
0.4444444444444444,
|
||
"#bd3786"
|
||
],
|
||
[
|
||
0.5555555555555556,
|
||
"#d8576b"
|
||
],
|
||
[
|
||
0.6666666666666666,
|
||
"#ed7953"
|
||
],
|
||
[
|
||
0.7777777777777778,
|
||
"#fb9f3a"
|
||
],
|
||
[
|
||
0.8888888888888888,
|
||
"#fdca26"
|
||
],
|
||
[
|
||
1,
|
||
"#f0f921"
|
||
]
|
||
],
|
||
"sequentialminus": [
|
||
[
|
||
0,
|
||
"#0d0887"
|
||
],
|
||
[
|
||
0.1111111111111111,
|
||
"#46039f"
|
||
],
|
||
[
|
||
0.2222222222222222,
|
||
"#7201a8"
|
||
],
|
||
[
|
||
0.3333333333333333,
|
||
"#9c179e"
|
||
],
|
||
[
|
||
0.4444444444444444,
|
||
"#bd3786"
|
||
],
|
||
[
|
||
0.5555555555555556,
|
||
"#d8576b"
|
||
],
|
||
[
|
||
0.6666666666666666,
|
||
"#ed7953"
|
||
],
|
||
[
|
||
0.7777777777777778,
|
||
"#fb9f3a"
|
||
],
|
||
[
|
||
0.8888888888888888,
|
||
"#fdca26"
|
||
],
|
||
[
|
||
1,
|
||
"#f0f921"
|
||
]
|
||
]
|
||
},
|
||
"colorway": [
|
||
"#636efa",
|
||
"#EF553B",
|
||
"#00cc96",
|
||
"#ab63fa",
|
||
"#FFA15A",
|
||
"#19d3f3",
|
||
"#FF6692",
|
||
"#B6E880",
|
||
"#FF97FF",
|
||
"#FECB52"
|
||
],
|
||
"font": {
|
||
"color": "#2a3f5f"
|
||
},
|
||
"geo": {
|
||
"bgcolor": "white",
|
||
"lakecolor": "white",
|
||
"landcolor": "#E5ECF6",
|
||
"showlakes": true,
|
||
"showland": true,
|
||
"subunitcolor": "white"
|
||
},
|
||
"hoverlabel": {
|
||
"align": "left"
|
||
},
|
||
"hovermode": "closest",
|
||
"mapbox": {
|
||
"style": "light"
|
||
},
|
||
"paper_bgcolor": "white",
|
||
"plot_bgcolor": "#E5ECF6",
|
||
"polar": {
|
||
"angularaxis": {
|
||
"gridcolor": "white",
|
||
"linecolor": "white",
|
||
"ticks": ""
|
||
},
|
||
"bgcolor": "#E5ECF6",
|
||
"radialaxis": {
|
||
"gridcolor": "white",
|
||
"linecolor": "white",
|
||
"ticks": ""
|
||
}
|
||
},
|
||
"scene": {
|
||
"xaxis": {
|
||
"backgroundcolor": "#E5ECF6",
|
||
"gridcolor": "white",
|
||
"gridwidth": 2,
|
||
"linecolor": "white",
|
||
"showbackground": true,
|
||
"ticks": "",
|
||
"zerolinecolor": "white"
|
||
},
|
||
"yaxis": {
|
||
"backgroundcolor": "#E5ECF6",
|
||
"gridcolor": "white",
|
||
"gridwidth": 2,
|
||
"linecolor": "white",
|
||
"showbackground": true,
|
||
"ticks": "",
|
||
"zerolinecolor": "white"
|
||
},
|
||
"zaxis": {
|
||
"backgroundcolor": "#E5ECF6",
|
||
"gridcolor": "white",
|
||
"gridwidth": 2,
|
||
"linecolor": "white",
|
||
"showbackground": true,
|
||
"ticks": "",
|
||
"zerolinecolor": "white"
|
||
}
|
||
},
|
||
"shapedefaults": {
|
||
"line": {
|
||
"color": "#2a3f5f"
|
||
}
|
||
},
|
||
"ternary": {
|
||
"aaxis": {
|
||
"gridcolor": "white",
|
||
"linecolor": "white",
|
||
"ticks": ""
|
||
},
|
||
"baxis": {
|
||
"gridcolor": "white",
|
||
"linecolor": "white",
|
||
"ticks": ""
|
||
},
|
||
"bgcolor": "#E5ECF6",
|
||
"caxis": {
|
||
"gridcolor": "white",
|
||
"linecolor": "white",
|
||
"ticks": ""
|
||
}
|
||
},
|
||
"title": {
|
||
"x": 0.05
|
||
},
|
||
"xaxis": {
|
||
"automargin": true,
|
||
"gridcolor": "white",
|
||
"linecolor": "white",
|
||
"ticks": "",
|
||
"title": {
|
||
"standoff": 15
|
||
},
|
||
"zerolinecolor": "white",
|
||
"zerolinewidth": 2
|
||
},
|
||
"yaxis": {
|
||
"automargin": true,
|
||
"gridcolor": "white",
|
||
"linecolor": "white",
|
||
"ticks": "",
|
||
"title": {
|
||
"standoff": 15
|
||
},
|
||
"zerolinecolor": "white",
|
||
"zerolinewidth": 2
|
||
}
|
||
}
|
||
},
|
||
"title": {
|
||
"text": "Rupture intensity distribution (AUM repaired)"
|
||
}
|
||
}
|
||
},
|
||
"image/png": "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"
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
}
|
||
],
|
||
"source": [
|
||
"# ============================================================\n",
|
||
"# 2. PREPARE FLOWS\n",
|
||
"# ============================================================\n",
|
||
"\n",
|
||
"flows_clean = (\n",
|
||
" flows\n",
|
||
" .groupby(\n",
|
||
" [\"Registrar Account - ID\",\"Product - Isin\",\"Centralisation Date\"],\n",
|
||
" as_index=False\n",
|
||
" )[\"Quantity - NetFlows\"]\n",
|
||
" .sum()\n",
|
||
")\n",
|
||
"\n",
|
||
"# ============================================================\n",
|
||
"# 3. MERGE\n",
|
||
"# ============================================================\n",
|
||
"\n",
|
||
"df = aum.merge(\n",
|
||
" flows_clean,\n",
|
||
" on=[\"Registrar Account - ID\",\"Product - Isin\",\"Centralisation Date\"],\n",
|
||
" how=\"left\"\n",
|
||
")\n",
|
||
"\n",
|
||
"df[\"Quantity - NetFlows\"] = df[\"Quantity - NetFlows\"].fillna(0)\n",
|
||
"\n",
|
||
"# ============================================================\n",
|
||
"# 4. SORT\n",
|
||
"# ============================================================\n",
|
||
"\n",
|
||
"df = df.sort_values(\n",
|
||
" [\"Registrar Account - ID\",\"Product - Isin\",\"Centralisation Date\"]\n",
|
||
")\n",
|
||
"\n",
|
||
"# ============================================================\n",
|
||
"# REBUILD ACCOUNTING IDENTITY WITH REPAIRED AUM\n",
|
||
"# ============================================================\n",
|
||
"\n",
|
||
"df[\"prev_aum\"] = df.groupby(\n",
|
||
" [\"Registrar Account - ID\",\"Product - Isin\"]\n",
|
||
")[\"Quantity - AUM\"].shift(1)\n",
|
||
"\n",
|
||
"df[\"prev_flow\"] = df.groupby(\n",
|
||
" [\"Registrar Account - ID\",\"Product - Isin\"]\n",
|
||
")[\"Quantity - NetFlows\"].shift(1).fillna(0)\n",
|
||
"\n",
|
||
"df[\"expected_aum\"] = df[\"prev_aum\"] + df[\"prev_flow\"]\n",
|
||
"\n",
|
||
"# ============================================================\n",
|
||
"# COMPUTE GAP\n",
|
||
"# ============================================================\n",
|
||
"\n",
|
||
"df[\"gap\"] = df[\"Quantity - AUM\"] - df[\"expected_aum\"]\n",
|
||
"df[\"gap_abs\"] = df[\"gap\"].abs()\n",
|
||
"\n",
|
||
"EPS = 10\n",
|
||
"\n",
|
||
"df[\"rupture_flag\"] = (\n",
|
||
" df[\"prev_aum\"].notna()\n",
|
||
" & (df[\"gap_abs\"] > EPS)\n",
|
||
")\n",
|
||
"# ============================================================\n",
|
||
"# 6. COMPUTE GAP\n",
|
||
"# ============================================================\n",
|
||
"\n",
|
||
"df[\"gap\"] = df[\"Quantity - AUM\"] - df[\"expected_aum\"]\n",
|
||
"df[\"gap_abs\"] = df[\"gap\"].abs()\n",
|
||
"\n",
|
||
"EPS = 10\n",
|
||
"\n",
|
||
"df[\"rupture_flag\"] = (\n",
|
||
" df[\"prev_aum\"].notna()\n",
|
||
" & (df[\"gap_abs\"] > EPS)\n",
|
||
")\n",
|
||
"\n",
|
||
"# ============================================================\n",
|
||
"# 7. BUILD RUPTURE SUMMARY\n",
|
||
"# ============================================================\n",
|
||
"\n",
|
||
"rupture_summary = (\n",
|
||
" df.groupby([\"Registrar Account - ID\",\"Product - Isin\"])\n",
|
||
" .agg(\n",
|
||
" n_ruptures=(\"rupture_flag\",\"sum\"),\n",
|
||
" total_obs=(\"rupture_flag\",\"count\"),\n",
|
||
" rupture_ratio=(\"rupture_flag\",\"mean\")\n",
|
||
" )\n",
|
||
" .reset_index()\n",
|
||
")\n",
|
||
"\n",
|
||
"# ============================================================\n",
|
||
"# 8. SAME CLASSIFICATION AS YOUR CODE\n",
|
||
"# ============================================================\n",
|
||
"\n",
|
||
"rs = rupture_summary.copy()\n",
|
||
"\n",
|
||
"bins = [0, 0.01, 0.10, 0.30, 1.01]\n",
|
||
"\n",
|
||
"labels = [\n",
|
||
" \"Clean / quasi-clean (≤1%)\",\n",
|
||
" \"Moderate (1–10%)\",\n",
|
||
" \"High (10–30%)\",\n",
|
||
" \"Severe (>30%)\"\n",
|
||
"]\n",
|
||
"\n",
|
||
"rs[\"rupture_class\"] = pd.cut(\n",
|
||
" rs[\"rupture_ratio\"],\n",
|
||
" bins=bins,\n",
|
||
" labels=labels,\n",
|
||
" include_lowest=True\n",
|
||
")\n",
|
||
"\n",
|
||
"# ============================================================\n",
|
||
"# 9. DISTRIBUTION\n",
|
||
"# ============================================================\n",
|
||
"\n",
|
||
"dist = (\n",
|
||
" rs[\"rupture_class\"]\n",
|
||
" .value_counts(normalize=True)\n",
|
||
" .sort_index()\n",
|
||
" * 100\n",
|
||
").round(1)\n",
|
||
"\n",
|
||
"# ============================================================\n",
|
||
"# 10. DONUT CHART\n",
|
||
"# ============================================================\n",
|
||
"\n",
|
||
"fig = go.Figure(\n",
|
||
" data=[go.Pie(\n",
|
||
" labels=dist.index,\n",
|
||
" values=dist.values,\n",
|
||
" hole=0.45,\n",
|
||
" textinfo=\"percent\",\n",
|
||
" hoverinfo=\"label+percent\"\n",
|
||
" )]\n",
|
||
")\n",
|
||
"\n",
|
||
"fig.update_layout(\n",
|
||
" title=\"Rupture intensity distribution (AUM repaired)\",\n",
|
||
" legend=dict(\n",
|
||
" orientation=\"h\",\n",
|
||
" yanchor=\"top\",\n",
|
||
" y=-0.15,\n",
|
||
" xanchor=\"center\",\n",
|
||
" x=0.5\n",
|
||
" ),\n",
|
||
" legend_title_text=\"Rupture ratio\"\n",
|
||
")\n",
|
||
"\n",
|
||
"fig.show()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "990898ea-ceca-46bb-bfb3-c87bf289d272",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"import seaborn as sns\n",
|
||
"import matplotlib.pyplot as plt\n",
|
||
"\n",
|
||
"df = merged_isin.copy()\n",
|
||
"\n",
|
||
"# Ajouter année / mois\n",
|
||
"df[\"year\"] = df[\"Centralisation Date\"].dt.year\n",
|
||
"df[\"month\"] = df[\"Centralisation Date\"].dt.month\n",
|
||
"\n",
|
||
"# 1. Nombre total de lignes par mois\n",
|
||
"total = df.groupby([\"year\", \"month\"]).size().reset_index(name=\"total_lines\")\n",
|
||
"\n",
|
||
"# 2. Nombre de ruptures par mois\n",
|
||
"ruptures = df[df[\"rupture_flag\"]].groupby([\"year\", \"month\"]).size().reset_index(name=\"n_ruptures\")\n",
|
||
"\n",
|
||
"# 3. Merge pour obtenir total + ruptures\n",
|
||
"ratio = total.merge(ruptures, on=[\"year\",\"month\"], how=\"left\")\n",
|
||
"ratio[\"n_ruptures\"] = ratio[\"n_ruptures\"].fillna(0)\n",
|
||
"\n",
|
||
"# 4. Proportion (en %)\n",
|
||
"ratio[\"rupture_ratio\"] = ratio[\"n_ruptures\"] / ratio[\"total_lines\"]\n",
|
||
"\n",
|
||
"# 5. Pivot pour heatmap\n",
|
||
"heatmap_ratio = ratio.pivot(index=\"year\", columns=\"month\", values=\"rupture_ratio\").fillna(0)\n",
|
||
"\n",
|
||
"# 6. Plot\n",
|
||
"plt.figure(figsize=(14, 7))\n",
|
||
"sns.heatmap(\n",
|
||
" heatmap_ratio, \n",
|
||
" cmap=\"Reds\",\n",
|
||
" linewidths=.3,\n",
|
||
" linecolor=\"grey\",\n",
|
||
" annot=True,\n",
|
||
" fmt=\".2%\",\n",
|
||
" cbar_kws={'label': 'Proportion de ruptures'}\n",
|
||
")\n",
|
||
"\n",
|
||
"plt.title(\"Heatmap de la proportion de ruptures (par année et mois)\", fontsize=16)\n",
|
||
"plt.xlabel(\"Mois\")\n",
|
||
"plt.ylabel(\"Année\")\n",
|
||
"plt.show()\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "4d335589-c519-458d-857d-a051813b950b",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"df = merged_isin.copy()\n",
|
||
"\n",
|
||
"# Ajouter year / month au cas où\n",
|
||
"df[\"year\"] = df[\"Centralisation Date\"].dt.year\n",
|
||
"df[\"month\"] = df[\"Centralisation Date\"].dt.month\n",
|
||
"\n",
|
||
"# Merge géographique\n",
|
||
"df = df.merge(\n",
|
||
" geo[[\"Registrar Account - ID\", \"country\"]],\n",
|
||
" on=\"Registrar Account - ID\",\n",
|
||
" how=\"left\"\n",
|
||
")\n",
|
||
"\n",
|
||
"df[\"country\"] = df[\"country\"].fillna(\"UNKNOWN\")\n",
|
||
"\n",
|
||
"# Total des lignes par pays\n",
|
||
"total_country = df.groupby(\"country\").size().reset_index(name=\"total_obs\")\n",
|
||
"\n",
|
||
"# Nombre de ruptures\n",
|
||
"rupt_country = (\n",
|
||
" df[df[\"rupture_flag\"]]\n",
|
||
" .groupby(\"country\")\n",
|
||
" .size()\n",
|
||
" .reset_index(name=\"ruptures\")\n",
|
||
")\n",
|
||
"\n",
|
||
"# Merge + ratios\n",
|
||
"country_stats = total_country.merge(rupt_country, on=\"country\", how=\"left\")\n",
|
||
"country_stats[\"ruptures\"] = country_stats[\"ruptures\"].fillna(0)\n",
|
||
"country_stats[\"rupture_ratio\"] = country_stats[\"ruptures\"] / country_stats[\"total_obs\"]\n",
|
||
"\n",
|
||
"# Tri (rupture ratio décroissant)\n",
|
||
"country_stats = country_stats.sort_values(\"rupture_ratio\", ascending=False)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "8a45a111-25da-4f5c-9723-c3efd25c906d",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# On ajoute une colonne en % pour l’affichage\n",
|
||
"import plotly.express as px\n",
|
||
"\n",
|
||
"country_stats_plot = country_stats.copy()\n",
|
||
"country_stats_plot[\"rupture_pct\"] = country_stats_plot[\"rupture_ratio\"] * 100\n",
|
||
"\n",
|
||
"# Tri décroissant par proportion de ruptures\n",
|
||
"country_stats_plot = country_stats_plot.sort_values(\"rupture_ratio\", ascending=False)\n",
|
||
"\n",
|
||
"fig = px.bar(\n",
|
||
" country_stats_plot,\n",
|
||
" x=\"country\",\n",
|
||
" y=\"rupture_ratio\",\n",
|
||
" hover_data={\n",
|
||
" \"rupture_pct\": ':.2f',\n",
|
||
" \"ruptures\": True,\n",
|
||
" \"total_obs\": True,\n",
|
||
" \"rupture_ratio\": False, # on cache la version décimale\n",
|
||
" },\n",
|
||
" labels={\n",
|
||
" \"country\": \"Pays\",\n",
|
||
" \"rupture_ratio\": \"Proportion de ruptures\",\n",
|
||
" \"rupture_pct\": \"% de ruptures\",\n",
|
||
" \"ruptures\": \"Nb de ruptures\",\n",
|
||
" \"total_obs\": \"Nb d'observations\"\n",
|
||
" },\n",
|
||
" title=\"Proportion de ruptures par pays (avec volumes au survol)\"\n",
|
||
")\n",
|
||
"\n",
|
||
"# Format en %\n",
|
||
"fig.update_yaxes(tickformat=\".1%\")\n",
|
||
"\n",
|
||
"fig.update_layout(\n",
|
||
" xaxis_tickangle=-45,\n",
|
||
" bargap=0.2\n",
|
||
")\n",
|
||
"\n",
|
||
"fig.show()\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "a4af9841-6cf9-4d27-8096-ac878e866bc6",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"rs = rupture_summary.copy()\n",
|
||
"\n",
|
||
"# 1. Stats numériques classiques\n",
|
||
"print(\"\\n=== BASIC NUMERIC STATS ===\")\n",
|
||
"print(rs[\"rupture_ratio\"].describe(percentiles=[0.01, 0.05, 0.10, 0.25, 0.5, 0.75, 0.90, 0.95, 0.99]))\n",
|
||
"\n",
|
||
"\n",
|
||
"# 2. Distribution par classes (bins)\n",
|
||
"\n",
|
||
"rs[\"rupture_bucket\"] = pd.cut(\n",
|
||
" rs[\"rupture_ratio\"],\n",
|
||
" bins=[0, 0.001, 0.01, 0.05, 0.10, 0.25, 0.50, 1.01],\n",
|
||
" labels=[\n",
|
||
" \"0–0.1%\",\n",
|
||
" \"0.1–1%\",\n",
|
||
" \"1–5%\",\n",
|
||
" \"5–10%\",\n",
|
||
" \"10–25%\",\n",
|
||
" \"25–50%\",\n",
|
||
" \"50–100%\"\n",
|
||
" ],\n",
|
||
" include_lowest=True\n",
|
||
")\n",
|
||
"\n",
|
||
"# Ajouter la catégorie \"0%\"\n",
|
||
"rs[\"rupture_bucket\"] = rs[\"rupture_bucket\"].cat.add_categories(\"0%\")\n",
|
||
"\n",
|
||
"# Remplacer les 0% exacts\n",
|
||
"rs.loc[rs[\"rupture_ratio\"] == 0, \"rupture_bucket\"] = \"0%\"\n",
|
||
"\n",
|
||
"bucket_counts = rs[\"rupture_bucket\"].value_counts().sort_index()\n",
|
||
"print(bucket_counts)\n",
|
||
"\n",
|
||
"\n",
|
||
"# 3. Pourcentages\n",
|
||
"bucket_percent = (bucket_counts / len(rs) * 100).round(2)\n",
|
||
"\n",
|
||
"print(\"\\n=== DISTRIBUTION (PERCENT) ===\")\n",
|
||
"print(bucket_percent)\n",
|
||
"\n",
|
||
"\n",
|
||
"# 4. Nombre de comptes totalement propres\n",
|
||
"no_rupture = (rs[\"n_ruptures\"] == 0).sum()\n",
|
||
"print(f\"\\nComptes avec 0 rupture = {no_rupture} ({no_rupture/len(rs)*100:.2f}%)\")\n",
|
||
"\n",
|
||
"# 5. Comptes extrêmement problématiques\n",
|
||
"severe = (rs[\"rupture_ratio\"] > 0.75).sum()\n",
|
||
"print(f\"Comptes avec rupture_ratio > 75% = {severe} ({severe/len(rs)*100:.2f}%)\")\n",
|
||
"\n",
|
||
"medium = (rs[\"rupture_ratio\"] > 0.10).sum()\n",
|
||
"print(f\"Comptes avec rupture_ratio > 10% = {medium} ({medium/len(rs)*100:.2f}%)\")\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "f39a9a5a-5f4e-4cac-9f63-e6952582b6ff",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"import plotly.express as px\n",
|
||
"\n",
|
||
"fig = px.histogram(\n",
|
||
" rs,\n",
|
||
" x=\"rupture_ratio\",\n",
|
||
" nbins=50,\n",
|
||
" title=\"Distribution du rupture_ratio\",\n",
|
||
" labels={\"rupture_ratio\": \"Rupture Ratio\"},\n",
|
||
")\n",
|
||
"fig.update_layout(bargap=0.05)\n",
|
||
"fig.show()\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "70132995-8379-44b6-8ff6-f09524c4e4d0",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# --- 1. Filtres de base ---\n",
|
||
"merged[\"year\"] = merged[\"Centralisation Date\"].dt.year\n",
|
||
"\n",
|
||
"# Filtrer uniquement l'année 2021\n",
|
||
"ruptures_2021 = merged[(merged[\"year\"] == 2021) & (merged[\"rupture_flag\"] == True)].copy()\n",
|
||
"\n",
|
||
"print(\"Nombre total de ruptures en 2021 :\", len(ruptures_2021))\n",
|
||
"\n",
|
||
"# --- 2. Classification du type de gap ---\n",
|
||
"ruptures_2021[\"gap_type\"] = np.where(ruptures_2021[\"gap\"] > 0, \"positive\", \"negative\")\n",
|
||
"\n",
|
||
"# --- 3. Statistiques globales ---\n",
|
||
"gap_counts = ruptures_2021[\"gap_type\"].value_counts()\n",
|
||
"gap_percent = ruptures_2021[\"gap_type\"].value_counts(normalize=True) * 100\n",
|
||
"\n",
|
||
"print(\"\\n=== RUPTURES 2021 — POSITIVES vs NEGATIVES ===\")\n",
|
||
"print(gap_counts)\n",
|
||
"print(\"\\n(%)\")\n",
|
||
"print(gap_percent.map(lambda x: f\"{x:.2f}%\"))\n",
|
||
"\n",
|
||
"# --- 4. Intensité des écarts ---\n",
|
||
"intensity_stats = ruptures_2021.groupby(\"gap_type\")[\"gap\"].describe()\n",
|
||
"print(\"\\n=== STATISTIQUES DES GAPS ===\")\n",
|
||
"print(intensity_stats)\n",
|
||
"\n",
|
||
"# --- 5. Visualisation rapide ---\n",
|
||
"import seaborn as sns\n",
|
||
"import matplotlib.pyplot as plt\n",
|
||
"\n",
|
||
"plt.figure(figsize=(10,5))\n",
|
||
"sns.histplot(data=ruptures_2021, x=\"gap\", hue=\"gap_type\", bins=80, kde=True)\n",
|
||
"plt.xlim(-merged[\"gap\"].abs().max(), merged[\"gap\"].abs().max())\n",
|
||
"plt.title(\"Distribution des gaps de rupture en 2021\")\n",
|
||
"plt.xlabel(\"Gap (AUM_{t} − Expected AUM_{t})\")\n",
|
||
"plt.show()\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "1faf943a-4703-4b19-a867-2670ac3a5209",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# --- 1. ADD YEAR ---\n",
|
||
"merged[\"year\"] = merged[\"Centralisation Date\"].dt.year\n",
|
||
"\n",
|
||
"# --- 2. DEFINE PERIODS ---\n",
|
||
"conditions = [\n",
|
||
" merged[\"year\"] < 2021,\n",
|
||
" merged[\"year\"] == 2021,\n",
|
||
" merged[\"year\"] > 2021\n",
|
||
"]\n",
|
||
"\n",
|
||
"period_labels = [\"before_2021\", \"during_2021\", \"after_2021\"]\n",
|
||
"\n",
|
||
"merged[\"period\"] = np.select(\n",
|
||
" conditions,\n",
|
||
" period_labels,\n",
|
||
" default=\"unknown\"\n",
|
||
")\n",
|
||
"\n",
|
||
"# --- 3. CREATE GAP TYPE & FILTER ONLY RUPTURES ---\n",
|
||
"merged[\"gap_type\"] = np.where(\n",
|
||
" merged[\"gap\"] > 0, \"positive\",\n",
|
||
" np.where(merged[\"gap\"] < 0, \"negative\", \"zero\")\n",
|
||
")\n",
|
||
"\n",
|
||
"ruptures = merged[merged[\"rupture_flag\"] == True].copy()\n",
|
||
"\n",
|
||
"# --- 4. TOTAL OBS PER PERIOD ---\n",
|
||
"total_obs = merged.groupby(\"period\").size().rename(\"total_obs\")\n",
|
||
"\n",
|
||
"# --- 5. TOTAL RUPTURES PER PERIOD ---\n",
|
||
"rupture_counts = ruptures.groupby(\"period\").size().rename(\"rupture_count\")\n",
|
||
"\n",
|
||
"# --- 6. PROPORTION OF RUPTURES ---\n",
|
||
"rupture_ratio = (rupture_counts / total_obs).rename(\"rupture_ratio\")\n",
|
||
"\n",
|
||
"# --- 7. POSITIVE / NEGATIVE GAPS (% among ruptures) ---\n",
|
||
"gap_dist = (\n",
|
||
" ruptures.groupby([\"period\", \"gap_type\"])\n",
|
||
" .size()\n",
|
||
" .groupby(level=0)\n",
|
||
" .apply(lambda x: (x / x.sum()) * 100) # % par période\n",
|
||
")\n",
|
||
"\n",
|
||
"\n",
|
||
"# --- 8. MERGE AND DISPLAY ---\n",
|
||
"summary = pd.concat([total_obs, rupture_counts, rupture_ratio], axis=1)\n",
|
||
"summary[\"rupture_ratio\"] = (summary[\"rupture_ratio\"] * 100).round(2)\n",
|
||
"\n",
|
||
"print(\"\\n=== RUPTURE SUMMARY (in %) ===\")\n",
|
||
"print(summary)\n",
|
||
"\n",
|
||
"print(\"\\n=== GAP POSITIVE / NEGATIVE DISTRIBUTION (in %) ===\")\n",
|
||
"print(gap_dist)\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "5abee764-b890-4ea1-8f98-5a0ff1512611",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"from plotly.subplots import make_subplots\n",
|
||
"import plotly.graph_objects as go\n",
|
||
"\n",
|
||
"# --- 1. DEFINE PERIODS ---\n",
|
||
"merged[\"period2\"] = np.where(\n",
|
||
" merged[\"Centralisation Date\"] < pd.Timestamp(\"2021-09-01\"),\n",
|
||
" \"Before Sep 2021\",\n",
|
||
" \"After Sep 2021\"\n",
|
||
")\n",
|
||
"\n",
|
||
"ruptures = merged[merged[\"rupture_flag\"] == True].copy()\n",
|
||
"\n",
|
||
"# --- 2. Ensure gap_type exists + no missing categories ---\n",
|
||
"ruptures[\"gap_type\"] = ruptures[\"gap_type\"].replace({\"zero\": \"positive\"}) # zero is equivalent to no-flow change\n",
|
||
"\n",
|
||
"# --- 3. Compute gap counts ---\n",
|
||
"gap_counts = (\n",
|
||
" ruptures.groupby([\"period2\", \"gap_type\"])\n",
|
||
" .size()\n",
|
||
" .unstack(fill_value=0)\n",
|
||
")\n",
|
||
"\n",
|
||
"# Ensure both columns exist\n",
|
||
"for col in [\"positive\", \"negative\"]:\n",
|
||
" if col not in gap_counts.columns:\n",
|
||
" gap_counts[col] = 0\n",
|
||
"\n",
|
||
"gap_counts = gap_counts[[\"positive\", \"negative\"]]\n",
|
||
"\n",
|
||
"# --- 4. Extract values ---\n",
|
||
"before_vals = gap_counts.loc[\"Before Sep 2021\"].values\n",
|
||
"after_vals = gap_counts.loc[\"After Sep 2021\"].values\n",
|
||
"\n",
|
||
"# --- 5. MAKE TWO DONUT CHARTS ---\n",
|
||
"fig = make_subplots(\n",
|
||
" rows=1, cols=2,\n",
|
||
" specs=[[{\"type\": \"pie\"}, {\"type\": \"pie\"}]],\n",
|
||
" subplot_titles=(\"Before Sep 2021\", \"After Sep 2021\")\n",
|
||
")\n",
|
||
"\n",
|
||
"fig.add_trace(\n",
|
||
" go.Pie(\n",
|
||
" labels=[\"Negative gaps\", \"Positive gaps\"],\n",
|
||
" values=before_vals,\n",
|
||
" marker_colors=[\"#E67E22\", \"#3498DB\"],\n",
|
||
" hole=0.45,\n",
|
||
" textinfo=\"label+percent\"\n",
|
||
" ),\n",
|
||
" row=1, col=1\n",
|
||
")\n",
|
||
"\n",
|
||
"fig.add_trace(\n",
|
||
" go.Pie(\n",
|
||
" labels=[\"Negative gaps\", \"Positive gaps\"],\n",
|
||
" values=after_vals,\n",
|
||
" marker_colors=[\"#E67E22\", \"#3498DB\"],\n",
|
||
" hole=0.45,\n",
|
||
" textinfo=\"label+percent\"\n",
|
||
" ),\n",
|
||
" row=1, col=2\n",
|
||
")\n",
|
||
"\n",
|
||
"fig.update_layout(\n",
|
||
" title=\"Nature des ruptures (positive / negative)\\nAvant vs Après Septembre 2021\",\n",
|
||
" showlegend=True\n",
|
||
")\n",
|
||
"\n",
|
||
"fig.show()\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "3aa3b8a0-f499-495a-9171-2e09d0bb1e5f",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"import plotly.graph_objects as go\n",
|
||
"\n",
|
||
"# --- 1. Compute gap counts by period ---\n",
|
||
"gap_counts = (\n",
|
||
" ruptures.groupby([\"period2\", \"gap_type\"])\n",
|
||
" .size()\n",
|
||
" .unstack(fill_value=0)\n",
|
||
")\n",
|
||
"\n",
|
||
"# Ensure both columns exist\n",
|
||
"for col in [\"positive\", \"negative\"]:\n",
|
||
" if col not in gap_counts.columns:\n",
|
||
" gap_counts[col] = 0\n",
|
||
"\n",
|
||
"gap_counts = gap_counts[[\"positive\", \"negative\"]]\n",
|
||
"\n",
|
||
"# --- 2. Extract values ---\n",
|
||
"before_vals = gap_counts.loc[\"Before Sep 2021\"].values\n",
|
||
"after_vals = gap_counts.loc[\"After Sep 2021\"].values\n",
|
||
"\n",
|
||
"# --- 3. Plot : TWO PIE CHARTS side by side ---\n",
|
||
"fig = make_subplots(\n",
|
||
" rows=1, cols=2,\n",
|
||
" specs=[[{\"type\": \"pie\"}, {\"type\": \"pie\"}]],\n",
|
||
" subplot_titles=(\"Before 2021\", \"After 2021\")\n",
|
||
")\n",
|
||
"\n",
|
||
"fig.add_trace(\n",
|
||
" go.Pie(\n",
|
||
" labels=[\"Negative gaps\", \"Positive gaps\"],\n",
|
||
" values=before_vals,\n",
|
||
" marker_colors=[\"#E67E22\", \"#3498DB\"],\n",
|
||
" hole=0.35\n",
|
||
" ),\n",
|
||
" row=1, col=1\n",
|
||
")\n",
|
||
"\n",
|
||
"fig.add_trace(\n",
|
||
" go.Pie(\n",
|
||
" labels=[\"Negative gaps\", \"Positive gaps\"],\n",
|
||
" values=after_vals,\n",
|
||
" marker_colors=[\"#E67E22\", \"#3498DB\"],\n",
|
||
" hole=0.35\n",
|
||
" ),\n",
|
||
" row=1, col=2\n",
|
||
")\n",
|
||
"\n",
|
||
"fig.update_layout(\n",
|
||
" title=\"Répartition des ruptures (positive / negative)\\nAvant vs Après 2021\"\n",
|
||
")\n",
|
||
"\n",
|
||
"fig.show()\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "d4f0dc74-649d-4105-9a1a-44a18d126a3c",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"import plotly.graph_objects as go\n",
|
||
"\n",
|
||
"# --- 1. Define periods ---\n",
|
||
"merged[\"period2\"] = np.where(\n",
|
||
" merged[\"Centralisation Date\"] < pd.Timestamp(\"2021-09-01\"),\n",
|
||
" \"Before Sep 2021\",\n",
|
||
" \"After Sep 2021\"\n",
|
||
")\n",
|
||
"\n",
|
||
"# --- 2. Keep only ruptures ---\n",
|
||
"ruptures = merged[merged[\"rupture_flag\"] == True].copy()\n",
|
||
"\n",
|
||
"# --- 3. Count ruptures per period ---\n",
|
||
"rupture_counts = ruptures[\"period2\"].value_counts().reindex(\n",
|
||
" [\"Before Sep 2021\", \"After Sep 2021\"]\n",
|
||
").fillna(0)\n",
|
||
"\n",
|
||
"# --- 4. Pie chart ---\n",
|
||
"fig = go.Figure(data=[\n",
|
||
" go.Pie(\n",
|
||
" labels=rupture_counts.index,\n",
|
||
" values=rupture_counts.values,\n",
|
||
" hole=0.45,\n",
|
||
" marker_colors=[\"#2ECC71\", \"#E74C3C\"],\n",
|
||
" textinfo=\"percent+value\",\n",
|
||
" )\n",
|
||
"])\n",
|
||
"\n",
|
||
"fig.update_layout(\n",
|
||
" title=\"Répartition des ruptures\"\n",
|
||
")\n",
|
||
"\n",
|
||
"fig.show()\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "ecccd73c-00a6-4ff3-b213-e85b98ec5a55",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"import pandas as pd\n",
|
||
"import numpy as np\n",
|
||
"\n",
|
||
"# 1. Filtre sur la période post-Sept 2021\n",
|
||
"cutoff = pd.Timestamp(\"2021-09-01\")\n",
|
||
"post = merged[merged[\"Centralisation Date\"] >= cutoff].copy()\n",
|
||
"\n",
|
||
"# 2. On ne garde que les ruptures\n",
|
||
"post_rupt = post[post[\"rupture_flag\"] == True].copy()\n",
|
||
"\n",
|
||
"# 3. Gap absolu + gap relatif (% du stock)\n",
|
||
"post_rupt[\"gap_abs\"] = post_rupt[\"gap\"].abs()\n",
|
||
"post_rupt[\"gap_rel\"] = post_rupt[\"gap_abs\"] / post_rupt[\"Quantity - AUM\"].replace(0, np.nan)\n",
|
||
"\n",
|
||
"# 4. Percentiles globaux\n",
|
||
"p90 = post_rupt[\"gap_abs\"].quantile(0.90)\n",
|
||
"p95 = post_rupt[\"gap_abs\"].quantile(0.95)\n",
|
||
"p99 = post_rupt[\"gap_abs\"].quantile(0.99)\n",
|
||
"\n",
|
||
"# 5. Classification automatique\n",
|
||
"def classify_gap(gap, gap_rel, acct):\n",
|
||
" # RESET → énorme choc (technique)\n",
|
||
" if gap_abs >= p99 or gap_rel >= 0.90:\n",
|
||
" return \"reset\"\n",
|
||
"\n",
|
||
" # SPIKE → très gros gap mais isolé\n",
|
||
" if gap_abs >= p95:\n",
|
||
" return \"spike\"\n",
|
||
"\n",
|
||
" # SHIFT → décalage permanent\n",
|
||
" # Test : moyenne des gaps du compte\n",
|
||
" return None\n",
|
||
"\n",
|
||
"# Calcul du shift (décalage directionnel)\n",
|
||
"shift_info = post_rupt.groupby(\"Registrar Account - ID\")[\"gap\"].mean().rename(\"avg_gap\")\n",
|
||
"\n",
|
||
"post_rupt = post_rupt.merge(shift_info, on=\"Registrar Account - ID\", how=\"left\")\n",
|
||
"\n",
|
||
"post_rupt[\"gap_type2\"] = np.where(\n",
|
||
" post_rupt[\"gap_abs\"] >= p99, \"reset\",\n",
|
||
" np.where(post_rupt[\"gap_abs\"] >= p95, \"spike\",\n",
|
||
" np.where(post_rupt[\"avg_gap\"].abs() > post_rupt[\"gap_abs\"].median(), \"shift\", \"micro\")))\n",
|
||
" \n",
|
||
"# 6. Statistiques globales\n",
|
||
"stats = post_rupt[\"gap_type2\"].value_counts(normalize=True).round(3) * 100\n",
|
||
"print(\"\\n=== DISTRIBUTION DES TYPES DE GAPS POST-2021 ===\")\n",
|
||
"print(stats)\n",
|
||
"\n",
|
||
"# 7. Stats par client\n",
|
||
"client_stats = (\n",
|
||
" post_rupt.groupby(\"Registrar Account - ID\")[\"gap_type2\"]\n",
|
||
" .value_counts(normalize=True)\n",
|
||
" .rename(\"ratio\")\n",
|
||
" .mul(100)\n",
|
||
" .reset_index()\n",
|
||
")\n",
|
||
"\n",
|
||
"# 8. Stats par ISIN\n",
|
||
"isin_stats = (\n",
|
||
" post_rupt.groupby(\"Product - Isin\")[\"gap_type2\"]\n",
|
||
" .value_counts(normalize=True)\n",
|
||
" .rename(\"ratio\")\n",
|
||
" .mul(100)\n",
|
||
" .reset_index()\n",
|
||
")\n",
|
||
"\n",
|
||
"print(\"\\n=== TOP ISIN PAR RESET ===\")\n",
|
||
"print(isin_stats[isin_stats[\"gap_type2\"]==\"reset\"].sort_values(\"ratio\", ascending=False).head(10))\n",
|
||
"\n",
|
||
"print(\"\\n=== TOP CLIENTS PAR RESET ===\")\n",
|
||
"print(client_stats[client_stats[\"gap_type2\"]==\"reset\"].sort_values(\"ratio\", ascending=False).head(10))\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "c2efc5e0-bc35-4fa7-ab5d-6be616964446",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"import plotly.graph_objects as go\n",
|
||
"\n",
|
||
"# --- Data from your output ---\n",
|
||
"labels = [\"Micro-ruptures\", \"Décalage\", \"Anomalies ponctuelles\", \"Remise à zéro\"]\n",
|
||
"values = [50.4, 44.6, 4.0, 1.0]\n",
|
||
"\n",
|
||
"# --- Pie chart ---\n",
|
||
"fig = go.Figure(\n",
|
||
" data=[go.Pie(\n",
|
||
" labels=labels,\n",
|
||
" values=values,\n",
|
||
" hole=0.35, # donut style (plus lisible)\n",
|
||
" textinfo='percent',\n",
|
||
" marker=dict(colors=[\"#3498DB\", \"#E67E22\", \"#9B59B6\", \"#E74C3C\"])\n",
|
||
" )]\n",
|
||
")\n",
|
||
"\n",
|
||
"fig.update_layout(\n",
|
||
" title=\"Typologie des ruptures depuis Septembre 2021\",\n",
|
||
" legend_title=\"Type de gap\",\n",
|
||
")\n",
|
||
"\n",
|
||
"fig.show()\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "744e04b6-3f34-40c9-95fe-a5605e7c7f02",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"merged[\"gap_abs\"] = merged[\"gap\"].abs()\n",
|
||
"\n",
|
||
"merged[\"gap_rel\"] = (\n",
|
||
" merged[\"gap_abs\"] /\n",
|
||
" merged[\"Quantity - AUM\"].replace(0, np.nan)\n",
|
||
")\n",
|
||
"\n",
|
||
"merged.loc[merged[\"rupture_flag\"], \"gap_rel\"].describe(\n",
|
||
" percentiles=[0.5, 0.75, 0.9, 0.95, 0.99]\n",
|
||
")\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "3d20625e-1045-4b7a-ab64-3381997e4131",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# uniquement sur les ruptures\n",
|
||
"df_r = merged[merged[\"rupture_flag\"]].copy()\n",
|
||
"\n",
|
||
"# seuils globaux (descriptifs, pas \"optimisés\")\n",
|
||
"q90 = df_r[\"gap_abs\"].quantile(0.90)\n",
|
||
"q99 = df_r[\"gap_abs\"].quantile(0.99)\n",
|
||
"\n",
|
||
"# moyenne directionnelle par compte\n",
|
||
"avg_gap_by_account = (\n",
|
||
" df_r.groupby(\"Registrar Account - ID\")[\"gap\"]\n",
|
||
" .mean()\n",
|
||
" .rename(\"avg_gap\")\n",
|
||
")\n",
|
||
"\n",
|
||
"df_r = df_r.merge(avg_gap_by_account, on=\"Registrar Account - ID\", how=\"left\")\n",
|
||
"\n",
|
||
"def classify_gap(row):\n",
|
||
" if row[\"gap_abs\"] >= q99:\n",
|
||
" return \"reset\"\n",
|
||
" if row[\"gap_abs\"] >= q90:\n",
|
||
" return \"spike\"\n",
|
||
" if abs(row[\"avg_gap\"]) > row[\"gap_abs\"]:\n",
|
||
" return \"shift\"\n",
|
||
" return \"micro\"\n",
|
||
"\n",
|
||
"df_r[\"discontinuity_type\"] = df_r.apply(classify_gap, axis=1)\n",
|
||
"df_r[\"discontinuity_type\"].value_counts(normalize=True) * 100\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "02806629-e454-4e10-82be-6e2239091088",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"merged[\"year\"] = merged[\"Centralisation Date\"].dt.year\n",
|
||
"\n",
|
||
"yearly_stats = merged.groupby(\"year\").agg(\n",
|
||
" total_obs=(\"gap\", \"count\"),\n",
|
||
" ruptures=(\"rupture_flag\", \"sum\")\n",
|
||
").reset_index()\n",
|
||
"\n",
|
||
"yearly_stats[\"rupture_rate\"] = (\n",
|
||
" yearly_stats[\"ruptures\"] / yearly_stats[\"total_obs\"]\n",
|
||
")\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "2edf2c55-45e7-4aad-b4f9-5c35178abad6",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"import matplotlib.pyplot as plt\n",
|
||
"import numpy as np\n",
|
||
"\n",
|
||
"df_r = merged[merged[\"rupture_flag\"]].copy()\n",
|
||
"\n",
|
||
"plt.figure(figsize=(12,4))\n",
|
||
"plt.hist(df_r[\"gap_abs\"], bins=100, log=True)\n",
|
||
"plt.title(\"Distribution of absolute gaps (log scale)\")\n",
|
||
"plt.xlabel(\"Absolute gap\")\n",
|
||
"plt.ylabel(\"Frequency (log)\")\n",
|
||
"plt.show()\n",
|
||
"\n",
|
||
"plt.figure(figsize=(12,4))\n",
|
||
"plt.hist(df_r[\"gap_rel\"].dropna(), bins=100, log=True)\n",
|
||
"plt.title(\"Distribution of relative gaps (|gap| / AUM)\")\n",
|
||
"plt.xlabel(\"Relative gap\")\n",
|
||
"plt.ylabel(\"Frequency (log)\")\n",
|
||
"plt.show()\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "981f2ec6-574b-41ea-b4bf-45be54aeda1f",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"plt.figure(figsize=(10,4))\n",
|
||
"plt.plot(yearly_stats[\"year\"], yearly_stats[\"rupture_rate\"], marker=\"o\")\n",
|
||
"plt.title(\"Evolution of AUM–Flow inconsistency rate over time\")\n",
|
||
"plt.xlabel(\"Year\")\n",
|
||
"plt.ylabel(\"Rupture rate\")\n",
|
||
"plt.grid(True)\n",
|
||
"plt.show()\n"
|
||
]
|
||
}
|
||
],
|
||
"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.13.11"
|
||
}
|
||
},
|
||
"nbformat": 4,
|
||
"nbformat_minor": 5
|
||
}
|