From 1d8267a6bfc4cb43f8b123fc7608316bf71f7469 Mon Sep 17 00:00:00 2001 From: ashyash Date: Thu, 23 Aug 2018 00:31:07 +0100 Subject: [PATCH] Amend --- .DS_Store | Bin 12292 -> 12292 bytes Codes/network_topology_analysis.ipynb | 363 ++++------- Codes/stockcomplexnetwork.py | 882 ++++++++++++++++++++++++++ 3 files changed, 1019 insertions(+), 226 deletions(-) create mode 100644 Codes/stockcomplexnetwork.py diff --git a/.DS_Store b/.DS_Store index 666d35e41cb7a482385a7712addfcc781847463c..3e5a9413e33e6fc2bae0642c8045017ad9508457 100644 GIT binary patch delta 152 zcmZokXi3;`fNk>(^b diff --git a/Codes/network_topology_analysis.ipynb b/Codes/network_topology_analysis.ipynb index 52bf0d2..20e439b 100644 --- a/Codes/network_topology_analysis.ipynb +++ b/Codes/network_topology_analysis.ipynb @@ -9,7 +9,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -46,7 +46,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -56,7 +56,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 3, "metadata": { "code_folding": [ 33, @@ -199,72 +199,6 @@ " return A" ] }, - { - "cell_type": "code", - "execution_count": 155, - "metadata": {}, - "outputs": [], - "source": [ - "D = list(range(10))" - ] - }, - { - "cell_type": "code", - "execution_count": 159, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2, 1]" - ] - }, - "execution_count": 159, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "D+D[8:0:-1]" - ] - }, - { - "cell_type": "code", - "execution_count": 158, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2, 1],\n", - " [1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2],\n", - " [2, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3],\n", - " [3, 2, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4],\n", - " [4, 3, 2, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5],\n", - " [5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6],\n", - " [6, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7],\n", - " [7, 6, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8],\n", - " [8, 7, 6, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9],\n", - " [9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8],\n", - " [8, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5, 6, 7],\n", - " [7, 8, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5, 6],\n", - " [6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5],\n", - " [5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4],\n", - " [4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 1, 2, 3],\n", - " [3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 1, 2],\n", - " [2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 1],\n", - " [1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]])" - ] - }, - "execution_count": 158, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "circulant(D+D[8:0:-1])" - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -274,7 +208,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 4, "metadata": {}, "outputs": [ { @@ -304,7 +238,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ @@ -314,7 +248,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 7, "metadata": { "code_folding": [ 24, @@ -458,7 +392,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 8, "metadata": { "code_folding": [] }, @@ -503,7 +437,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 9, "metadata": {}, "outputs": [], "source": [ @@ -534,7 +468,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 10, "metadata": {}, "outputs": [], "source": [ @@ -544,7 +478,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 11, "metadata": { "scrolled": true }, @@ -579,7 +513,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 12, "metadata": {}, "outputs": [], "source": [ @@ -611,7 +545,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 13, "metadata": {}, "outputs": [], "source": [ @@ -622,51 +556,12 @@ }, { "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([0. , 0.01515152, 0.03030303, 0.04545455, 0.06060606,\n", - " 0.07575758, 0.09090909, 0.10606061, 0.12121212, 0.13636364,\n", - " 0.15151515, 0.16666667, 0.18181818, 0.1969697 , 0.21212121,\n", - " 0.22727273, 0.24242424, 0.25757576, 0.27272727, 0.28787879,\n", - " 0.3030303 , 0.31818182, 0.33333333, 0.34848485, 0.36363636,\n", - " 0.37878788, 0.39393939, 0.40909091, 0.42424242, 0.43939394,\n", - " 0.45454545, 0.46969697, 0.48484848, 0.5 , 0.51515152,\n", - " 0.53030303, 0.54545455, 0.56060606, 0.57575758, 0.59090909,\n", - " 0.60606061, 0.62121212, 0.63636364, 0.65151515, 0.66666667,\n", - " 0.68181818, 0.6969697 , 0.71212121, 0.72727273, 0.74242424,\n", - " 0.75757576, 0.77272727, 0.78787879, 0.8030303 , 0.81818182,\n", - " 0.83333333, 0.84848485, 0.86363636, 0.87878788, 0.89393939,\n", - " 0.90909091, 0.92424242, 0.93939394, 0.95454545, 0.96969697,\n", - " 0.98484848, 1. , 1.01515152, 1.03030303, 1.04545455,\n", - " 1.06060606, 1.07575758, 1.09090909, 1.10606061, 1.12121212,\n", - " 1.13636364, 1.15151515, 1.16666667, 1.18181818, 1.1969697 ,\n", - " 1.21212121, 1.22727273, 1.24242424, 1.25757576, 1.27272727,\n", - " 1.28787879, 1.3030303 , 1.31818182, 1.33333333, 1.34848485,\n", - " 1.36363636, 1.37878788, 1.39393939, 1.40909091, 1.42424242,\n", - " 1.43939394, 1.45454545, 1.46969697, 1.48484848, 1.5 ])" - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "theta_thresholds_DR_all" - ] - }, - { - "cell_type": "code", - "execution_count": 18, + "execution_count": 15, "metadata": {}, "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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3rySkhLeeOMNCpqeNvlfe/bsIT8/H5PJxMSJE5k8ebKXIvSM1vIsLi7mvffew2g00q9fP1555RUMet15tVY89thjrY3ySTt37tReeOEFTdM07ejRo9rs2bNd4y5evKiNGzdOs9lsWk1Njeu9P3KX59mzZ7WMjAzNbrdrqqpqTzzxhFZaWuqtUG+au1yb/OlPf9Ief/xx7cMPP+zs8DzGXZ61tbXaI488opWXl2uapmmrVq1yvfc37vKsrq7WRo4cqdlsNq2qqkp74IEHvBWmR6xatUobN26c9vjjj1/zfWNjo/bggw9qVVVVms1m0yZMmKBdunTJS1HevNbytFqt2ujRozWLxaJpmqZlZmZqu3bt0l1eq+UqOTnZI9Wzs7S1u3i3bt1c3cX9kbs8b731Vt59912MRiOKomC32/26A4a7XAF27NiBoiiuafyVuzyPHj1Kv379yMnJYcqUKcTGxhJzMw3yvMhdnqGhocTHx2O1WrFarX65B9hcYmIieXl5133//fffk5iYSFRUFGazmZSUFL744gsvROgZreVpNptZu3YtoaGhAG3eFrVakJYuXXoTYXa+1rqLN4270e7ivspdnkFBQcTExKBpGjk5Odx999307dvXW6HeNHe5fvvttxQXF/Pss896KzyPcZdnZWUlhw4dYsGCBfz1r3/lvffe47TzSYN+x12eAL169eKRRx4hIyODp556yhsheszYsWNdzaSb60rbImg9T4PBQGxsLAAFBQVYLBbS0tJ0l6d7Y6y/8HR3cV/lLk8Am83GSy+9RHh4OFlZWd4I0WPc5bpp0ybKysqYNm0a58+fJygoiISEBO6//35vhdtu7vLs3r079957Lz179gRg6NChlJaW+uUPDXd5fvbZZ1y8eNF1sdSMGTNITk7ucs9I60rbIj2qqpKbm8vp06fJy8tr015vl7nsOzk5mc8++wygxe7iR44cwWazUVtb69fdxd3lqWkac+bMoX///rz66qsY3bdk9nnucl24cCHr16+noKCAjIwMnn76ab8sRuA+zwEDBvDtt99SUVGB3W6npKSEpKQkb4V6U9zlGRUVRUhICGazmeDgYLp160ZNTY23Qu0wd9xxB2fOnKGqqorGxka+/PJLhgwZ4u2wOsTSpUux2Wy88847rkN3errMHlKgdBd3l6eqqhw+fJjGxkY+//xzwPm8JX/9D6/3N+0q9PKcP38+M2fOBOCXv/yl3/6Y0stz//79TJ48GYPBQHJycpsO8fiLrVu3YrFYeOKJJ1i0aBEzZsxA0zQmTpzY4u01/qopz3vuuYfCwkKGDh3KtGnTAHjqqad0r5zUba4qhBBCdIYuc8hOCCGEf5OCJIQQwidIQRJCCOETpCAJIYTwCVKQhBBC+AQpSEK0QW1tLXPmzOHcuXOkp6d7fPlTp07l0KFDbZ4+Ly+vxZYtRUVFLFq0yJOhCdFppCAJ0QbV1dV+2/9QCH/RZW6MFaIjZWdnc/HiRZYtW0ZDQwOZmZmcOnWKyMhI8vPziY6OJjU1lQEDBnD58mUKCwtZs2YN27dvx+FwcN999/H8889TX1/Pc889x+XLlwGYO3eu6ybf9evXk5OTQ3V1NYsXLyY9PZ3Lly+zePFiLly4gMlkIjMz87qOFJs2bWLlypVERESQkJBAWFhYp//7COEJsockRBssWbKEuLg4XnzxRSoqKpg+fTrFxcXExsaybds2wNkIddasWWzevJkDBw5w4sQJCgsLXX33tmzZwieffEJCQgJFRUXk5uby5ZdfutYRGRlJUVERS5YsIT8/H4DXXnuN1NRUtm7dyttvv81LL73kKmYAZWVlvPHGG/z9739n3bp11/RJE8LfyB6SEDcoLi7O1fQzKSmJyspK17hBgwYBcODAAY4fP86ECRMAaGhoID4+nokTJ7JixQrKysp44IEHmDt3rmveBx988LplHjx4kOzsbAB69+7NoEGDKCkpcc1z9OhRhgwZ4uqs/Oijj3Lw4MGOSl2IDiUFSYgb1Ly7uqIoNO++FRISAoDD4WDatGlMnz4dgJqaGoxGI+Hh4Wzfvp3PP/+cvXv3snr1arZv3w7gaobbvCvyzzt7aZqGw+G4Zv2qqrYYmxD+Rg7ZCdEGJpPpmmf36ElNTWXz5s3U19djt9uZO3cuO3fu5IMPPiAvL49f/epXZGVlUVFRQW1trdvlFBYWAvCf//yHr776isGDB7vGp6SkUFJSQllZGaqqug4fCuGP5OeUEG3Qo0cP4uPjefHFF9s0fXp6OidPnmTy5Mk4HA5GjBhBRkaG66KGRx99FJPJxLx584iMjGx1OYsXL2bp0qUUFRUBzosr4uLiXONjY2NZsmQJTz/9NKGhoX77aAohQLp9CyGE8BFyyE4IIYRPkIIkhBDCJ0hBEkII4ROkIAkhhPAJUpCEEEL4BClIQgghfIIUJCGEED5BCpIQQgif8P9Pnn3iaTbTUgAAAABJRU5ErkJggg==\n", "text/plain": [ "
" ] @@ -1581,7 +1476,7 @@ }, { "cell_type": "code", - "execution_count": 1353, + "execution_count": 16, "metadata": {}, "outputs": [], "source": [ @@ -1603,7 +1498,7 @@ }, { "cell_type": "code", - "execution_count": 1370, + "execution_count": 17, "metadata": {}, "outputs": [ { @@ -1612,7 +1507,7 @@ "51037" ] }, - "execution_count": 1370, + "execution_count": 17, "metadata": {}, "output_type": "execute_result" } @@ -1641,7 +1536,7 @@ }, { "cell_type": "code", - "execution_count": 1371, + "execution_count": 18, "metadata": {}, "outputs": [ { @@ -1650,7 +1545,7 @@ "1418" ] }, - "execution_count": 1371, + "execution_count": 18, "metadata": {}, "output_type": "execute_result" } @@ -1661,42 +1556,141 @@ }, { "cell_type": "code", - "execution_count": 1372, + "execution_count": 45, "metadata": {}, "outputs": [ { - "ename": "NetworkXError", - "evalue": "Graph is not connected.", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mNetworkXError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mnx\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0maverage_shortest_path_length\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mG_conv\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;32m~/networkx/networkx/algorithms/shortest_paths/generic.py\u001b[0m in \u001b[0;36maverage_shortest_path_length\u001b[0;34m(G, weight)\u001b[0m\n\u001b[1;32m 322\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mnx\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mNetworkXError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Graph is not weakly connected.\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 323\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mG\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mis_directed\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mnx\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mis_connected\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mG\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 324\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mnx\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mNetworkXError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Graph is not connected.\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 325\u001b[0m \u001b[0;31m# Compute all-pairs shortest paths.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 326\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mweight\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mNetworkXError\u001b[0m: Graph is not connected." - ] + "data": { + "text/plain": [ + "51037" + ] + }, + "execution_count": 45, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ - "nx.average_shortest_path_length(G_conv)" + "G_conv.number_of_edges()" ] }, { "cell_type": "code", - "execution_count": 1357, + "execution_count": 28, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "51025.5" + "42.305273488434125" ] }, - "execution_count": 1357, + "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], + "source": [ + "np.mean([a[1] for a in list(G_conv.degree(weight='corr'))])" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [], + "source": [ + "a=nx.betweenness_centrality(G_conv)" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": {}, + "outputs": [], + "source": [ + "b=nx.algorithms.degree_assortativity_coefficient(G_int, weight='corr')" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.06138005376924545" + ] + }, + "execution_count": 44, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "b" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.0007464209710184614" + ] + }, + "execution_count": 38, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.mean(list(a.values()))" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "ename": "IndexError", + "evalue": "string index out of range", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mIndexError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmean\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mx\u001b[0m \u001b[0;32min\u001b[0m \u001b[0ma\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m(.0)\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmean\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mx\u001b[0m \u001b[0;32min\u001b[0m \u001b[0ma\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mIndexError\u001b[0m: string index out of range" + ] + } + ], + "source": [ + "np.mean([x[1] for x in a])" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'G' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mG\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnumber_of_edges\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m/\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mNameError\u001b[0m: name 'G' is not defined" + ] + } + ], "source": [ "G.number_of_edges() / 2" ] @@ -3024,27 +3018,6 @@ "powerlaw.plot_pdf(data, linear_bins = False, color = 'b');" ] }, - { - "cell_type": "code", - "execution_count": 1418, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "fig = plt.figure()\n", - "ax = fig.add_subplot()\n", - "ax." - ] - }, { "cell_type": "code", "execution_count": 1425, @@ -3100,13 +3073,6 @@ "powerlaw.plot_pdf(data, linear_bins = False, color = 'b');" ] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, { "cell_type": "markdown", "metadata": {}, @@ -3578,9 +3544,9 @@ " nodes_g = list(UndiG[i])\n", " n = len(nodes_g)\n", " if n > 0:\n", - " nodes_g.append(i)\n", + " #nodes_g.append(i)\n", " print('(%s)'%n, end=' ')\n", - " acc += calGlobalEfficiency(G.subgraph(nodes_g), nodes_g, n+1)\n", + " acc += calGlobalEfficiency(G.subgraph(nodes_g), nodes_g, n)\n", " return acc/G.number_of_nodes()" ] }, @@ -3811,23 +3777,6 @@ "calLocalEfficiency(G_rd)" ] }, - { - "cell_type": "code", - "execution_count": 1335, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Email sent!\n" - ] - } - ], - "source": [ - "SendEmail('LocalEfficiency Done!')" - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -4330,26 +4279,6 @@ "over_best_asgn = best_asgn.copy()" ] }, - { - "cell_type": "code", - "execution_count": 132, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "1" - ] - }, - "execution_count": 132, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "int(G.node['A']['community'])" - ] - }, { "cell_type": "code", "execution_count": 18, @@ -6762,24 +6691,6 @@ "colors = list(dict(mpl.colors.BASE_COLORS, **mpl.colors.CSS4_COLORS).values())" ] }, - { - "cell_type": "code", - "execution_count": 142, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "130" - ] - }, - "execution_count": 142, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [] - }, { "cell_type": "code", "execution_count": 145, @@ -7931,7 +7842,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### 随机选择部分结点生成网络" + "### Randomly choose some nodes to generate network" ] }, { @@ -10099,7 +10010,7 @@ }, { "cell_type": "code", - "execution_count": 1281, + "execution_count": 42, "metadata": {}, "outputs": [], "source": [ diff --git a/Codes/stockcomplexnetwork.py b/Codes/stockcomplexnetwork.py new file mode 100644 index 0000000..4adbc98 --- /dev/null +++ b/Codes/stockcomplexnetwork.py @@ -0,0 +1,882 @@ +from __future__ import division +import logging +import logging.config +import sys, csv, time, requests, statsmodels, math +from sklearn.linear_model import LinearRegression +from statsmodels.tsa.stattools import coint, adfuller, grangercausalitytests +import statsmodels.api as sm +from scipy import stats +import scipy.special +from scipy.stats import describe +from scipy.linalg import circulant +from contextlib import contextmanager +from datetime import datetime, timedelta +from dateutil.parser import parse +import collections +import random +import scipy.stats as ss +import seaborn as sns +import matplotlib.pyplot as plt +from matplotlib.lines import Line2D +import matplotlib as mpl +import pylab +import powerlaw +import networkx as nx +from networkx.algorithms import community +import pandas as pd +import numpy as np +from core import SendEmail, ROOTPATH, sri_SP500_log_return, sri_SP500_close +from preprocess_stocks import lst_tickers_stp, LENTCKR, LENTRGL, df_codes_and_title, DICT_STP, getIndustryCodeByStockCode + +sns.set(color_codes=True) +data_dir = ROOTPATH + r'/Codes' + +# function for generating PGD +def genPureDedirectedGraph(theta_1, theta_2, mat_1, mat_2): + G = nx.DiGraph() + G.add_nodes_from(lst_tickers_stp) + for i in lst_tickers_stp: + #print(i, end=' ') + matidx_i = EIO_industry_BEA_code_list.index( + df_codes_and_title.loc[i, 'BEA']) + for j in lst_tickers_stp: + if i != j: + matidx_j = EIO_industry_BEA_code_list.index( + df_codes_and_title.loc[j, 'BEA']) + a = mat_1[matidx_i, matidx_j] + b = mat_2[matidx_i, matidx_j] + if a > 0.0 and a > theta_1: + G.add_edge(i, j) + if b > 0.0 and b > theta_2: + G.add_edge(j, i) + return G + +def genWDGraphFromPureDirectedGraph(PGD, return_list, threshold=-1): + G = nx.DiGraph() + G.add_nodes_from(lst_tickers_stp) + for n, nbrs in PGD.adj.items(): + S1 = return_list[n] + for nbr, eattr in nbrs.items(): + S2 = return_list[nbr] + corr = S1.corr(S2) + if corr >= threshold: G.add_edge(n, nbr, corr=corr) + return G + +# function for generating PCGD +# generate partial correlation directed graph +def genPartCorrGraph(UGD): + G = nx.DiGraph() + G.add_nodes_from(lst_tickers_stp) + for n, nbrs in UGD.adj.items(): + for nbr, eattr in nbrs.items(): + G.add_edge(n, nbr, weight=eattr['corr']) + return G + +# function for generating ECGU +# generate entire correlation undirected graph +def genEntCorrGraph(): + G = nx.Graph() + G.add_nodes_from(lst_tickers_stp) + for i in range(LENTCKR): + S1 = df_stock_abr[lst_tickers_stp[i]] + for j in range(i+1, LENTCKR): + S2 = df_stock_abr[lst_tickers_stp[j]] + G.add_edge(n, nbr, weight=S1.corr(S2)) + return G + +def rmvEdgeAttrOfGraph(WG): + G = WG.copy() + for n, nbrs in G.adj.items(): + for nbr, eattr in nbrs.items(): + if 'corr' in eattr: del eattr['corr'] + return G + +def rmvIndepNodesFromGraph(WholeG): + G = WholeG.copy() + for n in WholeG.nodes(): + if WholeG.degree(n) == 0: G.remove_node(n) + return G + +def _distance_matrix(L): + Dmax = L//2 + + D = list(range(Dmax+1)) + D += D[-2+(L%2):0:-1] + + return circulant(D)/Dmax + +def _pd(d, p0, beta): + return beta*p0 + (d <= p0)*(1-beta) + +def watts_strogatz(L, p0, beta, directed=False, rngseed=1): + """ + Watts-Strogatz model of a small-world network + + This generates the full adjacency matrix, which is not a good way to store + things if the network is sparse. + + Parameters + ---------- + L : int + Number of nodes. + + p0 : float + Edge density. If K is the average degree then p0 = K/(L-1). + For directed networks "degree" means out- or in-degree. + + beta : float + "Rewiring probability." + + directed : bool + Whether the network is directed or undirected. + + rngseed : int + Seed for the random number generator. + + Returns + ------- + A : (L, L) array + Adjacency matrix of a WS (potentially) small-world network. + + """ + rng = np.random.RandomState(rngseed) + + d = _distance_matrix(L) + p = _pd(d, p0, beta) + + if directed: + A = 1*(rng.random_sample(p.shape) < p) + np.fill_diagonal(A, 0) + else: + upper = np.triu_indices(L, 1) + + A = np.zeros_like(p, dtype=int) + A[upper] = 1*(rng.rand(len(upper[0])) < p[upper]) + A.T[upper] = A[upper] + + return A + +dct_title_amt = dict(df_codes_and_title['Title'].value_counts()) +dct_BEA_amt = dict(df_codes_and_title['BEA'].value_counts()) + +def genEIODirectMatrix(directType, tradeoff = True, to_log = True): + global dct_title_amt + global EIO_industry_title_list + industry_list = EIO_industry_title_list + EIO_direct_matrix = np.matrix( + np.zeros( + (len(industry_list), + len(industry_list)), + dtype=np.float64)) + if directType is 'requirements': + for i in range(len(industry_list)): + for j in range(len(industry_list)): + if EIO_matrix[i, j] > 0: + m = np.float64(EIO_matrix[i, j]) / EIO_matrix[-1, j] + if tradeoff and industry_list[i] in dct_title_amt: + m /= dct_title_amt[industry_list[i]] + EIO_direct_matrix[i, j] = logarise(m) if to_log else m + elif directType is 'demands': + for i in range(len(industry_list)): + for j in range(len(industry_list)): + if EIO_matrix[i, j] > 0: + m = np.float64(EIO_matrix[i, j]) / EIO_matrix[i, -1] + if tradeoff and industry_list[j] in dct_title_amt: + m /= dct_title_amt[industry_list[j]] + EIO_direct_matrix[i, j] = logarise(m) if to_log else m + else: return None + return EIO_direct_matrix + +def getAllMatrixContent(mat): + arr = [] + for m in mat: + arr = np.append(arr, np.array(m)[0]) + return arr + +def getNonzeroMatrixContent(mat): + arr = [] + for m in mat: + ar_m = np.array(m)[0] + ar_m = ar_m[ar_m!=0] + arr = np.append(arr, ar_m) + return arr + +def genEdgeDensity(lst, bins=100): + theta_thresholds = np.linspace(np.floor(min(lst)*10.0)/10.0, np.ceil(max(lst)*10.0)/10.0, bins) + edge_densities = [] + n = 0 + LENLST_FLOAT = np.float(len(lst)) + for theta in theta_thresholds: + n += 1 + #print(n, end=' ') + edge_densities.append(sum(corr >= theta for corr in lst)/LENLST_FLOAT) + return theta_thresholds, edge_densities + +def logarise(n): return 0.0 if n == 0 else -1.0/np.log10(n) + +def combineThresholds(thresholds_1, thresholds_2, mat_1, mat_2): + LENMAT = mat_1.shape[0] + df = pd.DataFrame( + index=range(len(thresholds_1)*len(thresholds_2)), + columns=['theta_DR', 'theta_DD', 'no_directions']) + idx = 0 + print(len(thresholds_1), end='') + for t1 in thresholds_1: + print('.', end='') + exceeded = False + for t2 in thresholds_2: + cnt = 0 + if not exceeded: + for i in range(LENMAT): + for j in range(LENMAT): + a = mat_1[i, j] + b = mat_2[i, j] + if (a > 0.0 and a > t1) or (b > 0.0 and b > t2): + cnt += 1 + if cnt == 0: exceeded = True + df.iloc[idx,:] = [t1, t2, cnt] + idx += 1 + return df + +def combineThresholdsOfEIOAndCorrForAmtOfEdges(thresholds_eio, thresholds_corr, FG): + global lst_tickers_stp + df = pd.DataFrame( + index=range(len(thresholds_eio)*len(thresholds_corr)), + columns=['theta_EIO', 'theta_corr', 'no_edges']) + idx = 0 + numrow = 0 + for t1 in thresholds_eio: + print('[%s]' % numrow) + exceeded = False + for t2 in thresholds_corr: + cnt = 0 + if not exceeded: + for n, nbrs in FG.adj.items(): + for nbr, eattr in nbrs.items(): + if ('direct_requirement' in eattr and eattr['direct_requirement'] > t1) or ('direct_demand' in eattr and (eattr['direct_demand'] > t1)): + if eattr['corr'] > t2: cnt += 1 + if cnt == 0: exceeded = True + print(cnt, end=' ') + df.iloc[idx,:] = [t1, t2, cnt] + idx += 1 + numrow += 1 + return df + +def combineThresholdsOfEIOAndCorrForIsWeaklyConnected(thresholds_eio, thresholds_corr, FG): + global lst_tickers_stp + df = pd.DataFrame( + index=range(len(thresholds_eio)*len(thresholds_corr)), + columns=['EIO', 'corr', 'is_weakly_connected']) + idx = 0 + for t1 in thresholds_eio: + for t2 in thresholds_corr: + G = nx.DiGraph() + G.add_nodes_from(lst_tickers_stp) + for n, nbrs in FG.adj.items(): + for nbr, eattr in nbrs.items(): + if ('direct_requirement' in eattr and eattr['direct_requirement'] > t1) or ('direct_demand' in eattr and (eattr['direct_demand'] > t1)): + if eattr['corr'] > t2: G.add_edge(n, nbr) + G = rmvIndepNodesFromGraph(G) + print(G.number_of_nodes(), end=' ') + if G.number_of_nodes() > 0: + is_weakly_c = nx.is_weakly_connected(G) + print(is_weakly_c, end=' ') + df.iloc[idx,:] = [t1, t2, is_weakly_c] + else: + print('Nill', end=' ') + df.iloc[idx,:] = [t1, t2, False] + idx += 1 + return df + +def continueCombineThresholdsOfEIOAndCorrForIsWeaklyConnected(thresholds_eio, thresholds_corr, FG, start_point): + global df + i = 0 + idx = start_point + cnt = 0 + for t1 in thresholds_eio: + print('[%s]' % cnt) + for t2 in thresholds_corr: + if i < start_point: + i += 1 + continue + G = nx.DiGraph() + G.add_nodes_from(lst_tickers_stp) + for n, nbrs in FG.adj.items(): + for nbr, eattr in nbrs.items(): + if ('direct_requirement' in eattr and eattr['direct_requirement'] > t1) or ('direct_demand' in eattr and (eattr['direct_demand'] > t1)): + if eattr['corr'] > t2: G.add_edge(n, nbr) + G = rmvIndepNodesFromGraph(G) + print(G.number_of_nodes(), end=' ') + if G.number_of_nodes() > 0: + is_weakly_c = nx.is_weakly_connected(G) + print(is_weakly_c, end=' ') + df.iloc[idx,:] = [t1, t2, is_weakly_c] + else: + print('Nill', end=' ') + df.iloc[idx,:] = [t1, t2, False] + idx += 1 + cnt += 1 + +FILE_EIO_2016 = ROOTPATH + '/Source/lxl/EIO_2016.csv' +EIO_matrix = np.matrix(np.genfromtxt(open(FILE_EIO_2016, 'rb'), delimiter=',', skip_header=2)) +EIO_industry_BEA_code_list = list(pd.read_csv(FILE_EIO_2016, nrows=0).columns)[:-2] +EIO_industry_title_list = list(pd.read_csv(FILE_EIO_2016, skiprows=1).columns)[:-2] +FILE_STOCK_ABR = ROOTPATH + r'/Source/DF_STOCK_ABR.csv' +df_stock_abr = pd.read_csv(FILE_STOCK_ABR).set_index('Date') +df_stock_normal_return = pd.DataFrame(index=df_stock_abr.index, columns=df_stock_abr.columns) +for i in DICT_STP: df_stock_normal_return[i] = DICT_STP[i]['log_return'] + +EIO_direct_requirements_matrix = genEIODirectMatrix('requirements', tradeoff=True, to_log=True) +EIO_direct_demands_matrix = genEIODirectMatrix('demands', tradeoff=True, to_log=True) + +ar_all_DR_Mat = getAllMatrixContent(EIO_direct_requirements_matrix) +ar_all_DD_Mat = getAllMatrixContent(EIO_direct_demands_matrix) + +ar_all_DR_trans = [i for i in ar_all_DR_Mat] +ar_all_DD_trans = [i for i in ar_all_DD_Mat] + +theta_thresholds_DR_all, edge_densities_DR_all = genEdgeDensity(ar_all_DR_trans, 100) +theta_thresholds_DD_all, edge_densities_DD_all = genEdgeDensity(ar_all_DD_trans, 100) + +ar_nonzero_DR_Mat = getNonzeroMatrixContent(EIO_direct_requirements_matrix) +ar_nonzero_DD_Mat = getNonzeroMatrixContent(EIO_direct_demands_matrix) + +ar_nonzero_DR_trans = [i for i in ar_nonzero_DR_Mat] +ar_nonzero_DD_trans = [i for i in ar_nonzero_DD_Mat] + +theta_thresholds_DR, edge_densities_DR = genEdgeDensity(ar_nonzero_DR_trans, 100) +theta_thresholds_DD, edge_densities_DD = genEdgeDensity(ar_nonzero_DD_trans, 100) + +b1 = np.append(1.0, edge_densities_DR_all) +b1[1] = b1[2] +b2 = np.append(0, theta_thresholds_DR_all) + +x_dashline = 0.136 +fig = plt.figure() +ax = fig.add_subplot(2,1,1) +ax.set_xlabel('threshold') +ax.set_ylabel('Transaction density') +ax.set_xlim(left=-0.05, right=1.2) +ax.set_title('Normalised Direct Requirement', fontsize='large') +dashed_line = Line2D([x_dashline, x_dashline], [-1.05, 1.05], linestyle = '--', linewidth = 1, color = [0.3,0.3,0.3], zorder = 1, transform = ax.transData) +ax.lines.append(dashed_line) +ax.plot(b2, b1, color='blue', lw=2) +ax = fig.add_subplot(2,1,2) +ax.set_xlabel('threshold') +ax.set_ylabel('Transaction density') +ax.set_title('Normalised Direct Demand', fontsize='large') +dashed_line = Line2D([x_dashline, x_dashline], [-0.05, 1.05], linestyle = '--', linewidth = 1, color = [0.3,0.3,0.3], zorder = 1, transform = ax.transData) +ax.lines.append(dashed_line) +ax.set_xlim(left=-0.05, right=1.2) +ax.plot(b2, b1, color='blue', lw=2) +fig.tight_layout() + +df_combined_thresholds = combineThresholds( + theta_thresholds_DR, + theta_thresholds_DD, + EIO_direct_requirements_matrix, + EIO_direct_demands_matrix) + +pt = df_combined_thresholds.pivot_table(index='theta_DR', columns='theta_DD', values='no_directions', aggfunc=np.sum) +f, ax = plt.subplots(figsize = (10, 4)) +sns.heatmap(pt.iloc[:30,:20], cmap='rainbow', linewidths = 0.05, ax = ax) +ax.set_title('Amounts of directions per DR-threshold and DD-threshold') +ax.set_xlabel('theta_DD') +ax.set_ylabel('theta_DR') + +def genFullGraph(stock_return_df): + global lst_tickers_stp + global EIO_industry_BEA_code_list + global EIO_direct_requirements_matrix + G = nx.DiGraph() + G.add_nodes_from(lst_tickers_stp) + for i in lst_tickers_stp: + #print(i, end=' ') + matidx_i = EIO_industry_BEA_code_list.index(df_codes_and_title.loc[i, 'BEA']) + S1 = stock_return_df[i] + for j in lst_tickers_stp: + if i != j: + matidx_j = EIO_industry_BEA_code_list.index(df_codes_and_title.loc[j, 'BEA']) + if EIO_direct_requirements_matrix[matidx_i, matidx_j] > 0: + G.add_edge(i, j, direct_requirement = EIO_direct_requirements_matrix[matidx_i, matidx_j]) + if EIO_direct_demands_matrix[matidx_j, matidx_i] > 0: + G.add_edge(i, j, direct_demand = EIO_direct_demands_matrix[matidx_j, matidx_i]) + if G.has_edge(i, j): G.add_edge(i, j, corr=S1.corr(stock_return_df[j])) + return G + +FullG = genFullGraph(df_stock_normal_return) +direct_requirements_CN = [] +direct_demands_CN = [] +for n, nbrs in FullG.adj.items(): + for nbr, eattr in nbrs.items(): + if 'direct_requirement' in eattr.keys(): + direct_requirements_CN.append(eattr['direct_requirement']) + if 'direct_demand' in eattr.keys(): + direct_demands_CN.append(eattr['direct_demand']) + +corr_coef_CN = [] +for n, nbrs in FullG.adj.items(): + for nbr, eattr in nbrs.items(): + corr_coef_CN.append(eattr['corr']) + +plt.hist(corr_coef_CN, density=1, bins=260, histtype='bar') +plt.axis([-0.5, 1, 0, 3.2]) +plt.xlabel('correlation') +plt.ylabel('p(correlation)') + +describe(corr_coef_CN) + +corr_mean = np.mean(corr_coef_CN) +corr_std = np.std(corr_coef_CN) +corr_coef_CN_00 = [(i - corr_mean)/corr_std for i in corr_coef_CN] + +stats.probplot(corr_coef_CN, dist='norm', plot=pylab) +pylab.show() + +sm.qqplot(np.array(corr_coef_CN_00), line='45',) +pylab.show() + +ss.kstest(corr_coef_CN_00, 'norm') + +theta_thresholds_corr, edge_densities_corr = genEdgeDensity(corr_coef_CN, 100) + +fig = plt.figure() +ax = fig.add_subplot(1,1,1) +ax.set_xlabel('threshold') +ax.set_ylabel('Edge density') +ax.set_title('Correlation Coefficient', fontsize='large') +ax.plot(theta_thresholds_corr, edge_densities_corr, color='blue', lw=2) +fig.tight_layout() + +recalc = False +npzfile_name = data_dir + '/pt_cteac_0719.npz' +pt_cteac = None +if recalc == True: + df = pd.DataFrame( + index=range(len(theta_thresholds_DR)*len(theta_thresholds_corr)), + columns=['EIO', 'corr', 'is_weakly_connected']) + continueCombineThresholdsOfEIOAndCorrForIsWeaklyConnected( + theta_thresholds_DR, theta_thresholds_corr, FullG, 0) + df_cteac = df.copy() + pt_cteac = df_cteac.pivot_table( + index = 'EIO', columns='corr', + values = 'is_weakly_connected', aggfunc=np.sum) + outfile = open(npzfile_name, 'wb') + np.savez(outfile, ar_cteac=pt_cteac, col=pt_cteac.columns, ind=pt_cteac.index) + outfile.close() +else: + infile = open(npzfile_name, 'rb') + npzfile = np.load(infile) + infile.close() + ar_cteac = npzfile['ar_cteac'] + pt_cteac = pd.DataFrame(ar_cteac) + pt_cteac.columns = npzfile['col'] + pt_cteac.index = npzfile['ind'] + +f, ax = plt.subplots(figsize = (10, 4)) +sns.heatmap(pt_cteac.iloc[5:50,20:90], cmap='rainbow', linewidths = 0.05, ax = ax) +ax.set_title('Amounts of directions per DR-threshold and DD-threshold') +ax.set_xlabel('corr') +ax.set_ylabel('EIO'); + +recalc = True +npzfile_name = data_dir + '/pt_toeacfaoe_0719.npz' +pt_toeacfaoe = None +if recalc == True: + df_toeacfaoe = combineThresholdsOfEIOAndCorrForAmtOfEdges( + theta_thresholds_DR, theta_thresholds_corr, FullG) + pt_toeacfaoe = df_toeacfaoe.pivot_table( + index = 'theta_EIO', columns='theta_corr', + values = 'no_edges', aggfunc=np.sum) + outfile = open(npzfile_name, 'wb') + np.savez(outfile, ar_toeacfaoe=pt_toeacfaoe, + col=pt_toeacfaoe.columns, ind=pt_toeacfaoe.index) + outfile.close() +else: + infile = open(npzfile_name, 'rb') + npzfile = np.load(infile) + infile.close() + ar_toeacfaoe = npzfile['ar_toeacfaoe'] + pt_toeacfaoe = pd.DataFrame(ar_cteac) + pt_toeacfaoe.columns = npzfile['col'] + pt_toeacfaoe.index = npzfile['ind'] + +pt_toeacfaoe.index = [round(i, 4) for i in pt_toeacfaoe.index] +pt_toeacfaoe.columns = [round(i, 4) for i in pt_toeacfaoe.columns] + +f, ax = plt.subplots(figsize = (10, 4)) +sns.heatmap(pt_toeacfaoe.iloc[:24,:81], cmap='gist_ncar', linewidths = 0.05, ax = ax) +ax.set_xlabel(r'$\theta_{corr}$') +ax.set_ylabel(r'$\theta_{EIO}$'); + +threshold_eio = 0.29225 +threshold_corr = 0.378705 +DiUnwtG = genPureDedirectedGraph( + threshold_eio, #0.35 + threshold_eio, #0.35 + EIO_direct_requirements_matrix, + EIO_direct_demands_matrix) + +G = genWDGraphFromPureDirectedGraph(DiUnwtG, df_stock_normal_return, threshold_corr) +nonodes = G.number_of_nodes() +noedges = G.number_of_edges() +DiG_pureedge = rmvEdgeAttrOfGraph(G) +DiG_connected = rmvIndepNodesFromGraph(DiG_pureedge) + +def genConventionalGraph(theta, return_list): + global LENTCKR + global lst_tickers_stp + G = nx.Graph() + G.add_nodes_from(lst_tickers_stp) + for i in range(LENTCKR): + T1 = lst_tickers_stp[i] + S1 = return_list[T1] + for j in range(i+1, LENTCKR): + T2 = lst_tickers_stp[j] + S2 = return_list[T2] + corr = S1.corr(S2) + if corr > theta: G.add_edge(T1, T2, corr=corr) + return G + +G_conv = genConventionalGraph(0.4983, df_stock_normal_return) +G_conv.number_of_edges() + +data = [d for n, d in G.out_degree()] +plt.hist(data, density=1, bins=50, histtype='bar'); +fit = powerlaw.Fit(data) +fit.distribution_compare('power_law', 'lognormal') + +fig4 = fit.plot_ccdf(linewidth = 2) +fit.power_law.plot_ccdf(ax = fig4, color = 'r', linestyle = '--'); +fig4.set_xlabel('centrality') +fig4.set_ylabel('$p(X\geq x)$') +fig4.legend(('CCDF','Power-law fit')) +set_size(4,4,fig4) + +data = [d for n, d in G_rd.out_degree()] +plt.hist(data, density=1, bins=50, histtype='bar'); + +stats.probplot([d for n, d in G_rd.out_degree()], dist='norm', plot=pylab) + +fig = sns.distplot([d for n, d in G_rd.out_degree()]) +fig.set_xlabel('out-degree') +fig.set_ylabel('p(out-degree)') + +data = [d for n, d in G_ws_mat.out_degree()] +plt.hist(data, density=1, bins=50, histtype='barstacked'); + +data = [d for n, d in G_ws_mat.out_degree() if d > 0] +powerlaw.plot_pdf(data, linear_bins = False, color = 'b'); + +fig = plt.figure() +ax = fig.add_subplot(1,1,1) +data = [d for n, d in G.out_degree() if d > 0] +powerlaw.plot_pdf(data, linear_bins = False, color = 'b') +ax.set_xlabel('out-degree') +ax.set_ylabel('p(out-degree)') +set_size(4,4,ax) + +data = [d for n, d in G.in_degree() if d > 0] +powerlaw.plot_pdf(data, linear_bins = False, color = 'b'); + +data = [d for n, d in G.degree() if d > 0] +powerlaw.plot_pdf(data, linear_bins = False, color = 'b'); + +p0 = np.average([i[1] for i in G.out_degree()])/(nonodes-1) +ws_mat = watts_strogatz(L=nonodes, p0=p0, beta=0.5, directed=True) +G_ws_mat=nx.from_numpy_matrix(ws_mat, create_using=nx.DiGraph()) +G_ws_mat.number_of_edges() + +p = noedges / nonodes / (nonodes-1) +G_rd = nx.generators.gnp_random_graph(nonodes, p=p, directed=True) +G_rd.number_of_edges() + +def calGlobalEfficiency(G, lst_nodes, N): #N = 0, + #if N == 0: N = G.number_of_nodes() + #if lst_nodes == None: lst_nodes = G.nodes() + shortest_path = nx.shortest_path(G) + acc = 0.0 + for i in lst_nodes: + for j in lst_nodes: + if i != j and (j in shortest_path[i]): + acc += 1.0/(len(shortest_path[i][j])-1) + return acc/N/(N-1) + +def calLocalEfficiency(G): + UndiG = G.to_undirected() + lst_nodes = G.nodes() + acc = 0.0 + for i in lst_nodes: + print(i, end='') + nodes_g = list(UndiG[i]) + n = len(nodes_g) + if n > 0: + #nodes_g.append(i) + print('(%s)'%n, end=' ') + acc += calGlobalEfficiency(G.subgraph(nodes_g), nodes_g, n) + return acc/G.number_of_nodes() + +calGlobalEfficiency(DiG_connected, G.number_of_nodes()) +calGlobalEfficiency(G_ws_mat) +calLocalEfficiency(G) + +def detectCommunityForDirectedGraph(G): + lst_node = list(G.nodes) + NONODES = G.number_of_nodes() + NOEDGES = G.number_of_edges() + NOINDEGREES = G.in_degree() + NOOUTDEGREES = G.out_degree() + overall_asgn = [(0, 0)] * NONODES + + def getNodeSpace(node_space, upd_asgn, val): + return [node_space[i] for i in range(len(upd_asgn)) if upd_asgn[i] == val] + ''' + def fineTune(node_space, upd_asgn): + nonlocal G + nonlocal overall_asgn + nonlocal NONODES + for i in upd_asgn: + for j in node_space: +''' + def interateBisection(mod_mat, node_space, generation_mark): + nonlocal G + nonlocal overall_asgn + upd_asgn = subdivideCommunities(mod_mat) + # todo: fine-tune + + if len(np.unique(upd_asgn)) == 1: return + delta_Q = calDeltaQ(upd_asgn, mod_mat) + print('calDeltaQ: %s' % delta_Q) + if delta_Q < 0: return + node_space_1 = getNodeSpace(node_space, upd_asgn, -1) + if len(node_space_1) == 0: return + updCommunityAssignment(node_space_1, upd_asgn, generation_mark) + print('genGeneralisedModularityMatrix_1: %s:%s:%s' % (time.localtime()[3],time.localtime()[4],time.localtime()[5])) + mod_mat_1 = genGeneralisedModularityMatrix(node_space_1) + interateBisection(mod_mat_1, node_space_1, generation_mark+1) + node_space_2 = getNodeSpace(node_space, upd_asgn, 1) + if len(node_space_2) == 0: return + updCommunityAssignment(node_space_2, upd_asgn, generation_mark) + print('genGeneralisedModularityMatrix_2: %s:%s:%s' % (time.localtime()[3],time.localtime()[4],time.localtime()[5])) + mod_mat_2 = genGeneralisedModularityMatrix(node_space_2) + interateBisection(mod_mat_2, node_space_2, generation_mark+1) + return + + def genGeneralisedModularityMatrix(node_space):# Subgraph + nonlocal G + nonlocal lst_node + nonlocal NOEDGES + nonlocal NOINDEGREES + nonlocal NOOUTDEGREES + nonlocal overall_asgn + LENNODESPECE = len(node_space) + mod_mat = np.matrix(np.zeros((LENNODESPECE, LENNODESPECE), dtype=np.float64)) + for i in range(LENNODESPECE): + print(i, end=' ') + tckr_i = lst_node[node_space[i]] + for j in range(LENNODESPECE): + tckr_j = lst_node[node_space[j]] + Bij = G.has_edge(tckr_j, tckr_i) - NOINDEGREES[tckr_i] * NOOUTDEGREES[tckr_j] / NOEDGES + if overall_asgn[node_space[i]] == overall_asgn[node_space[j]]: + Ck = 0.0 + for k in node_space: + tckr_k = lst_node[k] + Ck += G.has_edge(tckr_k, tckr_i) + G.has_edge(tckr_i, tckr_k) - (NOINDEGREES[tckr_i] * NOOUTDEGREES[tckr_k] + NOINDEGREES[tckr_k] * NOOUTDEGREES[tckr_i]) / NOEDGES + mod_mat[i, j] = Bij - Ck / 2.0 + else: mod_mat[i, j] = Bij + print('/') + return mod_mat + + def updCommunityAssignment(node_space, upd_asgn, generation_mark): + nonlocal overall_asgn + global asgn_history + inreval_1 = 0 + inreval_2 = 0 + lst_gener_asgn = [] + for asgn in overall_asgn: + if asgn[0] == generation_mark: + lst_gener_asgn.append(asgn[1]) + for i in range(len(node_space)): + if i not in lst_gener_asgn: + inreval_1 = i + break + if upd_asgn.count(1) == 0: inreval_2 = inreval_1 + else: + for i in range(len(node_space)): + if i not in lst_gener_asgn: + inreval_2 = i + break + for i in range(len(node_space)): + if upd_asgn[i] == 1: overall_asgn[node_space[i]] = (generation_mark, inreval_1) + if upd_asgn[i] == -1: overall_asgn[node_space[i]] = (generation_mark, inreval_2) + #print(overall_asgn) + asgn_history.append(overall_asgn.copy()) + + def subdivideCommunities(mod_mat): + sym_mat = mod_mat + mod_mat.T + w, v = np.linalg.eigh(sym_mat) + eigv = v[:, len(w)-1] + return [np.sign(v.tolist()[0][0]) for v in eigv] + + def calDirectedGraphModularity(assignment): + nonlocal G + nonlocal lst_node + nonlocal NONODES + nonlocal NOEDGES + nonlocal NOINDEGREES + nonlocal NOOUTDEGREES + Q = 0.0 + for i in range(NONODES): + for j in range(NONODES): + if assignment[i] == assignment[j]: + Q += G.has_edge(lst_node[j], lst_node[i]) - NOINDEGREES[lst_node[i]] * NOOUTDEGREES[lst_node[j]] / NOEDGES + return Q / NOEDGES + + def calDeltaQ(upd_asgn, Bg): + nonlocal NOEDGES + sg = np.matrix(upd_asgn) + return 0.25/NOEDGES*np.dot(np.dot(sg, (Bg+Bg.T)), sg.T)[0,0] + + MODMAT = np.matrix(np.zeros((NONODES, NONODES), dtype=np.float64)) + for i in range(NONODES): + for j in range(NONODES): + MODMAT[i, j] = G.has_edge(lst_node[j], lst_node[i]) - NOINDEGREES[lst_node[i]] * NOOUTDEGREES[lst_node[j]] / NOEDGES + interateBisection(MODMAT, list(np.arange(NONODES)), 1) + return overall_asgn, calDirectedGraphModularity(overall_asgn) + +def calModularity(assignment): + global G + global lst_node + global NONODES + global NOEDGES + global NOINDEGREES + global NOOUTDEGREES + Q = 0.0 + for i in range(NONODES): + for j in range(NONODES): + if assignment[i] == assignment[j]: + Q += G.has_edge(lst_node[j], lst_node[i]) - NOINDEGREES[lst_node[i]] * NOOUTDEGREES[lst_node[j]] / NOEDGES + return Q / NOEDGES + +lst_node = list(G.nodes()) +NONODES = G.number_of_nodes() +NOEDGES = G.number_of_edges() +NOINDEGREES = G.in_degree() +NOOUTDEGREES = G.out_degree() + +over_best_asgn = [0] * len(lst_tickers_stp) +for i in range(len(lst_tickers_stp)): + over_best_asgn[i] = int(G.node[lst_tickers_stp[i]]['community']) + +best_asgn = over_best_asgn.copy() +origin_mod = calModularity(best_asgn) +for i in range(len(best_asgn)): + asgn = best_asgn[i] + for uniq in uniq_asgn: + if asgn != uniq: + best_asgn[i] = uniq + new_mod = calModularity(best_asgn) + if new_mod > origin_mod: + origin_mod = new_mod + asgn = uniq + else: best_asgn[i] = asgn + +lst_tckr_nonzero = [i[0] for i in G.degree if i[1]>0] +rdmchosen_tickers = np.random.choice(lst_tckr_nonzero, 1, replace=False) +nonzerodeg_subG = G.subgraph(lst_tckr_nonzero).copy() + +asgn_history = [] +overall_asgn, modularity = detectCommunityForDirectedGraph(nonzerodeg_subG) + +stp_group_tckr_index = sri_overall_asgn[sri_overall_asgn == v_c.index[0]].index.tolist() +stp_group_tckr = [lst_tickers_stp[i] for i in stp_group_tckr_index] +stp_group_indcode = getIndustryCodeByStockCode(stp_group_tckr, code_type='Title') +sri_community_1 = pd.Series(stp_group_indcode).value_counts() +stp_group_tckr_index = sri_overall_asgn[sri_overall_asgn == v_c.index[1]].index.tolist() +stp_group_tckr = [lst_tickers_stp[i] for i in stp_group_tckr_index] +stp_group_indcode = getIndustryCodeByStockCode(stp_group_tckr, code_type='Title') +sri_community_2 = pd.Series(stp_group_indcode).value_counts() +stp_group_tckr_index = sri_overall_asgn[sri_overall_asgn == v_c.index[2]].index.tolist() +stp_group_tckr = [lst_tickers_stp[i] for i in stp_group_tckr_index] +stp_group_indcode = getIndustryCodeByStockCode(stp_group_tckr, code_type='Title') +sri_community_3 = pd.Series(stp_group_indcode).value_counts() +stp_group_tckr_index = sri_overall_asgn[sri_overall_asgn == v_c.index[3]].index.tolist() +stp_group_tckr = [lst_tickers_stp[i] for i in stp_group_tckr_index] +stp_group_indcode = getIndustryCodeByStockCode(stp_group_tckr, code_type='Title') +sri_community_4 = pd.Series(stp_group_indcode).value_counts() +stp_group_tckr_index = sri_overall_asgn[sri_overall_asgn == v_c.index[4]].index.tolist() +stp_group_tckr = [lst_tickers_stp[i] for i in stp_group_tckr_index] +stp_group_indcode = getIndustryCodeByStockCode(stp_group_tckr, code_type='Title') +sri_community_5 = pd.Series(stp_group_indcode).value_counts() + +stp_group_tckr_index = [] +for i in range(5,11): stp_group_tckr_index += sri_overall_asgn[sri_overall_asgn == v_c.index[i]].index.tolist() +stp_group_tckr = [lst_tickers_stp[i] for i in stp_group_tckr_index] +stp_group_indcode = getIndustryCodeByStockCode(stp_group_tckr, code_type='Title') +sri_community_6 = pd.Series(stp_group_indcode).value_counts() + +uniq_ind = np.unique(df_codes_and_title.Title) + +lst_community_1 = [] +lst_community_2 = [] +lst_community_3 = [] +lst_community_4 = [] +lst_community_5 = [] +lst_community_6 = [] +for ind in uniq_ind: + if ind in sri_community_1.index: lst_community_1.append(sri_community_1[ind]) #/ sum(sri_overall_asgn == v_c.index[0])) + else: lst_community_1.append(0) + if ind in sri_community_2.index: lst_community_2.append(sri_community_2[ind]) #/ sum(sri_overall_asgn == v_c.index[1])) + else: lst_community_2.append(0) + if ind in sri_community_3.index: lst_community_3.append(sri_community_3[ind]) #/ sum(sri_overall_asgn == v_c.index[2])) + else: lst_community_3.append(0) + if ind in sri_community_4.index: lst_community_4.append(sri_community_4[ind]) #/ sum(sri_overall_asgn == v_c.index[3])) + else: lst_community_4.append(0) + if ind in sri_community_5.index: lst_community_5.append(sri_community_5[ind]) #/ sum(sri_overall_asgn == v_c.index[4])) + else: lst_community_5.append(0) + if ind in sri_community_6.index: lst_community_6.append(sri_community_6[ind]) #/ sum(sri_overall_asgn == v_c.index[5])) + else: lst_community_6.append(0) + +lst2_sector = [None] * len(uniq_ind) +for i in range(len(uniq_ind)): + lst2_sector[i] = [] + if uniq_ind[i] in sri_community_1.index: lst2_sector[i].append(sri_community_1[uniq_ind[i]]) + else: lst2_sector[i].append(0) + if uniq_ind[i] in sri_community_2.index: lst2_sector[i].append(sri_community_2[uniq_ind[i]]) + else: lst2_sector[i].append(0) + if uniq_ind[i] in sri_community_3.index: lst2_sector[i].append(sri_community_3[uniq_ind[i]]) + else: lst2_sector[i].append(0) + if uniq_ind[i] in sri_community_4.index: lst2_sector[i].append(sri_community_4[uniq_ind[i]]) + else: lst2_sector[i].append(0) + if uniq_ind[i] in sri_community_5.index: lst2_sector[i].append(sri_community_5[uniq_ind[i]]) + else: lst2_sector[i].append(0) + if uniq_ind[i] in sri_community_6.index: lst2_sector[i].append(sri_community_6[uniq_ind[i]]) + else: lst2_sector[i].append(0) + +idx = np.arange(6) +plt.figure(figsize=(15,15)) + +colors = list(dict(mpl.colors.BASE_COLORS, **mpl.colors.CSS4_COLORS).values()) +idx = np.arange(6) +plt.figure(figsize=(10,10)) +p = [] +for i in range(len(uniq_ind)): + bottom = [0] * 6 + for j in range(i): bottom = [a+b for a, b in zip(bottom, np.array(lst2_sector[j]))] + p.append(plt.bar(idx, lst2_sector[i], bottom=bottom, color=colors[np.random.randint(len(colors))])) +plt.xticks(idx, ['C1','C2','C3','C4','C5','Others']) + +idx = np.arange(len(uniq_ind)) +plt.figure(figsize=(15,15)) +p1 = plt.bar(idx, lst_community_1, color=(0.85, 0.5176, 1)) +p2 = plt.bar(idx, lst_community_2, bottom=lst_community_1, color=(0.553, 0.753, 0.0863)) +p3 = plt.bar(idx, lst_community_3, + bottom=np.array(lst_community_1)+np.array(lst_community_2), color=(0.4157, 0.7608, 1)) +p4 = plt.bar(idx, lst_community_4, + bottom=np.array(lst_community_1)+np.array(lst_community_2)+np.array(lst_community_3), color=[0.937255,0.851,0.25333]) +p5 = plt.bar(idx, lst_community_5, + bottom=np.array(lst_community_1)+np.array(lst_community_2)+np.array(lst_community_3)+np.array(lst_community_4), color=[0.898,0.5294,0.1294]) +p6 = plt.bar(idx, lst_community_6, + bottom=np.array(lst_community_1)+np.array(lst_community_2)+np.array(lst_community_3)+np.array(lst_community_4)+np.array(lst_community_5), color=[0.283,0.2823,0.282]) +plt.xticks(idx, uniq_ind, rotation=90) +plt.legend((p1[0], p2[0], p3[0], p4[0], p5[0], p6[0]), ('Community 1', 'Community 2', 'Community 3', 'Community 4', 'Community 5', 'Unclustered'));