Cómo dibujar una participación, cadenas de propiedad y calcular acciones de CFC

En la práctica legal de los abogados corporativos, relativamente recientemente (hace varios años), se hizo necesario redactar y presentar notificaciones sobre empresas extranjeras controladas (CFC) en virtud del art. 25.13 del Código Fiscal de la Federación de Rusia. La esencia de esta obligación es redactar y presentar un documento, que reflejará todas las conexiones de la empresa en el holding a lo largo de las cadenas de la LLC actual (JSC) en la Federación de Rusia al propietario-fiscal residente de la Federación de Rusia CFC. En pocas palabras, si el offshore es propiedad de un ruso (residente fiscal de la Federación de Rusia), y el offshore de una LLC rusa (incluso a través de la cerca de LLC intermedios) es más del 25%, habrá una notificación. Lo más destacado es que es necesario presentar a todas las LLC (JSC) en las que se observe esta situación y presentar tanto la información sobre la propiedad de más del 25% como los cambios posteriores en la participación de la propiedad de manera oportuna, de lo contrario, multas (100,000 rublos por cada empresa de la cadena - Art. 129.6 Código Fiscal de la Federación de Rusia).Dado que la explotación (un conjunto de entidades legales) es un organismo vivo y los cambios constantes en las acciones de propiedad son inevitables, es necesario controlar de alguna manera todo esto para no cobrar multas. Cómo simplificar el trabajo en esta dirección, automatizarlo, este artículo está dedicado. El artículo también será interesante desde el punto de vista de la presentación gráfica de estructuras relacionadas, por ejemplo, sociales. redes.







En este artículo, no nos detendremos en los aspectos legales de las notificaciones enviadas sobre un CFC, sobre la participación en un CFC, consideraremos el aspecto técnico del problema.



Sin duda, si el holding en cuestión se presenta como estructuras simples del tipo LLC-> KIK-> Ruso, entonces no es práctico construir algo aquí con la participación de una máquina, es otra cuestión si la estructura se bifurca, se duplica y no hay número de estos entretejidos.



Echemos un vistazo a varias soluciones gráficas existentes que simplificarán su trabajo.

Para facilitar la visualización, se utilizarán el cuaderno jupyter y el entorno de python.



Networkx



Esta solución es la más antigua de las presentadas y no puede presumir de su interactividad. Existe el mismo artículo antiguo sobre este paquete en Habré.



Sin embargo, lo antiguo no significa malo, y esta opción es una de las más acertadas tanto a nivel de dibujo como de computación.



Instale e importe el módulo a través de jupyter:



!pip install networkx
import networkx as nx


También importamos otros complementos. módulos que te ayudarán a dibujar formas:



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})


Construyamos la primera red usando 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)


Esto es lo que sucedió:







como puede ver, Ivanov posee dos CFC, que, a su vez, poseen entidades legales rusas. por personas.



Analicemos el código de arriba.



Importamos el módulo y especificamos desde dónde leeremos los datos en el disco:



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


El directorio actual se consideró 'example.edgelist':



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


* example.edgelist es un archivo de texto sin formato como este:



# source target
 1
 2
1 2
1 _
2 _


Los valores los registra alguien con un espacio entre ellos.



A continuación, determinamos cómo se verá la red:



pos = nx.spectral_layout(G)


Si cambiamos a pos = nx.spring_layout (G), entonces tomará la forma:







Y esta disposición, por extraño que parezca, es la más adecuada para estructuras más grandes.



Finalmente, dibujamos la red, marcando las sangrías:



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


Es fácil guardar una imagen:



plt.savefig('plot.png')


Cómo dibujar un segmento en networkx



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


No







sangramos aquí, y los nombres "se fueron": Networkx opera con los conceptos de nodos y enlaces entre ellos. En nuestra situación, los nodos son Ivanov, KIK1, KIK2, Romashka_OOO, Bucket_AO. Y los enlaces son los que se encuentran en el archivo example.edgelist.



Puede ver ambos simplemente consultando los métodos G.nodes y G.edges:







Gráfico dirigido en networkx (lista de bordes dirigidos)



Aclaremos un poco la red construida, agreguemos flechas:



# 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)


Pequeños cambios hicieron posible pintar una imagen más clara de quién es dueño de quién:



En el código, como puede ver, los cambios son mínimos.



El siguiente paso es crear un gráfico donde se verá el tamaño de los paquetes de propiedad.



Para hacer esto, necesita familiarizarse con el concepto de peso (peso) es el tercer parámetro principal con el que networkx puede trabajar. Para incluirlo en el trabajo, debe agregar estos mismos pesos a un archivo de texto, por ejemplo:



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


