python 기계 학습 기반 주식 거래 신호 예측

머리말
최근 몇 년 동안 기술 의 발전 에 따라 기계 학습 과 깊이 있 는 학습 이 금융 자산 계량 화 연구 에서 의 응용 이 점점 광범 위 하고 깊이 있 게 되 었 다.현재 대량의 데이터 과학자 들 은 Kaggle 사이트 에 머 신 러 닝/딥 러 닝 모델 로 주식,선물,비트 코 인 등 금융 자산 을 예측 하고 분석 하 는 글 을 올 렸 다.금융 투자 의 측면 에서 볼 때 이런 글 들 은 일정한 이론 적 기반(또는 거래 사고)이 부족 할 수 있 고 대부분이 데이터 발굴 을 바탕 으로 한다.그러나 양 적 인 측면 에서 볼 때 우리 가 참고 할 만 한 부분 이 많다.특히 Pyhton 의 깊이 있 는 응용,데이터 시각 화 와 기계 학습 모델 의 평가 와 최적화 등 이다.다음은 Kaggle 의 기 사 를 참고 하여 상기 증 지 수 를 예 로 들 어 쌍 균 선 거래 전략 을 구축 하고 거래 신 호 를 목표 변수 로 하 며 기술 분석 기준 을 예측 특징 변수 로 하고 다양한 기계 학습 모델 로 비교 평가 와 최적화 시킨다.글 에서 특징 변수 구축 과 추출,기계 학습 모델 의 비교 평가 와 결과 시각 화 는 모두 좋 은 참고 템 플 릿 이다.
데이터 획득 및 지표 구축
필요 한 libraries 를 먼저 도입 하 는 것 은 Python 언어의 뚜렷 한 특징 중 하나 입 니 다.이러한 관련 된 가방 은 비교적 많은 데 자주 사용 하 는 numpy,pandas,matplotlib,기술 분석 talib,기계 학습 sklearn 과 데이터 패키지 tushare 등 을 포함한다.

#          libraries
import numpy as np
import pandas as pd  
import tushare as ts
#    
import talib as ta
#      
from sklearn.linear_model import LogisticRegression
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.ensemble import GradientBoostingClassifier
from xgboost import XGBClassifier,XGBRegressor
from catboost import CatBoostClassifier,CatBoostRegressor
from sklearn.ensemble import RandomForestClassifier,RandomForestRegressor
from sklearn.model_selection import train_test_split,KFold,cross_val_score
from sklearn.metrics import accuracy_score
import shap
from sklearn.feature_selection import SelectKBest,f_regression
from sklearn import preprocessing
#  
import seaborn as sns
import matplotlib.pyplot as plt
import plotly.graph_objects as go
import plotly.express as px

%matplotlib inline   
#               
from pylab import mpl
mpl.rcParams['font.sans-serif']=['SimHei']
mpl.rcParams['axes.unicode_minus']=False
데이터 획득
tushare 로 상기 시세 데 이 터 를 분석 샘플 로 얻 습 니 다.

#             
def get_data(code='sh',start='2000-01-01',end='2021-03-02'):
    df=ts.get_k_data('sh',start='2005')
    df.index=pd.to_datetime(df.date)
    df=df[['open','high','low','close','volume']]
    return df
df=get_data()
df_train,df_test=df.loc[:'2017'],df.loc['2018':]
대상 변수 구축(target variable)
거래 신 호 를 목표 변수 로 하고 가격 정보 와 기술 지 표를 특징 변수 로 하여 예측 분석 을 한다.쌍 균형 선 거래 전략의 경우 단기 균형 선 이 장기 균형 선 을 위로 돌파 할 때 매입 신호(1 로 설정)가 형성 되 고 단기 균형 선 이 장기 균형 선 아래로 떨 어 질 때 매도 신호(0 으로 설정)를 보 낸 다음 에 기계 학습 모델 로 예측 과 평 가 를 한다.여기 서 단기 이동 평균치(SMA1)와 장기 이동 평균치(SMA2)의 매개 변 수 를 각각 10 과 60 으로 설정 하고 이들 의 설정 은 일정한 임 의성 을 가 지 며 매개 변수의 선택 은 후속 결과 에 영향 을 줄 수 있 기 때문에 이상 적 인 상황 에서 매개 변 수 를 최적화 시 켜 최 적 치 를 찾 아야 한다.

