콘텐츠로 이동
9 posts with the tag “주식”

퀀티랩 단타 모델 - 딥러닝으로 내일의 주가 방향을 예측하는게 가능할까?

기존의 퀀티랩 모델은 중/장기 투자를 목적으로 하는 딥러닝 모델입니다. 이 포스트에서는 데이트레이딩(일명 단타)를 위한 모델 구축에 대해 다룹니다.

이 글은 기계학습에 대한 기초 지식을 요합니다.

단타를 독려하는 것이 아니니 오해 없으셨으면 좋겠습니다.

우선 데이트레이딩에 대해 알아봅시다. 데이트레이딩에 대한 정의는 제각각이지만 대부분 다음 원칙을 가지고 있습니다.

  • 하루 안에서 모든 거래를 마친다. (오버나잇 하지 않는다.)
  • 종목을 발굴한다.
  • 현금을 많은 비중으로 둔다. (Ex. 90% 현금 보유)
  • 목표 수익률, 손절 라인을 설정한다. (1~2%의 낮은 손익률로 잡는다.)
  • 미수는 자제한다.
  • 장이 안좋을땐 관망한다.

데이트레이딩은 많은 지표들을 보고 종목을 발굴하고 하루동안 수십, 수백번의 매매를 하면서 수익을 내기위해 노력합니다. 매매를 위해 기술적 분석이 주로 사용되는데 기술적 분석 기법은 너무나도 다양해서 나열하기도 어렵습니다.

단타에서 주요 결정 사항 중 하나인 “어떤 종목을 노릴 것인가?”를 해결하기 위한 딥러닝 모델을 구축했습니다. 모델은 파이썬으로 구축했으며 사용한 프레임워크, 라이브러리는 다음과 같습니다.

  • TensorFlow 2.4 (with Keras)
  • Scikit-learn 0.22.1

학습데이터는 약 100개의 자질과 2.5M개의 인스턴스로 구성했습니다. 지도학습(Supervised Learning)으로 레이블(label)은 다음 거래일의 등락률의 sigmoid로 정했습니다. 그 수식은 다음과 같습니다.

y = sigmoid(next_close / today_close - 1)

자질들은 자세히 다루기 어렵지만 크게 다음 종류의 자질군으로 구성됩니다.

  • 종목 주가
  • 종목의 기본적 분석 지표
  • 종목의 기술적 분석 지표
  • 국내 주식 시장 지수
  • 해외 주식 시장 지수
  • 주요국 환율
  • 원자재 가격
  • … (기타 등등)

자질 값들의 스케일(Scale)이 달라서 Standardization 했습니다. 세 가지 스케일러(Scaler)를 시도해 봤는데 그 중에서 Robust Scaler를 채택했습니다.

신경망 아키텍처는 기본적인 Dense(Fully Connected) Layer를 다음과 같이 쌓았습니다.

model = tf.keras.models.Sequential([
tf.keras.layers.Dense(256, activation='linear'),
tf.keras.layers.Dense(128, activation='linear'),
tf.keras.layers.Dense(64, activation='linear'),
tf.keras.layers.Dense(1, activation='sigmoid'),
])

이렇게 마지막 레이어의 활성화 함수(Activation Function)을 Sigmoid로 정해서 0과 1사이의 값으로 Prediction 하도록 했습니다. 직관적으로는 Prediction 값이 0.5 이상(초과)이면 내일 오늘보다 주가가 오를 것이라 판단하는 것이고 0.5 이하(미만)이면 주가가 내릴 것이라 판단하는 것입니다.

이렇게 학습한 모델로 테스팅 데이터를 넣어서 내일의 주가 방향을 얼마나 잘 맞추는지 알아보았습니다. 테스팅 데이터는 20210101~20210305 동안의 인스턴스이며 당연히 학습 데이터에 없는 인스턴스들 입니다.

Prediction 값을 score라고 하겠습니다. score가 0.5, 0.6, 0.7, 0.8, 0.9 이상일 때의 Accuracy를 다음과 같이 확인했습니다.

  • score 0.5 이상: 313,319개 인스턴스에서 정확도 57.99%
  • score 0.6 이상: 51,390개 인스턴스에서 정확도 68.81%
  • score 0.7 이상: 10,962개 인스턴스에서 정확도 84.22%
  • score 0.8 이상: 3,864개 인스턴스에서 정확도 89.73%
  • score 0.9 이상: 113개 인스턴스에서 정확도 49.56%

1

Score가 마냥 높다고 정확도가 높아지는 것은 아니였습니다. 0.8 까지는 높아지다가 0.9 이상에서는 정확도가 오히려 급격하게 감소했습니다. 정확도가 가장 높은 범위를 찾아봤습니다.

Score 0.83 이상 0.835 미만의 295개 인스턴스에서 정확도 94.58%를 얻을 수 있었습니다.

2

여기에 포함된 Score Top 50 종목들은 다음과 같습니다.

동전주, 거래대금이 적은 종목은 제외(Filter Out)했습니다.

datenameclosescorediffratio_nextday
20200325삼강엠앤티2,3200.8350-0.43%
20200324E123,6500.83508.03%
20200325휴비스3,6250.83501.10%
20200325미창석유공업47,8500.83491.78%
20200409빙그레54,2000.8349-0.55%
20200323엘티씨5,1300.83498.38%
20200325갤럭시아머니트리1,9250.83490.78%
20200325한솔제지9,0000.83492.89%
20200325KC그린홀딩스2,5950.83495.97%
20200325이월드2,7300.834828.21%
20200325푸른기술5,9440.83475.82%
20200325신화인터텍1,6550.83478.76%
20200619아진엑스텍4,1230.83473.10%
20200325신세계건설16,4500.83478.81%
20200325애니플러스1,0300.83464.85%
20200323노랑풍선5,7200.83465.77%
20200325미래에셋생명2,5700.83469.14%
20200323유티아이7,0600.83467.51%
20200325스카이이앤엠1,5050.83451.33%
20200422코오롱생명과학41,1000.83453.53%
20200324디와이2,5000.83449.60%
20200325HSD엔진2,2200.83443.60%
20200325가온전선12,1000.83436.20%
20200325슈피겐코리아32,3000.8343-2.94%
20200323동국S&C1,1950.834310.88%
20200325케이씨티1,2100.83437.02%
20200325태림포장2,4550.83424.07%
20200325서플러스글로벌1,2500.83422.00%
20200325태웅4,2200.8342-1.66%
20200324노랑풍선6,0500.834210.74%
20200323일진다이아11,0000.834217.27%
20200324일진디스플1,8920.834111.89%
20200325하나마이크론3,7250.83416.58%
20200325파워넷2,2400.83414.69%
20200325홈캐스트2,4000.83403.12%
20200325유니온1,9400.83402.06%
20200325SCI평가정보1,4550.83404.12%
20200325우노앤컴퍼니2,5150.834029.82%
20200325화승알앤에이1,3000.83393.08%
20200324웨이브일렉트로8,5630.833914.56%
20200325잇츠한불9,5300.83398.60%
20200325파인디앤씨1,0000.83385.50%
20200323서연1,5550.833829.90%
20200323화신1,3900.83384.68%
20200325신도리코21,2000.83370.94%
20200323큐렉소2,4600.83376.71%
20200325휴스틸4,8050.83374.06%
20200325예림당1,7500.83379.71%
20200325빛샘전자3,2200.83376.21%
20200325정원엔시스1,0700.833714.02%

그럼 어제(20210304)의 상위 종목들 살펴보겠습니다.

datenameclosescorediffratio_nextday
20210304일양약품35,0000.6188-1.14%
20210304수산아이앤티28,5500.5753-5.43%
20210304대한그린파워1,4000.55327.50%
20210304진양산업4,3650.51960.46%
20210304이녹스11,0000.51742.27%
20210304인지컨트롤스18,6000.5040-3.23%
20210304웅진씽크빅2,6350.49853.04%
20210304세원셀론텍1,9950.4923-1.50%
20210304기가레인1,8250.4921-1.37%
20210304파루1,4500.49170.69%

최근 장이 안좋아서 그런지 Score 가장 높은게 0.6 정도입니다. 그럼 오늘 날짜의 Score 상위 종목에는 어떤 종목들이 있을까요?

datenameclosescore
20210305팬엔터테인먼트7,6700.8676
20210305풍강3,9900.8056
20210305중앙에너비스9,2000.5439
20210305플리토13,9000.5383
20210305한국주강1,7800.5381
20210305일양약품34,6000.5241
20210305극동유화3,4750.5151
20210305한일진공1,0400.5141
20210305인성정보2,3150.5056
20210305텔콘RF제약5,2700.4999

다음 거래일에 이 종목들이 어떤 움직임을 보일지 지켜보면 재미있을 것 같습니다.

어디까지나 투자는 본인이 결정하는 것입니다. 퀀티랩에서 제공하는 정보는 참고만 하시길 당부드립니다.

[2021-02-26] 딥러닝 모델 종목추천

퀀티랩 AI 주식 종목 랭킹 모델을 개선했습니다. 다양한 자질을 추가했고 학습 방식도 많이 변경했습니다. 백테스팅 결과 기존의 모델에 비해 더 나은 결과를 얻을 수 있었습니다.

특이 사항으로 거래 대금이 적은 종목에 약간의 패널티를 부여했습니다. 너무 거래가 적은 종목들은 피하자는 의도입니다.

개선한 모델의 2021년 2월 26일자 상위 랭크 종목들은 다음과 같습니다.

1

이들 중에 특히 주가가 많이 내려와 있는 KT&G, 한국전력이 눈에 뜁니다.

매일 업데이트 되는 랭킹 결과를 퀀티랩에서 확인하세요. 퀀티랩 AI 매매내역 페이지에서는 퀀티랩 AI의 수익률 차트, 현재 보유 종목, 매매 내역을 볼 수 있습니다.

요증 인플레이션 우려와 함께 미국 금리 인상이 앞당겨질 수 있다는 추측이 많아서 주식 시장이 좋지 않습니다. 잘 대응하셔서 성투하세요.

어디까지나 투자는 본인이 결정하는 것입니다. 퀀티랩에서 제공하는 정보는 참고만 하시길 당부드립니다.

파이썬으로 KRX에서 전종목 기본 정보 얻어오기

이번 포스트에서는 코스피, 코스닥, 코넥스의 상장 종목들을의 기본 정보를 파이썬으로 획득하는 방법을 다룹니다. 한국거래소(KRX)에서 운영하는 기업공시채널 KIND라는 서비스가 있는데 여기서 정보를 얻어와 보겠습니다.

네이버 웨일이나 구글 크롬으로 접속하시길 추천드립니다.

먼저 KIND에 접속합니다.

1

위 그림의 하단에 빨간 박스 표시한 상장법인상세정보 메뉴를 클릭합니다.

그럼 다음과 같은 화면이 나오는데 여기서 우측에 있는 상장법인목록 메뉴를 클릭합니다.

2

그럼 상장법인목록을 확인할 수 있는 페이지가 뜨는데 여기서 EXCEL 버튼을 누르면 전체 상장 법인 목록을 다운받을 수 있습니다.

3

상장법인 목록 파이썬으로 가져오기

섹션 제목: “상장법인 목록 파이썬으로 가져오기”

이 파일을 파이썬으로 바로 다운 받을 수도 있습니다. 다양한 방법이 있겠지만 여기서는 pandas의 read_html 함수를 사용하겠습니다.

