AAYMA
RU
Войти

MoneyGraph

Локальный MVP AML-анализа: из трёх parquet получаются объяснимые роли всех узлов, Louvain-кластеры, топ приоритетов с разложением вкладов и…

Доведённый продукт
Команда «Simplex» 10💬 0 комментариевс 23 сентября 2026 г.

О проекте

Команда: Simplex
Кейс HackAlem.ai: Финансы — Freedom
Стадия: Доведённый продукт

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

Суть

Локальный MVP AML-анализа: из трёх parquet получаются объяснимые роли всех узлов, Louvain-кластеры, топ приоритетов с разложением вкладов и автономный HTML-дашборд; есть анализ чувствительности и сценарии удаления узлов.

Как устроено

Пайплайн проверяет входные данные (типы, уникальность, согласованность транзакций с рёбрами, SHA-256), считает степени, обороты, betweenness на ориентированном графе по числу переходов, достижимость от seed и временные признаки (FIFO-совместимость за 1–2 дня, синхронные плательщики). Роли назначаются правилами с порогами из config.json; coordinator требует путей от ≥2 seed и соседей в ≥2 кластерах. Priority — взвешенная сумма лог-насыщенных на P95 признаков. Louvain запускается по каждой слабосвязной компоненте с весом log1p(сумма). sensitivity.py варьирует пороги и веса и проверяет устойчивость топ-20.

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

  • Louvain
  • betweenness centrality
  • seed reachability
  • temporal FIFO patterns
  • sensitivity analysis
  • log-saturation P95 scoring
  • top-N removal scenario

Метрики

Минимальное пересечение с базовым топ-20 при вариациях порогов и весов — 18 из 20

Особенности

Анализ чувствительности ролей и топа к порогам и весам. Сценарий достижимости от seed при исключении топ-1/3/5. Хранение gid строками из-за точности JS. Генератор синтетических данных для проверки без датасета. Методологическая аккуратность: не использовать суммы как расстояние в betweenness.

Стек

Python · NetworkX · pandas · PyArrow · HTML/JS · unittest · GitHub Actions


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

README

README.md

MoneyGraph · HackAlem AI

Локальный MVP для трека «Граф денег: восстановление финансовой структуры организованной группы по транзакционной сети».

Три Parquet-файла превращаются в объяснимые роли всех участников, кластеры, список приоритетов и интерактивную карту. Основной вопрос: кого проверить первым и какие наблюдения это обосновывают?

Это инструмент поддержки аналитика. Роли — гипотезы, role_score — сила формальных признаков, priority_score — приоритет проверки. Ни один скор не является вероятностью виновности. Реальные остатки на счетах и происхождение конкретных денег по этой выгрузке не восстанавливаются.

Быстрый старт

Нужен Python 3.12. Рабочая директория во всех командах — корень проекта.

Windows / PowerShell

py -3.12 -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r requirements.txt

Распакуйте архив организаторов data (1).zip в корень проекта. Должно получиться:

data/
  nodes.parquet
  edges.parquet
  transactions.parquet

Один запуск от сырых данных до всех результатов и интерфейса:

.\.venv\Scripts\python.exe run.py --data data --out results --serve --open

Откроется http://127.0.0.1:8765/dashboard.html.

Остановка сервера: Ctrl+C.

Активация окружения не требуется; менять PowerShell ExecutionPolicy не нужно.

macOS / Linux

python3.12 -m venv .venv
.venv/bin/python -m pip install -r requirements.txt
.venv/bin/python run.py --data data --out results --serve --open

Для расчёта без сервера:

python run.py --data data --out results

После него results/dashboard.html можно открыть локально. Данные, стили и код включены в HTML; CDN и интернет для работы интерфейса не требуются.

Интернет нужен только при первой установке библиотек.

Для полностью офлайн-машины можно заранее подготовить wheelhouse:

python -m pip download -r requirements.txt -d wheelhouse
python -m pip install --no-index --find-links wheelhouse -r requirements.txt

Проверка без закрытого датасета

python scripts/make_demo.py --out data-demo
python run.py --data data-demo --out results --serve

Генератор создаёт полностью вымышленные узлы и переводы, включая изолированный seed, четвёртое колено, веер и транзит. Это данные для демонстрации и тестирования, а не замена датасету хакатона.

Что готово

