4. 交易特征工程:金额、频率、时间、对手方等特征提取
特征工程这步,说白了就是给数据“化妆”。
原始的交易流水,就像素颜的照片——信息都在,但不够突出。我们要做的,是把那些藏在细节里的异常信号,通过特征提取的方式放大出来。我个人习惯把这部分工作分成四个维度:金额、频率、时间、对手方。咱们一个一个来拆。
4.1 金额特征:别只看绝对值
很多人做金额特征,上来就取个均值、最大值完事。这其实不够。
我在项目中遇到过一家贸易公司,单笔交易金额都在100万左右,看起来很正常。但仔细一算,金额的方差特别大——有时候一天内从50万跳到200万,又跳回80万。这种剧烈波动,往往是关联交易“倒账”的典型信号。
我常用的金额特征包括:
- 单笔金额统计:均值、中位数、最大值、最小值、标准差
- 金额分布特征:偏度(skewness)、峰度(kurtosis)——这两个能反映金额是否集中在某个“整数关口”
- 金额与账户余额的比值:比如一笔交易占账户余额的80%以上,这就不太像日常经营
- 金额的“整十整百”特征:关联交易经常出现100万、500万这种整数,而真实贸易往往有零有整
4.2 频率特征:节奏感很重要
交易频率,我把它叫做“交易的呼吸节奏”。
正常企业的交易频率,通常是有规律的。比如每天3-5笔,或者每周固定某几天有交易。但关联交易不一样——它往往在某个时间段内突然爆发,然后又沉寂很久。
我曾经处理过一个案例:某供应商平时一个月就几笔交易,但在季度末的最后三天,突然密集交易了47笔。这种“脉冲式”的频率变化,就是典型的关联交易特征。
我常用的频率特征:
- 日交易笔数:统计每天的交易次数,看是否有异常峰值
- 交易间隔时间:相邻两笔交易的时间差。正常交易间隔相对均匀,关联交易经常出现“连续几笔间隔几秒”的情况
- 周/月交易活跃度:比如一周内交易天数占比,一个月内交易周数占比
- 交易密度:单位时间内的交易笔数,比如“每小时交易笔数”
4.3 时间特征:深夜的交易最可疑
时间特征,很多人只取个“交易时间”字段就完事了。其实这里面能挖的东西很多。
你想想看,正常企业的交易时间,是不是集中在工作日的9点到17点?如果一家公司经常在凌晨2点、周末、法定节假日发生大额交易,这本身就值得怀疑。
我常用的时间特征:
- 交易时段:分为早(9-12)、中(12-14)、晚(14-17)、夜(17-次日9)四个时段
- 是否工作日:标记交易发生在工作日还是周末/节假日
- 交易时间与营业时间的偏差:如果企业申报的营业时间是9-18点,那18点之后的交易就要重点关注
- 交易时间的“整点”特征:比如交易时间是不是整点、半点——关联交易经常在整点发生
- 交易时间的周期性:比如是否每周五下午固定有一笔大额交易
4.4 对手方特征:关系网里找异常
对手方特征,是关联交易检测中最核心的部分。说白了,就是看“谁和谁在交易”。
我习惯把对手方特征分成两类:个体特征和关系特征。
个体特征:
- 对手方是否与本公司有股权关联(比如同一实际控制人)
- 对手方的注册地址是否与本公司相同或相近
- 对手方的注册时间——如果对手方刚注册就发生大额交易,这很可疑
- 对手方的行业类型是否与交易内容匹配
关系特征:
- 交易对手集中度:前三大对手方的交易金额占比。如果超过80%,说明交易高度集中
- 对手方重合度:多个子公司是否与同一个对手方交易
- 交易对手变更频率:频繁更换交易对手,可能是为了规避监管
- 循环交易特征:A→B→C→A 这种资金闭环,是关联交易的典型模式
4.5 特征组合:1+1>2
单个特征往往不够强,但组合起来威力就大了。
举个例子:“深夜大额整数交易”——这个组合特征,同时包含了时间(深夜)、金额(大额、整数)、行为模式(异常时段)三个维度的信息。我在实际项目中,这个特征的区分度能达到0.85以上。
我常用的特征组合方式:
- 金额 × 频率:比如“单日累计交易金额 / 日交易笔数”,反映单笔平均金额
- 时间 × 对手方:比如“非工作时间与关联对手方的交易笔数”
- 金额 × 时间:比如“凌晨时段的交易金额占比”
- 频率 × 对手方:比如“与同一对手方的交易频率变化率”
4.6 特征工程流程图
下面这张图,是我做特征工程时的标准流程。你可以参考一下:
4.7 代码示例:特征提取实战
说了这么多理论,咱们来点实际的。下面这段代码,是我在项目中常用的特征提取模板:
import pandas as pd
import numpy as np
# 假设df是原始交易数据
# 字段:trade_id, account_id, counterparty_id, amount, trade_time, trade_date
# 1. 金额特征
df['amount_log'] = np.log1p(df['amount']) # 对数变换,减少偏态
df['amount_round'] = (df['amount'] % 10000 == 0).astype(int) # 是否整万
# 2. 频率特征
# 按账户+日期分组,计算日交易笔数
daily_freq = df.groupby(['account_id', 'trade_date']).size().reset_index(name='daily_count')
df = df.merge(daily_freq, on=['account_id', 'trade_date'], how='left')
# 3. 时间特征
df['hour'] = pd.to_datetime(df['trade_time']).dt.hour
df['is_night'] = ((df['hour'] < 9) | (df['hour'] >= 18)).astype(int)
df['is_weekend'] = (pd.to_datetime(df['trade_date']).dt.dayofweek >= 5).astype(int)
# 4. 对手方特征
# 计算每个账户与每个对手方的交易次数
counterparty_freq = df.groupby(['account_id', 'counterparty_id']).size().reset_index(name='cp_trade_count')
df = df.merge(counterparty_freq, on=['account_id', 'counterparty_id'], how='left')
# 5. 特征组合
df['night_large_amount'] = df['is_night'] * (df['amount'] > df['amount'].quantile(0.95)).astype(int)
print("特征提取完成,特征维度:", df.shape[1])
嗯,特征工程这部分内容比较多,但核心就一句话:从原始数据中挖掘出能反映交易本质的信号。金额、频率、时间、对手方这四个维度,你吃透了,关联交易检测就成功了一半。
记住,特征不是越多越好。我见过有人提取了200多个特征,结果模型效果还不如只用20个核心特征的。关键是理解业务逻辑,知道哪些特征在关联交易场景下是有区分度的。
公众号:蓝海资料掘金营,微信deep3321