Forensic accounting / Neo4J 101

מסמכי פנמה הם כינוי להדלפת ענק של מסמכי משרד עורכי דין פנמי שמתעסק כנראה בעיקר בהקמת חברות קש במקלטי מס.
הכנראה מצביע על זה שאין לי כוונה לטעון בנחרצות דברים לגבי אף אחת מהישויות שיצוצו בקבצים. אם כבר נאמר משהו – הכל יהיה על פי מקורות זרים.
כוונת הפוסט היא רק לספק קרקע נוחה ומעניינת למשחק  hands on עם טכנולוגיית הGraphDB ואין בסיס נתונים מעניין יותר מאשר מסמכי פנמה לצורך העניין.
(ויקי אנגלית, ויקי עברית, האתר עצמו: Offshore Leaks Database )

הנתונים עצמם נמצאים כאן:
וניתנים להורדה בשתי צורות: CSV או DB מוכן של Neo4J בשני המקרים שמתי את הלינק לקובץ הטורנט.

הצעד הראשון הוא הורדה של הDB עצמו מכאן.
לאחר הורדה התקנה והרצה (next next)
יפתח לינק לBrowser מגניב מעל הDB הלוקאלי בכתובת: http://localhost:7474/browser

בכניסה הראשונה צריך להתחבר לשרת עם הסיסמא הדיפולטית, להגדיר חדשה ואז אתם בפנים.

Learn about  Neo4J נוגע קצת במונחים והJump into code מאפשר צלילה מאוד נוחה ליצירת DB סרטים ואז תיחקור שלו.
התחקור מתבצע בשפת Cypher שהיא חלק גדול מהיופי בכל העניין.

בהחלט ראוי לאזכר כאן את היפותזת ספיר-וולף שהשפה משפיעה על אופני החשיבה. גם אם אפשר לתחקר הכל בSQL, או בשפת תכנות הרי ששפת התחקור ללא ספק הופכת שאלות רבות לנגישות יותר לשאלה.

MATCH (actor:Person)-[:ACTED_IN]->(movie:Movie)
WHERE movie.title STARTS WITH "T"
RETURN movie.title AS title, collect(actor.name) AS cast
ORDER BY title ASC LIMIT 10;

השפה עצמה מאוד מזכירה SQL עם קצת לוגיקה של RegEx
השאילתא הבסיסית כפי שהיא מופיעה למעלה כוללת:
MATCH – חלק שבו נתאר תבנית שלפיה נפלטר דאטה שתואמת לה. (או מספר תבניות מופרדות בפסיק)

MATCH (_ALIAS_TO_BE_USED_LATER_IN_THE QUERY_:_NODE_TYPE_)-[:_RELATION_TYPE_]->(movie:Movie)

 WHERE – סטנדרטי כמו בSQL. (שימו לב לשימוש בmovie הalias שהוגדר בMATCH)

RETURN – אחרי שהגדרנו ופילטרנו אפשר להגדיר מה נרצה להחזיר. שימו לב שיש כאן בעצם implicit group by על פי השדות המוחזרים ושאינם aggregated (במקרה שלנו movie.title)
והפונקציה collect אוגדת לערך אחד מספר ערכים.


שיחקתם עם הMovie DB => בואו נעבור הלאה.

עכשיו הזמן להוריד  ולהשתמש ב DB של מסמכי פנמה שהורדתם. ( לינק )

סדר הפעולות הוא:
1. stop
2. choose the "panama-papers-windows\neo4j.data\panama.graphdb" directory
3. start

כדי לוודא שהכל עבד בוא נריץ את הquery :

MATCH (a)
where 
a.countries = 'Israel'
RETURN labels(a) , count(*)

ואנחנו אמורים לקבל:

count(*) labels(a)
1094 [Officer]
663 [Entity]
865 [Address]
146 [Intermediary]

ועכשיו אנחנו בתוך הDB של מסמכי פנמה, מוכנים לקצת Forensic accounting.

הquery הראשון שנריץ יהיה:

MATCH (a)-[*1..1]-(b)
where 
labels(a) <> 'Address'
and a.countries = 'Israel'
RETURN a.node_id,labels(a),a.name,count(*) as cnt 
ORDER BY cnt desc
limit 10

ונקבל:

a.node_id labels(a) a.name cnt
11013202 [Intermediary] OFIR TSHORNY, ADV (CPA) 215
10165699 [Entity] ParagonEX Limited 80
11003993 [Intermediary] MORDECHAI KUPERSCHMIDT, ADVOCATE 49
11006928 [Intermediary] MOSSACK FONSECA & CO. (ISRAEL) LIMITED 24
11009424 [Intermediary] BANK HAPOALIM SWITZERLAND 23
12223915 [Officer] SEMION BUKHMAN 17
10097850 [Entity] G.S.S. Group Ltd. 16
21957 [Officer] Tal Hackmey 15
11004430 [Intermediary] LAURENCE WIZEL FAMILY OFFICE 15

כל הישויות האלו מופיעות במסמכים.
ואפשר להתחיל לצלול ולראות איך נראה מה שנחשף.

נתמקד לדוגמא בישות השניה
השאילתא הבאה מגדירה תבנית של קשר אחד (a מקושר לb)
מגדירה את a כישות מסויימת ( node_id:10165699 ) ובעצם מחזירה את כל הקשרים שלו.

אחד הדברים שמאוד מקל על הבנת התוצאות זה הviewer שמציג גרפים ומאפשר גם לטייל בהם.
(מצד שני עבודה יותר משמעותית איתו מסבירה את הגדולה בממשק של פלנטיר)

MATCH (a)-[*1..1]-(b)
where 
a.node_id = "10165699"
RETURN a,b

מה שבעצם רואים כאן
זה ישות מרכזית אחת: ParagonEX Limited
עם כמה עשרות קשרים לישויות מסוג Officer שמוגדרות כ SHAREHOLDER ששימשו (אני מניח) לחלוקת אופציות בחלקן. (שמות כגון: ESOP for X)

חלק מהשמות צפו מאז הפרסום בעיתונות : ( לדוגמא כאן )

רוצים לדעת עוד?
תורידו ותשתעשעו
it's that simple

כתיבת תגובה

האימייל לא יוצג באתר. שדות החובה מסומנים *