第4章:网络数据获取——公开数据源、数据清洗与预处理、网络构建实战

各位同学,今天咱们聊聊金融网络仿真里最基础、也最磨人的一步——数据获取与清洗。

说实话,我见过太多项目,模型建得花里胡哨,结果数据源一塌糊涂,最后全白干。你想想看,网络结构再漂亮,输入的是垃圾数据,输出能靠谱吗?

这一章,我就带大家走一遍完整流程:从央行、BIS这些公开数据源捞数据,到清洗预处理,最后亲手搭出一个金融网络。

4.1 公开数据源:央行与BIS

做金融网络分析,数据源就那么几个靠谱的。我个人最常用的是两个:

  • 中国人民银行(PBOC):发布银行间市场数据、同业拆借利率、资产负债表等。我习惯去“调查统计司”栏目扒数据。
  • 国际清算银行(BIS):全球银行间跨境头寸数据、衍生品统计。BIS的“Locational Banking Statistics”是构建国际金融网络的宝藏。

嗯,这里要注意:BIS的数据是季度更新的,而且有3个月左右的滞后期。别指望拿它做实时风控。

核心数据字段

  • 报告国(Reporting Country)
  • 对手国(Counterparty Country)
  • 资产/负债类型(Loans, Deposits, Derivatives)
  • 金额(百万美元)
  • 时间戳(季度末)

4.2 数据清洗与预处理

数据拿到手,别急着用。我曾经有一次直接从BIS下载CSV,里面居然混着法文注释和空行,跑脚本直接报错。从那以后,我养成了固定清洗流程。

4.2.1 常见脏数据

问题类型 表现 处理方法
缺失值 某些国家间无交易记录 填充0或插值(看场景)
重复行 同一笔交易出现两次 按时间戳+对手方去重
单位不一致 有的用百万,有的用十亿 统一转为百万美元
编码问题 国家名用中文、英文混排 统一ISO 3166-1 alpha-2代码

避坑指南:我曾经在处理BIS数据时,发现日本和英国之间的交易额突然暴增。排查了半天,原来是某行把“JPY”和“GBP”的单位搞混了。所以,清洗时一定要做单位校验。

4.2.2 清洗代码示例(Python)

import pandas as pd
import numpy as np

# 读取原始数据
df = pd.read_csv('bis_data_raw.csv', encoding='utf-8')

# 1. 去除空行和注释行
df = df.dropna(how='all')
df = df[~df['country'].str.startswith('#', na=False)]

# 2. 统一国家代码
country_map = {'中国': 'CN', '美国': 'US', '日本': 'JP'}
df['country_code'] = df['country'].map(country_map)

# 3. 金额单位统一(假设原始是十亿,转百万)
df['amount_million'] = df['amount_billion'] * 1000

# 4. 去重
df = df.drop_duplicates(subset=['reporting_country', 'counterparty_country', 'quarter'])

# 5. 缺失值处理:无交易填0
df['amount_million'] = df['amount_million'].fillna(0)

print(f"清洗后数据量:{len(df)} 行")

4.3 网络构建实战

数据洗干净了,接下来就是搭网络。说白了,就是把国家/银行看成节点,交易金额看成边的权重。

4.3.1 邻接矩阵构建

我习惯用NetworkX库。先建一个有向图,方向从“报告国”指向“对手国”,权重就是交易金额。

import networkx as nx

# 创建有向图
G = nx.DiGraph()

# 添加边(从清洗后的数据)
for _, row in df.iterrows():
    G.add_edge(
        row['reporting_country'],
        row['counterparty_country'],
        weight=row['amount_million']
    )

# 查看网络基本信息
print(f"节点数:{G.number_of_nodes()}")
print(f"边数:{G.number_of_edges()}")

4.3.2 网络可视化

光看数字不过瘾,咱们画出来。下面这张SVG图展示了核心逻辑:

中国 美国 日本 $1200M $800M $500M 图例:节点=国家,有向边=资金流向,权重=交易金额(百万美元)

4.3.3 网络指标计算

网络搭好了,咱们算几个关键指标。我个人最关注的是“度中心性”和“中介中心性”——前者看谁交易多,后者看谁控制着资金流。

# 计算度中心性(入度+出度)
degree_centrality = nx.degree_centrality(G)
# 计算中介中心性
betweenness_centrality = nx.betweenness_centrality(G, weight='weight')

# 输出Top 3
top_degree = sorted(degree_centrality.items(), key=lambda x: x[1], reverse=True)[:3]
top_between = sorted(betweenness_centrality.items(), key=lambda x: x[1], reverse=True)[:3]

print("度中心性Top3:")
for node, val in top_degree:
    print(f"  {node}: {val:.4f}")

print("中介中心性Top3:")
for node, val in top_between:
    print(f"  {node}: {val:.4f}")

注意:中介中心性在有向加权图上计算量很大。我当年用1000个节点的网络跑过一次,等了半小时才出结果。建议先做子图采样,或者用近似算法。

4.4 实战小结

这一章咱们走完了从数据到网络的完整链路。你想想看,其实核心就三步:

  1. 找数据:央行、BIS,别去野鸡网站扒。
  2. 洗数据:缺失、重复、单位、编码,一个都不能放过。
  3. 建网络:用NetworkX搭图,算指标,画出来看看。

嗯,最后提醒一句:公开数据虽然方便,但精度有限。真要拿来做风控,还得结合内部交易数据。我当年在银行做项目时,就是先用公开数据搭个框架,再拿内部数据去校准,效果还不错。


公众号:蓝海数据掘金营,微信deep3321