ТребованиеРеализация
Воспроизводимый пайплайн < 5 минутrun.py, закреплённые версии, проверка входа и выхода, SHA-256 входных файлов
Роль у каждого узлаВсе nodes.gid, включая изолированные; шесть ролей обязательного словаря
Формальные объясненияПороги в config.json, методика ниже и в docs/METHODOLOGY.md; числовое evidence ≤ 200 символов
КластерыLouvain по отдельным компонентам, включая singleton-кластеры изолятов
Топ ≥ 20По умолчанию топ-50, отдельное объяснение вкладов факторов
ВизуализацияСтрелки, роли/кластеры, поиск точного gid, карточки, масштабирование и фильтры
Учёт обрываУзлы depth=4 с нулевым выходом не получают terminal; положительные признаки входа сохраняются
Временные паттерныFIFO-совместимость за 1–2 дня, синхронные плательщики, доля пикового дня
Структурный сценарийДостижимость от seed при исключении топ-1/3/5
Чувствительность выводовОтдельный отчёт по изменению порогов ролей и весов приоритета
ВоспроизводимостьЛокальные unittest-тесты; CI-конфигурация для Windows/Linux включена в .github/workflows/ci.yml

В текущем MVP нет внешнего LLM, GPU, платных API и обучения с размеченными ролями. Используются объяснимые правила и кластеризация без учителя.

Нельзя заявлять accuracy: истинные роли не размечены. AI/LLM-ассистент может быть подключён отдельным слоем поверх рассчитанного графа, не заменяя формальные правила ролей и приоритета.

Выходные файлы

ФайлСодержимое
nodes_roles.csvgid, role, role_score, cluster_id, priority_score, evidence, далее наблюдаемые метрики
clusters.csvcluster_id, n_nodes, n_seed, sum_kzt_internal, top_gids, hypothesis
top_nodes.csvrank, gid, role, priority_score, why; минимум 20 при наличии ≥20 узлов
dashboard.htmlПолностью автономный интерактивный интерфейс
graph.jsonДанные интерфейса, альтернативные роли, временные ряды, сценарии
audit.jsonОбъёмы, проверки, ограничения, распределение ролей, время расчёта
manifest.jsonПараметры, версии Python/библиотек, хеши входных Parquet
sensitivity.jsonДополнительный отчёт устойчивости, создаётся отдельной командой

CSV — UTF-8 с BOM, разделитель — запятая.

gid в CSV хранится точной десятичной записью int64. При импорте в Excel выберите для gid тип «Текст»: Excel может округлять длинные числа.

В JSON и браузере gid представлены строками, поскольку эти значения могут выходить за точный целочисленный диапазон JavaScript.

top_gids — до пяти gid через ;, по убыванию приоритета.

Внутренний оборот кластера считает каждое направленное ребро один раз. Сумма внутренних оборотов может быть меньше общего оборота из-за межкластерных переводов.

Объяснение произвольного узла

Проверить произвольный узел без браузера:

python run.py --out results --explain <полный_gid>

Проверка чувствительности

После подготовки данных:

Windows / PowerShell

.\.venv\Scripts\python.exe scripts\sensitivity.py --data data --out results\sensitivity.json

macOS / Linux

python scripts/sensitivity.py --data data --out results/sensitivity.json

Анализ чувствительности:

  • изменяет пороги числа плательщиков и получателей на ±1;
  • изменяет каждый вес приоритета на ±20%;
  • нормирует итоговую сумму весов;
  • сравнивает изменения ролей;
  • проверяет устойчивость состава топ-20.

В sensitivity.json сохраняются gid с изменившейся ролью и узлы, вошедшие или выбывшие из топа.

Это проверка зависимости результата от настроек, а не измерение accuracy или вероятности виновности.

На предоставленном датасете при проверенных вариациях минимальное пересечение с базовым топ-20 составило 18 из 20 узлов. Этот результат относится только к реализованным сценариям чувствительности и не является гарантией устойчивости при любых параметрах.

Формальные правила ролей

I, O — суммы наблюдаемого входа/выхода.

din, dout — число разных контрагентов.

R = O / I, только при I > 0.

Для seed и обрезанных узлов R не участвует в назначении транзита/стока.

РольУсловие допуска по умолчанию
consolidatordin ≥ 3
distributordout ≥ 10
transitНе seed, не обрыв, I>0, dout>0, 0.8 ≤ R ≤ 1.2
terminalНе seed, не обрыв, I>0, R ≤ 0.1, есть вход до последних двух дней и нет входа в последние два дня
coordinatorНе обрыв; din≥2, dout≥2; направленные пути от ≥2 разных seed; соседи в ≥2 внешних кластерах; положительное посредничество ≥P90 положительных значений
peripheralНи одно из правил не выполнено; означает недостаток признаков, а не безопасность клиента