이제 개발자 도구를 열어봅니다. 웨일의 경우 다음과 같은 방법으로 개발자 도구를 열 수 있습니다.

  • 우측 상단의 ፧ 버튼을 클릭하고 기타 / 고급기능 / 개발자 도구를 클릭
  • Ctrl + Shift + I
  • F12

그럼 다음과 같이 개발자 도구가 나타납니다. (브라우저 하단에 뜰 수도 있습니다.)

4

여기서 Network 탭으로 이동합니다. 이동한 다음 상장법인목록 페이지의 EXCEL 버튼을 클릭합니다.

그럼 개발자 도구의 Network 탭에 다음과 같이 요청 정보가 표시됩니다.

5

여기서 빨간색 박스로 표시한 Request URL을 확인하고 아래로 쭉 내려서 Form Data를 확인합니다.

6

이제 이 정보를 가지고 요청 코드를 작성합니다.

def get_stocks(market=None):
market_type = ''
if market == 'kospi':
market_type = '&marketType=stockMkt'
elif market == 'kosdaq':
market_type = '&marketType=kosdaqMkt'
elif market == 'konex':
market_type = '&marketType=konexMkt'
url = 'http://kind.krx.co.kr/corpgeneral/corpList.do?currentPageSize=5000&pageIndex=1&method=download&searchType=13{market_type}'.format(market_type=market_type)
list_df_stocks = pd.read_html(url, header=0, converters={'종목코드': lambda x: str(x)})
df_stocks = list_df_stocks[0]
return df_stocks

read_html 함수를 호출할 때 첫 번째 행을 헤더로 인식하도록 headers=0을 넣어줬고 종목코드를 숫자로 인식하지 않도록 converters 인자를 주었습니다.

이렇게 코스피, 코스닥, 코넥스 전체 또는 시장 별로 종목 목록을 받아올 수 있습니다.

받아온 데이터에는 다음과 같이 회사명, 종목코드, 업종, 주요제품, 상장일, 결산월, 대표자명, 홈페이지, 지역 정보가 포함됩니다.

회사명종목코드업종주요제품상장일결산월대표자명홈페이지지역
DSR1556601차 비철금속 제조업합섬섬유로프2013-05-1512월홍석빈http://www.dsr.com부산광역시
GS글로벌001250상품 종합 도매업수출입업(시멘트,철강금속,전기전자,섬유,기계화학),상품중개,광업,채석업/하수처리 서비스/부동산 임대1976-06-2612월김태형http://www.gsgcorp.com서울특별시
HDC현대산업개발294870건물 건설업외주주택, 자체공사, 일반건축, 토목 등2018-06-1212월권순호, 정경구http://www.hdc-dvp.com서울특별시
KG케미칼001390기초 화학물질 제조업콘크리트혼화제, 비료, 친환경농자재, 수처리제1989-08-2512월곽정현, 김재익http://www.kgchem.co.kr울산광역시
LG이노텍011070전자부품 제조업기타 전자부품 제조업2008-07-2412월정철동http://www.lginnotek.co.kr서울특별시

[2020-H1] 딥러닝 주식종목 랭킹모델 백테스팅

이번 포스트에서는 최근 구축한 주식종목 랭킹모델의 2020년 상반기 백테스팅 결과를 정리합니다.

백테스팅 환경은 이 포스트에 정리한 것과 같습니다.

비교 대상(baseline)은 코스피 인덱스로 잡았습니다.

백테스팅 결과

진한 선이 포트폴리오 가치(PV)이고 연한 선이 코스피입니다. 변화율을 y축으로 정했습니다. 0.2는 20%라는 뜻입니다.

2020년 상반기 백테스팅 결과를 보면 퀀티랩 PV 수익률은 약 +20.3%에 달하고 코스피 수익률은 약 -3.1% 입니다.

Maxium Drawdown(MDD)은 퀀티랩 딥러닝 모델은 약 -23.1%, 코스피는 -35.7%로 퀀티랩 딥러닝 모델의 위험이 더 작았습니다.

2020년 상반기 퀀티랩 딥러닝 주식투자 모델의 백테스팅의 매매 내역은 다음과 같습니다.

dateactioncodenamepriceamountprofitlosseval
20200102buy028300에이치엘비101,3159899,998,511
20200102buy005930삼성전자55,20018199,997,012
20200102buy140410메지온193,8005199,995,529
20200102buy196170알테오젠69,80014399,994,032
20200102buy032500케이엠더블유57,30017499,992,537
20200103buy000660SK하이닉스94,50010598,904,030
20200103buy068270셀트리온177,5005698,902,539
20200103buy002360SH에너지화학1,1258,88898,901,039
20200103buy053800안랩76,00013198,899,546
20200103buy005380현대자동차116,0008698,898,050
20200108sell002360SH에너지화학1,6208,88844.00%99,729,899
20200108buy078130국일제지5,3501,86999,728,400
20200219sell196170알테오젠98,50014341.12%107,025,215
20200219buy096530씨젠34,900286107,023,718
20200306sell096530씨젠48,35028638.54%104,062,865
20200313sell053800안랩49,750131-34.54%92,553,090
20200316buy140410메지온112,900191,114,960
20200318buy000660SK하이닉스73,100188,061,293
20200423buy196170알테오젠97,900102106,097,159
20200511sell196170알테오젠168,40010272.01%115,562,596
20200615sell078130국일제지5,4201,8691.31%116,858,954
20200619buy053800안랩51,400194119,638,858
20200625buy229000젠큐릭스21,650461120,262,761

[2019] 딥러닝 주식종목 랭킹모델 백테스팅

이번 포스트에서는 최근 구축한 주식종목 랭킹모델의 2019년도 1년치 백테스팅 결과를 정리합니다.

퀀티랩의 주식종목 랭킹모델은 PER/PBR/ROE 등의 기본적 분석 지표, OHLCV/MACD/RSI 등의 기술적 분석 지표, 수익률, 변동성, 거래규모 등을 종합적으로 고려하여 학습했습니다.

이렇게 학습한 모델의 출력 값이 높을 수록 매수 고려 대상 종목이 되는 매매 전략을 세웠습니다. 매수, 익절, 손절 등의 기준은 다음과 같습니다.

  • 매수: 종목 랭킹 결과 Top 5 종목
  • 익절: 60%
  • 손절: -60%
  • 청산: 과거 평가 수익 고점 대비 -20%
  • …

이러한 기준으로 종가 매매를 진행하며 최대 10개 종목을 보유할 수 있도록 제한했습니다.

자본금은 1억원으로 정하고 종목당 1천만원까지 매수할 수 있도록 했습니다.

매수/매도 거래 비용을 다음과 같이 현실적으로 적용했습니다.

  • 거래세: 0.25%
  • 매매 수수료: 0.015%

비교 대상(baseline)을 코스피 인덱스로 정하여 백테스팅 결과를 차트로 그려보면 다음과 같습니다.

백테스팅 결과

진한 검정 선이 포트폴리오 가치(PV)를, 연한 회색 선이 코스피 인덱스를 보여줍니다.

동일한 스케일로 표시하기 위해 PV, 코스피 인덱스의 처음 값을 0으로 두고 변화율을 표시했습니다.

그 결과 퀀티랩 주식 종목 랭킹 모델은 약 15% 수익을, 코스피 Buy & Hold 전략 수익률은 약 9% 로 구해졌습니다.

백테스팅 과정에서 매매한 종목들의 내역은 다음과 같습니다.

dateactioncodenamepriceamountprofitlosseval
20190102buy042110에스씨디1,4556,87299,998,500
20190102buy028300에이치엘비76,30013199,997,000
20190102buy095190이엠코리아7,4301,34599,995,501
20190102buy011320유니크7,7201,29599,994,002
20190103buy017900광전자2,2454,45499,188,832
20190103buy115440우리넷7,2701,37599,187,332
20190103buy225570넷게임즈9,5801,04399,185,834
20190103buy041960코미팜19,31051799,184,336
20190104buy004720우리들제약8,7701,140101,308,762
20190104buy041140넥슨지티9,7701,023101,307,262
20190110sell225570넷게임즈10,5001,0439.60%104,164,638
20190110buy039830오로라10,150985104,163,138
20190116sell041140넥슨지티12,7501,02330.50%110,248,684
20190116buy007720대명소노시즌2,5853,868110,247,184
20190117sell095190이엠코리아10,2001,34537.28%114,231,397
20190117sell011320유니크12,8001,29565.80%114,187,471
20190117buy108230톱텍9,9701,003114,185,971
20190117buy036200유니셈4,0952,442114,184,471
20190117buy007390네이처셀11,744851114,182,972
20190131sell039830오로라10,3009851.48%117,832,543
20190219sell042110에스씨디1,8956,87230.24%127,255,406
20190219buy008370원풍4,0502,469127,253,906
20190219buy250000보라티알8,6501,156127,252,406
20190308sell036200유니셈4,1252,4420.73%118,311,856
20190325sell028300에이치엘비78,0001312.23%120,028,982
20190325buy056080유진로봇4,4752,234120,027,483
20190325buy208860엔지스테크널러지6,9001,449120,025,983
20190411sell041960코미팜20,5405176.37%121,651,076
20190423sell007390네이처셀11,7448510.00%117,992,185
20190423buy097230한진중공업12,036830117,990,686
20190423buy000440중앙에너비스8,3801,193117,989,187
20190520sell017900광전자2,4354,4548.46%99,035,671
20190524sell097230한진중공업8,150830-32.29%103,109,920
20190524buy083640인콘3,2003,125103,108,420
20190524buy010660화천기계2,4904,016103,106,920
20190610sell115440우리넷9,9901,37537.41%106,821,419
20190628sell010660화천기계3,1204,01625.30%108,235,770
20190628buy004540깨끗한나라2,4154,140108,234,270
20190628buy004830덕성3,2003,125108,232,770
20190628buy019540일지테크3,1503,174108,231,270
20190708sell083640인콘2,1853,125-31.72%108,047,706
20190711sell019540일지테크4,2753,17435.71%112,418,803
20190725sell056080유진로봇3,0902,234-30.95%108,903,860
20190725buy230980솔트웍스3,8002,631108,902,361
20190725buy002070남영비비안1,5456,472108,900,861
20190726sell007720대명소노시즌1,7903,868-30.75%110,587,888
20190729sell004720우리들제약5,9601,140-32.04%112,485,768
20190729sell002070남영비비안2,6056,47268.61%112,441,090
20190729buy012700리드코프6,9501,438112,439,591
20190729buy000140하이트진로홀딩스12,000833112,438,091
20190729buy012610경인양행9,4001,063112,436,592
20190731sell004830덕성3,3003,1253.12%111,465,379
20190801sell250000보라티알9,0001,1564.05%107,712,924
20190801buy036030KTH5,3401,872107,711,424
20190801buy207760미스터블루7,4301,345107,709,925
20190801buy086980쇼박스4,0502,469107,708,425
20190805sell000440중앙에너비스5,6201,193-32.94%105,756,923
20190805sell230980솔트웍스2,4452,631-35.66%105,739,876
20190806sell208860엔지스테크널러지4,6901,449-32.03%105,802,627
20190806buy041960코미팜11,550865105,801,129
20190806buy007390네이처셀6,9001,449105,799,629
20190807sell004540깨끗한나라3,1804,14031.68%106,554,466
20190819sell207760미스터블루9,6901,34530.42%107,638,863
20190819buy006090사조오양9,6001,041107,637,364
20190819buy189860서전기전3,7902,638107,635,865
20191011sell189860서전기전3,9202,6383.43%109,339,291
20191024sell007390네이처셀9,4701,44937.25%115,558,718
20191024buy056080유진로봇3,0003,333115,557,218
20191024buy028300에이치엘비163,98460115,555,742
20191024buy039830오로라12,650790115,554,243
20191213sell028300에이치엘비87,04460-46.92%114,112,748
20191217sell012700리드코프7,1101,4382.30%113,575,584
20191219sell036030KTH5,4101,8721.31%113,394,701
20191219buy000440중앙에너비스8,6301,158113,393,202
20191219buy000520삼일제약22,700440113,391,704
20191223sell041960코미팜15,45086533.77%113,165,219

