Wie zeichnet man eine Holdinggesellschaft, Eigentümerketten und berechnet CFC-Aktien

In der Rechtspraxis von Unternehmensanwälten wurde es vor relativ kurzer Zeit (vor einigen Jahren) notwendig, Meldungen über kontrollierte ausländische Unternehmen (CFCs) gemäß Art. 25.13 der Abgabenordnung der Russischen Föderation. Der Kern dieser Verpflichtung besteht darin, ein Dokument zu erstellen und einzureichen, das alle Verbindungen des Unternehmens in der Holding entlang der Ketten von der derzeitigen LLC (JSC) in der Russischen Föderation an die in der Russischen Föderation ansässige Eigentümersteuer CFC widerspiegelt. Einfach ausgedrückt, wenn das Offshore einem Russen gehört (steuerlich in der Russischen Föderation ansässig) und das Offshore einer russischen LLC (selbst durch den Zaun von Zwischen-LLCs) mehr als 25% beträgt, erfolgt eine Benachrichtigung. Das Highlight ist, dass es notwendig ist, allen LLCs (JSCs), in denen diese Situation beobachtet wird, Informationen über das Eigentum von mehr als 25% und nachfolgende Änderungen des Eigentumsanteils rechtzeitig vorzulegen, andernfalls Bußgelder (100.000 Rubel für jedes Unternehmen in der Kette - Art. 129.6 Steuergesetzbuch der Russischen Föderation).Da es sich bei der Holding (einer Reihe von juristischen Personen) um einen lebenden Organismus handelt und ständige Änderungen der Eigentumsanteile unvermeidlich sind, muss dies alles irgendwie überwacht werden, um keine Geldbußen zu erheben. Wie man die Arbeit in diese Richtung vereinfacht, automatisiert, ist dieser Artikel gewidmet. Der Artikel wird auch unter dem Gesichtspunkt der grafischen Darstellung verwandter Strukturen, beispielsweise sozialer Strukturen, interessant sein. Netzwerke.







In diesem Artikel werden wir uns nicht mit den rechtlichen Aspekten der eingereichten Benachrichtigungen zu einem FCKW befassen, sondern mit der technischen Seite des Problems.



Wenn sich die betreffende Holding als einfache Strukturen vom Typ LLC-> KIK-> Russisch darstellt, ist es zweifellos unpraktisch, hier unter Beteiligung einer Maschine etwas zu bauen. Es ist eine andere Sache, wenn sich die Struktur verzweigt, verdoppelt und es keine Anzahl dieser Verflechtungen gibt.



Schauen wir uns einige vorhandene Grafiklösungen an, die Ihre Arbeit vereinfachen.

Zur Vereinfachung der Visualisierung werden die Jupyter-Notebook- und Python-Umgebung verwendet.



Networkx



Diese Lösung ist die älteste der vorgestellten und kann sich ihrer Interaktivität nicht rühmen. Es gibt den gleichen alten Artikel über dieses Paket auf Habré.



Das Alte bedeutet jedoch nicht schlecht, und diese Option ist eine der erfolgreichsten in Bezug auf Zeichnen und Rechnen.



Installieren und importieren Sie das Modul über jupyter:



!pip install networkx
import networkx as nx


Wir importieren auch andere hinzufügen. Module, mit denen Sie Formen zeichnen können:



from matplotlib import pyplot as plt
%matplotlib inline
plt.rcParams.update({
    'figure.figsize': (7.5, 7.5),
    'axes.spines.right': False,
    'axes.spines.left': False,
    'axes.spines.top': False,
    'axes.spines.bottom': False})


Erstellen wir das erste Netzwerk mit networkx:



from pathlib import Path
data_dir = Path('.') / 'data'
# Read edge list
G = nx.read_edgelist('example.edgelist')
# Draw network
#pos = nx.spring_layout(G)
pos = nx.spectral_layout(G)
#pos = nx.planar_layout(G)
nx.draw_networkx(G, pos)
plt.gca().margins(0.15, 0.15)


Folgendes ist passiert:







Wie Sie sehen können, besitzt Ivanov zwei FCKW, die wiederum russische juristische Personen besitzen. von Personen.



Lassen Sie uns den obigen Code analysieren.



Wir haben das Modul importiert und angegeben, woher wir die Daten auf der Festplatte lesen sollen:



from pathlib import Path
data_dir = Path('.') / 'data'


Das aktuelle Verzeichnis wurde als 'example.edgelist' betrachtet:



G = nx.read_edgelist('example.edgelist')


* example.edgelist ist eine einfache Textdatei wie diese:



# source target
 1
 2
1 2
1 _
2 _


Die Werte werden von jemandem mit einem Leerzeichen dazwischen aufgezeichnet.



Als nächstes haben wir festgelegt, wie das Netzwerk aussehen wird:



pos = nx.spectral_layout(G)


Wenn wir zu pos = nx.spring_layout (G) wechseln, hat dies die Form:







Und diese Anordnung ist seltsamerweise am besten für größere Strukturen geeignet.



