-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrun_multi_level_analysis.py
More file actions
132 lines (110 loc) · 4.72 KB
/
run_multi_level_analysis.py
File metadata and controls
132 lines (110 loc) · 4.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Multi-level Ownership Analysis Script
This script analyzes multi-level ownership structures by discovering and analyzing
indirect ownership relationships using the Neo4j graph database.
"""
import os
import sys
import time
import logging
import argparse
from pathlib import Path
from dotenv import load_dotenv
# Add the src directory to the path
current_dir = Path(__file__).resolve().parent
sys.path.append(str(current_dir / "src"))
# Import required modules
from graph.neo4j_connection import Neo4jConnection
from graph.indirect_ownership import IndirectOwnershipDiscovery
# Set up logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.StreamHandler(),
logging.FileHandler('multi_level_demo.log')
]
)
logger = logging.getLogger(__name__)
def main():
"""Main function to execute the multi-level ownership analysis."""
# Parse command line arguments
parser = argparse.ArgumentParser(
description="Analyze multi-level ownership structures"
)
parser.add_argument(
"--krs",
type=str,
default="0000010078",
help="KRS number of the company to analyze (default: 0000010078 - Cyfrowy Polsat)"
)
parser.add_argument(
"--depth",
type=int,
default=3,
help="Maximum depth for ownership analysis (default: 3)"
)
parser.add_argument(
"--synthetic",
action="store_true",
help="Create synthetic test data before analysis"
)
args = parser.parse_args()
# Load environment variables
load_dotenv()
# Create Neo4j connection
neo4j = Neo4jConnection()
try:
# Verify Neo4j connectivity
if not neo4j.verify_connectivity():
print("\nError: Could not connect to Neo4j database. Please check your connection settings.")
return
print(f"\nConnected to Neo4j database at {neo4j.uri}")
# Create the discovery service
discovery_service = IndirectOwnershipDiscovery(neo4j)
# Create synthetic test data if requested
if args.synthetic:
print("\nCreating synthetic test data for demonstration...")
stats = discovery_service.create_synthetic_test_data()
print(f"Created {stats['companies_created']} companies, {stats['shareholders_created']} shareholders, "
f"and {stats['relationships_created']} relationships")
# Discover indirect relationships
print(f"\nAnalyzing multi-level ownership for company with KRS: {args.krs} (depth: {args.depth})")
start_time = time.time()
# Execute discovery
stats = discovery_service.discover_indirect_relationships(args.krs, args.depth)
# Calculate execution time
execution_time = time.time() - start_time
# Print results
print(f"\nAnalysis completed in {execution_time:.2f} seconds!")
print(f"\nResults:")
print(f"* Created {stats['upstream_relationships']} upstream indirect ownership relationships")
print(f"* Created {stats['downstream_relationships']} downstream indirect ownership relationships")
print(f"* Total: {stats['total_relationships']} indirect ownership relationships")
print(f"* Linked {stats['companies_linked']} companies and {stats['shareholders_linked']} shareholders")
# Print example Cypher queries
print("\nYou can now explore the multi-level ownership network in Neo4j Browser.")
print("\nExample Cypher queries:")
print("""
// View all indirect ownership relationships for the company
MATCH (entity)-[r:INDIRECT_OWNER_OF]->(company:Company {krs: "%s"})
RETURN entity.name AS Owner, company.name AS Company, r.percentage AS Percentage
ORDER BY r.percentage DESC
// View multi-level ownership paths
MATCH path = (entity)-[:OWNS_SHARES_IN|INDIRECT_OWNER_OF*1..%d]-(company:Company {krs: "%s"})
RETURN path
// Find ultimate beneficial owners (individuals who indirectly control the company)
MATCH (person:Shareholder {shareholder_type: 'individual'})-[r:INDIRECT_OWNER_OF]->(company:Company {krs: "%s"})
RETURN person.name AS UltimateOwner, r.percentage AS EffectiveControl
ORDER BY r.percentage DESC
""" % (args.krs, args.depth, args.krs, args.krs))
except Exception as e:
logger.error(f"Error in multi-level ownership analysis: {e}")
print(f"\nError: {e}")
finally:
# Close the Neo4j connection
neo4j.close()
if __name__ == "__main__":
main()