def trade_signal(data,short=10,long=60,tr_id=False):
    data['SMA1'] = data.close.rolling(short).mean()
    data['SMA2'] = data.close.rolling(long).mean() 
    data['signal'] = np.where(data['SMA1'] >data['SMA2'], 1.0, 0.0) 
    if(tr_id is not True):
        display(data['signal'].value_counts())

df_tr1 = df_train.copy(deep=True)  
df_te1 = df_test.copy(deep=True) 
trade_signal(df_tr1)  #
trade_signal(df_te1,tr_id=True)  
plt.figure(figsize=(14,12), dpi=80)
ax1 = plt.subplot(211)
plt.plot(df_tr1.close,color='b')
plt.title('      ',size=15)
plt.xlabel('')
ax2 = plt.subplot(212)
plt.plot(df_tr1.signal,color='r')
plt.title('    ',size=15)
plt.xlabel('')
plt.show()

df_tr1[['SMA1','SMA2','signal']].iloc[-250:].plot(figsize=(14,6),secondary_y=['signal'])
plt.show()

#      
df_tr1=df_tr1.drop(['SMA1','SMA2'], axis=1)
df_te1=df_te1.drop(['SMA1','SMA2'], axis=1)
#                  
cmap = sns.diverging_palette(220, 10, as_cmap=True)
def corrMat(df,target='demand',figsize=(9,0.5),ret_id=False):

    corr_mat = df.corr().round(2);shape = corr_mat.shape[0]
    corr_mat = corr_mat.transpose()
    corr = corr_mat.loc[:, df.columns == target].transpose().copy()

    if(ret_id is False):
        f, ax = plt.subplots(figsize=figsize)
        sns.heatmap(corr,vmin=-0.3,vmax=0.3,center=0, 
                     cmap=cmap,square=False,lw=2,annot=True,cbar=False)
        plt.title(f'Feature Correlation to {target}')

    if(ret_id):
        return corr
corrMat(df_tr1,'signal',figsize=(7,0.5))

현재 의 특징 인 open,high,low,close,volumes 는 목표 변수의 선형 관련 값 이 매우 작다.이것 은 높 은 비 선형,상대 적 으로 안정 적 인 값 의 안정 적 인 진동(원형 산란)이 존재 하거나 이상 적 인 예측 특징 변수 가 아 닐 수도 있 기 때문에 다음 에 특징 구축 과 선택 을 해 야 한다.
기술 지표 특징 구축
분석 을 편리 하 게 하기 위해 다음은 흔히 볼 수 있 는 몇 가지 기술 기준 을 특징 으로 특징 행렬 을 도입 하고 구체 적 인 기준 은 다음 과 같다.
이동 평균 선:이동 평균 선 은 소음 을 줄 여 가격 의 운동 추 세 를 가리킨다.
랜 덤 발진기%K 와%D:랜 덤 발진기 는 운동량 표시 기 로 특정한 증권 종가 와 일정 기간 의 가격 범 위 를 비교 합 니 다.%K,%D 는 각각 느 리 고 빠 른 지표 다.
상대 적 인 강약 지수(RSI):운동량 지표 로 최근 가격 변화의 폭 을 평가 하여 주식 이나 다른 자산 의 가격 초과 구 매 또는 초과 판매 상황 을 평가한다.
변화 율(ROC):운동량 발진기,현재 가격 과 n 기 과거 가격 간 의 백분율 변 화 를 측정 합 니 다.ROC 수치 가 높 을 수록 초과 구 매 가능성 이 있 고,낮 을 수록 초과 판매 가능성 이 있다.
운동량(MOM):증권 가격 이나 거래 량 이 가속 화 되 는 속도;가격 변화의 속도.

#       
df_tr2=df_tr1.copy(deep=True)
df_te2=df_te1.copy(deep=True)
계산 기술 지표

#  talib            
#            
def indicators(data):
    data['MA13']=ta.MA(data.close,timeperiod=13)
    data['MA34']=ta.MA(data.close,timeperiod=34)
    data['MA89']=ta.MA(data.close,timeperiod=89)
    data['EMA10']=ta.EMA(data.close,timeperiod=10)
    data['EMA30']=ta.EMA(data.close,timeperiod=30)
    data['EMA200']=ta.EMA(data.close,timeperiod=200)
    data['MOM10']=ta.MOM(data.close,timeperiod=10)
    data['MOM30']=ta.MOM(data.close,timeperiod=30)
    data['RSI10']=ta.RSI(data.close,timeperiod=10)
    data['RSI30']=ta.RSI(data.close,timeperiod=30)
    data['RS200']=ta.RSI(data.close,timeperiod=200)
    data['K10'],data['D10']=ta.STOCH(data.high,data.low,data.close, fastk_period=10)
    data['K30'],data['D30']=ta.STOCH(data.high,data.low,data.close, fastk_period=30)
    data['K20'],data['D200']=ta.STOCH(data.high,data.low,data.close, fastk_period=200)