모델을 지속적으로 발전시켜 나가며 종목 랭킹 결과 및 운용 시뮬레이션 결과를 퀀티랩에서 제공할 계획입니다.

[2018-05-22] 파마+LSV 콤보 주식 종목 랭킹 (저PER + 저PBR + 저PCR + 소형주)

강환국 - 할 수 있다! 퀀트 투자에서 참고한 파마+LSV 콤보 전략을 파이썬으로 구현했습니다.

  • PBR이 0.2 미만이면 제외
  • 소형주 (시가총액 10분위 하위 1분위)
  • 순위 합산 = 저PER 순위 + 저PBR 순위 + 저PCR 순위
  • 순위 합산으로 랭킹

다음은 2018년 05월 22일 기준 파마+LSV 콤보 전략으로 랭킹한 주식 종목 순위입니다.

종목코드 종목명 PER PBR PCR rank_PER rank_PBR rank_PCR rank_sum
101930 인화정공 4.05 0.29 2.29 1 0 3 4
071090 하이스틸 5.35 0.33 3.40 3 2 6 11
006200 한국전자홀딩스 8.55 0.30 2.14 13 1 2 16
012620 원일특강 6.04 0.42 5.14 4 5 18 27
038010 제일테크노스 9.20 0.46 3.64 15 7 10 32
019770 서연탑메탈 9.01 0.54 3.43 14 11 7 32
025880 케이씨피드 5.23 0.60 4.06 2 19 12 33
071970 STX중공업 0.15 0.78 0.15 0 34 0 34
208890 에듀케이션파트너 12.62 0.49 1.25 29 10 1 40
011390 부산산업 9.99 0.63 3.25 21 20 5 46
010240 흥국 6.26 0.79 4.24 5 35 13 53
031310 아이즈비전 8.07 0.58 6.21 12 14 28 54
060540 에스에이티 7.16 0.68 5.58 8 27 22 57
060380 동양에스텍 9.80 0.59 5.83 19 17 24 60
019180 티에이치엔 9.72 0.81 3.10 18 39 4 61
215790 이노인스트루먼트 9.26 0.65 5.87 16 24 25 65
045300 성우테크론 6.49 0.88 4.96 7 44 17 68
009180 한솔로지스틱스 11.76 0.72 5.49 24 31 21 76
072950 빛샘전자 10.01 0.64 7.26 22 21 34 77
101670 코리아에스이 8.04 0.86 5.89 11 42 26 79
030720 동원수산 7.38 1.00 5.17 9 53 19 81
007770 한일화학 12.61 0.47 8.78 28 9 47 84
033310 디케이디앤아이 10.25 0.67 7.88 23 25 37 85
002870 신풍제지 31.03 0.55 3.58 66 12 9 87
039020 이건홀딩스 16.27 0.45 7.48 46 6 35 87
002710 TCC동양 27.58 0.40 5.81 63 3 23 89
003010 혜인 22.10 0.41 6.45 55 4 31 90
054410 케이피티 7.66 0.99 6.32 10 51 30 91
005670 푸드웰 14.98 0.87 4.84 36 43 15 94
130740 티피씨글로벌 16.89 0.46 8.20 48 8 41 97
224110 에이텍티앤 6.34 1.45 6.03 6 73 27 106
053270 구영테크 28.16 0.71 4.33 64 29 14 107
016920 카스 14.77 0.86 7.23 34 41 33 108
048830 엔피케이 16.38 0.88 4.89 47 45 16 108
075970 동국알앤에스 17.29 0.60 8.54 49 18 44 111
091340 S&K폴리텍 14.98 0.95 6.24 35 48 29 112
051390 YW 15.59 0.57 12.67 41 13 64 118
021650 한국큐빅 41.39 0.72 3.67 79 30 11 120
035200 프럼파스트 9.60 1.23 8.17 17 64 40 121
073190 듀오백 18.83 0.67 8.91 51 26 49 126
234070 에이원알폼 13.49 2.37 3.53 30 89 8 127
130500 GH신소재 15.04 0.81 9.44 38 38 52 128
043260 성호전자 57.55 0.70 5.22 85 28 20 133
086670 비엠티 15.75 0.82 8.98 44 40 50 134
123570 이엠넷 11.99 1.06 10.34 25 56 54 135
009730 코센 9.99 1.48 8.23 20 74 42 136
044060 조광ILI 14.51 0.94 11.62 33 47 60 140
079810 디이엔티 12.46 1.32 9.03 27 70 51 148
220110 드림티엔터테인먼트 15.73 1.49 7.06 43 75 32 150
131400 액트 29.83 0.97 7.69 65 50 36 151
032820 우리기술 15.10 1.31 8.91 39 67 48 154
032750 삼진 20.79 0.91 10.54 54 46 56 156
077280 한컴지엠디 27.36 0.73 12.29 62 32 62 156
031820 콤텍시스템 39.12 0.59 13.13 76 16 65 157
091440 텔레필드 39.43 0.80 8.61 77 37 45 159
033050 제이엠아이 71.01 0.76 7.94 89 33 38 160
148140 비디아이 12.45 1.73 11.14 26 77 57 160
101160 월덱스 15.11 1.97 8.08 40 82 39 161
052860 아이앤씨 13.56 1.91 10.09 31 80 53 164
086060 진바이오텍 19.39 1.00 11.27 52 54 59 165
026150 특수건설 88.20 0.59 12.65 91 15 63 169
202960 판도라티비 15.65 2.47 8.31 42 90 43 175
278990 파인이엠텍 24.91 0.96 13.78 60 49 68 177
003780 진양산업 22.81 1.11 13.38 57 58 66 181
009470 삼화전기 14.15 3.38 10.52 32 98 55 185
002680 한탑 43.26 0.79 16.48 81 36 78 195
044780 에이치케이 88.64 0.64 21.61 92 22 82 196
203450 유니온커뮤니티 24.52 1.32 14.99 59 69 71 199
064090 에프앤리퍼블릭 14.98 3.09 14.25 37 95 69 201
052460 아이크래프트 22.69 1.26 17.96 56 65 81 202
046310 백금T&A 26.21 2.22 11.26 61 85 58 204
093230 이아이디 57.69 0.64 41.52 86 23 96 205
091580 상신이디피 36.24 2.32 8.73 73 87 46 206
045520 크린앤사이언스 18.07 2.58 13.51 50 91 67 208
136660 큐엠씨 16.03 7.13 12.12 45 102 61 208
002410 범양건영 38.91 0.99 23.54 75 52 85 212
038620 위즈코프 35.44 1.22 16.15 72 63 77 212
131090 시큐브 20.32 2.29 17.43 53 86 79 218
065770 CS 33.98 1.80 14.66 71 78 70 219
124500 아이티센 41.95 1.27 15.57 80 66 75 221
131220 대한과학 36.91 1.56 15.55 74 76 74 224
100030 모바일리더 40.65 1.09 28.19 78 57 90 225
141020 포티스 24.33 2.11 22.86 58 84 84 226
051980 중앙리빙테크 48.76 1.18 22.65 83 62 83 228
217620 디딤 32.00 2.37 15.15 68 88 72 228
081970 넥스지 33.05 1.91 17.82 69 81 80 230
053160 프리엠스 45.33 1.15 38.36 82 60 93 235
025870 신라에스지 94.85 1.41 15.35 93 71 73 237
181340 이즈미디어 106.47 1.12 42.73 95 59 97 251
233250 메디안디노스틱 33.86 3.37 24.61 70 97 87 254
069140 누리플랜 754.06 1.01 47.02 102 55 98 255
232140 와이아이케이 31.30 5.56 27.45 67 101 88 256
150900 파수닷컴 78.59 2.75 15.87 90 93 76 259
032860 GMR 머티리얼즈 130.32 1.17 80.16 97 61 102 260
019990 에너토크 147.03 1.44 35.41 98 72 92 262
013000 세우글로벌 95.48 1.32 66.60 94 68 101 263
149010 아이케이세미콘 50.60 4.13 24.15 84 99 86 269
094860 코닉글로리 180.53 2.06 27.98 99 83 89 271
218410 RFHIC 60.00 2.96 40.42 87 94 94 275
056000 신스타임즈 198.89 1.83 41.05 101 79 95 275
210120 빅텐츠 60.66 3.17 52.55 88 96 99 283
127120 디엔에이링크 184.46 2.63 29.15 100 92 91 283
007460 에이프로젠 KIC 110.92 4.33 56.85 96 100 100 296

파이썬으로 네이버 금융 뉴스 크롤링하기

네이버 주식에서 뉴스를 크롤링하는 간단한 파이썬 코드를 소개합니다.

  • Dependency
    • python 3
    • requests
    • BeautifulSoup
    • webob

뉴스 문서를 질의 (Query)나 종목코드로 크롤링 해와서 문서에 포함된 글과 종목코드들을 반환해 줍니다.

import json
import os
from bs4 import BeautifulSoup
import re
import requests
from webob.compat import urlparse
class NaverFinanceNewsCrawler:
URL_NAVER_FINANCE = "http://finance.naver.com"
URL_NAVER_FINANCE_NEWS_QUERY = "http://finance.naver.com/news/news_search.nhn?q=%s&x=0&y=0" # params: query
URL_NAVER_FINANCE_NEWS_CODE = "http://finance.naver.com/item/news_news.nhn?code=%s&page=%s" # params: (code, page)
URL_NAVER_NEWS_FLASH = "http://finance.naver.com/news/news_list.nhn?mode=LSS2D&section_id=101&section_id2=258"
URL_NAVER_STOCK_NOTICE = "http://finance.naver.com/item/news_notice.nhn?code=%s&page=%s" # params: (code, page)
def __init__(self):
pass
def crawl(self, query=None, code=None, page=1):
"""
:param query:
:param code:
:param page:
:return:
"""
if query:
return self._crawl_by_query(query)
elif code:
return self._crawl_by_code(code, page=page)
else:
raise Exception("[Error] 'query' or 'code' should be entered.")
def _crawl_by_query(self, query):
"""
Crawl Naver Finance News
:param query: string; search keywords
:return: generator; [{title, summary, url, articleId, content, codes}, ...]
"""
# Convert the query to euc-kr string
q = ""
for c in query.encode('euc-kr'):
q += "%%%s" % format(c, 'x').capitalize()
r_url = NaverFinanceNewsCrawler.URL_NAVER_FINANCE_NEWS_QUERY % (q)
r = requests.get(r_url)
soup = BeautifulSoup(r.text, "lxml")
news = soup.find('div', class_='newsSchResult').find('dl', class_='newsList')
news_title = news.find_all('dt', class_='articleSubject')
news_summary = news.find_all('dd', class_='articleSummary')
for title, summary in zip(news_title, news_summary):
url = NaverFinanceNewsCrawler.URL_NAVER_FINANCE + title.a.get("href")
res = {
"title": title.a.text,
"summary": summary.find(text=True).strip(' \t\n\r'),
"url": url,
"articleId": urlparse.parse_qs(urlparse.urlparse(url).query)["article_id"][0]
}
res.update(self._crawl_content(url))
yield res
def _crawl_by_code(self, code, page=1):
"""
Crawl Naver Stock News
:param code: string; a stock code
:return: generator;
"""
r_url = NaverFinanceNewsCrawler.URL_NAVER_FINANCE_NEWS_CODE % (code, page)
r = requests.get(r_url)
soup = BeautifulSoup(r.text, "lxml")
news_rows = soup.find('table', class_='type2').find_all('td', class_='title')
for row in news_rows:
yield {"title": row.a.text.strip(' \t\n\r'), "url": row.a.get('href')}
def _crawl_content(self, url):
r = requests.get(url)
soup = BeautifulSoup(r.text, "lxml")
content = soup.find('div', id="content", class_='articleCont')
codes = re.findall(r"\d{6}", content.text)
return {"content": content.text.strip(' \t\n\r'), "codes": codes}

