AAYMA
RU
Войти

Граф денег

Детерминированный пайплайн, который по графу транзакций присваивает узлам роли (coordinator, transit, consolidator, distributor, terminal)…

Рабочий MVP
Команда «Ghost in the Shell» 4💬 0 комментариевс 23 сентября 2026 г.

О проекте

Команда: Ghost in the Shell
Кейс HackAlem.ai: Финансы — Freedom
Стадия: Рабочий MVP

Задача кейса: «Граф денег»: восстановить структуру организованной группы по сети транзакций (AML)

Суть

Детерминированный пайплайн, который по графу транзакций присваивает узлам роли (coordinator, transit, consolidator, distributor, terminal), кластеризует сеть и выдаёт топ-лист для AML-проверки со Streamlit-просмотрщиком.

Как устроено

pipeline.py читает parquet (2248 узлов, 3119 рёбер), считает betweenness centrality, соотношение out/in, задержки переводов и число независимых seed-цепочек. Роли назначаются правилами сверху вниз, кластеры строятся Louvain, priority_score взвешивает роль, уверенность, seed-цепочки и степень. На выходе nodes_roles.csv, clusters.csv, top_nodes.csv с текстовыми обоснованиями; Streamlit + pyvis показывают поиск по gid, топ-лист и схему сети.

Ключевые решения

  • betweenness centrality
  • Louvain
  • NetworkX
  • pyvis
  • правила ролей по порогам
  • upstream_seeds

Особенности

Хорошо описаны ограничения данных (обрыв на 4-м колене понижает уверенность роли terminal, занижение входящих у seed, порог 5000 KZT) и план масштабирования до 1 млн узлов через приближённый betweenness и графовую БД.

Стек

Python · pandas · NetworkX · Streamlit · pyvis · parquet


Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-3bb6f822-ghost-in-the-shell.

README

README.md

hack-3bb6f822-ghost-in-the-shell

Hackathon team repository for Ghost in the Shell

Ghost in the Shell Hackathon Solution

Граф денег: роли, кластеры, приоритеты

Пайплайн восстанавливает финансовую структуру сети по графу транзакций: определяет роль каждого узла, кластеризует сеть на сообщества и ранжирует узлы по приоритету для ручной проверки AML-аналитиком.

Все правила детерминированные (без ML/LLM) — результат воспроизводим.

Быстрый запуск (одна команда для пайплайна)

pip install -r requirements.txt
python pipeline.py

На выходе в текущей папке появятся: nodes_roles.csv, clusters.csv, top_nodes.csv. Время выполнения на предоставленном объёме (2248 узлов / 3119 рёбер) — менее минуты.

Интерфейс просмотра

streamlit run app.py

Откроется локально (localhost:8501). Вкладки:

  • Поиск по gid — вводишь gid, видишь роль, обоснование и интерактивную схему связей узла (входящие/исходящие, до 3 шагов вглубь);
  • Топ-лист приоритетов — таблица с сортировкой;
  • Кластеры — состав каждого кластера + гипотеза, с визуализацией;
  • Вся сеть — общая схема с подсветкой ролей (ограничена по числу узлов для читаемости).

Структура репозитория

data/ -------- исходные .parquet (описание полей — data/README.md)
pipeline.py -- весь расчёт: роли, кластеры, приоритеты → 3 CSV
app.py -------- экран просмотра (Streamlit)
requirements.txt

Роли узлов — критерии и пороги

Правила применяются сверху вниз, срабатывает первое подходящее:

РольПравило
coordinatorУзел-мост: betweenness centrality в топ-10% по сети, при этом ≥3 входящих и ≥3 исходящих связей
transitОтдаёт почти всё полученное дальше: out/in от 0.8 до 1.2, и с момента первого входящего до первого исходящего перевода проходит ≤3 дней
consolidatorПолучает от ≥3 разных плательщиков (или от ≥3 независимых seed-цепочек), и заметно удерживает средства (out/in < 0.6, либо нет исходящих вовсе)
distributor≥5 исходящих связей и ≤2 входящих — веерная раздача без накопления
terminalЕсть входящие, исходящих в графе нет. Если узел на 4-м колене — уверенность снижена (0.45 вместо 0.85): это может быть не реальный конечный получатель, а артефакт обрыва обхода на максимальной глубине
peripheralНе подошёл ни под одно правило выше — недостаточно сигналов

role_score (0–1) — эвристическая уверенность в присвоенной роли, не вероятность в статистическом смысле. priority_score — взвешенная комбинация: вес роли × уверенность + число независимых seed-цепочек, доходящих до узла + степень узла (кол-во связей) + бонус, если узел сам является seed.

Почему transit проверяется раньше consolidator

Условие consolidator (≥3 плательщика) само по себе широкое и без дополнительной проверки поймало бы и узлы, которые просто быстро пропускают деньги дальше от нескольких источников (чистый транзит). Чтобы не путать накопление с транзитом, transit проверяется первым, а в consolidator добавлена проверка удержания средств (ratio < 0.6).

