250x250
Notice
Recent Posts
Recent Comments
Link
코딩걸음마
주식 정보 불러와서 미래수익률 예측기 만들기 (with Pykrx) 본문
728x90
간단한 아이디어가 갑자기 번뜩 떠올랐다.
기술적분석한 값을 input data로 두고 target으로 미래수익률을 두고
모델을 훈련시키면 좋을거 같은데?
이 간단한 생각을 적용해서 모델을 만들어 봤다.
1. 필요한 모듈 불러오기
# 우선 모듈 설치부터!
# !pip install mpl_finance
# !pip install matplotlib
# !pip install IPython
# !pip install datetime
# !pip install pandas_datareader
# !pip install pykrx
# !pip install ta
# !pip install --upgrade mplfinance
#모듈 불러오기
import matplotlib.pyplot as plt
import pandas as pd
from pandas_datareader import data
from datetime import datetime
from pykrx import stock
import numpy as np
import ta
from tqdm import tqdm
2. 기초 변수 가져오기
#오늘 날짜를 가져오는 함수
today = str(datetime.now())
today = today.replace("-","")[:8]
#년도를 바꾸는 함수
def year_change(date,x):
year = str(int(date[:4])-x)
month_day = date[4:]
return str(year+month_day)
#종목명 -> 티커 반환 함수
def stock_name(name,date=today):
df = stock.get_market_price_change(date,date)
return df[df["종목명"]==name].index[0]
#날짜 형식 변경
def date_split(x):
x = x[2:]
return x
#int 형식 변경
def change_to_int(x):
if x>-1:
x = int(x)
return x
3. 사용자 입력 Data (여기에 내가 궁금한 자료를 입력하자)
#-----[분석 Data 입력구간]-------------------------------------------------------------------------------------------------------------------
#Data 기간
year = 10
#x일후 수익률 예측
next_day =1
#분석 종료일자 (자동입력)
end_date = "20220608" #today
#--------------------------------------------------------------------------------------------------------------------------
#분석 시작일자
start_date = year_change(end_date,year) #10년 data 가져오기
4. 종목 리스트 불러오기
# kospi 종목 리스트
kospi_tickers = stock.get_market_ticker_list(end_date, market="KOSPI")
# kosdaq 종목 리스트
kodaq_tickers = stock.get_market_ticker_list(end_date, market="KOSDAQ")
tickers = kospi_tickers + kodaq_tickers
# 빈 데이터 프레임 생성
data = pd.DataFrame(columns=['pc', 'MA5_dis','MA60_dis', ,'MA224_dis','RSI', 'macd_signal',
'bol_h','bol_l', 'past_1day_pc', 'past_2day_pc', 'past_3day_pc', 'past_4day_pc', 'past_5day_pc', 'next_1day_pc', 'next_2day_pc', 'next_3day_pc', 'next_4day_pc', 'next_5day_pc'])
5. 주가 패턴 Data 수집
처음 모델을 무작정 돌렸을 때 값이 생각보다 만족스럽게 나오지 않았다.
Scaling 문제인가?
아니면 신규상장 종목의 data 부족?
액면분할 종목의 가격 왜곡현상?
이 부분을 고려하여
분석 data를 백분율로 scaling 해주고
특정 년수 이하의 종목은 제외하고
액면분할 경험이 있던 종목도 모두 제외하여 분석했다.
working_day = year*240
for ticker in tqdm(tickers):
df_real = stock.get_market_ohlcv(start_date,end_date, ticker, adjusted=False)
if len(df_real) > working_day:
df=df_real.copy()
try:
df_detail = stock.get_stock_major_changes(ticker)
if df_detail['액면변경전'].sum()==0:
print("액면분할 없음")
#등락률 이름 변경
df['pc'] = df['등락률']
# print("pc_complete")
#평균선 괴리도(%)
df['MA5_dis'] = (df['종가']-df['종가'].rolling(5).mean())/df['종가']
df['MA60_dis'] = (df['종가']-df['종가'].rolling(60).mean())/df['종가']
df['MA224_dis'] = (df['종가']-df['종가'].rolling(224).mean())/df['종가']
# print("MA_complete")
#RSI
df['RSI'] = ta.momentum.rsi(df['종가'])
df['RSI'] = (df['RSI'].map(change_to_int)+0.000000001)/100
# print("RSI_complete")
#macd_signal
df['macd_signal'] = ta.trend.macd_signal(df['종가'])/df['종가']
# print("MACD_complete")
#bolinzer band
df['bol_h'] = ta.volatility.bollinger_hband(df['종가'])/df['종가']
df['bol_l'] = ta.volatility.bollinger_lband(df['종가'])/df['종가']
# print("bolinzer_complete")
#지난 5일 동안의 수익률
df['past_1day_pc'] = (df["종가"].shift(+next_day)-df["종가"])/df["종가"]*100
df['past_2day_pc'] = (df["종가"].shift(+next_day+1)-df["종가"])/df["종가"]*100
df['past_3day_pc'] = (df["종가"].shift(+next_day+2)-df["종가"])/df["종가"]*100
df['past_4day_pc'] = (df["종가"].shift(+next_day+3)-df["종가"])/df["종가"]*100
df['past_5day_pc'] = (df["종가"].shift(+next_day+4)-df["종가"])/df["종가"]*100
# print("past_complete")
#현재시점부터 보유 5일후 수익률 (target)
df['next_1day_pc'] = (df["종가"].shift(-next_day)-df["종가"])/df["종가"]*100
df['next_2day_pc'] = (df["종가"].shift(-next_day-1)-df["종가"])/df["종가"]*100
df['next_3day_pc'] = (df["종가"].shift(-next_day-2)-df["종가"])/df["종가"]*100
df['next_4day_pc'] = (df["종가"].shift(-next_day-3)-df["종가"])/df["종가"]*100
df['next_5day_pc'] = (df["종가"].shift(-next_day-4)-df["종가"])/df["종가"]*100
# print("next_complete")
df = df.iloc[223:-5,7:]
data = data.append(df)
print(f"{ticker}_complete")
except:
continue
data.to_csv('stock_data_5days.csv')
6. 머신러닝 분석 (lightgbm 적용)
.
df = pd.read_csv('stock_data.csv')
df.head(2)
X_features = df.iloc[:,1:-11]
Y_target = df.iloc[:,-1:]
# lightGBM <- fix
from sklearn.metrics import mean_absolute_error
from lightgbm.sklearn import LGBMRegressor
from sklearn.model_selection import train_test_split
train_x, test_x, train_y, test_y = train_test_split(
X_features, Y_target, test_size=0.3, random_state=123) # test_size 0.3 30%가 test set
#모델에 data 넣기
model = LGBMRegressor().fit(train_x, train_y)
pred = model.predict(test_x)
print(f"model_ LGBMRegressor MAE : {mean_absolute_error(test_y, pred)}")
MAE 오차는 평균적으로 위/아래로 MAE%만큼 오차가 있다는 뜻이다
낮을수록 모델이 좋은 성능인 것으로 해석할 수 있다.
7. 개별종목의 Data 가져오기
224일선의 정보를 가져오기 위해서 2년치 data를 불러온다.
# 종목명 -> 티커 반환 함수
def stock_name(name, date=today):
df = stock.get_market_price_change(date, date)
return df[df["종목명"] == name].index[0]
# -----[분석 Data 입력구간]-------------------------------------------------------------------------------------------------------------------
# Data 기간
year = 2
# 분석 종료일자 (자동입력)
# today 당일 수급데이터가 없음
start_date = year_change(end_date, year) # 10년 data 가져오기
# --------------------------------------------------------------------------------------------------------------------------
# 개별 종목 티커 반환
ticker = stock_name(name, end_date)
# kospi 종목 리스트
kospi_tickers = stock.get_market_ticker_list(end_date, market="KOSPI")
# kosdaq 종목 리스트
kodaq_tickers = stock.get_market_ticker_list(end_date, market="KOSDAQ")
ticker = stock_name(name, end_date)
df_now = stock.get_market_ohlcv(start_date, end_date, ticker, adjusted=False)
# 등락률 이름 변경
df_now['pc'] = df_now['등락률']
# 평균선 괴리도(%)
df_now['MA5_dis'] = (df_now['종가']-df_now['종가'].rolling(5).mean())/df_now['종가']
df_now['MA60_dis'] = (df_now['종가']-df_now['종가'].rolling(60).mean())/df_now['종가']
df_now['MA224_dis'] = (df_now['종가']-df_now['종가'].rolling(224).mean())/df_now['종가']
# RSI
df_now['RSI'] = ta.momentum.rsi(df_now['종가'])
df_now['RSI'] = df_now['RSI'].map(change_to_int)
# macd_signal
df_now['macd_signal'] = ta.trend.macd_signal(df_now['종가'])/df_now['종가']
# bolinzer band
df_now['bol_h'] = ta.volatility.bollinger_hband(df_now['종가'])/df_now['종가']
df_now['bol_l'] = ta.volatility.bollinger_lband(df_now['종가'])/df_now['종가']
# 일목균형표
#지난 5일 동안의 수익률
df_now['past_1day_pc'] = (df_now["종가"].shift(+next_day)-df_now["종가"])/df["종가"]*100
df_now['past_2day_pc'] = (df_now["종가"].shift(+next_day+1)-df_now["종가"])/df["종가"]*100
df_now['past_3day_pc'] = (df_now["종가"].shift(+next_day+2)-df_now["종가"])/df["종가"]*100
df_now['past_4day_pc'] = (df_now["종가"].shift(+next_day+3)-df_now["종가"])/df["종가"]*100
df_now['past_5day_pc'] = (df_now["종가"].shift(+next_day+4)-df_now["종가"])/df["종가"]*100
print("past_complete")
#현재시점부터 보유 5일후 수익률 (target)
df_now['next_1day_pc'] = (df_now["종가"].shift(-next_day)-df_now["종가"])/df["종가"]*100
df_now['next_2day_pc'] = (df_now["종가"].shift(-next_day-1)-df_now["종가"])/df["종가"]*100
df_now['next_3day_pc'] = (df_now["종가"].shift(-next_day-2)-df_now["종가"])/df["종가"]*100
df_now['next_4day_pc'] = (df_now["종가"].shift(-next_day-3)-df_now["종가"])/df["종가"]*100
df_now['next_5day_pc'] = (df_now["종가"].shift(-next_day-4)-df_now["종가"])/df["종가"]*100
print("next_complete")
df_now_data = df_now.iloc[223:-5, 7:]
8. 5일 후, 수익률 추정
# 오늘 data를 입력하여 내일 데이터를 추정하기
df_today = df_now.iloc[-1:, 7:-11]
pred_next_5day = lgbm_x_day(5).predict(df_today)
print(f"5일후 수익률 예측 : {pred_next_5day[0]:.2}%")
주식은 머신러닝/딥러닝을 공부하기에 참 좋은 Data임에 틀림없다.
끝없이 생산되고 결측치나 오류가 적기 때문이다.
728x90
'나만의 프로그램' 카테고리의 다른 글
공공데이터 API를 활용한 데이터 크롤링 방법 (ex.경주마 성적정보) (0) | 2022.07.10 |
---|---|
[딥러닝] 딥러닝 기본 흐름도 (0) | 2022.06.30 |
주식 매매시뮬레이션게임 (with 파이썬) (0) | 2022.06.20 |
특정기간 상승률 순위 검색기 (0) | 2022.06.20 |
종목별 테마 크롤링 코드(with Naver 금융) (0) | 2022.06.19 |
Comments