삼성전자에 관한 뉴스를 가져와 보겠습니다.

if __name__ == "__main__":
crawler = NaverFinanceNewsCrawler()
docs = crawler.crawl(query='삼성전자')
for i, d in enumerate(docs):
print("{i}번째 문서".format(i=i+1), end=" " + "-" * 50)
print("-" * 50)
print("내용: {content}".format(content=d["content"]))
print("문서에 포함된 종목 코드: {codes}".format(codes=d["codes"]))

이렇게 돌리면 결과는 다음과 같습니다.

1번째 문서 ----------------------------------------------------------------------------------------------------
내용: 【서울=뉴시스】 김지은 기자 = 코스피가 8일 사흘 만에 반등에 성공하며 2550선을 회복했다. 코스닥은 연중 최고치를 경신했다. 이날 코스피 지수는 전 거래일(2545.44)보다 6.96포인트(0.27%) 오른 2552.40에 장을 마쳤다.지수는 미국 증시 혼조세와 한미 자유무엽협정(FTA) 재협상에 대한 경계감에 전 거래일보다 10.96포인트(0.43%) 내린 2534.21로 출발했다. 하지만 이내 장중 낙폭을 줄이고 상승 전환해 2540선에서 등락을 거듭하다 개인의 매수세에 2550를 넘었다.이날 개인투자자는 618억원 어치의 주식을 사며 지수 상승을 이끌었다. 기관은 1055억, 외국인은 38억원 순매도했다. 간밤 미국 증시는 세제개편안 통과에 대한 불확실성이 부각되며 혼조세로 마감했다.뉴욕증권거래소(NYSE)에서 다우존스30 산업평균지수는 전날보다 8.81포인트(0.04%) 오른 2만3557.23으로 거래를 마쳤다. 스탠더드앤드푸어스(S&P) 500지수는 전날보다 0.49포인트(0.02%) 하락한 2590.64에 장을 닫았다. 기술주 중심의 나스닥은 18.65포인트(0.27%) 내린 6767.78을 기록했다. 키움증권 서상영 연구원은 "세제개편안 통과에 대한 불확실성의 부각으로 인한 미국 증시의 혼조세와 한미 자유무역협정(FTA) 재협상 요인 등은 한국 증시 하락 요인으로 작용할 가능성이 높다"면서도 "전날 트럼프가 북한과의 대화를 언급하는 등 지정학적 우려 완화에 대한 기대감을 높인 점은 긍정적"이라고 말했다.업종별로는 등락이 엇갈렸다.의약품(1.13%), 전기전자(1.05%), 섬유의복(0.95%), 비금속광물(0.77%), 종이목재(0.71%), 제조업(0.62%), 서비스업(0.60%), 전기가스업(0.53%) 등은 상승했다.반면 철강금속(-1.51%), 보험(-1.17%) 통신업(-0.99%), 은행(-0.76%), 의료정밀(-0.76%), 운수창고(-0.73%), 금융업(-0.69%) 등은 하락했다.시가총액 상위종목을 보면 '대장주' 삼성전자는 2만원(0.71%) 오른 282만5000원에 거래를 마쳤다. 2등주 SK하이닉스도 1200원(1.46%) 오른 8만3600원을 기록했다.이에 반해 현대차(-0.32%), 네이버(-1.63%), 포스코(-2.62%), 삼성물산(-0.34%), 삼성생명(-1.87%), 현대모비스(-0.19%), 삼성바이오로직스(-0.64%) 등은 떨어졌다.코스닥 지수는 전 거래일(701.14)보다 7.97포인트(1.14%) 오른 709.11로 마감, 연중 최고치를 기록했다.전년에 견줘서는 12.3% 상승했다.개인은 808억원 매도 우위를 보였지만 외국인과 기관은 각각 25억원, 900억원 어치 사들였다.정부의 코스닥 활성화 정책에 대한 기대감과 연기금의 코스닥 투자 확대 논의에 힘입어 상승세가 이어진 것으로 풀이된다.시가총액은 248조6000억원으로 전년 대비 23.4%늘었다. [email protected]▶ 뉴시스 빅데이터 MSI 주가시세표 바로가기 ▶ 네이버 채널에서 뉴시스를 구독해주세요뉴시스 관련뉴스언론사 페이지로 이동합니다.[빅데이터MSI]8일 주식시장 심리 1→1→1→1단계 '매우 나쁨'시장심리 톱5…신세계·한국토지신탁·영풍·삼성중공업·한미반도체8일 빅데이터 '핫 키워드'…기능·사람·본문·복사·제품코스피, 사흘 만에 반등 2550선 회복…2552.40 마감김동연 "한미 정상회담서 FTA 깊은 논의 없어"
문서에 포함된 종목 코드: []
2번째 문서 ----------------------------------------------------------------------------------------------------
내용: - 대부분 해외 투자 집중…코스피 수익률 못따라잡아- 국내 투자도 비용 이유로 ETF 투자 중심- 종목 투자는 삼성전자 쏠림 현상으로 재미 못봐[이데일리 안혜신 기자] 로보어드바이저펀드에 투자하면 안정적으로 수익을 올릴 수 있다는 말에 적지 않은 자금을 투자했던 투자자들이 부진한 수익률때문에 한숨을 쉬고 있다.◇로보어드바이저 펀드 대부분 해외 투자 집중우후죽순 격으로 늘어나는 로보어드바이저펀드를 운용하는 ‘로봇 펀드매니저’가 고른 투자대상을 들여다보면 그 대답의 단초를 발견할 수 있다. 우선 로보어드바이저펀드의 투자 유형을 살펴봐야 하는데 펀드평가사인 KG제로인에 따르면 현재 운용순자산 10억원 이상의 로보어드바이저펀드 17개 가운데 해외채권이나 주식에 투자하는 상품이 12개로 압도적이다. 로보어드바이저펀드 내에 해외투자상품이 유독 많은 이유는 미국을 중심으로 한 전세계 로보어드바이저 상품 자체가 글로벌하게 자산을 배분하는 상품이 대부분이라는 점이 꼽힌다. 로보어드바이저펀드 후발주자인 우리 입장에서는 해외 사례를 벤치마킹한 측면이 강하다는 얘기다.아울러 국내 주식에 대한 기대 투자수익률이 낮아진 점도 해외투자상품이 많은 이유 중 하나다. 과거 7% 경제성장률을 달성할 때와 현재 2~3% 수준의 경제성장률을 이어가고 있는 상황에서의 주식시장에 대한 기대감은 다를 수 밖에 없다는 것. 업계 관계자는 “국내 자산만으로는 자산 배분에 한계를 느끼고 있다”며 “전세계적으로 놓고 보면 국내뿐만 아니라 다양한 투자 기회가 생길 수 있다”고 설명했다.하지만 해외투자 비중 증가는 아이러니하게도 로보어드바이저펀드 수익률 부진으로 이어졌다. 올해 국내 증시 상승률이 두드러지면서 상대적으로 해외투자 수익률이 이를 따라잡지 못한 것. 실제 올들어 전세계 주가지수는 지난 10월까지 평균 17% 상승했다. 반면 코스피 상승률은 22.9%로 홍콩, 브라질에 이어 상승률에서 3위를 기록하고 있다.◇국내 종목 투자는 삼성전자 쏠림에 재미 못봐그렇다면 국내 투자에 집중하는 로보어드바이저펀드의 선택 종목은 무엇일까. 대부분 펀드의 포트폴리오는 상장지수펀드(ETF)가 차지하고 있다. 분산투자로 상대적으로 안정성이 높은 ETF의 특성상 주식 직접투자보다 체감 수익률이 낮을 수밖에 없는 것이다. 최근 로보어드바이저펀드 중 가장 수익률이 높은 ‘미래에셋AI스마트베타마켓헤지자(주식-재간접)종류F’의 경우 펀드 내 비중이 21.37%로 압도적인 삼성전자(005930)를 제외하고는 일시적으로 낙폭이 큰 우량주 30종목에 투자하는 ‘TIGER 가격조정’(13.96%), 최근 성과가 좋은 종목에 투자하는 ‘TIGER 모멘텀’(13.09%), 변동석이 적은 종목에 투자하는 ‘TIGER 로우볼’(12.55%) 등 7개 ETF를 담고 있다. ‘대신로보어드바이저자산배분성과보수 1[혼합-재간접]Class C’ 역시 ‘KODEX 200’(25.45%), ‘아리랑 배당주’(7.31%), ‘KODEX 코스닥 150’(4.2%) 등 주식에 투자한 10개 종목이 모두 ETF다. ‘하이ROKI1글로벌로보어드바이저증권투자신탁 H[혼합-재간접형]’도 ‘TIGER200’(14.86%)를 비롯해 총 9개의 국내외 ETF로 포트폴리오를 채우고 있다.로보어드바이저펀드가 주로 ETF에 투자하는 이유는 간단하다. 일단 투자비용이 상대적으로 저렴하다. 업계 관계자는 “과거에는 펀드 투자성과가 잘 나오는 편이었지만 최근은 수익 내기가 쉽지 않아졌다”며 “초과 성과도 잘 나오지 않는 상황에서 비용이 더 싼 ETF를 담을 수밖에 없다”고 말했다.ETF보다 주식에 주로 투자하는 펀드도 있다. 다만 최근 코스피 정보기술(IT)주 쏠림이 심화하면서 수익률이 좋지 않다. ‘에셋플러스알파로보코리아그로스증권자투자신탁 1-1(주식)’는 LG디스플레이(034220)·NAVER(035420)·현대건설(000720)·현대산업(012630)·GS리테일(007070)·LG이노텍(011070)·롯데케미칼(011170)·현대중공업(009540)·LG전자(066570)·사람인에이치알(143240) 등 80개 종목에 투자 중이며 ‘에셋플러스알파로보글로벌인컴성과보수증권자투자신탁 1-2(주식)’는 LG디스플레이(034220)·현대건설(000720)·롯데케미칼(011170)·아모레G(002790)·엔씨소프트(036570)·한화(000880)·농심(004370)·GS(078930)·롯데칠성(005300)·한국타이어월드와이드(000240) 등 총 80개 종목에 투자중이다. 에셋플러스자산운용 관계자는 “성장에 중심을 두는 그로스펀드와 안정적인 수익 추구를 하는 인컴펀드의 투자 종목이 다르다”며 “ETF보다 액티브펀드에 종점을 두고 있는 회사인만틈 ETF 투자가 아닌 종목 투자로 로보어드바이저펀드를 연구했다”고 설명했다.‘DB밸류아이로보어드바이저증권자투자신탁(H)[채권혼합-재간접형]’ 역시 개별종목 투자비중이 높은 펀드 중 하나다. 이 펀드는 SK하이닉스(000660)·고려아연(010130)·LG(003550)·두산인프라코어(042670)·대우건설(047040)·롯데하이마트(071840)·롯데정밀화학(004000) 등에 투자하고 있다.이창헌 미래에셋자산운용 패시브솔루션팀장은 “로보어드바이저펀드는 자산배분 전략을 사용하고 있어 단순히 코스피와 수익률을 비교하는 것은 맞지 않다고 본다”며 “단기 투자 실적에 투자자들이 민감하다는 것은 알지만 로보어드바이저펀드는 꾸준히 장기적인 관점에서 수익을 봐야 한다”고 말했다.안혜신 ([email protected])▶이데일리 개편기념 이벤트 - 갤럭시 노트8 쏩니다▶[카카오톡] 플친 맺으면 스타벅스 쿠폰 팡팡~♥<ⓒ종합 경제정보 미디어 이데일리 - 무단전재 & 재배포 금지>이데일리 관련뉴스언론사 페이지로 이동합니다.미소 띤 트럼프, 한미 FTA '돌출 발언' 사라진 이유[단독]종교인 과세 50년만에 내년 시행 '가닥'…기독교계는 반발조두순 '재심'은 불가능..출소 전 타이트한 '보안 처분' 이뤄져야멜라니아, '델포조' 코트 벗고 '제이멘델' 시스루 드레스 입어'비행기 사고로 사망' 할러데이에 메이저리그 애도 물결
문서에 포함된 종목 코드: ['005930', '034220', '035420', '000720', '012630', '007070', '011070', '011170', '009540', '066570', '143240', '034220', '000720', '011170', '002790', '036570', '000880', '004370', '078930', '005300', '000240', '000660', '010130', '003550', '042670', '047040', '071840', '004000']
3번째 문서 ----------------------------------------------------------------------------------------------------
내용: - 코스피지수 2550선 회복…삼성전자·SK하이닉스등 IT관련주 상승전환- 트럼프, 北이슈 완화발언·FTA 언급자제…“긍정적으로 평가”- “IT업종 하반기 랠리 주도…반도체 업종 상승추세 여전”[이데일리 윤필호 기자] 도널드 트럼프 미국 대통령의 방한에 잔뜩 긴장했던 국내 주식시장이 안도랠리를 보였다. 우려와 달리 돌발변수가 발생하지 않자 투자심리가 안정을 되찾은 것. 특히 올해 상승장을 이끌고 있는 정보기술(IT) 관련주(株)와 제약·바이오주 등 기존 주도주들이 최근 조정세를 접고 다시 힘을 내고 있는 양상이다.◇IT·바이오주 주도로 증시 반등…트럼프 리스크 해소8일 마켓포인트에 따르면 코스피지수는 전거래일대비 6.96포인트(0.27%) 오른 2552.40에 장을 마감했다. 코스피지수는 이번 주 들어 트럼프 방한을 앞두고 부진한 모습을 보였다. 지난 6일부터 8.56포인트, 7일 3.97포인트 각각 빠지며 조정국면에 들어가는 것이 아니냐는 전망도 나왔지만 별다른 충격없이 트럼프 방한 일정이 마무리되자 시장은 기존 상승추세를 회복하는 모습이다. 특히 기존 주도주였던 IT관련주가 재차 상승세를 타면서 전기전자업종지수도 5거래일 만에 반등했다. 대장주인 삼성전자(005930)는 5거래일 만에 상승세를 보였고 SK하이닉스(000660)도 3거래일만에 상승 전환했다. 코스닥지수의 경우 제약·바이오의 약진이 돋보였다. 지난 3일 700선을 넘긴 이후 방한 이슈와는 별도로 꾸준한 상승세를 이어가고 있다.트럼프 대통령 방한으로 비롯된 불확실성이 해소된 데 따른 것으로 보인다. 트럼프 대통령은 이날 국회 연설에서 북한 핵미사일 이슈와 관련해 “북한은 미국을 유약하다고 해석했는데 이것은 치명적인 오산이 될 것“이라고 경고하며 강한 어조로 비판했다. 하지만 전날인 7일 문재인 대통령과의 공동 기자회견에서는 “북한은 협상 테이블에 나와 우리와 합의를 도출하는 것이 좋을 것”이라고 밝혀 그간 초강경 기조보다 완화됐다는 평가를 받았다.한국과 미국간 자유무역협정(FTA) 개정 문제에 대해서도 압박의 강도가 높지 않았다는 평가다. 트럼프 대통령은 국회 연설에서 이에 대해 한 차례 언급을 하는데 그쳤다. 전날 공동기자회견에서도 “현재 협정은 성공적이지 못했고 미국에는 그렇게 좋은 협상은 아니었다고 말씀드리고 싶다”고 말해 원론적인 입장을 강조하는데 그쳤다.◇“트럼프 방한 긍정적…IT관련주, 다시 상승장 이끌 것”증권가에서는 트럼프 대통령의 방한에 대체로 긍정적 평가를 내놓았다. 아울러 증시에서 IT주 등 기존 주도주들이 다시 상승랠리를 이끌 것이라고 전망했다. 박중제 메리츠종금증권 투자전략팀장은 “트럼프 대통령 방문에서 북한 문제에 완화된 모습은 긍정적”이라면서도 “FTA 재협상 문제의 경우 아직 어떤 방향으로 합의가 되고 얼마나 시간이 걸릴지 등에 대한 정보가 부족하기 때문에 당장 반영되는 이슈가 아니다”고 말했다. 그는 “IT업종은 올해 주도주였고 실적도 좋았다”며 “최근 상승세가 주춤한 것은 다른 업종과의 수익률 격차가 크게 벌어진데 따른 단기적 숨고르기 정도로 보인다”며 “하지만 전망도 여전히 좋고 이익도 증가하고 있어서 연말까지는 순환매가 나올 수 있다고 보고 있다”고 진단했다.이상재 유진투자증권 투자전략팀장은 최근 코스피지수 부진에 대해 “상승국면에서 잠시 쉬어가는 흐름으로 시장 방향성과 관련해 논란이 제기될 상황은 아니다”고 판단했다. 그러면서 트럼프 대통령의 북한 관련 발언에 대해서는 “북한 리스크와 관련해 종전의 강한 기조에서 물러나 대화를 시사하는 등 비교적 우호적 모습을 보였다”고 평가했다. 이 팀장은 IT관련주 부진에 대해 “IT주는 잠시 쉬어가는 정도지 조정이라고 말할 순 없다”면서 “단기 급등에 따른 조정은 있을 수 있지만 반도체 업황에 대한 긍정적 기대가 여전한 만큼 상승추세는 유효하다”고 점쳤다.윤필호 ([email protected])▶이데일리 개편기념 이벤트 - 갤럭시 노트8 쏩니다▶[카카오톡] 플친 맺으면 스타벅스 쿠폰 팡팡~♥<ⓒ종합 경제정보 미디어 이데일리 - 무단전재 & 재배포 금지>이데일리 관련뉴스언론사 페이지로 이동합니다.미소 띤 트럼프, 한미 FTA '돌출 발언' 사라진 이유[단독]종교인 과세 50년만에 내년 시행 '가닥'…기독교계는 반발조두순 '재심'은 불가능..출소 전 타이트한 '보안 처분' 이뤄져야멜라니아, '델포조' 코트 벗고 '제이멘델' 시스루 드레스 입어'비행기 사고로 사망' 할러데이에 메이저리그 애도 물결
문서에 포함된 종목 코드: ['005930', '000660']
4번째 문서 ----------------------------------------------------------------------------------------------------
내용: [서울경제] 코스피 지수가 사흘 만에 상승세로 전환했다. 8일 코스피 지수는 전 거래일 대비 6.96포인트(0.27%) 오른 2,552.40에 장을 마쳤다. 이 날 지수는 전일 대비 0.43% 하락한 2,534.48에 장을 시작했으나 외국인과 개인의 매수세에 힘입어 장중 반등에 성공했다. 장중 국내 주식을 사들이던 외국인은 오후 장에서 매도세로 전환했다. 외국인과 기관은 각각 38억원 1,059억원 어치 주식을 팔아치웠으며 개인만 홀로 매수 우위를 나타냈다. 도널드 트럼프 미국 대통령 방문으로 일부 불확실성이 해소되면서 일부 업종이 상승 전환한 게 주효했다. 업종별로는 의약품이 1.13% 상승했으며 전기전자(1.05%), 음식료품(0.59%), 섬유의복(0.95%), 종이목재(0.71%), 화학(0.40%), 비금속광물(0.77%) 등이 올랐다. 철강금속은 한미FTA 재협상 우려로 1.51% 하락했고 기계(-0.51%), 의료정밀(-0.76%), 운송장비(-0.18%), 통신업(-0.99%), 보험(-1.17%) 등이 약세를 나타냈다. 시가총액 상위 종목 중에는 삼성전자(005930)와 SK하이닉스(000660)가 각각 1.18%, 0.97% 상승하며 지수 상승을 이끌었다. 다른 상위 종목은 대개 약세로 마감했으며 한미FTA 재협상 가능성이 야기되면서 포스코가 2.31% 하락 마감했다. 코스닥은 전일 대비 7.97포인트(1.14%) 오른 709.11에 마감했다./서지혜기자 [email protected][서울경제 바로가기]1997년 이래 대한민국 최고의 과학자 DB [바로가기]서울경제의 모든 연재물!... 서경Cube [바로가기▶]저작권자 ⓒ 서울경제, 무단 전재 및 재배포 금지서울경제 관련뉴스언론사 페이지로 이동합니다.[단독] 트럼프 맞아 청와대가 공수해 건 그림은?北에 등돌리는 중국? 갑자기 평양관광 금지한 이유멜라니아 트럼프가 샤이니 민호에게 활짝 웃어준 까닭? "훈훈한 분위기"조두순 사건 영화 '소원' 재조명...이준익 감독이 영화를 만든 이유는?장훈 감독 입장은? "조덕제 나를 만신창이 만들어" 메이킹 영상 "처절하게 강간당하는 모습
문서에 포함된 종목 코드: ['005930', '000660']