indicators(df_tr2)
indicators(df_te2)
corrMat(df_tr2,'signal',figsize=(15,0.5))

위의 그림 에서 뚜렷 한 선형 과 관련 된 특징 은 특징 공정 의 결과 로 만들어 진 것 을 볼 수 있다.특징 매트릭스 에서 기본 데이터 세트 특징 을 사용 하면 목표 변수의 변화 에 영향 이 적 거나 영향 을 주지 않 을 수 있 습 니 다.다른 한편,새로 만 든 특징 은 상당히 넓 은 관련 값 범 위 를 가지 는데 이것 은 상당히 중요 하 다.목표 변수(거래 신호)와 의 상관 성 은 그리 높 지 않다.

#     
df_tr2 = df_tr2.dropna() 
df_te2 = df_te2.dropna()
모델 예측 및 평가
다음은 자주 사용 하 는 기계 학습 알고리즘 을 사용 하여 데이터 에 대해 의합 과 교차 검증 평 가 를 실시한다.

models.append(('RF', RandomForestClassifier(n_estimators=25)))

models = []
#      
#      
models.append(('LR', LogisticRegression(n_jobs=-1)))
models.append(('TREE', DecisionTreeClassifier())) 
#     
models.append(('LDA', LinearDiscriminantAnalysis())) 
models.append(('KNN', KNeighborsClassifier())) 
models.append(('NB', GaussianNB())) 
#    
models.append(('GBM', GradientBoostingClassifier(n_estimators=25)))
models.append(('XGB',XGBClassifier(n_estimators=25,use_label_encoder=False)))
models.append(('CAT',CatBoostClassifier(silent=True,n_estimators=25)))
구축 모델 평가 함수

def modelEval(ldf,feature='signal',split_id=[None,None],eval_id=[True,True,True,True],
              n_fold=5,scoring='accuracy',cv_yrange=None,hm_vvals=[0.5,1.0,0.75]):

    ''' Split Train/Evaluation <DataFrame> Set Split '''

    # split_id : Train/Test split [%,timestamp], whichever is not None
    # test_id : Evaluate trained model on test set only

    if(split_id[0] is not None):
        train_df,eval_df = train_test_split(ldf,test_size=split_id[0],shuffle=False)
    elif(split_id[1] is not None):
        train_df = df.loc[:split_id[1]]; eval_df = df.loc[split_id[1]:] 
    else:
        print('Choose One Splitting Method Only')

    ''' Train/Test Feature Matrices + Target Variables Split'''
    y_train = train_df[feature]
    X_train = train_df.loc[:, train_df.columns != feature]
    y_eval = eval_df[feature]
    X_eval = eval_df.loc[:, eval_df.columns != feature]
    X_one = pd.concat([X_train,X_eval],axis=0)
    y_one = pd.concat([y_train,y_eval],axis=0)

    ''' Cross Validation, Training/Evaluation, one evaluation'''
    lst_res = []; names = []; lst_train = []; lst_eval = []; lst_one = []; lst_res_mean = []
    if(any(eval_id)):
        for name, model in models:  
            names.append(name)

            # Cross Validation Model on Training Se
            if(eval_id[0]):
                kfold = KFold(n_splits=n_fold, shuffle=True)
                cv_res = cross_val_score(model,X_train,y_train, cv=kfold, scoring=scoring)
                lst_res.append(cv_res)

            # Evaluate Fit Model on Training Data
            if(eval_id[1]):
                res = model.fit(X_train,y_train)
                train_res = accuracy_score(res.predict(X_train),y_train); lst_train.append(train_res)
            if(eval_id[2]):
                if(eval_id[1] is False):  # If training hasn't been called yet
                    res = model.fit(X_train,y_train)
                eval_res = accuracy_score(res.predict(X_eval),y_eval); lst_eval.append(eval_res)

            # Evaluate model on entire dataset
            if(eval_id[3]):
                res = model.fit(X_one,y_one)
                one_res = accuracy_score(res.predict(X_one),y_one); lst_one.append(one_res)

            ''' [out] Verbal Outputs '''
            lst_res_mean.append(cv_res.mean())
            fn1 = cv_res.mean()
            fn2 = cv_res.std();
            fn3 = train_res
            fn4 = eval_res
            fn5 = one_res

    s0 = pd.Series(np.array(lst_res_mean),index=names)
    s1 = pd.Series(np.array(lst_train),index=names)
    s2 = pd.Series(np.array(lst_eval),index=names)
    s3 = pd.Series(np.array(lst_one),index=names)
    pdf = pd.concat([s0,s1,s2,s3],axis=1)
    pdf.columns = ['cv_average','train','test','all']

    ''' Visual Ouputs '''
    sns.set(style="whitegrid")
    fig,ax = plt.subplots(1,2,figsize=(15,4))
    ax[0].set_title(f'{n_fold} Cross Validation Results')
    sns.boxplot(data=lst_res, ax=ax[0], orient="v",width=0.3)
    ax[0].set_xticklabels(names)
    sns.stripplot(data=lst_res,ax=ax[0], orient='v',color=".3",linewidth=1)
    ax[0].set_xticklabels(names)
    ax[0].xaxis.grid(True)
    ax[0].set(xlabel="")
    if(cv_yrange is not None):
        ax[0].set_ylim(cv_yrange)
    sns.despine(trim=True, left=True)
    sns.heatmap(pdf,vmin=hm_vvals[0],vmax=hm_vvals[1],center=hm_vvals[2],
            ax=ax[1],square=False,lw=2,annot=True,fmt='.3f',cmap='Blues')
    ax[1].set_title('Accuracy Scores')
    plt.show()