Обоснование для аналитика (evidence / why)

Каждая строка в nodes_roles.csv и top_nodes.csv содержит текстовое объяснение на естественном языке — конкретные цифры (кол-во контрагентов, суммы, задержки), а не абстрактный скор. Формулировки намеренно осторожные («кандидат», «признаки», «требует проверки») — это гипотезы для дальнейшей проверки аналитиком, а не утверждения о причастности.

Ограничения подхода

  • Обрыв на 4-м колене. 444 узла с depth=4 и без исходящих связей — это в значительной части артефакт глубины обхода (граф просто не прослеживался дальше), а не доказательство того, что деньги там осели. Учтено понижением role_score для таких узлов в роли terminal.
  • Только исходящие переводы. Входящие потоки на узлы вне выборки не видны — полный баланс узла посчитать нельзя, работаем только с тем, что видно внутри графа.
  • У seed-клиентов входящие занижены — граф собран от них, а не к ним; соотношение «отдал/получил» для seed интерпретировать буквально нельзя.
  • Порог 5 000 KZT. Дробление переводов ниже порога в данных не видно — возможна намеренная фрагментация транзакций, скрытая от графа.
  • Сеть не монолитна — 16 слабосвязных компонент, часть узлов вне главной компоненты; кластеризация (Louvain) не объединяет их искусственно.
  • Нет ground truth и атрибутов клиента. Оценка идёт по обоснованности критериев, а не по accuracy; никакие данные о личности клиентов не используются и не восстанавливаются.

Масштабирование до ~1 млн узлов

При росте графа на два-три порядка текущий подход потребует изменений:

  • Betweenness centrality считается точно за O(V·E) — на 1 млн узлов это неприемлемо долго. Нужна аппроксимация (например, k-sampling в networkx/igraph) или переход на приближённые меры центральности.
  • Louvain на всём графе в памяти упрётся в лимиты pandas/networkx — нужно либо переходить на графовую БД с инкрементальной кластеризацией (Neo4j GDS, igraph на диске), либо партиционировать граф по слабосвязным компонентам и кластеризовать каждую отдельно.
  • upstream_seeds (счётчик независимых seed-цепочек) считается за один проход по рёбрам, отсортированным по depth — остаётся линейным по числу рёбер и масштабируется нормально, но при 1 млн узлов данные стоит хранить не в parquet-файлах целиком в памяти, а в графовой БД с индексами по src/dst.
  • Интерфейс. Полная отрисовка сети в pyvis нежизнеспособна на миллионах узлов — уже сейчас app.py ограничивает схему топ-N узлами по приоритету; при росте графа этот подход остаётся единственным рабочим — рендерить только релевантный подграф вокруг искомого gid, а не всю сеть целиком.

Данные

Repository: https://github.com/BAITC-Hacks/hack-3bb6f822-ghost-in-the-shell

Presentation: [https://docs.google.com/presentation/d/1PCglSGLlLyTean3qFoHPjy5VmfYUaGBy/edit?usp=sharing&ouid=115657269000839204838&rtpof=true&sd=true]

Demo: локальный запуск через streamlit run app.py Описание полей и параметров сбора графа — в data/README.md.

Звёзды
⭐ 0
Форки
0
Язык
Python
Последний push
в прошлом месяце
Коммиты
18
Авторы
1
Файлы
7
Ветки
1

Авторы коммитов

Bahittosan 18

История коммитов

  • 2026-09-23 17:48Update README with repository and demo informationBahittosan
  • 2026-09-23 17:24Revise README for clarity and updated instructionsBahittosan
  • 2026-09-23 17:19Refactor role classification logic in pipeline.pyBahittosan
  • 2026-09-23 17:16Add files via uploadBahittosan
  • 2026-09-23 17:11add data filesBahittosan
  • 2026-09-23 17:02Delete transactions.parquetBahittosan
  • 2026-09-23 17:02Delete edges.parquetBahittosan
  • 2026-09-23 17:02Delete nodes.parquetBahittosan
Все коммиты (18)
  • 2026-09-23 17:01Improve formatting and clarity in README.mdBahittosan
  • 2026-09-23 16:39Refactor README for better structure and readabilityBahittosan
  • 2026-09-23 16:16Enhance README with project details and instructionsBahittosan
  • 2026-09-23 15:20add data folderBahittosan
  • 2026-09-23 15:18Delete transactions.parquetBahittosan
  • 2026-09-23 15:18Delete nodes.parquetBahittosan
  • 2026-09-23 15:18Delete edges.parquetBahittosan
  • 2026-09-23 15:12Update README with project details and setup instructionsBahittosan
  • 2026-09-23 14:24feat: add dataBahittosan
  • 2026-09-23 13:59init: project structure, pipeline stub, READMEBahittosan
Структура репозитория (7 файлов)
README.md
app.py
data/edges.parquet
data/nodes.parquet
data/transactions.parquet
pipeline.py
requirements.txt

Обсуждение 0 комментариев

Войдите, чтобы комментировать

Пока нет комментариев — будьте первым.