Допущенные роли получают собственный скор.

coordinator имеет приоритет как более специфический структурный паттерн; иначе выбирается максимальный скор.

Альтернативные роли сохраняются и видны в карточке. Формулы и tie-break описаны в методике.

Координатор в интерфейсе назван «кандидат-мост»: центральность сама по себе не доказывает управление группой.

terminal отображается как «гипотеза стока». Даже внутри глубины 4 невозможно доказать, что деньги остались на счёте: отсутствуют остатки, межбанк и следующий период.

Приоритет проверки

priority = 0.30 × S(seed_reach)
         + 0.25 × S(in_degree)
         + 0.15 × S(max(in_kzt, out_kzt))
         + 0.15 × S(betweenness)
         + 0.10 × S(out_degree)
         + 0.05 × temporal_share

S(x) = min(1, log(1+x) / log(1+P95 положительных x))

Если положительных значений нет, S=0.

Временной вклад равен нулю для seed и обрыва.

Метрики считаются по всей сети, а не только по крупнейшей компоненте.

Сортировка: score по убыванию, затем точный числовой gid по возрастанию.

Насыщение на P95 может давать одинаковые scores; такой порядок не означает доказанное превосходство одного узла над другим.

Веса — документированная эвристика MVP. Они не обучены на скрытом «правильном ответе». Оценивать нужно обоснованность и устойчивость, а не заявлять неподтверждённую точность.

Кластеры и направление денег

Исходный граф всегда ориентированный.

Для Louvain строится отдельная неориентированная проекция:

  • суммы A→B и B→A складываются;
  • вес — log1p(сумма);
  • каждая слабосвязная компонента кластеризуется отдельно;
  • изоляты получают отдельные кластеры;
  • случайное зерно — 42;
  • ID кластеров канонизируются по размеру и минимальному gid;
  • самопетли не усиливают Louvain.

Число кластеров не задаётся заранее.

«8 сообществ с несколькими seed» из ТЗ — ориентир организаторов, а не требование получить ровно восемь кластеров.

Кластер — структурная гипотеза, а не доказанное сообщество соучастников.

Посредничество считается на ориентированном графе по числу переходов.

Суммы денег нельзя использовать как расстояние в betweenness_centrality: в таком случае крупный перевод ошибочно стал бы длинным путём.

Данные и ограничения

Период по умолчанию — 01–31 июля 2026.

Датасет содержит только внутрибанковские исходящие цепочки до четырёх колен и переводы от 5 000 KZT.

Персональных атрибутов нет; приложение их не придумывает и не обогащает внешними источниками.

При чтении проверяются:

  • типы;
  • уникальность gid/пар;
  • диапазоны глубины;
  • принадлежность концов рёбер списку узлов;
  • даты;
  • положительные суммы;
  • порог сбора;
  • совпадение сумм и числа операций между транзакциями и агрегированными рёбрами.

Совпадающие строки транзакций сохраняются: без transaction_id нельзя считать их дублями.

Особенности фактического датасета

  • 2 248 узлов;
  • 3 119 направленных рёбер;
  • 4 840 транзакций;
  • 81 seed;
  • 16 компонент с рёбрами + 19 изолированных seed = 35 компонент полного графа;
  • 444 узла обрезаны на четвёртом колене;
  • 31 seed не имеет исходящих переводов;
  • у 354 узлов с положительным наблюдаемым входом выход больше входа;
  • ещё у 23 узлов есть выход при нулевом наблюдаемом входе;
  • 97 полностью совпадающих строк транзакций сохранены, агрегаты сходятся;
  • оборот по рёбрам — 365 890 012.01 KZT.

Оборот — это сумма по наблюдаемым рёбрам, а не объём уникальных денег и не оценка преступного дохода.

Фактические исходные данные и рассчитанные результаты остаются локальными и исключены из Git.

Датасет предоставлен организаторами для хакатона; исходники проекта не расширяют права на его распространение.

dashboard.html содержит встроенные данные, поэтому с ним следует обращаться как с аналитической выгрузкой.

Архитектура

