其他
YYDS!使用 Python 全面分析股票数据特征
The following article is from 数据STUDIO Author 云朵君
数据准备
DatetimeIndex: 1260 entries, 2015-12-31 to 2020-12-31
Data columns (total 6 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Open 1260 non-null float64
1 High 1260 non-null float64
2 Low 1260 non-null float64
3 Close 1260 non-null float64
4 Adj Close 1260 non-null float64
5 Volume 1260 non-null int64
dtypes: float64(5), int64(1)
memory usage: 68.9 KB
特征构造
df['O-C'] = df['Adj Close'] - df['Open']
df['3day MA'] = df['Adj Close'].shift(1).rolling(window=3).mean()
df['10day MA'] = df['Adj Close'].shift(1).rolling(window=10).mean()
df['30day MA'] = df['Adj Close'].shift(1).rolling(window=30).mean()
df['Std_dev'] = df['Adj Close'].rolling(5).std()
df.dtypes
描述性统计
缺失值分析
检查缺失值
High 0
Low 0
Close 0
Adj Close 0
Volume 0
H-L 0
O-C 0
3day MA 3
10day MA 10
30day MA 30
Std_dev 4
dtype: int64
缺失值可视化
# -1表示缺失数据
# 另一个不常见的设置画布的方法
plt.rcParams['figure.figsize'] = (15,8)
df_missing_count.plot.bar()
plt.show()
print("column nunique NaN")
print("{0:15} {1:6d} {2:6}".format(
column, df[column].nunique(),
(df[column] == -1).sum()))
Open 1082 0
High 1083 0
Low 1025 0
Close 1098 0
Adj Close 1173 0
Volume 1250 0
H-L 357 0
O-C 1237 2
3day MA 1240 0
10day MA 1244 0
30day MA 1230 0
Std_dev 1252 0
特征间相关性分析
# 一个设置色板的方法
# cmap = sns.diverging_palette(220, 10,
as_cmap=True)
sns.heatmap(df.iloc[:df.shape[0]].corr()
,annot = True, cmap = 'Blues')
特征值分布
直方图
df.hist(layout = (3,4), column = columns_multi)
# 一种不常用的调整画布大小的方法
fig=plt.gcf()
fig.set_size_inches(20,9)
密度图
df.plot(kind='density', subplots=True,
layout=(3,4), sharex=False)
特征间的关系
diag_kind="kde")
特征重要性
导入相关模块
from sklearn.linear_model import (LinearRegression, Ridge, Lasso,LarsCV)
from stability_selection import StabilitySelection, RandomizedLasso
from sklearn.preprocessing import MinMaxScaler
from sklearn.ensemble import RandomForestRegressor
from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import SVR
线性回归系数大小排序
创建排序函数
Y = df['Adj Close'].values
X = df.values
colnames = df.columns
# 定义字典来存储的排名
ranks = {}
# 创建函数,它将特征排名存储到rank字典中
def ranking(ranks, names, order=1):
minmax = MinMaxScaler()
ranks = minmax.fit_transform(
order*np.array([ranks]).T).T[0]
ranks = map(lambda x: round(x,2), ranks)
res = dict(zip(names, ranks))
return res
多个回归模型系数排序
lr = LinearRegression(normalize=True)
lr.fit(X,Y)
ranks["LinReg"] = ranking(np.abs(lr.coef_), colnames)
# 使用 Ridge
ridge = Ridge(alpha = 7)
ridge.fit(X,Y)
ranks['Ridge'] = ranking(np.abs(ridge.coef_), colnames)
# 使用 Lasso
lasso = Lasso(alpha=.05)
lasso.fit(X, Y)
ranks["Lasso"] = ranking(np.abs(lasso.coef_), colnames)
随机森林特征重要性排序
对于随机森林中的每一颗决策树, 使用相应的OOB(袋外数据)数据来计算它的袋外数据误差 ,记为. 随机地对袋外数据OOB所有样本的特征X加入噪声干扰 (就可以随机的改变样本在特征X处的值), 再次计算它的袋外数据误差 ,记为. 假设随机森林中有 棵树,那么对于特征X的重要性,之所以可以用这个表达式来作为相应特征的重要性的度量值是因为:若给某个特征随机加入噪声之后,袋外的准确率大幅度降低,则说明这个特征对于样本的分类结果影响很大,也就是说它的重要程度比较高。
连续型特征重要性
feature_importances_
属性。'Increase_Decrease','Buy_Sell_on_Open',
'Buy_Sell', 'Returns']]
y_1 = dataset['Adj Close']
# 创建决策树分类器对象
clf = RandomForestRegressor(random_state=0, n_jobs=-1)
# 训练模型
model = clf.fit(X_1, y_1)
# 计算特征重要性
importances = model.feature_importances_
# 按降序排序特性的重要性
indices = np.argsort(importances)[::-1]
# 重新排列特性名称,使它们与已排序的特性重要性相匹配
names = [dataset.columns[i] for i in indices]
# 创建画布
plt.figure(figsize=(10,6))
# 添加标题
plt.title("Feature Importance")
# 添加柱状图
plt.bar(range(X.shape[1]), importances[indices])
# 为x轴添加特征名
plt.xticks(range(X.shape[1]), names, rotation=90)
分类型特征重要性
feature_importances_
属性。'Volume', 'Buy_Sell_on_Open',
'Buy_Sell', 'Returns']]
y2 = dataset['Increase_Decrease']
clf = RandomForestClassifier(random_state=0, n_jobs=-1)
model = clf.fit(X2, y2)
importances = model.feature_importances_
indices = np.argsort(importances)[::-1]
names = [dataset.columns[i] for i in indices]
plt.figure(figsize=(10,6))
plt.title("Feature Importance")
plt.bar(range(X2.shape[1]), importances[indices])
plt.xticks(range(X2.shape[1]), names, rotation=90)
plt.show()
本案例中使用回归模型
rf.fit(X,Y)
ranks["RF"] = ranking(rf.feature_importances_, colnames);
RandomizedLasso
rlasso = RandomizedLasso(alpha=0.04)
selector = StabilitySelection(base_estimator=rlasso, lambda_name='alpha',
lambda_grid=lambda_grid, threshold=0.9, verbose=1)
selector.fit(X, Y)
# 运行随机Lasso的选择稳定性方法
ranks["rlasso/Stability"] = ranking(np.abs(selector.stability_scores_.max(axis=1)), colnames)
print('finished')
'Close': 1.0, 'Adj Close': 0.99, 'Volume': 0.0,
'H-L': 0.0, 'O-C': 1.0, '3day MA': 1.0,
'10day MA': 0.27, '30day MA': 0.75, 'Std_dev': 0.0}
finished
稳定性得分可视化
fig.set_size_inches(15,6)
fig.show()
查看得分超过阈值的变量索引及其得分
selected_variables = selector.get_support(indices=True)
selected_scores = selector.stability_scores_.max(axis=1)
print('Selected variables are:')
print('-----------------------')
for idx, (variable, score) in enumerate(
zip(selected_variables,
selected_scores[selected_variables])):
print('Variable %d: [%d],
score %.3f' % (idx + 1, variable, score))
-----------------------
Variable 1: [0], score 1.000
Variable 2: [1], score 1.000
Variable 3: [3], score 1.000
Variable 4: [4], score 0.990
Variable 5: [7], score 1.000
Variable 6: [8], score 1.000
RFE递归特征消除特征排序
首先,在初始特征集上训练评估器,并通过任何特定属性或可调用属性来获得每个特征的重要性。 然后,从当前的特征集合中剔除最不重要的特征。 这个过程在训练集上递归地重复,直到最终达到需要选择的特征数。
*, n_features_to_select=None,
step=1, verbose=0,
importance_getter='auto')
estimator Estimator instance
一种带有""拟合""方法的监督学评估器,它提供关于特征重要性的信息(例如"coef_"、"feature_importances_")。n_features_to_select int or float, default=None
要选择的功能的数量。如果'None',则选择一半的特性。如果为整数,则该参数为要选择的特征的绝对数量。如果浮点数在0和1之间,则表示要选择的特征的分数。step int or float, default=1
如果大于或等于1,那么'step'对应于每次迭代要删除的(整数)特征数。如果在(0.0,1.0)范围内,则'step'对应于每次迭代中要删除的特性的百分比(向下舍入)。verbose int, default=0
控制输出的冗长。importance_getter str or callable, default='auto'
如果是'auto',则通过估计器的'coef_'或'feature_importances_'属性使用特征重要性。
lr.fit(X,Y)
# 当且仅当剩下最后一个特性时停止搜索
rfe = RFE(lr, n_features_to_select=1, verbose =3)
rfe.fit(X,Y)
ranks["RFE"] = ranking(list(map(float, rfe.ranking_)),
colnames, order=-1)
...
Fitting estimator with 2 features.
RFECV
RFE
包,可以用于特征消除,还提供了 RFECV
,可以通过交叉验证来对的特征进行排序。svr_mod = SVR(kernel="linear")
rfecv = RFECV(svr_mod, cv=5)
# 训练模型
rfecv.fit(X, Y)
ranks["RFECV"] = ranking(list(map(float, rfecv.ranking_)), colnames, order=-1)
# Print support and ranking
print(rfecv.support_)
print(rfecv.ranking_)
print(X.columns)
LarsCV
# X = X.drop('sex', axis=1)
# 实例化
larscv = LarsCV(cv=5, normalize=False)
# 训练模型
larscv.fit(X, Y)
ranks["LarsCV"] = ranking(list(map(float, larscv.ranking_)), colnames, order=-1)
# 输出r方和估计alpha值
print(larscv.score(X, Y))
print(larscv.alpha_)
创建特征排序矩阵
for name in colnames:
r[name] = round(np.mean([ranks[method][name]
for method in ranks.keys()]), 2)
methods = sorted(ranks.keys())
ranks["Mean"] = r
methods.append("Mean")
print("\t%s" % "\t".join(methods))
for name in colnames:
print("%s\t%s" % (name, "\t".join(map(str,
[ranks[method][name] for method in methods]))))
Open 1.0 1.0 0.02 0.91 0.47 1.0 0.73
High 0.14 0.0 0.1 0.36 0.06 1.0 0.28
Low 0.02 0.0 0.08 0.73 0.05 0.76 0.27
Close 0.14 0.0 0.64 0.55 0.32 1.0 0.44
Adj Close 0.02 1.0 1.0 0.82 1.0 0.99 0.8
Volume 0.0 0.0 0.0 0.0 0.0 0.0 0.0
H-L 0.0 0.0 0.0 0.45 0.01 0.0 0.08
O-C 0.85 1.0 0.0 1.0 0.53 1.0 0.73
3day MA 0.0 0.0 0.0 0.27 0.01 1.0 0.21
10day MA 0.0 0.0 0.02 0.09 0.0 0.27 0.06
30day MA 0.0 0.0 0.0 0.18 0.0 0.75 0.16
Std_dev 0.0 0.0 0.0 0.64 0.01 0.0 0.11
绘制特征重要性排序图
# 排序
meanplot = meanplot.sort_values('Mean Ranking', ascending=False)
g=sns.factorplot(x="Mean Ranking", y="Feature", data = meanplot, kind="bar",
size=14, aspect=1.9, palette='coolwarm')
觉得本文对你有帮助?请分享给更多人
推荐关注「Python开发者」,提升Python技能
点赞和在看就是最大的支持❤️