一個簡單的XGBoost選股模型

今天分享一個簡單的XGBoost選股模型。

導入包

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# 解決坐標軸刻度負號亂碼
plt.rcParams['axes.unicode_minus'] = False
# 解決中文亂碼問題
plt.rcParams['font.sans-serif'] = ['Simhei']

一、讀入數(shù)據(jù)

我們的數(shù)據(jù)是滬深300成分股2013-2016年每個季度的包括盤面信息、基本面信息的17個因子特征。

data = pd.read_csv("300Data.csv")
data.head()
源數(shù)據(jù)

可以看一下我們的17個因子:

data['factor'].unique()
因子特征

二、特征工程

我們首先要定義label:
下個季度股價漲跌幅超過滬深300指數(shù)的漲跌幅,則我們認為本季度該股票應該買入,label設為1;否則為0。
首先找出滬深300每個季度的漲跌幅作為benchmark,計算出每只成分股每個季度相對于基準的漲跌幅。

# 獲取每只個股每個季度的漲跌幅
p_chg_df=data[data['factor']=='漲跌幅']
# 找到滬深300的季度漲跌幅
p_chg300=p_chg_df[p_chg_df['stock']=='滬深300']
p_chg300
滬深300季度漲跌幅
# 計算每只成分股每個季度相對于基準的漲跌幅
for col in p_chg_df.columns[2:]:
    p_chg_df[col]=p_chg_df[col] - p_chg300.loc[563,col]         # 滬深300的索引是563,這一步計算每只股票對于滬深300的相對漲幅

p_chg_df.head()
季度相對漲跌幅

這里需要注意,我們計算的是本季度相對于基準的漲跌幅,但我們本季度【是否買入】應該根據(jù)下一季度相對漲跌幅的情況而定。

# 獲取下一季度的超漲跌幅
p_chg_df.iloc[:,2:]=p_chg_df.iloc[:,2:].shift(-1,axis=1)
p_chg_df.head()
下一季度相對漲跌幅

接來下我們需要將每只股票每個季度的17個因子提出來,作為一條記錄。

# 定義數(shù)據(jù)轉換函數(shù),行名為股票名,列名為特征名
def transform_data(df, value):
    result = (df.pivot_table(index=df['stock'], columns=[
              df['factor']], values=value).reset_index())
    return(result)

header=[i for i in data.columns if 'Q' in i]  # 存儲每個季度的名字

column=list(data['factor'].unique())          # 存儲特征名
column.append('超漲幅')

stock_df = pd.DataFrame(columns = column) 

for col in header:
    df=transform_data(data, col)
    df=df.merge(p_chg_df[['stock',col]],on='stock',how='left')
    df.rename(columns={col:'超漲幅'},inplace=True)
    stock_df=stock_df.append(df,ignore_index=True)

stock_df['是否買入']=np.where(stock_df['超漲幅']>0,1,0)
stock_df.head()
特征
# 空值處理:由于如果用填充法需要行業(yè)數(shù)據(jù),我們這里直接簡單粗暴刪除空值行
stock_df1=stock_df.dropna(axis=0)

stock=stock_df1.copy()

y=stock['是否買入'].values

del stock['stock']
del stock['超漲幅']
del stock['是否買入']

X=stock.values
print('特征維度是{}\n標簽維度是{}'.format(X.shape,y.shape))
image.png
pd.Series(y).value_counts()
標簽分布

可以看到,漲跌記錄數(shù)量相差不大,不存在數(shù)據(jù)不平衡的問題。

三、建立XGBoost模型

# 劃分訓練集和測試集
from sklearn.model_selection import train_test_split

X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.3,random_state=420)

import xgboost as xgb
from sklearn import metrics

dtrain=xgb.DMatrix(X_train,label=y_train)
dtest=xgb.DMatrix(X_test)

# 給定模型參數(shù)
params={'booster':'gbtree',
    'objective': 'binary:logistic',
    'eval_metric': 'auc',
    'max_depth':8,
    'gamma':0,
    'lambda':2,
    'subsample':0.7,
    'colsample_bytree':0.8,
    'min_child_weight':3,
    'eta': 0.2,
    'nthread':8,
     'silent':1}
# 用于觀察弱分類器訓練過程
watchlist = [(dtrain,'train')]
# 建立xgboost模型
bst=xgb.train(params,dtrain,num_boost_round=100,evals=watchlist)
# 漲跌概率
y_prob=bst.predict(dtest)
# 設置閾值, 輸出一些評價指標
y_pred = (ypred >= 0.5)*1
# 獲取真陽率、偽陽率、閾值
fpr_xgb,tpr_xgb,threshold_xgb = metrics.roc_curve(y_test,y_prob) 
auc_xgb = metrics.auc(fpr_xgb,tpr_xgb)                             # AUC得分
score_xgb = metrics.accuracy_score(y_test,y_pred)                  # 模型準確率
print([score_xgb,auc_xgb])

最終預測準確率為57.62%,AUC值為0.6096。

可以看到,這個結果并不高。當然,一是因為股市預測中擾動因素太多,很難有非常高的預測準確率,二是本例僅僅是一個簡單的建模過程,大家有興趣,可以通過選取其他因子、重新定義標簽、對xgboost模型進一步調參(小白這里模型參數(shù)都是直接從我別的案例里拷過來的并未調參)等方式改進,相信會有一個更佳的結果。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • xgboost: 速度快效果好的boosting模型 Python R 本文作者:何通,SupStat Inc(總...
    hzyido閱讀 2,417評論 0 14
  • 我只是想讓你看見我的開心 就連雪花都是溫柔的暖 湖風不寒 冬雨的淅瀝淅瀝 藏了悄悄話的溫
    魚小姐是個花姑娘閱讀 241評論 0 1
  • 今天早上,收到吳先森的情人節(jié)特殊的愛的表達,幸福滿滿!晚上在酒店一樓發(fā)現(xiàn)一個房間一屋子的假花,居然沒鎖門,進去后看...
    虹丞閱讀 331評論 0 0
  • 幾年前說自己是90后,感覺還挺年輕。無論怎么任性,都還有機會重來一次。如今提及90后的我們,我們不由得說都30歲的...
    Koreyoshi_pyc閱讀 203評論 0 1
  • 百刊爭頌文明事, 花綻香飄醉大家。 園里高人留妙韻, 美心真意贊中華。 注:此詩系藏頭詩。《百花園》系簡書群里一家...
    艾思閱讀 900評論 40 56

友情鏈接更多精彩內容