flowchart LR
  A[3 Parquet] --> B[Проверка схемы и агрегатов]
  B --> C[Ориентированный граф со всеми узлами]
  C --> D[Структурные метрики и seed-пути]
  C --> E[Louvain по компонентам]
  B --> F[Временные признаки 1–2 дня]
  D --> G[Правила ролей и вклад в приоритет]
  E --> G
  F --> G
  G --> H[3 CSV и аудит]
  G --> I[Автономный HTML-интерфейс]
  G --> J[Анализ чувствительности]

Отдельная схема для демонстрации: docs/architecture.svg.

Структура проекта

run.py                        CLI, объяснение узла, локальный HTTP-сервер
config.json                   пороги, период, зерно, размер топ-листа

moneygraph/data.py            проверка и нормализация входа
moneygraph/temporal.py        временное FIFO-сопоставление
moneygraph/analysis.py        граф, роли, кластеры, приоритеты, сценарии
moneygraph/pipeline.py        контракты, экспорт, аудит, встраивание данных
moneygraph/web/dashboard.html интерактивный интерфейс без внешних зависимостей

scripts/make_demo.py          вымышленный датасет для тестирования
scripts/check_submission.py   проверка сдачи на датасете хакатона
scripts/sensitivity.py        анализ чувствительности порогов и весов

tests/test_core.py            тесты критических свойств
docs/                         методика, план MVP, демонстрация, схема

Проверки

Unit tests

python -m unittest discover -s tests -v

Полный расчёт

python run.py --data data --out results

Проверка сдачи

python scripts/check_submission.py --data data --out results

Тесты проверяют:

  • обрыв на четвёртом колене;
  • особенности seed;
  • период наблюдения;
  • отсутствие двойного расходования входа;
  • неизвестные/округлённые gid;
  • несовпадение агрегатов;
  • сохранение изолятов;
  • точность ID в JSON;
  • повторяемость CSV;
  • независимость результата от порядка строк;
  • корректность sensitivity-отчёта и сравнения топов.

CI-конфигурация для Windows и Linux находится в .github/workflows/ci.yml.

Локальные итоги проверки реальных файлов описаны в docs/VALIDATION.md.

До 1 млн узлов

Текущая реализация рассчитана на объём хакатона; обещания пяти минут для миллиона узлов нет.

При росте нужны:

  1. Агрегация Parquet через DuckDB/Polars с чтением по колонкам и партициями по датам.
  2. igraph/CSR вместо Python-объектов NetworkX; Leiden/Louvain по компонентам.
  3. Приближённое посредничество по выборке источников вместо полного Brandes.
  4. Ограниченные обходы от seed, пакетная обработка и битовые множества для достижимости.
  5. Временные признаки в отсортированном потоке по gid/дате и инкрементальный пересчёт затронутых узлов.
  6. Серверная выдача подграфов с пагинацией вместо загрузки миллиона узлов в один HTML.
  7. Версионирование расчётов, контроль доступа и журнал действий аналитиков перед эксплуатацией.

Следующие шаги команды

Практический план MVP и разделение работ: docs/MVP_PLAN.md.

Пятиминутная защита: docs/DEMO.md.

Ближайшие улучшения после рабочего MVP:

  • AI-ассистент аналитика поверх рассчитанного графа;
  • анализ устойчивости кластеров;
  • временные повторяющиеся маршруты;
  • проверяемые запросы на естественном языке.

Новые функции не должны заменять формальные правила ролей и приоритета. AI-слой должен использовать рассчитанные метрики и связи как источник фактов и формулировать результаты как гипотезы для аналитической проверки.

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

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

Anzy737 4esenkhannurali-ux 1

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

  • 2026-09-23 17:39Update README documentationAnzy737
  • 2026-09-23 16:39Fix direct sensitivity script executionAnzy737
  • 2026-09-23 15:53Add sensitivity analysis for roles and priority rankingesenkhannurali-ux
  • 2026-09-23 15:26Improve README for submissionAnzy737
  • 2026-09-23 14:51Add MoneyGraph MVPAnzy737
Структура репозитория (22 файлов)
.github/workflows/ci.yml
.gitignore
README.md
config.json
data/.gitkeep
docs/DEMO.md
docs/METHODOLOGY.md
docs/MVP_PLAN.md
docs/VALIDATION.md
docs/architecture.svg
moneygraph/__init__.py
moneygraph/analysis.py
moneygraph/data.py
moneygraph/pipeline.py
moneygraph/temporal.py
moneygraph/web/dashboard.html
requirements.txt
run.py
scripts/check_submission.py
scripts/make_demo.py
scripts/sensitivity.py
tests/test_core.py

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

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

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