기준 모델:원시 시세 데 이 터 를 특징 으로 사용 합 니 다.

modelEval(df_tr1,split_id=[0.2,None])

결과,crossval_score 는 정확도=0.5 의 구역 을 맴 돌 고 있다.이 는 지수/주식 의 가격 데이터(개장,최고,최저,거래 량,장 마감)만 으로 는 가격 변동 의 방향 성 을 정확하게 예측 하기 어렵 다 는 것 을 보 여 준다.대부분의 모델 의 훈련 점 수 는 교차 검증 점수 보다 높다.재 미 있 는 것 은 DecisionTreeClassifier&RandomForest 가 매우 높 은 점 수 를 얻 을 것 이 라 고 예상 하 지 는 않 지만 교차 검증 의 점 수 는 낮 아 훈련 데이터 에 과도 한 적합 이 있 음 을 나타 낸다.
가입 기술 지표 특징

modelEval(df_tr2,split_id=[0.2,None],cv_yrange=(0.8,1.0),hm_vvals=[0.8,1.0,0.9])
그 결과 기준 모델 에 비해 정확도 점수 가 눈 에 띄 게 높 아 졌 다.선형 판별 분석(LDA)의 활약 이 뛰 어 나 훈련 집 뿐만 아니 라 교차 검증 에서 도 득점 이 눈 에 띄 게 높 아 졌 다.의심 할 여지없이 더욱 복잡 한 모델 GBM,XGB,CAT,RF 는 전체 샘플 에서 평가 점수 가 비교적 높다.감독 학습 모델 이 있 는 것 과 비교 하면 kNN 과 GaussianNB 의 무 감독 모델 은 비교적 나쁘다.
특징의 최적화

def feature_importance(ldf,feature='signal',n_est=100):
    # Input dataframe containing feature & target variable
    X = ldf.copy()
    y = ldf[feature].copy()
    del X[feature]
    # CORRELATION
    imp = corrMat(ldf,feature,figsize=(15,0.5),ret_id=True)
    del imp[feature]
    s1 = imp.squeeze(axis=0);s1 = abs(s1)
    s1.name = 'Correlation'      
    # SHAP
    model = CatBoostRegressor(silent=True,n_estimators=n_est).fit(X,y)
    explainer = shap.TreeExplainer(model)
    shap_values = explainer.shap_values(X)
    shap_sum = np.abs(shap_values).mean(axis=0)
    s2 = pd.Series(shap_sum,index=X.columns,name='Cat_SHAP').T
    #  RANDOMFOREST
    model = RandomForestRegressor(n_est,random_state=0, n_jobs=-1)
    fit = model.fit(X,y)
    rf_fi = pd.DataFrame(model.feature_importances_,index=X.columns,                                  
            columns=['RandForest']).sort_values('RandForest',ascending=False)
    s3 = rf_fi.T.squeeze(axis=0)
    # XGB 
    model=XGBRegressor(n_estimators=n_est,learning_rate=0.5,verbosity = 0)
    model.fit(X,y)
    data = model.feature_importances_
    s4 = pd.Series(data,index=X.columns,name='XGB').T
    # KBEST
    model = SelectKBest(k=5, score_func=f_regression)
    fit = model.fit(X,y)
    data = fit.scores_
    s5 = pd.Series(data,index=X.columns,name='K_best')
    # Combine Scores
    df0 = pd.concat([s1,s2,s3,s4,s5],axis=1)
    df0.rename(columns={'target':'lin corr'})
    x = df0.values 
    min_max_scaler = preprocessing.MinMaxScaler()
    x_scaled = min_max_scaler.fit_transform(x)
    df = pd.DataFrame(x_scaled,index=df0.index,columns=df0.columns)
    df = df.rename_axis('Feature Importance via', axis=1)
    df = df.rename_axis('Feature', axis=0)
    pd.options.plotting.backend = "plotly"
    fig = df.plot(kind='bar',title='Scaled Feature Importance')
    fig.show()
