allow for self surgeries
This commit is contained in:
parent
bb2f24563c
commit
4d1e08274e
|
|
@ -15,17 +15,17 @@ import s3fs
|
||||||
# ─────────────────────────────────────────────
|
# ─────────────────────────────────────────────
|
||||||
# PARAMÈTRES
|
# PARAMÈTRES
|
||||||
# ─────────────────────────────────────────────
|
# ─────────────────────────────────────────────
|
||||||
ALPHA = 0.03 # tolérance réconciliation : 3% du stock à t
|
ALPHA = 0.03 # tolérance réconciliation : 5% du stock à t
|
||||||
MIN_AUM_EUR = 5e6 # seuil filtrage étape 1 — 0 pour les heads de test
|
MIN_AUM_EUR = 0 # seuil filtrage étape 1 — 0 pour les heads de test, 5e6 en prod
|
||||||
MIN_JACCARD = 0.3 # seuil minimal similarité portefeuille pour chirurgie
|
MIN_JACCARD = 0.3 # seuil minimal similarité portefeuille pour chirurgie
|
||||||
SCORE_DROP_THRESHOLD = 0.1 # si score chute de >10% → candidat chirurgie
|
SCORE_DROP_THRESHOLD = 0.1 # si score chute de >10% → candidat chirurgie
|
||||||
|
|
||||||
EXCLUDE_REGISTRAR = ["Off Distribution", "Private Clients"]
|
EXCLUDE_REGISTRAR = ["Off Distribution", "Private Clients"]
|
||||||
|
|
||||||
# ─────────────────────────────────────────────
|
# ─────────────────────────────────────────────
|
||||||
# 1. CHARGEMENT
|
# 1. CHARGEMENT
|
||||||
# ─────────────────────────────────────────────
|
# ─────────────────────────────────────────────
|
||||||
def load_data(aum_path, flows_path):
|
def load_data():
|
||||||
fs = s3fs.S3FileSystem(
|
fs = s3fs.S3FileSystem(
|
||||||
client_kwargs={'endpoint_url': 'https://'+'minio-simple.lab.groupe-genes.fr'},
|
client_kwargs={'endpoint_url': 'https://'+'minio-simple.lab.groupe-genes.fr'},
|
||||||
key = os.environ["AWS_ACCESS_KEY_ID"],
|
key = os.environ["AWS_ACCESS_KEY_ID"],
|
||||||
|
|
@ -501,8 +501,11 @@ def run_surgery_pass(scores_history, errors_history, panel, monthly_flows,
|
||||||
# ── ISIN du compte courant à t_curr (pour pré-filtre) ──
|
# ── ISIN du compte courant à t_curr (pour pré-filtre) ──
|
||||||
isin_curr = reg_isin_at_date.get(reg_curr, {}).get(t_curr, set())
|
isin_curr = reg_isin_at_date.get(reg_curr, {}).get(t_curr, set())
|
||||||
|
|
||||||
# ── Candidats disponibles (non déjà mappés) ──
|
# ── Candidats disponibles ──
|
||||||
available = all_regs_in_panel - set(mapping_inv.keys()) - {reg_curr}
|
# On exclut les codes déjà mappés à un autre compte,
|
||||||
|
# mais reg_curr lui-même est un candidat valide (self-mapping :
|
||||||
|
# le compte existait déjà sous ce code à t-1, dormant ou partiel).
|
||||||
|
available = (all_regs_in_panel - set(mapping_inv.keys())) | {reg_curr}
|
||||||
|
|
||||||
best_candidate = None
|
best_candidate = None
|
||||||
best_score_after = score_prev_no_surgery # baseline = pas de chirurgie
|
best_score_after = score_prev_no_surgery # baseline = pas de chirurgie
|
||||||
|
|
@ -549,9 +552,12 @@ def run_surgery_pass(scores_history, errors_history, panel, monthly_flows,
|
||||||
f"score {score_curr:.4f}→{best_score_after:.4f})")
|
f"score {score_curr:.4f}→{best_score_after:.4f})")
|
||||||
|
|
||||||
# Mise à jour mapping
|
# Mise à jour mapping
|
||||||
if reg_curr in mapping_inv:
|
# Si self-mapping (best_candidate == reg_curr), on ne touche pas
|
||||||
del mapping_inv[reg_curr]
|
# mapping_inv car le code ne change pas — on met juste à jour le score.
|
||||||
mapping_inv[best_candidate] = reg_orig
|
if best_candidate != reg_curr:
|
||||||
|
if reg_curr in mapping_inv:
|
||||||
|
del mapping_inv[reg_curr]
|
||||||
|
mapping_inv[best_candidate] = reg_orig
|
||||||
new_mapping[reg_orig] = best_candidate
|
new_mapping[reg_orig] = best_candidate
|
||||||
new_scores[reg_orig] = best_score_after
|
new_scores[reg_orig] = best_score_after
|
||||||
else:
|
else:
|
||||||
|
|
@ -617,13 +623,13 @@ def export_results(scores_history, mapping_history, surgery_log, all_months, out
|
||||||
# ─────────────────────────────────────────────
|
# ─────────────────────────────────────────────
|
||||||
# 8. PIPELINE PRINCIPAL
|
# 8. PIPELINE PRINCIPAL
|
||||||
# ─────────────────────────────────────────────
|
# ─────────────────────────────────────────────
|
||||||
def run_pipeline(aum_path, flows_path):
|
def run_pipeline():
|
||||||
print("=" * 60)
|
print("=" * 60)
|
||||||
print("CARMIGNAC — Pipeline de réparation des Registrar IDs")
|
print("CARMIGNAC — Pipeline de réparation des Registrar IDs")
|
||||||
print("=" * 60)
|
print("=" * 60)
|
||||||
|
|
||||||
# Chargement
|
# Chargement
|
||||||
aum, flows = load_data(aum_path, flows_path)
|
aum, flows = load_data()
|
||||||
|
|
||||||
# Étape 1 — Univers de référence
|
# Étape 1 — Univers de référence
|
||||||
aum_ref, weights, universe, t_ref = build_reference_universe(aum)
|
aum_ref, weights, universe, t_ref = build_reference_universe(aum)
|
||||||
|
|
@ -673,7 +679,4 @@ def run_pipeline(aum_path, flows_path):
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
df_scores, df_mapping, surgery_log, scores_history, mapping_history = run_pipeline(
|
df_scores, df_mapping, surgery_log, scores_history, mapping_history = run_pipeline()
|
||||||
"s3://projet-bdc-data/carmignac/AUM ENSAE V2 -20251105.csv",
|
|
||||||
"s3://projet-bdc-data/carmignac/Flows ENSAE V2 -20251105.csv"
|
|
||||||
)
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user