Schließlich haben wir das Netz gezeichnet und die Einrückungen markiert:



nx.draw_networkx(G, pos)
plt.gca().margins(0.15, 0.15)


Es ist einfach, ein Bild zu speichern:



plt.savefig('plot.png')


So zeichnen Sie ein Segment in networkx



#
H = G.subgraph(['', '1', '_'])
plt.subplot(212) 
print(":") 
nx.draw_networkx(H)


Wir haben hier nicht







eingerückt , und die Namen "links": Networkx arbeitet mit den Konzepten von Knoten und Verknüpfungen zwischen ihnen. In unserer Situation sind die Knoten Ivanov, KIK1, KIK2, Romashka_OOO, Bucket_AO. Die Links befinden sich in der Datei example.edgelist.



Sie können beide einfach anhand der Methoden G.nodes und G.edges sehen:







Gerichtete Grafik in networkx (Liste der gerichteten Kanten)



Lassen Sie uns das aufgebaute Netzwerk ein wenig verdeutlichen und Pfeile hinzufügen:



# Read edge list
G = nx.read_edgelist(
    str('example.edgelist'),
    create_using=nx.DiGraph)
pos = nx.spectral_layout(G)
# Draw network
nx.draw_networkx(G, pos, arrowsize=20)
plt.gca().margins(0.15, 0.15)


Kleine Änderungen ermöglichten es, ein klareres Bild davon zu zeichnen, wem wer gehört:



Wie Sie sehen, sind die Änderungen im Code minimal.



Der nächste Schritt besteht darin, ein Diagramm zu erstellen, in dem die Größe der Besitzpakete sichtbar ist.



Dazu müssen Sie sich mit dem Konzept des Gewichts (Gewichts) vertraut machen. Dies ist der dritte Hauptparameter, mit dem networkx arbeiten kann. Um es in die Arbeit aufzunehmen, müssen Sie einer Textdatei dieselben Gewichte hinzufügen, zum Beispiel:



# source target
 1 100
 2 100
1 2 50
1 _ 100
2 _ 100


Lassen Sie uns nun das Netzwerk mithilfe der Gewichte neu erstellen und sie in der Grafik festlegen:



# Read edge list
G = nx.read_weighted_edgelist(
    str('example2.edgelist'))
# Extract weights
weights = [d['weight'] for s, t, d in G.edges(data=True)]
nx.draw_networkx(G,pos)
labels = nx.get_edge_attributes(G,'weight')
nx.draw_networkx_edge_labels(G,pos,edge_labels=labels)
plt.gca().margins(0.15, 0.15)


* example2.edgelist ist die Datei, die oben mit Gewichten generiert wird.



Lassen Sie uns das folgende Bild bekommen:







Wem gehört wer und wie, networkx



Jetzt müssen wir als Anwalt-Programmierer verstehen, in welcher Reihenfolge und in welcher Menge Ivanov zum Beispiel Bucket_AO besitzt und ob er es überhaupt besitzt. Dies ist erforderlich, um die Tatsache des Eigentums an der verzweigten Holding und allen Ketten an die Ziel-LLC (JSC) zu bestimmen, damit diese Ketten später in der CFC-Benachrichtigung registriert werden können.



Mit networkx können Sie dies wie folgt tun:



list(nx.all_simple_paths(G,'', '_'))


Das erste Argument ist der Besitzerknoten, das zweite ist der Knoten, zu dem wir Pfade erstellen.



Mit dieser Methode können Sie sehen, dass Ivanovs Bucket_AO zu den folgenden Ketten gehört:



[['', '1', '2', '_'], ['', '2', '_']]


Dies wird grafisch bestätigt.



Sie können den Eigentumsanteil ermitteln, indem Sie die Gewichte zwischen den entsprechenden Knoten multiplizieren: 1 * 0,5 * 1 = 0,5, 1 * 1 = 1. Anteil von mehr als 25%, muss eine Benachrichtigung eingereicht werden.



Im Code erfolgt die Multiplikation mit den folgenden Krücken (eine elegantere Methode wurde noch nicht gefunden):



x=0
b=0
c=[]
for i in list(nx.all_simple_paths(G,'', '_')):    
    for a in i:        
        if x>len(i)-2:
            pass                        
        else:            
            b=int(nx.bidirectional_dijkstra(G, i[x],i[x+1])[0])#                        
            x+=1
            c.append(b/100)              
print(c)
import numpy as np
print(np.prod(c))


x=0
b=0
c=[]
for i in list(nx.all_shortest_paths(G,'', '_')):
    for a in i:        
        if x>len(i)-2:
            pass                      
        else:            
            b=int(nx.bidirectional_dijkstra(G, i[x],i[x+1])[0])#                        
            x+=1
            c.append(b/100)              
print(c)
import numpy as np
print(np.prod(c))


Im ersten Fall wird ein Bruchteil von 0,5 angezeigt, im zweiten 1.



Welche anderen Visualisierungsoptionen stehen zur Verfügung? Zum Beispiel Netwulf.



