250x250
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
Tags
- 코딩
- tensorflow
- API
- Regression
- CLI
- 딥러닝
- 코딩테스트
- 기초
- 크롤링
- Linear
- 주식매매
- 연습
- 템플릿
- 주식
- python
- 머신러닝
- 회귀
- 주식연습
- 선형회귀
- 알고리즘
- DeepLearning
- 추천시스템
- PyTorch
- 프로그래머스
- 가격맞히기
- 게임
- 재귀함수
- 흐름도
- 주가예측
- 파이썬
Archives
- Today
- Total
코딩걸음마
주식 정보 불러와서 미래수익률 예측기 만들기 (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