Ahora reconstruyamos la red usando los pesos y designémoslos en el gráfico:



# 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 es el archivo que se genera arriba con pesos.



Obtenemos la siguiente imagen:







Quién es el propietario de quién y cómo, networkx



Ahora nosotros, como abogados-programadores, necesitamos entender en qué secuencia y en qué cantidad Ivanov posee, por ejemplo, la empresa Bucket_AO y si es de su propiedad. Esto es necesario para determinar el hecho de la propiedad en la explotación ramificada y todas las cadenas a la LLC objetivo (JSC), para que posteriormente estas cadenas puedan registrarse en la notificación CFC.



Con networkx, puede hacer esto de la siguiente manera:



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


El primer argumento es el nodo propietario, el segundo es el nodo al que construiremos las rutas.



Con este método, puede ver que Bucket_AO de Ivanov pertenece a las siguientes cadenas:



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


Esto se confirma gráficamente.



Puede averiguar la participación en la propiedad multiplicando los pesos entre los nodos correspondientes: 1 * 0.5 * 1 = 0.5, 1 * 1 = 1. Proporción de más del 25%, se debe enviar una notificación.



En el código, la multiplicación se realiza con las siguientes muletas (aún no se ha encontrado un método más elegante):



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))


En el primer caso mostrará una fracción de 0,5, en el segundo 1.



¿Qué otras opciones de visualización están disponibles? Por ejemplo, Netwulf.



Netwulf



La documentación está aquí .



La red en sí es interactiva, esta es su principal ventaja. Después de instalar el paquete de Python, construyamos la red:



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)


Después de ejecutar el código, jupyter se congela, y en una ventana adicional del navegador que se abre, puede ver el resultado:







En el lado derecho del panel, puede ver las opciones, cambiando las que afectan la red construida en línea.



La desventaja de este paquete es que aún no es posible mostrar los pesos y flechas entre los nodos, pero los autores prometieron refinarlo.



* para volver a jupyter, debe hacer clic en la opción "publicar en python":







Otra buena opción para una visualización de este tipo para python es el proyecto young webweb.



Webweb



La documentación está aquí .



La red está construida de manera similar:



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()






De las claras ventajas sobre netwulf: la capacidad de resaltar nodos clave con color, búsqueda de texto para nodos resaltados en la red: en







resumen, podemos decir que los descendientes en desarrollo de networkx: netwulf y webweb son buenos para construir una imagen rápida de la estructura de una pequeña explotación. Ambos módulos tienen un modo de congelación para congelar los nodos que se pegan juntos en una pila debido a la interactividad del gráfico. Sin embargo, incluso usándolos, no es fácil trabajar con estructuras a gran escala, donde el número de nodos es más de 200.



"Pedestal" del Ministerio de Finanzas, propiedad de cruz y anillo



Todo estaría muy bien a la hora de construir tales estructuras, si no fuera por una cosa que estropea todo el panorama. Sin embargo, esto radica en el hecho de que las participaciones de la empresa se poseen a través de otras entidades legales. caras y esto se llama propiedad cruzada o en anillo.



En las imágenes de las cartas del Ministerio de Finanzas (por ejemplo, del 02.07.2013 -4-13 / 11912) se ve así.



Propiedad cruzada: en forma de anillo







:







veamos cómo networkx define los vínculos para el esquema de propiedad cruzada de la participación de D en B.



Creemos un edgelist con vínculos:



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


Habiendo construido una red con pesos, puede ver que la retroalimentación entre A y B no se refleja:







se puede ver si construye una red sin pesos, con flechas:







¿Qué pasa con los cálculos? ¿Cuál es la participación acumulada de D en B?



Todo parece transparente aquí, 45%



Y networkx se rinde con la lista de comandos (nx.all_simple_paths (G, 'D', 'B')):

[['D', 'B']]

Pero no todo es tan simple.



El Ministerio de Finanzas dice que la participación total de D en B está determinada por la fórmula:







Y será 57.69%.



¿Qué hacer? networkx es impotente?



En absoluto, networkx revelará tales situaciones, pero la fórmula de cálculo será diferente, según la “letra de la ley”.



El problema se puede resolver parcialmente agregando entradas

AA

BB al edgelist

Además, con la lista de comandos (nx.nodes_with_selfloops (G)), puede ver los nodos con participación en sí mismos, pero esto aún no se tiene en cuenta al determinar las rutas de D a B.



Descarga del cuaderno jupyter - aquí .



All Articles