같은 테마주들을 보면 같은 날 상한 VI가 걸리는 경우가 많더군요.
그래서 각각의 종목들이 같은날 상한 VI가 걸리는 날을 카운팅해서 관련주를 찾아보려고 합니다.
- 동적 VI 발동 : 개별종목 직전 체결가에서 2~3% 이상 변동이 발생하는 경우
- 정적 VI 발동 : 종목별 전일 종가 기준으로 10% 이상 변동이 발생하는 경우
VI가 걸린 종목들을 가져오는 방법을 모르기 때문에 저는 전일 종가대비 당일 고가가 10프로 이상일 경우를 상한 VI가 걸렸다고 가정하고 카운팅하겠습니다.
2022.05.02 - [데이터로 보는 주식] - [Python] 주식 종목 간 상관관계 분석해서 관련주 찾기
1. 국내 주식들 가격 가져오기
우선 국내 주식들의 주가를 가져와야합니다.
키움증권 api로 주가를 가져오는게 가장 깔끔하겠지만 개발환경이 맥북임으로 다른 방법을 사용하겠습니다.
저는 사용하기 편한 pykrx api를 사용하여 주가를 가져오겠습니다.( https://github.com/sharebook-kr/pykrx )
모든 종목의 2021년 05월 01부터 2022년 05 01일까지 1년 주가를 종가와 고가만 가져와 dataframe으로 만들겠습니다.
def get_stock_price2(start_day, end_day):
print("start get_stock_price")
def str_day(d):
return d.strftime('%Y%m%d')
# 입력한 기간동안에 개장일을 구하기
tmpDays = stock.get_market_ohlcv(start_day, end_day, "005930")
days = list(map(str_day, tmpDays.index.to_list()))
tmp = stock.get_market_ohlcv(days[0], market="ALL")
# 종가와 고가를 "종가,고가" 형식으로 합치겠습니다.
tmp["종고"] = tmp["종가"].map(str) + "," + tmp["고가"].map(str)
viPrice = tmp["종고"].to_frame(name=days[0]).T
for day in tqdm(days[1:]):
ddf = stock.get_market_ohlcv(day, market="ALL")
# vi
ddf["종고"] = ddf["종가"].map(str) + "," + ddf["고가"].map(str)
tmp_vi = ddf["종고"].to_frame(name=str(day)).T
viPrice = pd.concat([viPrice, tmp_vi])
def removeNull(df_stock):
df_stock = df_stock.fillna(method='ffill')
df_stock = df_stock.fillna(method='bfill')
# df_stock = df_stock.dropna(axis=0)
df = stock.get_market_ohlcv(days[-1], market="KOSPI")
df2 = stock.get_market_ohlcv(days[-1], market="KOSDAQ")
codeList = df.loc[df["저가"] != 0].index.tolist() + df2.loc[df2["저가"] != 0].index.tolist()
df_stock = df_stock[codeList]
def codeChangeName(code):
name = stock.get_market_ticker_name(code)
return name
df_code = df_stock.columns.tolist()
df_stock.columns = list(map(codeChangeName, df_code))
return df_stock
vi = removeNull(viPrice)
vi.to_csv("stockPrice2.csv", mode='w')
get_stock_price2("20210501", "20220501")
print(pd.read_csv("stockPrice2.csv", dtype=str, index_col=0))
AJ네트웍스 AK홀딩스 BGF ... 흥국에프엔비 희림 힘스
20210503 5760,5980 30250,31550 6960,7060 ... 4220,4340 8200,8440 12800,13200
20210504 5820,5890 30000,30750 6900,6980 ... 4205,4280 8670,8760 13050,13050
20210506 5890,5950 32300,32550 7110,7130 ... 4205,4255 8640,8780 13100,13200
20210507 5910,5940 32900,33400 7060,7110 ... 4295,4320 9020,9130 13250,13300
20210510 6140,6240 34700,35000 7240,7290 ... 4255,4315 9360,9360 13250,13350
... ... ... ... ... ... ... ...
20220425 6630,6750 22100,22600 5610,5690 ... 4570,4720 7770,8080 8960,9170
20220426 6660,6740 22100,22300 5630,5690 ... 4605,4855 8140,9000 9090,9100
20220427 6660,6660 21300,21600 5580,5630 ... 4440,4750 8500,8850 9030,9040
20220428 6640,6750 21100,21500 5650,5710 ... 4445,4625 8510,8930 8920,9050
20220429 6650,6650 21500,21700 5690,5710 ... 4375,4470 8640,8860 9030,9040
2. 상한 VI 카운팅하기
def get_vi_count():
print("start get_vi_count")
vi = pd.read_csv("stockPrice2.csv", dtype=str, index_col=0)
dic = dict.fromkeys(vi.columns, dict.fromkeys([str(i) for i in range(1, len(vi.columns) + 1)], ""))
viDic = {}
for dayId in (range(1, vi.shape[0])):
yDay = vi.iloc[dayId - 1]
tDay = vi.iloc[dayId]
viList = []
for codeId in range(vi.shape[1]):
yDayCPrice = yDay.iloc[codeId].split(",")[0]
tDayHPrice = tDay.iloc[codeId].split(",")[1]
#전날 가격보다 오늘 가격이 10프로 이상오른경우
if int(tDayHPrice) / int(yDayCPrice) > 1.1 and yDay.iloc[codeId] != tDay.iloc[codeId]:
viList.append(vi.columns[codeId])
viDic[vi.index[dayId]] = viList
permut = []
for key in tqdm(viDic.keys()):
p = list(itertools.product(viDic[key], repeat=2))
# p = list(itertools.permutations(viDic[key], 2))
permut.extend(p)
per = Counter(permut)
df = pd.DataFrame(index=vi.columns, columns=vi.columns)
df = df.fillna(0)
for key, value in tqdm(per.items()):
df.loc[key[0], key[1]] += int(value)
df.to_csv("viCount.csv", mode='w')
return df
# get_vi_count()
def search_viCount(stockName):
vi = pd.read_csv("viCount.csv", dtype=str, index_col=0)
result = vi.loc[stockName].astype(int).sort_values(ascending=False).head(10)
print(result)
search_viCount("팜스토리")
데이터프레임을 2중 딕셔너리에 카운팅하여서 이를 다시 df으로 변환하였습니다.
아래는 현대사료가 같은날 상한 VI가 같이 걸린 날을 카운팅한 것입니다.
현대사료 29
한일사료 17
팜스토리 13
일동홀딩스 13
에디슨INNO 12
미래생명자원 12
지에스이 11
중앙에너비스 10
하이스틸 10
이스트아시아홀딩스 9
사료 관련주 현대 사료입니다. 기존에 상관계수로 관련주를 찾는거 보다 훨씬 좋은 성능을 보여줍니다.
위에 현대사료 같은경우 사료로 묶인 한일사료, 팜스토리, 미래생명자원이 상위권에있습니다
저같은 경우 이걸 보고 현대사료와 한일사료가 계속 상을 치길래 비교적 덜 오른 팜스토리를 4월 초에 샀었고
4월 19일에 10프로 먹고 팔았슴돠.
근데 오늘 보니까 4월 25~27일 따따따상 간거 보니 매우 배가 아프네여 ㅎㅎ
우진 25
일진파워 15
서전기전 14
에너토크 13
한신기계 13
두산2우B 12
우리기술 11
보성파워텍 10
비에이치아이 9
원전 관련주 우진 입니다. 상당히 좋은 성능을 보여줍니다. 신기하네요
NE능률 27
덕성우 17
덕성 15
웹스 14
서연 13
위즈코프 13
웅진 12
노루홀딩스우 11
동양3우B 11
아이비김영 10
윤석률 관련주 ne능률입니다. 이것도 꽤 정확합니다
랩지노믹스 24
휴마시스 10
수젠텍 10
엑세스바이오 8
아이진 7
KG ETS 7
EDGC 6
인성정보 6
키네마스터 6
신풍제약우 6
코로나 자가진단키트 랩지노믹스입니다. 이것도 좋네요
2. 전체 코드
def get_stock_price2(start_day, end_day):
print("start get_stock_price")
def str_day(d):
return d.strftime('%Y%m%d')
# 입력한 기간동안에 개장일을 구하기
tmpDays = stock.get_market_ohlcv(start_day, end_day, "005930")
days = list(map(str_day, tmpDays.index.to_list()))
tmp = stock.get_market_ohlcv(days[0], market="ALL")
# 종가와 고가를 "종가,고가" 형식으로 합치겠습니다.
tmp["종고"] = tmp["종가"].map(str) + "," + tmp["고가"].map(str)
viPrice = tmp["종고"].to_frame(name=days[0]).T
for day in tqdm(days[1:]):
ddf = stock.get_market_ohlcv(day, market="ALL")
# vi
ddf["종고"] = ddf["종가"].map(str) + "," + ddf["고가"].map(str)
tmp_vi = ddf["종고"].to_frame(name=str(day)).T
viPrice = pd.concat([viPrice, tmp_vi])
def removeNull(df_stock):
df_stock = df_stock.fillna(method='ffill')
df_stock = df_stock.fillna(method='bfill')
# df_stock = df_stock.dropna(axis=0)
df = stock.get_market_ohlcv(days[-1], market="KOSPI")
df2 = stock.get_market_ohlcv(days[-1], market="KOSDAQ")
codeList = df.loc[df["저가"] != 0].index.tolist() + df2.loc[df2["저가"] != 0].index.tolist()
df_stock = df_stock[codeList]
def codeChangeName(code):
name = stock.get_market_ticker_name(code)
return name
df_code = df_stock.columns.tolist()
df_stock.columns = list(map(codeChangeName, df_code))
return df_stock
vi = removeNull(viPrice)
vi.to_csv("stockPrice2.csv", mode='w')
# get_stock_price2("20210501", "20220501")
# print(pd.read_csv("stockPrice2.csv", dtype=str, index_col=0))
def get_vi_count():
print("start get_vi_count")
vi = pd.read_csv("stockPrice2.csv", dtype=str, index_col=0)
dic = dict.fromkeys(vi.columns, dict.fromkeys([str(i) for i in range(1, len(vi.columns) + 1)], ""))
viDic = {}
for dayId in (range(1, vi.shape[0])):
yDay = vi.iloc[dayId - 1]
tDay = vi.iloc[dayId]
viList = []
for codeId in range(vi.shape[1]):
yDayCPrice = yDay.iloc[codeId].split(",")[0]
tDayHPrice = tDay.iloc[codeId].split(",")[1]
#전날 가격보다 오늘 가격이 10프로 이상오른경우
if int(tDayHPrice) / int(yDayCPrice) > 1.1 and yDay.iloc[codeId] != tDay.iloc[codeId]:
viList.append(vi.columns[codeId])
viDic[vi.index[dayId]] = viList
permut = []
for key in tqdm(viDic.keys()):
p = list(itertools.product(viDic[key], repeat=2))
# p = list(itertools.permutations(viDic[key], 2))
permut.extend(p)
per = Counter(permut)
df = pd.DataFrame(index=vi.columns, columns=vi.columns)
df = df.fillna(0)
for key, value in tqdm(per.items()):
df.loc[key[0], key[1]] += int(value)
df.to_csv("viCount.csv", mode='w')
return df
# get_vi_count()
def search_viCount(stockName):
vi = pd.read_csv("viCount.csv", dtype=str, index_col=0)
result = vi.loc[stockName].astype(int).sort_values(ascending=False).head(10)
print(result)
search_viCount("랩지노믹스")
코드나 데이터가 잘못될 수도 있으니 투자에 참고만 해야겠지만 꽤 의미있는 정보인거 같습니다
'주식 데이터 분석' 카테고리의 다른 글
| 네이버 주식 관련 블로그 크롤링 (파이썬) (0) | 2024.06.16 |
|---|---|
| [Python] Dataframe을 [컬럼명,인덱스,값] 2차원 리스트로 만들기 (0) | 2022.11.13 |
| [python] 네이버 뉴스 갯수 크롤링하여 날짜별로 카운팅하기 (주식 종목별로) (0) | 2022.06.03 |
| [Python] 국내 주식 종목 간 상관관계 분석해서 관련주 찾기 (0) | 2022.05.02 |