분봉 수급 점수 계산하기

여기서 구하고자 하는 피쳐는 분봉 수급 점수입니다.

분봉 수급 점수: 1분동안 체결이 많이 이루어진 분봉들 중에서 매수세가 강한 분봉들의 비율로 [-1, 1]의 범위를 가짐

아래와 같은 1분봉차트가 있습니다. 분봉들이 아주 많아서 사람이 직접 점수를 계산하기는 어려울 수 있습니다.

분봉동시호가제외

분봉차트 CSV 파일

이를 파이썬으로 계산해 보겠습니다.

python3, numpy, pandas, matplotlib, mpl_finance 등을 필요로 합니다.

mpl_finance는 https://github.com/matplotlib/mpl_finance 에서 받을 수 있습니다.

우선 필요한 라이브러리들 부터 임포트합니다.

import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
import mpl_finance
if __name__ == '__main__':
pass

이제 아래 코드로 main을 채웁니다.

df_chart = pd.read_csv('data/000660_m_in.csv') # 다운받은 데이터의 경로로 변경하십시오
# 고려할 분봉 수 결정
# df_chart = df_chart.iloc[-60*6*5:] # 약 5일치 분봉
# 동시호가 거래 없애기
df_chart['체결일'] = (df_chart['체결시간'] / 1000000).astype(int)
df_chart['체결시분'] = df_chart['체결시간'].mod(1000000).astype(int)
df_chart = df_chart[df_chart['체결시분'] < 153000]
# 거래량이 평균+표준편자*2 보다 많았던 분봉들만 남깁니다
df_chart = df_chart[df_chart['거래량'] > df_chart['거래량'].mean() + df_chart['거래량'].std() * 2]
# [수요 거래대금 + 공급 거래대금]을 구합니다
supdemand = ((df_chart['현재가'] - df_chart['시가']).abs() * df_chart['거래량']).sum()
# [수요 거래대금 - 공급 거래대금]을 구합니다
demand = ((df_chart['현재가'] - df_chart['시가']) * df_chart['거래량']).sum()
# [(수요 거래대금 - 공급 거래대금) / (수요 거래대금 + 공급 거래대금)]을 구합니다
score_demand = float(demand) / supdemand