feature_importance(df_tr2)

많은 특징 에 대해 상관 성(Pearson's value)이 작은 것 은 다른 방법 에서 도 작은 점 수 를 주 는 것 으로 나 타 났 다.마찬가지 로 높 은 관련 특징 은 다른 특징의 중요성 방법 에서 도 높 은 점 수 를 받 았 다.특징의 중요성 을 이야기 할 때 일부 특징 은 경미 한 일치 하지 않 음 을 나타 내 고 전체적으로 보면 대부분 방법 은 특징 평가 의 유사 성 을 관찰 할 수 있다.기계 학습 에서 일부 특징 은 대부분 방법 에 있어 매우 낮은 상대 적 인 수치 가 있 기 때문에 아무런 영향 이 없 을 수 있 으 며 삭제 하 더 라 도 모델 의 정확성 을 떨 어 뜨리 지 않 을 것 이다.영향 을 받 지 않 을 수 있 는 특성 을 삭제 하면 전체 방법 이 더욱 효과 적 이 고 더 길 고 깊이 있 는 초 매개 변수 격자 검색 에 전념 하여 원래 모델 보다 더 정확 한 결 과 를 얻 을 수 있 습 니 다.

df_tr2_FI = df_tr2.drop(columns=['open','high','low','close','EMA10'])
modelEval(df_tr2_FI,split_id=[0.2,None],cv_yrange=(0.8,1.0),hm_vvals=[0.8,1.0,0.9])

결어
본 고 는 상기 증 지 수 를 예 로 들 어 기술 기준 을 특징 으로 기계 학습 알고리즘 을 사용 하여 주식 거래 신호(여 기 는 주가 나 수익 률 이 아 닙 니 다)를 예측 평 가 했 을 뿐 Python 기계 학습 이 금융 계량 화 연구 에서 의 응용 을 독자 에 게 보 여 주 는 데 목적 을 둔다.금융 차원 에서 볼 때 분석의 깊이 가 비교적 얕 고 실제 적 으로 주가 예측 에 유용 한 특징 이 많다.예 를 들 어 주식 관련 회사 의 경쟁 상대,고객,글로벌 경제,지연 정치 정세,재정 과 화폐 정책,자본 획득 등 을 포함한다.따라서 회사 주 가 는 다른 회사 의 주가 뿐만 아니 라 대형 상품,외환,광의 지수,심지어 고정 수익 증권 등 다른 자산 과 도 관련 이 있 을 수 있다.2)주가 시장 요인,예 를 들 어 많은 투자 자 들 이 기술 지표 에 관심 을 가진다.(3)회사 의 기본 적 인 요소,예 를 들 어 회사 의 년도 와 분기 보고 서 는 순자 산 수익 률(ROE)과 시장 이익률(price-to-earnings)등 관건 적 인 지 표를 추출 하거나 확정 할 수 있다.또 뉴스 는 곧 발생 할 사건 을 예고 할 수 있 으 며,이 사건 들 은 주 가 를 어느 방향 으로 발전 시 킬 수 있다.주식 가격 예측 에 관심 을 가 질 때 우 리 는 비슷 한 방법 으로 예측 변수 에 영향 을 주 는 요 소 를 구축 할 수 있 고 본 고 는 벽돌 을 던 져 옥 을 끌 어 올 리 는 역할 을 하 기 를 바란다.
이상 은 python 이 기계 학습 을 바탕 으로 주식 거래 신 호 를 예측 하 는 상세 한 내용 입 니 다.python 이 주식 거래 신 호 를 예측 하 는 데 관 한 자 료 는 저희 의 다른 관련 글 을 주목 하 십시오!

좋은 웹페이지 즐겨찾기