目录
上一篇讲解了如何创立新环境并安装模组 XGBoost,环境的设定是基础,一开始出问题的话,后面会有许多奇奇怪怪的 Error,如果还没看过上一篇的话,可以点这这里,这一篇我们要对资料做一些处理,完成后再带入模型里让机器去学习,学习后可以去预测未来的报酬,也可以看哪一个因子对预测是最有效果的!
本文使用 Mac OS 并以 Jupyter Notebook 作为编辑器
# basic import numpy as np import pandas as pd
# graphy import matplotlib.pyplot as plt %matplotlib inline
# machine learning from sklearn.metrics import mean_squared_error from sklearn.model_selection import train_test_split import xgboost as xgb
# TEJ import tejapi tejapi.ApiConfig.api_key = "Your Key" tejapi.ApiConfig.ignoretz = True
TWN/APRCM
,涵盖2000年以来各学者衡量因子的指标,资料频率为月资料TWN/APRCM
,以上市的证券及指数为收录对象我们会使用 2000~2015的所有上市柜公司的投资因子,用以预测2016~2017 月报酬率为正或是负。
df = tejapi.get('TWN/AFF_RAW', mdate={'gte': '2000-01-01', 'lte':'2015-12-31'}, opts={'columns':['coid','mdate','pbr','per', 'div_yid','mom','str','ltr','profit','invest', 'dd_merton','dd_kmv','illiq','idiosyncratic', 'hhi','skew']}, chinese_column_name = True, paginate = True)
df.isnull().sum(axis=0)
如果有缺失值,直接丢入模型的话,会导致无法计算,不过 XGBoost 模型能处理稀疏矩阵,可以容许有缺失值的存在,不过如果我们能合理的填补缺失值,这有助于我们增强模型的配适度,常见的方法为填补「平均值」、「中位数」,或是直接填上 0,使用的语法是 fillna
,至于要填入什么的话,可以先对资料做一些 探索式资料分析(Exploratory Data Analysis,EDA),那这会是另一个重点,未来我们再另花篇幅去介绍!
# 处理时间 from datetime import date, timedelta import calendar
将月份都加上一个月
df['年月'] = df['年月'].apply(lambda x: x + timedelta(days=calendar.monthrange(x.year, x.month)[1]))
一般来说机器学习时,对资料做标准化,会提高模型的预测力,但在 XGBoost 却不需要这一步,大略的解释为:标准化是处理连续特征,主要作用是进行数值缩放 ( 减去平均值、除以标准差 )。而数值缩放的目的是解决梯度下降时,等高线会是椭圆导致迭代次数增多的问题。但是上一篇提到 XGBoost是树模型,是不能进行梯度下降的,因为树模型是阶越的,不可做导数。反而是透过寻找特征的最优分裂点来完成优化的,由于标准化不会改变分裂点的位置,因此 XGBoost 不需要对资料进行标准化!
df_label = tejapi.get('TWN/APRCM', mdate={'gte': '2000-01-01', 'lte':'2015-12-31'}, opts = {'columns':['coid','mdate','roi']}, chinese_column_name = True, paginate = True)
如果是正报酬则设为 1,负报酬则为 0
df_label['报酬率%_月'] = df_label['报酬率%_月'].apply(lambda x: 1 if x>0 else 0) df_label.rename(columns={'证券代码':'证券码'}, inplace=True)
data = pd.merge(df , df_label, on=['证券码', '年月'])
X, y = data.iloc[:,2:-1],data.iloc[:,-1]
通常在执行机器学习时,我们不会把所有资料都拿去做训练,因为这样做的话,我们很难判断他的学习效果是好还是不好,因此我们会切一部分出来,以下我们拆成 8:2 ,20% 的资料作为模型后续的评估
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
from xgboost import XGBClassifier from sklearn.metrics import accuracy_score
将分类器命为 model,后面那串代表我们已经自行将标签改成我们要的编码
model = XGBClassifier(use_label_encoder=False)
开始训练模型!
model.fit(X_train, y_train)
我们来检视这模型在测试集的预测准确度
y_pred = model.predict(X_test) predictions = [round(value) for value in y_pred] accuracy = accuracy_score(y_test, predictions) print("Accuracy: %.2f%%" % (accuracy * 100.0))
df_pred = tejapi.get('TWN/AFF_RAW', coid = '2330', mdate={'gte': '2015-12-01', 'lte':'2017-11-30'}, opts={'columns': 如文章第一段} chinese_column_name = True, paginate = True)
df_pred_label = tejapi.get('TWN/APRCM', coid = comp, mdate={'gte': '2016-01-01', 'lte':'2017-12-31'}, opts = {'columns':['mdate','roi']}, chinese_column_name = True, paginate = True)
pred2 = model.predict(df_pred.iloc[:,2:]) df_pred_label['报酬率预测'] = pred2
accuracy = accuracy_score(df_pred_label['报酬率%_月'].apply(lambda x: 1 if x>0 else 0), pred2) print("Accuracy: %.2f%%" % (accuracy * 100.0))
import matplotlib.pyplot as plt import matplotlib.font_manager plt.rcParams['font.sans-serif'] = 'Arial Unicode MS' plt.rcParams['axes.unicode_minus'] = False
plt.figure(figsize=(30,10)) xgb.plot_tree(model,num_trees=0) plt.rcParams['figure.figsize'] = [1300, 1000] plt.show()
plt.figure(figsize=(10,40)) xgb.plot_importance(model) plt.rcParams['figure.figsize'] = [5, 5] plt.show()
今天的教学其实就是目前机器学习比赛常见的架构了,模型的开发其实都是很复杂的数学,而我们可以理解他的特质和性能来去使用它,并不用去深入了解他的数学计算,除非对这块很有兴趣,关于预测的准确度,其关键常在资料的前处理,包括遗失值、偏锋态、共线性等数据处理,或是从相关论文发现可以组合出有效的特征。
本篇因为 TEJ 已经整理好相关因子的数据,所以在前处理上相对轻松很多,但还是要强调一点是,由于金融上有非常多的不确定性,现在的准确度无法代表未来的准确度,但可以理解的一点是,这些因子都是目前金融正在寻找股价的特征,不过现实生活有很多数据可以拿来玩,现在赶快把资料丢进 XGBoost 吧!
本文仅供参考之用,并不构成要约、招揽或邀请、诱使、任何不论种类或形式之申述或订立任何建议及推荐,读者务请运用个人独立思考能力,自行作出投资决定,如因相关建议招致损失,概与作者无涉。