여기서 score_demand가 분봉 수급 점수입니다. 이 점수가 1에 가까울수록 수요 거래대금이 컸다는 의미이고 -1에 가까울수록 공급 거래대금이 많았다는 의미입니다.

위의 1분봉 차트에 대해서 분봉 수급 점수는 0.1252 입니다. 양수이므로 수요 거래대금이 더 많았다는 뜻입니다.

물론 이 지표만으로 투자를 결정할 수는 없습니다. 앞으로 다양한 지표들을 개발하고 데이터를 기반으로 이유있는 투자를 하고자 합니다.

파이썬을 이용한 자동 주식투자 시스템 개발 튜토리얼 - 키움증권편

많은 분들이 주식투자를 해보셨거나 적어도 관심은 있으실 것입니다. 그러나 막상 주식투자를 해서 수익을 내는 분들은 많지 않은 것이 현실입니다. 많은 분들이 주식시장에서 이기지 못합니다. 그 이유는 욕심때문에 종목 매매를 객관적으로 하지 못해서, 계속해서 주식시장을 들여다볼 시간이 없어서일 수 있습니다. 시스템 트레이딩은 정해진 규칙으로 객관적으로 종목을 매매하여 객관성을 유지하고, 시스템이 자동으로 투자하기 때문에 주식시장을 계속 들여다보지 않아도 되는 등의 다양한 장점을 가집니다. 이 책을 통해 자신만의 자동 투자 시스템을 구현하여 모두 주식시장에서 성공적인 투자자가 될 수 있기를 바라봅니다.

이 책은 파이썬으로 키움증권 Open API를 활용하여 시스템 트레이딩 프로그램 개발의 전반을 설명합니다. 파이썬에 대한 기초적인 지식이 있다면 이 책을 읽기가 더욱 수월할 것입니다. 파이썬을 전혀 몰라도 이 책의 내용을 충분히 이해할 수 있도록 소스 코드에 대해 상세히 설명하며 필요한 파이썬 기초 문법도 다룹니다.