Netwulf



Die Dokumentation finden Sie hier .



Das Netzwerk selbst ist interaktiv, dies ist sein Hauptvorteil. Lassen Sie uns nach der Installation des Python-Pakets das Netzwerk erstellen:



import netwulf as nw
plt.figure(figsize=(200,200))
G = nx.read_weighted_edgelist(str('example2.edgelist'),create_using=nx.DiGraph)
pos = nx.spring_layout(G)
nw.visualize(G)


Nach dem Ausführen des Codes friert jupyter ein und in einem zusätzlichen Browserfenster, das geöffnet wird, sehen Sie das Ergebnis:







Auf der rechten Seite des Bedienfelds sehen Sie die Optionen, deren Änderung sich auf das online erstellte Netzwerk auswirkt.



Der Nachteil dieses Pakets ist, dass es noch nicht möglich ist, die Gewichte und Pfeile zwischen den Knoten anzuzeigen, aber die Autoren versprachen, es zu verfeinern.



* Um zu jupyter zurückzukehren, müssen Sie auf die Option "Post to Python" klicken:







Eine weitere gute Option für eine solche Visualisierung für Python ist das junge Webweb-Projekt.



Webweb



Die Dokumentation finden Sie hier .



Das Netzwerk ist auf ähnliche Weise aufgebaut:



from webweb import Web
web = Web(title='kitchen_sink')

web.display.networkName = 'tree'
web.display.networkLayer = 2
web.display.colorBy = 'ring'
web.display.sizeBy = 'degree'
web.display.gravity = .3
web.display.charge = 30
web.display.linkLength = 15
web.display.colorPalette = 'Greens'
web.display.scaleLinkOpacity = False
web.display.scaleLinkWidth = True

from pathlib import Path
data_dir = Path('.') / 'data'
# Read edge list
G = nx.read_edgelist('example.edgelist',create_using=nx.DiGraph)
plt.figure(figsize=(200,200))
# Draw network
pos = nx.spring_layout(G)
Web(list(G.edges)).show()






Von den klaren Vorteilen gegenüber netwulf: die Fähigkeit, Schlüsselknoten mit Farbe hervorzuheben, Textsuche nach Knoten mit Hervorhebung im Netzwerk:







Zusammenfassend können wir sagen, dass die sich entwickelnden Nachkommen von networkx - netwulf und webweb gut sind, um ein schnelles Bild der Struktur eines kleinen Betriebs zu erstellen. Beide Module verfügen über einen Einfriermodus zum Einfrieren von Knoten, die aufgrund der Interaktivität des Diagramms zusammenkleben. Selbst wenn sie verwendet werden, ist es jedoch nicht einfach, mit großen Strukturen zu arbeiten, bei denen die Anzahl der Knoten mehr als 200 beträgt.



"Podest" vom Finanzministerium, Cross- und Ringbesitz



Beim Bau solcher Strukturen wäre alles sehr gut, wenn nicht eine Sache, die das ganze Bild verdirbt. Dies liegt jedoch in der Tatsache, dass sich die Beteiligungen der Gesellschaft über andere juristische Personen besitzen. Gesichter und dies wird entweder Kreuz- oder Ringbesitz genannt.



Auf den Bildern in Briefen des Finanzministeriums (zum Beispiel vom 02.07.2013 -4-13 / 11912) sieht es so aus.



Cross-Ownership: Ringförmig







: Mal







sehen, wie networkx die Links für das Cross-Ownership-Schema der Teilnahme von D an B definiert.



Lassen Sie uns eine Kantenliste mit Links erstellen:



# source target
D B 45
B A 40
A B 55
E A 60


Nachdem Sie ein Netzwerk mit Gewichten aufgebaut haben, können Sie sehen, dass die Rückkopplung zwischen A und B nicht wiedergegeben wird:







Es ist ersichtlich, wenn Sie ein Netzwerk ohne Gewichte mit Pfeilen aufbauen:







Was ist mit den Berechnungen? Was ist der kumulierte Anteil von D an B?



Hier scheint alles transparent zu sein, 45%



Und networkx gibt mit der Befehlsliste (nx.all_simple_paths (G, 'D', 'B')) aus:

[['D', 'B']]

Aber es ist nicht so einfach.



Das Finanzministerium sagt, dass der Gesamtanteil von D an B durch die Formel bestimmt wird:







Und wird 57,69% betragen.



Was zu tun ist? networkx ist machtlos?



Networkx wird solche Situationen überhaupt nicht aufdecken, aber die Berechnungsformel wird gemäß dem „Buchstaben des Gesetzes“ unterschiedlich sein.



Das Problem kann teilweise durch Hinzufügen von

AA

BB- Einträgen zur Kantenliste behoben werden

Ferner können Sie mit der Befehlsliste (nx.nodes_with_selfloops (G)) die Knoten mit Beteiligung an sich anzeigen, dies wird jedoch bei der Bestimmung der Pfade von D nach B immer noch nicht berücksichtigt.



jupyter copybook herunterladen - hier .



All Articles