진행하다 막히는 부분이 있으면 Github 리포지토리(https://github.com/quantylab/systrader) 또는 이메일([email protected])을 통해 트러블슈팅(Trouble Shooting)을 도와드립니다.

파이썬에서 키움증권 API를 사용하여 자동투자 시스템을 개발하는데 다음 환경을 권장합니다.

  • 윈도우 7+
  • 파이썬 3.5+ x86(32 비트)
  • PyCharm
  • 키움증권 API

여기서는 파이썬 3.5+ 32비트 버전을 사용합니다. 파이썬 2를 사용해도 무방하지만 32비트를 사용해야 합니다. 그리고 꼭 파이썬 2를 사용해야 하는 것이 아니라면 파이썬 3를 사용할 것을 권장합니다.

추가로 파이썬 라이브러리들을 설치해야 하는데, 본 책에서 활용하는 주요 라이브러리들은 다음과 같습니다.

  • PyQt5
  • NumPy
  • Pandas
  • Bokeh

Anaconda3는 파이썬 3와 대부분의 주요 라이브러리들을 포함하고 있습니다. 번거로움을 줄이고자 이들을 별도로 설치하는 것 보다 Anaconda3를 설치하기를 권장합니다.

다음 사이트에서 무료로 Anaconda3를 받을 수 있습니다.

https://www.continuum.io/downloads

Anaconda3 다운로드 사이트 화면

왼쪽 아래의 빨간 박스로 표시한 링크를 다운받기를 권장합니다.

다운받은 파일로 설치를 진행합니다. 별도의 설정 변경 없이 설치를 진행하면 되기 때문에 어려운 부분은 없습니다.

여기서는 VSCode를 주 IDE(Integrated Development Environment)로 사용합니다. VSCode는 마이크로소프트에서 만든 오픈소스 코드 편집기 입니다. https://code.visualstudio.com/에서 VSCode를 무료로 다운받을 수 있습니다.

파이썬 IDE로 대표적인 PyCharm 또한 SysTrader 개발에 사용하기 적합합니다. 다음 사이트에서 무료로 PyCharm Community 버전을 다운받을 수 있습니다.

https://www.jetbrains.com/pycharm/

Professional 버전은 유료이니 Community 버전을 받으시면 됩니다. Community 버전도 자동 투자 시스템을 만드는데 충분합니다.

이제 키움증권의 Open API를 설치할 차례입니다. 먼저 브라우저를 통해 키움증권 홈페이지(https://www1.kiwoom.com)에 들어갑니다. 메인화면의 최하단을 보시면 다음과 같이 Open API 메뉴가 있습니다.

openapi

클릭하여 들어가시면 다음과 같은 화면을 볼 수 있습니다.

openapi

여기서 표시해 놓은 사용 신청하러 가기와 키움 Open API+ 모듈 다운로드를 진행해 주시면 됩니다.

이렇게 다운받은 OpenAPISetup.exe파일을 실행시켜서 설치하시면 키움증권 API 설치가 완료됩니다.

추가로 KOA Studio를 설치하여 키움증권 API를 살펴볼 수 있습니다. KOA Studio를 실행했을 때 mfc100.dll을 찾을 수 없다는 에러화면을 보게 될 수도 있습니다.

koastudio 에러

이 때는 MS Visual C++ 2010 x86을 설치하면 에러가 해결됩니다.

MS VC++ 다운로드 페이지: https://www.microsoft.com/en-us/download/details.aspx?id=5555

키움증권을 통해 주식 투자를 하기 위해 우선 키움증권 계좌를 개설해야 합니다. 키움증권 홈페이지 메인화면의 우측에 다음 화면이 있습니다.

계좌개설

여기서 키움 계좌 개설 메뉴를 클릭하시고 계좌 개설을 진행해 주시면 됩니다.

자동투자 시스템을 구현하면서는 모의투자 계좌를 이용하셔야 합니다. 키움증권 홈페이지 메인화면의 최하단을 보시면 다음과 같이 상시 모의투자 메뉴가 있습니다.

모의투자

클릭하여 들어가시면 왼쪽 메뉴 리스트에 참가신청 메뉴가 있고, 클릭하여 들어가시면 다음과 같이 상시모의투자 참가신청란이 있습니다.

모의투자

신청 완료하시면 왼쪽 메뉴 리스트의 계좌정보 메뉴를 통해 주식계좌를 확인할 수 있습니다.

키움증권 API는 크게 TR과 REAL로 구분되는 API 집합으로 구성되어 있습니다.

  • TR은 요청을 보내면 그 결과가 콜백 함수로 전달되는 API들로, 시세조회, 관심종목조회, 조건검색 등을 포함합니다.
  • REAL은 키움증권 시스템에서 콜백 함수에 실시간으로 데이터를 전달하는 API들로, 매매 체결, 업종/종목의 실시간 시세, 실시간 조검검색 등을 포함합니다.

KOA Studio프로그램을 이용하면 API에 대한 상세 정보를 확인할 수 있습니다.

앞으로 활용할 주요 API들을 살펴보겠습니다. 여기서는 API에 포함되어 있는 함수들의 형태 (Signature)만 보여주고 파이썬에서의 호출 방법은 뒤에서 설명합니다.

로그인 함수는 아주 간단합니다. CommConnect()를 호출하면 키움증권 로그인 창이 뜨고 로그인 성공시 1, 로그인 실패시 0을 반환합니다. 키움증권 로그인 창이 뜨면 아이디, 비밀번호, 공인인증서비밀번호 입력란이 있습니다. 개발 동안에는 모의투자를 체크하여 아이디와 비밀번호만 입력하시길 강력 권장합니다.

키움증권의 로그인 창은 다음과 같습니다. 여기서 아이디를 저장하고, 모의투자 모드로 설정할 수 있습니다. 이 창을 파이썬으로 띄우는 방법은 개발 관련 장에서 설명합니다.

로그인

그렇다면 매번 아이디, 비밀번호, 공인인증서번호를 입력해야 할까요? 다행히 자동로그인 기능이 있습니다. 먼저 계좌 비밀번호를 저장해야 합니다. 이를위해 다음과 같이 Windows 우측 하단의 트레이 아이콘을 우클릭하여 계좌비밀번호 저장 메뉴를 통해 계좌 비밀번호를 저장할 수 있습니다. 트레이 아이콘이 숨어져 있을 수도 있으니, 화살표를 눌러서 확인해보시기 바랍니다. 물론 로그인이 되어 있는 상태에서만 아이콘을 확인할 수 있으니, 개발 관련 장에서 확인하시면 됩니다.

계좌비밀번호저장

다음과 같이 자동로그인을 활성화할 수 있습니다. 먼저 계좌 비밀번호를 등록하고, 계좌번호 바로 밑에 있는 AUTO를 체크합니다. 이렇게 하면 앞으로 로그인할 때 비밀번호를 입력하지 않아도 자동으로 로그인이 됩니다.

계좌비밀번호저장

이제 키움증권 API를 사용할 환경이 갖추어 졌습니다. 로그인한 계좌의 현황을 확인할 수 있는 API들을 살펴보겠습니다. 살펴볼 주요 API는 다음과 같습니다.

  • 현재 잔고 (Balance) 확인
  • 보유 종목 확인

현재 잔고를 확인하는 API는 예수금상세현황요청 기능을 이용하시면 됩니다. TR 목록의 opw00001을 활용하면 됩니다. 호출 방법은 다음과 같습니다.

SetInputValue("계좌번호", <계좌번호>)
CommRqData("예수금상세현황요청", "opw00001", 0, <화면번호>)

여기서 <계좌번호>에는 여러분의 모의투자 또는 실계좌 계좌번호를 입력하시면되고, 화면번호에는 임의의 값을 정해주시면 됩니다. 계좌번호가 8자리라면 11을 붙여서 10자리로 만들어 줍니다. 이렇게 호출하면 OnReceiveTrData() 함수가 콜백됩니다. 콜백이란 필요한 처리 후 시스템에서 함수를 호출해 준다는 의미를 가지는 컴퓨터 용어입니다. 주로 이름이 On으로 시작하는 함수들이 콜백 합수입니다.

화면번호의 값을 상수화하여 사용하시길 권장합니다. 키움증권에서 사용할 수 있는 화면번호가 200개로 제한되어 있기 때문입니다.

OnReceiveTrData()의 형태는 다음과 같습니다.

OnReceiveTrData(sScrNo, sRQName, sTRCode, sRecordName, sPreNext, nDataLength, sErrorCode, sMessage, sSPlmMsg)
  • sScrNo: 화면번호
  • sRQName: 사용자 구분명
  • sTRCode: TR이름
  • sRecordName: 레코드 이름
  • sPreNext: 연속조회 유무를 판단하는 값 0: 연속(추가조회)데이터 없음, 2:연속(추가조회) 데이터 있음
  • nDataLength: 사용안함
  • sErrorCode: 사용안함
  • sMessage: 사용안함
  • sSPlmMsg: 사용안함

이 콜백 함수 내에서 sRQName가 예수금상세현황요청인지 확인하고, 다음과 같이 주문가능금액을 얻어올 수 있습니다.

GetCommData(sTRCode, sRQName, 0, "주문가능금액")

매수 주문을 넣고, 주문이 체결되면 보유 종목이 생깁니다. 보유 종목은 주로 매도의 관점에서 모니터링 해야 합니다. 물론 추가 매수를 할 수도 있습니다. 보유 종목의 수익률을 확인하는 API를 살펴보겠습니다. 보유종목 정보를 받아오는 TR 코드는 OPT10085 입니다.

SetInputValue("계좌번호", <계좌번호>)
CommRqData("계좌수익률요청", "opt10085", 0, <화면번호>)

여기서 화면번호를 임의의 문자열을 넣어주면 됩니다. 화면번호는 다른 요청과 겹치지 않는 것이 좋습니다.

실제로 투자를 할때 하는 일들을 살펴볼 필요가 있습니다. 다음과 같이 정리해 보겠습니다.

  • 시장의 상황을 파악합니다. 궂이 불구덩이에 뛰어들 필요는 없습니다. 약세장일때는 피하는게 상책이죠.
  • 계좌의 현재 상태를 파악합니다. 매수 가능 금액이 얼마나 있는지 알아야 합니다.
  • 매수를 고려할 종목을 선택 합니다. 아무리 강세장에서도 오를 종목만 오릅니다.
  • 보유종목을 모니터링 합니다. 자신의 규칙에 따라 익절, 손절하는 것이 필요하죠.
  • 매수할 종목을 선택합니다.
  • 매도할 보유종목을 선택합니다.
  • 투자 손익을 파악합니다.

자동 투자 시스템을 구현할 때, 위 일들을 별도의 모듈로 구현하는 것이 유지보수 측면에서 좋을 것입니다. 위에서 나열한 일들을 수행하는 모듈들을 정해 보겠습니다.

  • 시장모니터 (Markets Monitor): 코스피, 코스닥 시장을 모니터링하여 강세장, 약세장을 판단하는 모듈
  • 계좌관리자 (Account Manager): 잔고를 파악하는 모듈
  • 보유종목모니터 (Holdings Monitor): 보유종목의 수익률 등을 모니터링 하는 모듈
  • 종목모니터 (Stocks Monitor): 실시간 종목 검색, 종목 상세 정보 획득 등을 수행하는 모듈
  • 매매판단자 (Decision Maker): 종목의 매수, 매도를 판단하는 모듈

파이썬은 컴퓨터 비전공자도 쉽게 접근할 수 있으면서 강력한 고급 프로그래밍 언어입니다. 전세계적으로 사용자가 크게 늘고 있는 추세이고, 구글을 비롯한 여러 업체의 실서비스에서도 사용하고 있습니다. 본 튜토리얼에서는 이후에 나오는 소스코드들을 따라할 수 있을 정도의 문법만 다룹니다.

우선 프로그래밍 언어를 처음 배울 때 꼭 한번씩 해보는 “Hello World!” 문자열을 출력해 보겠습니다.

if __name__ == "__main__":
print("Hello World!")

실행해 보면 Hello World!가 출력되는 것을 확인할 수 있습니다.

파이썬으로 객체지향 프로그램을 작성할 수 있습니다. 이를 위해서 파이썬에는 모듈과 클래스 개념이 들어있습니다. 파이썬에서 모듈은 하나의 .py 파일이라고 볼 수 있습니다. 하나의 파이썬 파일에 여러 클래스들이 포함될 수 있습니다.

이제 main.py 모듈을 하나 만들겠습니다. 그리고 아래의 코드를 작성합니다.

class SysTrader():
def __init__(self):
"""자동투자시스템 메인 클래스
"""
self.hello()
def hello(self):
print("Hello World!")
if __name__ == "__main__":
trader = SysTrader()

이렇게 클래스 하나를 선언하고 클래스의 객체를 생성하고 hello() 함수를 호출하여 똑같이 Hello World!를 출력했습니다. 앞으로 이 SysTrader 클래스를 차근차근 이름값 하게 만들어 보겠습니다.

로거는 시스템이 동작하는 동안 발생하는 정보를 기록하기 위한 모듈입니다. 단순히 print() 함수를 써서 출력하는 것보다 로거를 쓰는 것이 정보를 콘솔, 파일로 관리할 수 있어서 효과적입니다. 또한 로거는 출력할 정보에 레벨 (Level)을 부여하여 정보의 중요 정도를 정할 수 있습니다.

이제 시스템에 로거를 추가해 보겠습니다.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import logging
from logging.handlers import TimedRotatingFileHandler
class SysTrader():
def __init__():
"""자동투자시스템 메인 클래스
"""
pass
if __name__ == "__main__":
# --------------------------------------------------
# 로거 (Logger) 준비하기
# --------------------------------------------------
# 로그 파일 핸들러
fh_log = TimedRotatingFileHandler('logs/log', when='midnight', encoding='utf-8', backupCount=120)
fh_log.setLevel(logging.DEBUG)
# 콘솔 핸들러
sh = logging.StreamHandler()
sh.setLevel(logging.DEBUG)
# 로깅 포멧 설정
formatter = logging.Formatter('[%(asctime)s][%(levelname)s] %(message)s')
fh_log.setFormatter(formatter)
sh.setFormatter(formatter)
# 로거 생성 및 핸들러 등록
logger = logging.getLogger(__file__)
logger.setLevel(logging.DEBUG)
logger.addHandler(fh_log)
logger.addHandler(sh)
# --------------------------------------------------
# 자동투자시스템 시작
# --------------------------------------------------
trader = SysTrader()

여기서는 로그를 파일과 콘솔에 출력합니다. 이를 위해 먼저 logging 모듈을 임포트합니다. 그리고 일별로 로그파일을 관리하기 위해 TimedRotatingFileHandler 클래스를 임포트 했습니다. TimedRotatingFileHandler의 생성자 파라미터로 파일 경로, 새로운 파일을 생성할 기준 (여기서는 자정 midnight으로 설정했습니다.), 파일 인코딩, 최대 파일 개수 backupCounting을 정해줍니다. 이렇게 하면 현재 로그는 logs/log 파일에 출력되고, 파일이 새로 생성될때 이전에 쌓였던 로그는 logs/log.2017-08-15와 같은 이름의 파일로 생성됩니다.

콘솔에서도 로그를 확인하기 위해 StreamHandler 클래스도 사용합니다.

각 핸들러에 setLevel()을 호출하는데, 레벨의 개념을 간략히 설명하겠습니다.

로깅 레벨과 그 값은 다음과 같습니다.

레벨값
CRITICAL50
ERROR40
WARNING30
INFO20
DEBUG10
NOTSET0

이 중에서 하나를 지정하여 사용합니다. (자신만의 레벨을 만들수도 있지만, 미리 정의되어 있는 것을 사용하시는 것을 권장합니다.) 로깅 핸들러는 지정한 레벨보다 값이 높은 레벨의 로그들을 출력합니다. 주로 DEBUG, INFO, ERROR를 사용합니다.

이렇게 준비한 핸들러들을 logger에 등록합니다. 코드에서 볼 수 있듯이, 로거 수준에서 레벨을 지정할 수도 있습니다. 로그를 남기는 방법은 다음과 같습니다.

  • DEBUG 레벨 로그: logger.debug()
  • INFO 레벨 로그: logger.info()
  • ERROR 레벨 로그: logger.error()

키움증권 API는 시세조회, 관심종목조회, 조건검색 등의 대부분 TR 조회를 아울러 1초당 5회로 제한하고 있습니다. 즉 TR 요청을 동시에 보내지 않고 0.2초 간격으로 순차적(동기적)으로 보내는 것이 좋습니다.

이를 위해 본 튜토리얼에서는 파이썬의 고급 기능을 활용하여 요청들을 줄을 세우고, 0.2초의 간격으로 하나씩 처리하는 자료구조와 프로세스를 쓰레드로 구현합니다.

큐(Queue)는 선입선출(FIFO, First In First Out) 자료구조 입니다. 요청큐

쓰레드는 독자적으로 알고리즘을 수행하는 프로그램 속의 작은 독립적인 프로그램이라고 생각하시면 됩니다. 수행이 독립적으로 일어나기는 하지만 쓰레드 간에 데이터를 공유할 수는 있습니다.

구현은 다음과 같은 단계로 진행됩니다.

  • 단계 1. RequestThreadWorker 클래스 구현
  • 단계 2. SysTrader 클래스의 __init__() 함수에서 RequestThreadWorker 클래스의 객체 생성, 요청 쓰레드 객체 생성, 요청 쓰레드에 생성한 RequestThreadWorker 클래스의 객체 할당, 요청 쓰레드 객체 실행
  • 단계 3. SyncRequestDecorator 데코레이터 클래스 구현
  • 단계 4. 키움증권 API 요청 및 콜백 함수에 SyncRequestDecorator 데코레이터 설정

RequestThreadWorker는 요청들을 줄세울 수 있도록 큐(Queue) 자료구조를 가지고, 여기서 요청들을 하나씩 빼내서 0.2초 이상의 간격으로 호출하는 프로세스를 가지고 있습니다.

from collections import deque
from threading import Lock
class RequestThreadWorker(QObject):
def __init__(self):
"""요청 쓰레드
"""
super().__init__()
self.request_queue = deque() # 요청 큐
self.request_thread_lock = Lock()
# 간혹 요청에 대한 결과가 콜백으로 오지 않음
# 마지막 요청을 저장해 뒀다가 일정 시간이 지나도 결과가 안오면 재요청
self.retry_timer = None
def retry(self, request):
logger.debug("키움 함수 재시도: %s %s %s" % (request[0].__name__, request[1], request[2]))
self.request_queue.appendleft(request)
def run(self):
while True:
# 큐에 요청이 있으면 하나 뺌
# 없으면 블락상태로 있음
try:
request = self.request_queue.popleft()
except IndexError as e:
time.sleep(요청주기)
continue
# 요청 실행
logger.debug("키움 함수 실행: %s %s %s" % (request[0].__name__, request[1], request[2]))
request[0](trader, *request[1], **request[2])
# 요청에대한 결과 대기
if not self.request_thread_lock.acquire(blocking=True, timeout=5):
# 요청 실패
time.sleep(요청주기)
self.retry(request) # 실패한 요청 재시도
time.sleep(요청주기) # 0.2초 이상 대기 후 마무리

__init__() 함수는 RequestThreadWorker 클래스의 객체가 초기화될 때 실행됩니다. 여기서 request_queue 속성를 deque 객체로 할당합니다. 이 속성에 요청을 넣으면

SysTrader 클래스의 __init__() 함수에서 RequestThreadWorker를 실행할 요청 쓰레드인 request_thread 속성을 생성합니다. RequestThreadWorker 클래스의 객체를 request_thread에 할당하고, 요청 쓰레드가 시작될 때 RequestThreadWorker의 run() 함수가 실행되도록 설정합니다. 최종적으로 요청쓰레드를 시작합니다.

class SysTrader(QObject):
def __init__(self):
# (중략)
# 요청 쓰레드
self.request_thread_worker = RequestThreadWorker()
self.request_thread = QThread()
self.request_thread_worker.moveToThread(self.request_thread)
self.request_thread.started.connect(self.request_thread_worker.run)
self.request_thread.start()

QThread 클래스는 Qt 애플리케이션에서 사용하는 쓰레드 구현체입니다.

키움증권 API의 요청 결과는 대부분 콜백 함수로 전달됩니다. 그러므로 요청을 동기적으로 하기 위해서는 이전에 호출한 요청의 결과가 콜백 함수로 전달될때까지 기다려야 합니다. 이를 위해 SyncRequestDecorator 클래스를 구현합니다. SyncRequestDecorator 클래스는 키움증권 API를 호출하는 요청 함수들에 적용할 데코레이터와 콜백 함수들에 적용할 데코레이터를 가집니다.

kiwoom_sync_request() 데코레이터에서는 요청 함수, 함수에 입력된 인자값들을 요청 큐(request_queue)에 넣어주는 역할을 합니다.

kiwoom_sync_callback()은 콜백 함수를 실행한 후 요청 쓰레드의 잠금을 해제합니다.

class SyncRequestDecorator:
'''키움 API 동기화 데코레이터
'''
@staticmethod
def kiwoom_sync_request(func):
def func_wrapper(self, *args, **kwargs):
self.request_thread_worker.request_queue.append((func, args, kwargs))
return func_wrapper
@staticmethod
def kiwoom_sync_callback(func):
def func_wrapper(self, *args, **kwargs):
logger.debug("키움 함수 콜백: %s %s %s" % (func.__name__, args, kwargs))
func(self, *args, **kwargs) # 콜백 함수 호출
if self.request_thread_worker.request_thread_lock.locked():
self.request_thread_worker.request_thread_lock.release() # 요청 쓰레드 잠금 해제
return func_wrapper

이제 키움증권 API를 호출하는 함수들에 단계 3에서 만든 데코레이터를 달아 줍니다. 키움증권 API 관련 함수들은 뒤에서 기능별로 소개할 것이기 때문에 여기서는 데코레이터를 함수에 적용시키는 방법만 다루겠습니다.

SysTrader에서 키움증권의 요청 API는 kiwoom_로 시작하고 콜백은 kiwoom_On으로 시작합니다. 데코레이터는 함수 선언 위에 @로 적용합니다.

@SyncRequestDecorator.kiwoom_sync_request~
def kiwoom_REQUESTNAME(self, x):
pass
@SyncRequestDecorator.kiwoom_sync_callback
def kiwoom_OnCALLBACKNAME(self, x):
pass

이렇게 하면 kiwoom_REQUESTNAME()가 호출될 때 kiwoom_sync_request가, kiwoom_OnCALLBACKNAME()가 호출될 때 kiwoom_sync_callback가 먼저 호출됩니다.

이제 키움증권 API를 이용하여 투자 시스템에 로그인 해보겠습니다. 우선 Qt 애플리케이션을 생성하고 키움증권 API의 컨트롤 객체를 생성합니다. 여기서 Qt 관련 클래스들을 자세히 설명하지는 않겠습니다. 이들 클래스에 대한 깊은 이해가 없어도 자동투자 시스템을 개발하기에 무리가 없습니다.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import logging
from logging.handlers import TimedRotatingFileHandler
from PyQt5.QAxContainer import QAxWidget
from PyQt5.QtCore import QObject
from PyQt5.QtWidgets import QApplication
class SysTrader(QObject):
def __init__():
"""자동투자시스템 메인 클래스
"""
self.kiwoom = QAxWidget("KHOPENAPI.KHOpenAPICtrl.1")
self.kiwoom.OnEventConnect.connect(self.kiwoom_OnEventConnect) # 로그인 결과를 받을 콜백함수 연결
# -------------------------------------
# 로그인 관련함수
# -------------------------------------
@SyncRequestDecorator.kiwoom_sync_request
def kiwoom_CommConnect(self):
"""로그인 요청
키움증권 로그인창 띄워주고, 자동로그인 설정시 바로 로그인 진행됨.
OnEventConnect()으로 콜백 전달됨.
:param kwargs:
:return: 1: 로그인 요청 성공, 0: 로그인 요청 실패
"""
lRet = self.kiwoom.dynamicCall("CommConnect()")
return lRet
@SyncRequestDecorator.kiwoom_sync_callback
def kiwoom_OnEventConnect(self, nErrCode):
"""로그인 결과 수신
:param nErrCode: 0: 로그인 성공, 100: 사용자 정보교환 실패, 101: 서버접속 실패, 102: 버전처리 실패
:param kwargs:
:return:
"""
if nErrCode == 0:
logger.debug("로그인 성공")
elif nErrCode == 100:
logger.debug("사용자 정보교환 실패")
elif nErrCode == 101:
logger.debug("서버접속 실패")
elif nErrCode == 102:
logger.debug("버전처리 실패")
if __name__ == "__main__":
# (중략)
# --------------------------------------------------
# 자동투자시스템 시작
# --------------------------------------------------
app = QApplication(sys.argv) # Qt 애플리케이션 생성
trader = SysTrader() # QObject를 상속하는 자동투자시스템 객체 생성
trader.kiwoom_CommConnect() # 로그인
sys.exit(app.exec_())

kiwoom_CommConnect() 함수에서 키움증권 API 컨트롤을 통해 CommConnect() API를 호출하여 로그인 요청을 합니다. 처음에는 키움증권 로그인 창이 나타나고 아이디, 비밀번호 등을 입력하여 로그인합니다. 로그인 결과는 콜백으로 kiwoom_OnEventConnect() 함수에 전달됩니다. 이때 파라미터로 넘어오는 nErrCode의 값으로 로그인 결과를 판단합니다. 이 값이 0일 경우 로그인 성공입니다.

자동로그인을 설정해 놓은 경우 아이디, 비밀번호 입력 없이 자동으로 로그인이 진행되고, 그 결과가 콜백 함수로 들어옵니다.

키움증권 API에 로그인을 했으면 이제 계좌의 잔고를 확인해 보겠습니다. 다음 스텝으로 구현합니다.

  • 단계 1. SysTrader 클래스에 kiwoom_SetInputValue(), kiwoom_CommRqData(), kiwoom_TR_OPW00001_예수금상세현황요청(), kiwoom_OnReceiveTrData() 함수 추가
  • 단계 2.

먼저 다음 함수를 SysTrader 클래스에 추가합니다.

def kiwoom_SetInputValue(self, sID, sValue):
"""
:param sID:
:param sValue:
:return:
"""
res = self.kiwoom.dynamicCall("SetInputValue(QString, QString)", [sID, sValue])
return res
def kiwoom_CommRqData(self, sRQName, sTrCode, nPrevNext, sScreenNo):
"""
:param sRQName:
:param sTrCode:
:param nPrevNext:
:param sScreenNo:
:return:
"""
res = self.kiwoom.dynamicCall("CommRqData(QString, QString, int, QString)",
[sRQName, sTrCode, nPrevNext, sScreenNo])
return res
@SyncRequestDecorator.kiwoom_sync_request
def kiwoom_TR_OPW00001_예수금상세현황요청(self, 계좌번호, **kwargs):
"""계좌수익률요청
:param 계좌번호: 계좌번호
:param kwargs:
:return:
"""
res = self.kiwoom_SetInputValue("계좌번호", 계좌번호)
res = self.kiwoom_CommRqData("예수금상세현황요청", "opw00001", 0, 화면번호_예수금상세현황)
@SyncRequestDecorator.kiwoom_sync_callback
def kiwoom_OnReceiveTrData(self, sScrNo, sRQName, sTRCode, sRecordName, sPreNext, nDataLength, sErrorCode, sMessage, sSPlmMsg, **kwargs):
"""TR 요청에 대한 결과 수신
데이터 얻어오기 위해 내부에서 GetCommData() 호출
GetCommData(
BSTR strTrCode, // TR 이름
BSTR strRecordName, // 레코드이름
long nIndex, // TR반복부
BSTR strItemName) // TR에서 얻어오려는 출력항목이름
:param sScrNo: 화면번호
:param sRQName: 사용자 구분명
:param sTRCode: TR이름
:param sRecordName: 레코드 이름
:param sPreNext: 연속조회 유무를 판단하는 값 0: 연속(추가조회)데이터 없음, 2:연속(추가조회) 데이터 있음
:param nDataLength: 사용안함
:param sErrorCode: 사용안함
:param sMessage: 사용안함
:param sSPlmMsg: 사용안함
:param kwargs:
:return:
"""
if sRQName == "예수금상세현황요청":
self.int_주문가능금액 = int(self.kiwoom_GetCommData(sTRCode, sRQName, 0, "주문가능금액"))
logger.debug("주문가능금액: %s" % (self.int_주문가능금액,))

먼저 계좌번호를 SetInputValue() 함수로 입력하고, 예수금상세현황요청을 CommRqData() 함수로 호출합니다. 이 요청에 대한 결과는 OnReceiveTrData() 콜백 함수를 통해 확인할 수 있습니다.

이 콜백 함수를 키움증권 API 컨트롤에 연결해 주어야 합니다.

def __init__():
"""자동투자시스템 메인 클래스
"""
self.kiwoom = QAxWidget("KHOPENAPI.KHOpenAPICtrl.1")
self.kiwoom.OnEventConnect.connect(self.kiwoom_OnEventConnect) # 로그인 결과를 받을 콜백함수 연결
self.kiwoom.OnReceiveTrData.connect(self.kiwoom_OnReceiveTrData)
self.kiwoom_CommConnect() # 로그인

조건 종목 검색을 위해 우선 다음 두 함수 kiwoom_GetConditionLoad(), kiwoom_OnReceiveConditionVer()를 정의합니다.

# -------------------------------------
# 조건검색 관련함수
# GetConditionLoad(), OnReceiveConditionVer(), SendCondition(), OnReceiveRealCondition()
# -------------------------------------
@SyncRequestDecorator.kiwoom_sync_request
def kiwoom_GetConditionLoad(self, **kwargs):
"""
조건검색의 조건목록 요청
:return:
"""
lRet = self.kiwoom.dynamicCall("GetConditionLoad()")
return lRet
@SyncRequestDecorator.kiwoom_sync_callback
def kiwoom_OnReceiveConditionVer(self, lRet, sMsg, **kwargs):
"""
조건검색의 조건목록 결과 수신
GetConditionNameList() 실행하여 조건목록 획득.
첫번째 조건 이용하여 [조건검색]SendCondition() 실행
:param lRet:
:param sMsg:
:param kwargs:
:return:
"""
if lRet:
sRet = self.kiwoom.dynamicCall("GetConditionNameList()")
pairs = [idx_name.split('^') for idx_name in [cond for cond in sRet.split(';')]]
if len(pairs) > 0:
nIndex = pairs[0][0]
strConditionName = pairs[0][1]
self.kiwoom_SendCondition(strConditionName, nIndex)