Package: koapy
Kiwoom Open Api Plus PythonFree software:MITORApache-2.0ORGPL-3.0-or-laterDocumentation:https://koapy.readthedocs.io.IntroductionKOAPY 는키움증권의 OpenAPI+를Python에서 쉽게 사용할 수 있도록 만든
라이브러리 패키지 및 툴입니다.키움에서 제공하는 OpenAPI+ 를 활용하는데 필요한 구체적인 지식들을 전혀 알지 못해도,
기본적인Python에 대한 지식만 어느 정도 있다면 쉽게 사용할 수 있도록 하는 것에
초점을 두었습니다.예를 들어Python기준으로 아래와 같은 내용들을 잘 모르더라도 충분히 모든 기능을
사용할 수 있음을 의미합니다.키움에서 제공하는 OpenAPI+ 의 OCX 라이브러리 구조OCX 를Python에서 구동하기 위해PyQt5/PySide2라이브러리의QAxWidget생성컨트롤에서 함수 호출을 위해dynamicCall함수 사용이벤트 처리를 위해 적절한signal/slot설정 및 이벤트 처리Showcase테이블 데이터 처리를 위한 pandas 임포트>>>importpandasaspd엔트리포인트 객체 생성>>>fromkoapyimportKiwoomOpenApiPlusEntrypoint>>>entrypoint=KiwoomOpenApiPlusEntrypoint()키움증권 서버와의 연결 확인 및 로그인 처리>>>entrypoint.IsConnected()False>>>entrypoint.EnsureConnected()True>>>entrypoint.IsConnected()True종목 리스트 및 종목 코드와 이름 확인>>>code_list=entrypoint.GetCodeListByMarketAsList("0")>>>code_list['000020','000040','000050','000060','000070',...]>>>name_list=[entrypoint.GetMasterCodeName(code)forcodeincode_list]>>>name_list['동화약품','KR모터스','경방','메리츠화재','삼양홀딩스',...]>>>code_by_name={name:codeforcode,nameinzip(code_list,name_list)}>>>name="삼성전자">>>code=code_by_name[name]>>>code'005930'단일 종목의 기본정보 확인>>>info=entrypoint.GetStockBasicInfoAsDict(code)>>>info{'종목코드':'005930','종목명':'삼성전자','결산월':'12','액면가':'100','자본금':'7780','상장주식':'5969783','신용비율':'+0.12','연중최고':'+79800','연중최저':'-71200','시가총액':'4417639','시가총액비중':'','외인소진률':'+52.09','대용가':'57170','PER':'19.27','EPS':'3841','ROE':'10.0','PBR':'1.88','EV':'5.09','BPS':'39406','매출액':'2368070','영업이익':'359939','당기순이익':'264078','250최고':'+86400','250최저':'-68300','시가':'+74300','고가':'+74600','저가':'+73400','상한가':'+95200','하한가':'-51400','기준가':'73300','예상체결가':'-0','예상체결수량':'0','250최고가일':'20210202','250최고가대비율':'-14.35','250최저가일':'20211013','250최저가대비율':'+8.35','현재가':'+74000','대비기호':'2','전일대비':'+700','등락율':'+0.95','거래량':'12730034','거래대비':'-71.74','액면가단위':'원','유통주식':'4459119','유통비율':'74.7'}복수 종목의 기본정보 확인>>>code_list_info=entrypoint.GetStockQuoteInfoAsDataFrame(code_list)>>>code_list_info종목코드종목명현재가기준가전일대비전일대비기호등락율\0000020동화약품+1245012300+1502+1.221000040KR모터스+810790+202+2.532000050경방+1445014200+2502+1.763000060메리츠화재4945049450030.004000070삼양홀딩스+9070088400+23002+2.60........................1744580031KB인버스KOSDAQ150선물ETN-1093010960-305-0.271745580032KB레버리지구리선물ETN(H)-2051520560-455-0.221746580033KB인버스2X구리선물ETN(H)+1835018280+702+0.381747580010KBWise분할매매ETN+1082010770+502+0.461748590018미래에셋중국심천100ETN+1881018645+1652+0.88거래량거래대금체결량...ELW만기일미결제약정미결제전일대비이론가내재변동성델타감마쎄타베가\01355131670+500...000000001230165186-10...00000000262148997...00000000341158420423-4...0000000049052813+5...00000000.....................................174420-1...00000000174500...000000001746170+10...00000000174700...00000000174810+1...00000000로01234.....17441745174617471748[1749rowsx63columns]특정 종목의 차트 데이터 확인>>>chart_data=entrypoint.GetDailyStockDataAsDataFrame(code)>>>chart_data종목코드현재가거래량거래대금일자시가고가저가수정주가구분\00059307400012730034941413202202047430074600734001733001774472113145062022020374900749007330027330021367447155258620220128713007370071200371300222747771603685202201277380074000713004733001297673095554720220126739007440073100..............................97978010497011985010982408240795097988300129304198501088400840083009799841011810319850107840085008390980083901660019850105840084408390980184501710019850104850085008450수정비율대업종구분소업종구분종목정보수정주가이벤트전일종가01234.....................97979798979998009801[9802rowsx15columns]키움증권의 TR 메타 정보 확인>>>fromkoapyimportKiwoomOpenApiPlusTrInfo>>>tr_info_list=KiwoomOpenApiPlusTrInfo.get_trinfo_list()>>>data=pd.DataFrame.from_records([(info.tr_code,info.name)forinfointr_info_list],columns=['tr_code','name'])>>>datatr_codename0opt10001주식기본정보요청1opt10059종목별투자자기관별요청2opt10087시간외단일가요청3opt50037코스피200지수요청4opt90005프로그램매매추이요청........220opw20013계좌미결제청산가능수량조회요청221opw20014선옵실시간증거금산출요청222opw20015옵션매도주문증거금현황요청223opw20016신용융자가능종목요청224opw20017신용융자가능문의[225rowsx2columns]OPT10001 TR 요청 전송 및 응답 처리 (싱글데이터)>>>opt10001_info=KiwoomOpenApiPlusTrInfo.get_trinfo_by_code("opt10001")>>>opt10001_infoKiwoomOpenApiPlusTrInfo('opt10001','주식기본정보요청','STOCK','','1','',[KiwoomOpenApiPlusTrInfo.Field('종목코드',0,6,9001)],'주식기본정보',[KiwoomOpenApiPlusTrInfo.Field('종목코드',0,20,389),KiwoomOpenApiPlusTrInfo.Field('종목명',20,50,302),KiwoomOpenApiPlusTrInfo.Field('결산월',40,20,315),KiwoomOpenApiPlusTrInfo.Field('액면가',60,20,310),KiwoomOpenApiPlusTrInfo.Field('자본금',80,20,309),KiwoomOpenApiPlusTrInfo.Field('상장주식',100,20,312),KiwoomOpenApiPlusTrInfo.Field('신용비율',120,20,329),KiwoomOpenApiPlusTrInfo.Field('연중최고',140,20,1006),KiwoomOpenApiPlusTrInfo.Field('연중최저',160,20,1009),KiwoomOpenApiPlusTrInfo.Field('시가총액',180,20,311),KiwoomOpenApiPlusTrInfo.Field('시가총액비중',200,20,336),KiwoomOpenApiPlusTrInfo.Field('외인소진률',220,20,314),KiwoomOpenApiPlusTrInfo.Field('대용가',240,20,308),KiwoomOpenApiPlusTrInfo.Field('PER',260,20,1600),KiwoomOpenApiPlusTrInfo.Field('EPS',280,20,1604),KiwoomOpenApiPlusTrInfo.Field('ROE',300,20,1630),KiwoomOpenApiPlusTrInfo.Field('PBR',320,20,1601),KiwoomOpenApiPlusTrInfo.Field('EV',340,20,1608),KiwoomOpenApiPlusTrInfo.Field('BPS',360,20,1605),KiwoomOpenApiPlusTrInfo.Field('매출액',380,20,1610),KiwoomOpenApiPlusTrInfo.Field('영업이익',400,20,1611),KiwoomOpenApiPlusTrInfo.Field('당기순이익',420,20,1614),KiwoomOpenApiPlusTrInfo.Field('250최고',440,20,1000),KiwoomOpenApiPlusTrInfo.Field('250최저',460,20,1003),KiwoomOpenApiPlusTrInfo.Field('시가',480,20,16),KiwoomOpenApiPlusTrInfo.Field('고가',500,20,17),KiwoomOpenApiPlusTrInfo.Field('저가',520,20,18),KiwoomOpenApiPlusTrInfo.Field('상한가',540,20,305),KiwoomOpenApiPlusTrInfo.Field('하한가',560,20,306),KiwoomOpenApiPlusTrInfo.Field('기준가',580,20,307),KiwoomOpenApiPlusTrInfo.Field('예상체결가',600,20,10023),KiwoomOpenApiPlusTrInfo.Field('예상체결수량',620,20,10024),KiwoomOpenApiPlusTrInfo.Field('250최고가일',640,20,1001),KiwoomOpenApiPlusTrInfo.Field('250최고가대비율',660,20,1002),KiwoomOpenApiPlusTrInfo.Field('250최저가일',680,20,1004),KiwoomOpenApiPlusTrInfo.Field('250최저가대비율',700,20,1005),KiwoomOpenApiPlusTrInfo.Field('현재가',720,20,10),KiwoomOpenApiPlusTrInfo.Field('대비기호',740,20,25),KiwoomOpenApiPlusTrInfo.Field('전일대비',760,20,11),KiwoomOpenApiPlusTrInfo.Field('등락율',780,20,12),KiwoomOpenApiPlusTrInfo.Field('거래량',800,20,13),KiwoomOpenApiPlusTrInfo.Field('거래대비',820,20,30),KiwoomOpenApiPlusTrInfo.Field('액면가단위',840,20,796),KiwoomOpenApiPlusTrInfo.Field('유통주식',840,20,1683),KiwoomOpenApiPlusTrInfo.Field('유통비율',840,20,1684)],'',[])>>>opt10001_info.inputs[KiwoomOpenApiPlusTrInfo.Field('종목코드',0,6,9001)]>>>opt10001_info.single_outputs[KiwoomOpenApiPlusTrInfo.Field('종목코드',0,20,389),KiwoomOpenApiPlusTrInfo.Field('종목명',20,50,302),KiwoomOpenApiPlusTrInfo.Field('결산월',40,20,315),KiwoomOpenApiPlusTrInfo.Field('액면가',60,20,310),KiwoomOpenApiPlusTrInfo.Field('자본금',80,20,309),KiwoomOpenApiPlusTrInfo.Field('상장주식',100,20,312),KiwoomOpenApiPlusTrInfo.Field('신용비율',120,20,329),KiwoomOpenApiPlusTrInfo.Field('연중최고',140,20,1006),KiwoomOpenApiPlusTrInfo.Field('연중최저',160,20,1009),KiwoomOpenApiPlusTrInfo.Field('시가총액',180,20,311),KiwoomOpenApiPlusTrInfo.Field('시가총액비중',200,20,336),KiwoomOpenApiPlusTrInfo.Field('외인소진률',220,20,314),KiwoomOpenApiPlusTrInfo.Field('대용가',240,20,308),KiwoomOpenApiPlusTrInfo.Field('PER',260,20,1600),KiwoomOpenApiPlusTrInfo.Field('EPS',280,20,1604),KiwoomOpenApiPlusTrInfo.Field('ROE',300,20,1630),KiwoomOpenApiPlusTrInfo.Field('PBR',320,20,1601),KiwoomOpenApiPlusTrInfo.Field('EV',340,20,1608),KiwoomOpenApiPlusTrInfo.Field('BPS',360,20,1605),KiwoomOpenApiPlusTrInfo.Field('매출액',380,20,1610),KiwoomOpenApiPlusTrInfo.Field('영업이익',400,20,1611),KiwoomOpenApiPlusTrInfo.Field('당기순이익',420,20,1614),KiwoomOpenApiPlusTrInfo.Field('250최고',440,20,1000),KiwoomOpenApiPlusTrInfo.Field('250최저',460,20,1003),KiwoomOpenApiPlusTrInfo.Field('시가',480,20,16),KiwoomOpenApiPlusTrInfo.Field('고가',500,20,17),KiwoomOpenApiPlusTrInfo.Field('저가',520,20,18),KiwoomOpenApiPlusTrInfo.Field('상한가',540,20,305),KiwoomOpenApiPlusTrInfo.Field('하한가',560,20,306),KiwoomOpenApiPlusTrInfo.Field('기준가',580,20,307),KiwoomOpenApiPlusTrInfo.Field('예상체결가',600,20,10023),KiwoomOpenApiPlusTrInfo.Field('예상체결수량',620,20,10024),KiwoomOpenApiPlusTrInfo.Field('250최고가일',640,20,1001),KiwoomOpenApiPlusTrInfo.Field('250최고가대비율',660,20,1002),KiwoomOpenApiPlusTrInfo.Field('250최저가일',680,20,1004),KiwoomOpenApiPlusTrInfo.Field('250최저가대비율',700,20,1005),KiwoomOpenApiPlusTrInfo.Field('현재가',720,20,10),KiwoomOpenApiPlusTrInfo.Field('대비기호',740,20,25),KiwoomOpenApiPlusTrInfo.Field('전일대비',760,20,11),KiwoomOpenApiPlusTrInfo.Field('등락율',780,20,12),KiwoomOpenApiPlusTrInfo.Field('거래량',800,20,13),KiwoomOpenApiPlusTrInfo.Field('거래대비',820,20,30),KiwoomOpenApiPlusTrInfo.Field('액면가단위',840,20,796),KiwoomOpenApiPlusTrInfo.Field('유통주식',840,20,1683),KiwoomOpenApiPlusTrInfo.Field('유통비율',840,20,1684)]>>>opt10001_info.multi_outputs[]>>>request_name="주식기본정보요청"# 사용자 구분명, 구분가능한 임의의 문자열>>>tr_code="opt10001">>>screen_no="0001"# 화면번호, 0000 을 제외한 4자리 숫자 임의로 지정, None 의 경우 내부적으로 화면번호 자동할당>>>inputs={..."종목코드":"005930",# 삼성전자 종목코드...}>>>output={}>>>foreventinentrypoint.TransactionCall(request_name,tr_code,screen_no,inputs):...names=event.single_data.names...values=event.single_data.values...forname,valueinzip(names,values):...output[name]=value>>>output{'종목코드':'005930','종목명':'삼성전자','결산월':'12','액면가':'100','자본금':'7780','상장주식':'5969783','신용비율':'+0.12','연중최고':'+79800','연중최저':'-71200','시가총액':'4417639','시가총액비중':'','외인소진률':'+52.09','대용가':'57170','PER':'19.27','EPS':'3841','ROE':'10.0','PBR':'1.88','EV':'5.09','BPS':'39406','매출액':'2368070','영업이익':'359939','당기순이익':'264078','250최고':'+86400','250최저':'-68300','시가':'+74300','고가':'+74600','저가':'+73400','상한가':'+95200','하한가':'-51400','기준가':'73300','예상체결가':'-0','예상체결수량':'0','250최고가일':'20210202','250최고가대비율':'-14.35','250최저가일':'20211013','250최저가대비율':'+8.35','현재가':'+74000','대비기호':'2','전일대비':'+700','등락율':'+0.95','거래량':'12730034','거래대비':'-71.74','액면가단위':'원','유통주식':'4459119','유통비율':'74.7'}OPT10081 TR 요청 전송 및 응답 처리 (멀티데이터)>>>opt10081_info=KiwoomOpenApiPlusTrInfo.get_trinfo_by_code("opt10081")>>>opt10081_infoKiwoomOpenApiPlusTrInfo('opt10081','주식일봉차트조회요청','SCHART','','1','3003',[KiwoomOpenApiPlusTrInfo.Field('종목코드',0,20,9001),KiwoomOpenApiPlusTrInfo.Field('기준일자',20,20,9004),KiwoomOpenApiPlusTrInfo.Field('수정주가구분',40,20,9055)],'주식일봉차트',[KiwoomOpenApiPlusTrInfo.Field('종목코드',0,20,9001)],'주식일봉차트조회',[KiwoomOpenApiPlusTrInfo.Field('종목코드',0,20,9001),KiwoomOpenApiPlusTrInfo.Field('현재가',0,20,10),KiwoomOpenApiPlusTrInfo.Field('거래량',40,20,13),KiwoomOpenApiPlusTrInfo.Field('거래대금',60,20,14),KiwoomOpenApiPlusTrInfo.Field('일자',80,20,22),KiwoomOpenApiPlusTrInfo.Field('시가',100,20,16),KiwoomOpenApiPlusTrInfo.Field('고가',120,20,17),KiwoomOpenApiPlusTrInfo.Field('저가',140,20,18),KiwoomOpenApiPlusTrInfo.Field('수정주가구분',160,20,3502),KiwoomOpenApiPlusTrInfo.Field('수정비율',180,20,3503),KiwoomOpenApiPlusTrInfo.Field('대업종구분',200,20,317),KiwoomOpenApiPlusTrInfo.Field('소업종구분',220,20,318),KiwoomOpenApiPlusTrInfo.Field('종목정보',240,20,370),KiwoomOpenApiPlusTrInfo.Field('수정주가이벤트',260,20,3501),KiwoomOpenApiPlusTrInfo.Field('전일종가',280,20,346)])>>>opt10081_info.inputs[KiwoomOpenApiPlusTrInfo.Field('종목코드',0,20,9001),KiwoomOpenApiPlusTrInfo.Field('기준일자',20,20,9004),KiwoomOpenApiPlusTrInfo.Field('수정주가구분',40,20,9055)]>>>opt10081_info.single_outputs[KiwoomOpenApiPlusTrInfo.Field('종목코드',0,20,9001)]>>>opt10081_info.multi_outputs[KiwoomOpenApiPlusTrInfo.Field('종목코드',0,20,9001),KiwoomOpenApiPlusTrInfo.Field('현재가',0,20,10),KiwoomOpenApiPlusTrInfo.Field('거래량',40,20,13),KiwoomOpenApiPlusTrInfo.Field('거래대금',60,20,14),KiwoomOpenApiPlusTrInfo.Field('일자',80,20,22),KiwoomOpenApiPlusTrInfo.Field('시가',100,20,16),KiwoomOpenApiPlusTrInfo.Field('고가',120,20,17),KiwoomOpenApiPlusTrInfo.Field('저가',140,20,18),KiwoomOpenApiPlusTrInfo.Field('수정주가구분',160,20,3502),KiwoomOpenApiPlusTrInfo.Field('수정비율',180,20,3503),KiwoomOpenApiPlusTrInfo.Field('대업종구분',200,20,317),KiwoomOpenApiPlusTrInfo.Field('소업종구분',220,20,318),KiwoomOpenApiPlusTrInfo.Field('종목정보',240,20,370),KiwoomOpenApiPlusTrInfo.Field('수정주가이벤트',260,20,3501),KiwoomOpenApiPlusTrInfo.Field('전일종가',280,20,346)]>>>importdatetime>>>date=datetime.datetime.now().strftime("%Y%m%d")>>>date'20220206'>>>request_name="주식일봉차트조회요청"# 사용자 구분명, 구분가능한 임의의 문자열>>>tr_code="opt10081">>>screen_no="0001"# 화면번호, 0000 을 제외한 4자리 숫자 임의로 지정, None 의 경우 내부적으로 화면번호 자동할당>>>inputs={..."종목코드":"005930",# 삼성전자 종목코드..."기준일자":"20220206",# 가장 최근 날짜의 YYYYMMDD 포맷..."수정주가구분":"0",# 0:일반주가, 1:수정주가...}>>>data_list=[]>>>foreventinentrypoint.TransactionCall(request_name,tr_code,screen_no,inputs):...columns=event.multi_data.names...records=[values.valuesforvaluesinevent.multi_data.values]...data=pd.DataFrame.from_records(records,columns=columns)...data_list.append(data)>>>data=pd.concat(data_list,axis=0).reset_index(drop=True)>>>data종목코드현재가거래량거래대금일자시가고가저가수정주가구분\00059307400012730034941413202202047430074600734001733001774472113145062022020374900749007330027330021367447155258620220128713007370071200371300222747771603685202201277380074000713004733001297673095554720220126739007440073100..............................97978010497011985010982408240795097988300129304198501088400840083009799841011810319850107840085008390980083901660019850105840084408390980184501710019850104850085008450수정비율대업종구분소업종구분종목정보수정주가이벤트전일종가01234.....................97979798979998009801[9802rowsx15columns]조건검색 조건식 설정 불러오기>>>entrypoint.IsConditionLoaded()False>>>entrypoint.EnsureConditionLoaded()1>>>entrypoint.IsConditionLoaded()True불러온 조건식 목록 확인>>>condition_name_list=entrypoint.GetConditionNameListAsList()>>>condition_name_list[(0,'대형 저평가 우량주'),(1,'중소형 저평가주')]조건식 단순 검색>>>condition_name="대형 저평가 우량주">>>condition_met_code_list,condition_met_code_list_info=entrypoint.GetCodeListByCondition(condition_name,with_info=True)>>>condition_met_code_list['000240','001800','001880','003230','003550','004000','006040','006390','006650','007700','009970','011780','014830','020000','021240','025540','030520','033290','033780','036830','042420','056190','057050','060150','064960','069080','081660','095660','096530','110790','111770','137310','161390','161890','185750','192080','192400','200130','243070','271560','284740','285130','294870','300720','950130']>>>condition_met_code_list_info# same as entrypoint.GetStockQuoteInfoAsDataFrame(condition_met_code_list)종목코드종목명현재가기준가전일대비전일대비기호등락율거래량거래대금\0000240한국앤컴퍼니+1350013400+1002+0.75564847601001800오리온홀딩스+1460014250+3502+2.466982710082001880DL건설-2795028050-1005-0.36209255833003230삼양식품+9130090000+13002+1.445866052894003550LG+7630074600+17002+2.2824941518925.............................40284740쿠쿠홈시스+3670035900+8002+2.2330134110241285130SK케미칼+130500129500+10002+0.7758032754442294870HDC현대산업개발+1560014600+10002+6.8531453564910643300720한일시멘트+1925018750+5002+2.67159419302144950130엑세스바이오-1840022400-40005-17.865877689119649체결량...ELW만기일미결제약정미결제전일대비이론가내재변동성델타감마쎄타베가로05549...000000001+1...000000002369...000000003+2...000000004+100...00000000................................40-3...0000000041-1...0000000042-25...0000000043-4...0000000044-36...00000000[45rowsx63columns]GRPC 스트림 처리 관련 유틸리티 함수 (데모 목적)>>>importcontextlib>>>importthreading>>>importwarnings>>>importgrpc>>>@contextlib.contextmanager...defwarn_on_rpc_error_context():...try:...yield...exceptgrpc.RpcErrorase:...warnings.warn(str(e))>>>defwarn_on_rpc_error(stream):...withwarn_on_rpc_error_context():...foreventinstream:...yieldevent>>>defcancel_after(stream,after):...timer=threading.Timer(after,stream.cancel)...timer.start()...returnwarn_on_rpc_error(stream)조건식 실시간 검색>>>condition_name="중소형 저평가주">>>stream=entrypoint.GetCodeListByConditionAsStream(condition_name)>>>condition_met_code_list=[]>>>data_list=[]>>>foreventincancel_after(stream,10):...ifevent.name=="OnReceiveTrCondition":...initially_included_code_list=event.arguments[1].string_value...initially_included_code_list=initially_included_code_list.rstrip(';').split(';')ifinitially_included_code_listelse[]...condition_met_code_list.extend(initially_included_code_list)...elifevent.name=="OnReceiveRealCondition":...code=event.arguments[0].string_value...condition_type=event.arguments[1].string_value...ifcondition_type=="I":...code_inserted=code...condition_met_code_list.append(code_inserted)...elifcondition_type=="D":...code_deleted=code...condition_met_code_list.remove(code_deleted)...elifevent.name=="OnReceiveTrData":...columns=event.multi_data.names...records=[values.valuesforvaluesinevent.multi_data.values]...data=pd.DataFrame.from_records(records,columns=columns)...data_list.append(data)>>>condition_met_code_list['900290','900310','900340','002170','017890','023600','036190','037710','049430','073560','140910','187870','192440','210540','225220','263690','352700','950190','900280','900250']>>>data_list[]계좌정보 확인>>>account_list=entrypoint.GetAccountList()>>>account_list['8014526011']>>>first_account_no=entrypoint.GetFirstAvailableAccount()>>>first_account_no'8014526011'주문 요청 (삼성전자 시장가 매수)>>>request_name="삼성전자 1주 시장가 신규 매수"# 사용자 구분명, 구분가능한 임의의 문자열>>>screen_no="0001"# 화면번호, 0000 을 제외한 4자리 숫자 임의로 지정, None 의 경우 내부적으로 화면번호 자동할당>>>account_no="8014526011"# 계좌번호 10자리, 여기서는 계좌번호 목록에서 첫번째로 발견한 계좌번호로 매수처리>>>order_type=1# 주문유형, 1:신규매수>>>code="005930"# 종목코드, 앞의 삼성전자 종목코드>>>quantity=1# 주문수량, 1주 매수>>>price=0# 주문가격, 시장가 매수는 가격 설정 의미 없으므로 기본값 0 으로 설정>>>quote_type="03"# 거래구분, 03:시장가>>>original_order_no=""# 원주문번호, 주문 정정/취소 등에서 사용>>>stream=entrypoint.OrderCall(request_name,screen_no,account_no,order_type,code,quantity,price,quote_type,original_order_no)>>>foreventinwarn_on_rpc_error(stream):...ifevent.name=="OnReceiveTrData":...order_no=event.single_data.values[0]...elifevent.name=="OnReceiveChejanData":...gubun=event.arguments[0].string_value...data=dict(zip(event.single_data.names,event.single_data.values))...ifgubun=="0":...status=data["주문상태"]...ifstatus=="접수":...pass...elifstatus=="체결":...orders_filled=data["체결량"]...orders_left=data["미체결수량"]...elifstatus=="확인":...org_order_no=data["원주문번호"]...assertoriginal_order_no==org_order_no...elifgubunin["1","4"]:...stocks=data["보유수량"]키움증권의 실시간 데이터 메타 정보 확인>>>fromkoapyimportKiwoomOpenApiPlusRealType>>>realtype_list=KiwoomOpenApiPlusRealType.get_realtype_info_list()>>>realtype_descs=[realtype.descforrealtypeinrealtype_list]>>>realtype_descs['주식시세','주식체결','주식상하한','주식우선호가','주식호가잔량','주식시간외호가','주식당일거래원','ETF NAV','ELW 지표','ELW 이론가','주식예상체결','주식종목정보','임의연장정보','ECN주식시세','ECN주식체결','ECN주식우선호가','ECN주식호가잔량','ECN주식시간외호가','ECN주식당일거래원','시간외종목정보','주식거래원','주식거래원(1LINE)','종목별프로그램매매','VI정적예상가','VI발동/해제-종목별','종목별프로그램매매2','종목투자자(잠정)','종목투자자(거래소)','대주가능수량','선물옵션우선호가','선물시세','선물호가잔량','선물이론가','선물기초자산시세','실시간상하한가','옵션시세','옵션호가잔량','옵션이론가','주식옵션시세','주식옵션호가잔량','주식옵션이론가','업종지수','업종등락','자체업종지수','예상업종지수','시황/뉴스','환률','장시작시간','투자자ticker','상하한가폭변경','VI발동/해제','투자자별매매','프로그램매매','해외시세','주문체결','파생잔고','현물잔고','예수금','해외주문체결','해외잔고','순간체결량','주문체결서버상태','증거금','CFD주문','CFD체결','CFD마진콜경고','CFD입출고','자유포멧','조건검색','일반신호','리얼잔고','해외리얼잔고','리얼잔고총합','해외잔고총합','스톱로스','선물옵션합계','스톱주문','CFD주문체결','CFD리얼잔고','CFD리얼잔고총합','모니터링 실시간LOG','주식선물호가잔량','실시간증거금','X-Ray순간체결량','매입인도체결','매입인도호가','코넥스경매매체결','데이터셋실시간','홍콩체결','홍콩시세','홍콩호가잔량','홍콩단일가시세','홍콩업종지수','홍콩실시간상하한가','수동자동주문','자동주문결과','TS고저변경','잔고편입','기준가변경','멀티차단','잔고청산삭제','후강퉁체결','후강퉁시세','후강퉁호가잔량','후강퉁단일가시세','후강퉁업종지수','미체결통보시스템','채널K실시간티커','빅데이터종목1분','빅데이터종목10분','빅데이터종목1시간','빅데이터종목당일','빅데이터뉴스','신호관리자투자정보','빅데이터급상승','빅데이터종목30초','알-종목포착이탈','알-매도감시시작','알-매도감시포착','알-주문결과','알-청산시작','알-청산완료','알-감시시작','알-내조건식수정','알-주문조건수정','알-제한여부','알-멀티차단','알-TS변경','알-모의주문체결','알-모의현물잔고','알-모의 주문체결','알-모의 리얼잔고','알-모의리얼잔고총합','채권체결','채권호가잔량','소액채권체결','소액채권호가잔량','CME시세','CME미결제약정','CME호가잔량','EUF시세','EUF호가잔량','EUREX시세','EUREX호가','배치데이터갱신','종목마스터갱신','해외주식주문','해외주식체결','해외실시간잔고조회','미국입출고','미국종목변경','CME/EUREX주문','CME/EUREX체결','CME배치','EUREX배치','CME미체결','CME실시간잔고','CME잔고합','분할반복주문']>>>realtype_info=KiwoomOpenApiPlusRealType.get_realtype_info_by_name("주식시세")>>>realtype_infoKiwoomOpenApiPlusRealType('0A','주식시세',21,[10,11,12,27,28,13,14,16,17,18,25,26,29,30,31,32,311,822,567,568,732])>>>fid_list=KiwoomOpenApiPlusRealType.get_fids_by_realtype_name("주식시세")>>>fid_list[10,11,12,27,28,13,14,16,17,18,25,26,29,30,31,32,311,822,567,568,732]>>>KiwoomOpenApiPlusRealType.Fid.get_name_by_fid(10)'현재가'>>>fid_names=KiwoomOpenApiPlusRealType.get_field_names_by_realtype_name("주식시세")>>>fid_names['현재가','전일대비','등락율','매도호가','매수호가','누적거래량','누적거래대금','시가','고가','저가','전일대비기호','거래량전일대비','거래대금증감','전일거래량대비율','거래회전율','거래비용','시가총액','822','567','568','732']실시간 데이터 요청 (삼성전자 주식시세 실시간 데이터 요청)>>>code_list=["005930"]>>>fid_list=KiwoomOpenApiPlusRealType.get_fids_by_realtype_name("주식시세")>>>opt_type="0"# 기존 화면에 추가가 아니라 신규 생성>>>stream=entrypoint.GetRealDataForCodesAsStream(...code_list,...fid_list,...opt_type,...screen_no=None,# 화면번호, 0000 을 제외한 4자리 숫자 임의로 지정, None 의 경우 내부적으로 화면번호 자동할당...infer_fids=True,# True 로 설정 시 주어진 fid_list 를 고집하지 말고 이벤트 처리 함수의 인자로 전달받는 실시간데이터 이름에 따라 유연하게 fid_list 를 추론...readable_names=True,# True 로 설정 시 각 fid 마다 숫자 대신 읽을 수 있는 이름으로 변환하여 반환...fast_parse=False,# True 로 설정 시 이벤트 처리 함수내에서 데이터 값 읽기 시 GetCommRealData() 함수 호출 대신, 이벤트 처리 함수의 인자로 넘어오는 데이터를 직접 활용, infer_fids 가 True 로 설정된 경우만 유의미함...)>>>foreventincancel_after(stream,10):...ifevent.name=="OnReceiveRealData":...data=dict(zip(event.single_data.names,event.single_data.values))...if"현재가"indata:...current_price=data["현재가"]사용 종료 후 엔트리포인트 객체 리소스 해제 (연결 해제 및 서버 어플리케이션 종료)직접close()메소드 호출:>>>entrypoint.close()혹은 처음부터 컨텍스트 매니저 형태로 리소스 관리:>>>withKiwoomOpenApiPlusEntrypoint()asentrypoint:...entrypoint.EnsureConnected()......Installation대표적으로 아래와 같이PyPI를 통해서 설치가 가능합니다:$pipinstallkoapy만약에 개발 환경을 구축하고자 하는 경우에는poetry를 활용해 구성합니다.$# Install poetry (here using pipx)$python-mpipinstallpipx$python-mpipxensurepath$pipxinstallpoetry$# Clone repository$gitclonehttps://github.com/elbakramer/koapy.git$cdkoapy/$# Install dependencies and hooks$poetryinstall$poetryrunpre-commitinstall이외에 자세한 설치방법과 관련해서는Installation문서를 참고하세요.Usage설치 이후 일반적인 사용법에 대해서는Usage를 참고하세요.추가적으로 사용법과 관련된 다양한 예시들은examples폴더 및notebooks_ipynb폴더에서도 확인 가능합니다.
혹시나notebooks_ipynb폴더의.ipynb파일들을 Github 을 통해서 보는데 문제가 있는 경우,
해당 노트북 주소를nbviewer에 입력하여 확인해 보세요.현재 알파 단계이기 때문에 많은 기능들이 실제로 문제없이 동작하는지 충분히 테스트되지 않았습니다.
만약에 실전 트레이딩에 사용하려는 경우 자체적으로 충분한 테스트를 거친 후 사용하시기 바랍니다.개발자는 라이브러리 사용으로 인해 발생하는 손실에 대해 어떠한 책임도 지지 않습니다.또한 알파 단계에서 개발이 진행되면서 라이브러리의 구조가 계속 급격하게 변경될 수 있으니 참고 바랍니다.FeaturesKOAPY 는 아래와 같은 방향성을 가지고 개발되었습니다.GUI 어플리케이션만으로 제한되지 않는 다양한 사용성일반적으로 인터넷 등지에서 접하기 쉬운 관련 예시들을 처음으로 따라가다 보면, 자기도
모르는 사이에 Qt 기반 어플리케이션을 하나 만들고, 버튼을 하나 추가하고, 이후 모든
기능들을 죄다 해당 버튼을 클릭 시 작동하는 콜백 함수 하나에 쑤셔 넣고 있는.. 자신을
발견하게 되더군요.# https://wikidocs.net/4240importsysfromPyQt5.QtWidgetsimport*fromPyQt5.QtGuiimport*fromPyQt5.QAxContainerimport*classMyWindow(QMainWindow):def__init__(self):super().__init__()self.setWindowTitle("PyStock")self.setGeometry(300,300,300,150)self.kiwoom=QAxWidget("KHOPENAPI.KHOpenAPICtrl.1")btn1=QPushButton("Login",self)btn1.move(20,20)btn1.clicked.connect(self.btn1_clicked)btn2=QPushButton("Check state",self)btn2.move(20,70)btn2.clicked.connect(self.btn2_clicked)defbtn1_clicked(self):ret=self.kiwoom.dynamicCall("CommConnect()")defbtn2_clicked(self):ifself.kiwoom.dynamicCall("GetConnectState()")==0:self.statusBar().showMessage("Not connected")else:self.statusBar().showMessage("Connected")if__name__=="__main__":app=QApplication(sys.argv)myWindow=MyWindow()myWindow.show()app.exec_()사실 기반 라이브러리가 애초에 OCX 형태로서 제공되는 것도 있고, 다른 여러 가지 이유들로
인해 이처럼 GUI 어플리케이션 형태로 개발을 하는 것이 자연스러운 흐름이고 절대
잘못되었다고 생각되진 않습니다.다만 이러한 GUI 환경이 일반적으로 Python 에서 REPL 혹은 Jupyter Notebook 등을 통해서
인터랙티브하게 결과 값들을 확인해가면서 조금씩 개발해 나가던 것과는 거리가 멀어지면서
결론적으로 생산성이 떨어지게 되는 건 아닌가 하는 생각이 들었고, 그로 인해 KOAPY 의
기본적인 인터페이스는 기반이 되는 Qt 환경을 개발자가 직접적으로 고려하진 않으면서도
기능은 쉽게 사용해 볼 수 있게 끔 하는 게 좋겠다고 생각했습니다.따라서 KOAPY 의 기본적인 디자인은 우선 외적으로 봤을 때 이게 내부적으로는 Qt 같은
환경하에서 돌아간다는 것을 바로 알아챌 순 없게 끔 되어 있습니다. 그리고 기본적인
기능들을 이용하는 데에 있어서도 버튼 클릭 등의 이벤트에 기반한 호출보단 일반적인 함수
호출과 같은 명령형 프로그래밍이 가능하도록 디자인 하였으며, 문서에서도 해당 사용
시나리오들을 중점적으로 먼저 소개하고 있습니다.fromkoapyimportKiwoomOpenApiPlusEntrypointwithKiwoomOpenApiPlusEntrypoint()asentrypoint:entrypoint.EnsureConnected()is_connected=entrypoint.IsConnected()print(is_connected)결론적으로PyQt5혹은PySide2를 기반한 GUI 환경에 얽매일 필요 없이 일반적인
라이브러리처럼 가져다 활용할 수 있으며, 여전히 GUI 기반 어플리케이션 개발이 필요하다면
내부적으로 사용되는 요소들을 통해 직접 GUI 방향으로 개발을 할 수도 있습니다.fromkoapy.compat.pyside2.QtWidgetsimportQApplication,QMainWindowfromkoapyimportKiwoomOpenApiPlusQAxWidgetclassMyWindow(QMainWindow):def__init__(self):super().__init__()self.kiwoom=KiwoomOpenApiPlusQAxWidget()...함수 호출등의 과정에서 일반적인 Python 의 관습을 크게 해치지 않는 매끄러운 인터페이스 구성Qt 를 통해서 COM/OLE/OCX 객체의 메서드를 호출하려면dynamicCall함수를 활용해야 합니다.해당dynamicCall함수는 호출하고자 하는 메서드의 프로토타입을 문자열 형태 인자로서
입력하도록 되어있는데, 단순하게는 매번 메서드를 호출하고자 할 때마다 해당 메서드의
프로토타입이 어떻게 생겼는지를 문서 등을 참고하고 일일이 적어 넣어줘야 할 수 있습니다.control=QAxWidget("KHOPENAPI.KHOpenAPICtrl.1")control.dynamicCall("SetInputValue(const QString&, const QString&)","종목코드",code)그 다음으로 보다 나은 방식으로는 이러한 프로토타입을 모든 함수들에 대해서 확인해서
간단한 래퍼 함수들을 만들어두고 활용하는 게 있겠죠.defSetInputValue(name,value):returncontrol.dynamicCall("SetInputValue(const QString&, const QString&)",name,value)일반적으로는 이런 방식들로도 충분히 사용하는데 무리가 없으리라 생각됩니다만
개인적으로는 위와 같은 접근 방식에서 몇 가지 우려되는 점들이 신경이 쓰였습니다.프로토타입을 입력하거나 래퍼 함수들을 만들어 넣는 과정에서 발생할 수 있는 휴먼에러래퍼 함수들을 만들어 놓았더라도 추후 함수의 목록 혹은 특정 함수의 프로토타입에서
변경이 발생하는 경우 매번 직접적인 대응이 필요함따라서 KOAPY 에서는 이러한 지원 함수 목록 및 함수별 프로토타입 정보 확인, 그리고
이것들을 활용해 특정 메서드를 호출하는 과정까지를 어떻게 프로그래밍적으로 대응할 수
없을까를 고민했고, 현재는 OpenAPI+ OCX 의 TypeLib 정보를 읽어와 메서드들을 동적으로
생성하도록 구현해 위에서 우려했던 점들을 해결했습니다.최종적으론 컨트롤 함수 호출 시 매뉴얼의 명세에 적혀있는 형태 그대로 Python 함수였던
것처럼 호출이 가능하며, 이후는 KOAPY 가 유연하게 처리합니다. 매번 명세에 맞게dynamicCall함수의 인자를 적어 넣거나, 모든 존재하는 함수에 대해 미리 래퍼 함수를
손 아프게 만들어놓을 필요가 없습니다.control=KiwoomOpenApiPlusQAxWidget()control.SetInputValue("종목코드",code)이벤트 처리 및 비동기 프로그래밍 관련 복잡하지 않은 인터페이스 제공비동기 프로그래밍은 일반적으로 어렵습니다. 특히 OpenAPI+ 및 KOAPY 의 경우를 예로
들어보면 아래와 같은 고민해 볼 만한 부분들이 있습니다.여러 요청에 대한 응답 결과들을 이벤트 타입별 하나씩의 통로로 처리하기 때문에 그들
간의 교통정리부터 필요합니다.콜백 함수 내에서 OpenAPI+ 가 기대하는 혹은 가이드하는 방식에 맞춰서 처리해 주어야
하는 특정 단계 혹은 프로세스가 존재하며 이를 적절히 대응해 주어야 합니다.콜백 함수에서 받은 결과를 최종적으로 해당 결과가 필요한 곳으로 (일반적으론 요청한
대상에게로) 잘 전달해 주어야 합니다.KOAPY 에서는 위의 문제들을 나름의 방식대로 고민하였고 문제들을 해결하여 더 쉽고 나은
인터페이스를 사용자에게 제공하고 있습니다.구체적으로 예를 하나 들자면, 일반적인 요청-응답 과정에서 내부적으로 gRPC
클라이언트-서버 관계를 만들어 요청자가 gRPC 를 통해 특정 요청을 전달하면, 이후 gRPC
서버에서는 해당 요청에 대한 응답들만 추려서 결과를 요청자측에 스트림 형태로 전달하도록
디자인되어 있는데요. 여기서 교통정리 및 결과 전달 문제가 자연스럽게 해결되며 부수적으로
사용자 입장에서는 직접 콜백 함수를 다루기보다는 간접적으로 스트림을
(for문을 활용하여) 다룸으로써 더 쉽게 비동기 프로그래밍이 필요한 기능들을 사용할
수 있는 이점이 있습니다.PySide2 를 통한 직접적인 방식:# 컨트롤 객체control=QAxWidget("KHOPENAPI.KHOpenAPICtrl.1")# 이벤트 시그널on_receive_tr_data_signal=SIGNAL("OnReceiveTrData(const QString&, const QString&, const QString&, const QString&, const QString&, int, const QString&, const QString&, const QString&)")# 이벤트 콜백 함수defon_receive_tr_data(screen_no,request_name,tr_code,record_name,prev_next,data_length,error_code,message,splmmsg):handle_event(...)# 이벤트 처리 후 필요하다면 등록된 콜백 함수 제거ifshould_disconnect:control.disconnect(on_receive_tr_data_signal,on_receive_tr_data)# 이벤트 시그널에 콜백 함수 연결control.connect(on_receive_tr_data_signal,on_receive_tr_data)# TR 입력값 설정control.dynamicCall("SetInputValue(const QString&, const QString&)",...,...)...# TR 요청err_code=control.dynamicCall("CommRqData(const QString&, const QString&, int, const QString&)",request_name,tr_code,prev_next,screen_no,)KOAPY 방식:# TR 요청 후 이벤트가 스트림 형태로 반환foreventinentrypoint.TransactionCall(request_name,tr_code,screen_no,inputs):handle_event(event)결론적으로는 사용자가 이벤트 처리 및 비동기 프로그래밍에 익숙하지 않더라도 그보다
비교적 쉬운 인터페이스를 통해 관련 기능들을 활용할 수 있습니다.더 나아가서는 가장 간단한 로그인 처리부터 TR/실시간 데이터 처리, 그리고 주문처리까지
다양한 시나리오에 대한 기본 이벤트 처리 로직을 구현해 제공해 사용자들이 비동기
프로그래밍이 필요한 기능 중 주로 사용되는 기능들에 쉽게 접근할 수 있도록 했습니다.stream=entrypoint.LoginCall()stream=entrypoint.TransactionCall(request_name,tr_code,screen_no,inputs)stream=entrypoint.RealCall(screen_no,codes,fids,opt_type)stream=entrypoint.OrderCall(request_name,screen_no,account_no,order_type,code,quantity,price,quote_type,original_order_no)여러 일반적인 시나리오들에 대한 다양한 기본 구현체들을 제공KOAPY 에서는 일반적으로 자주 사용되는 기능들에 대해서 사용자들이 쉽게 접근할 수 있도록,
예를 들어 주식 기본정보 요청부터 일봉/분봉 등 시세 데이터 확인 그리고 예수금/잔고 확인 등등에 대해 미리 구현된 함수를 제공합니다.stock_info=entrypoint.GetStockBasicInfoAsDict(stock_code)stock_chart_data=entrypoint.GetDailyStockDataAsDataFrame(stock_code)account_deposit=entrypoint.GetDepositInfo(account_no)account_evaluation=(account_evaluation_summary,account_evaluation_per_stock,)=entrypoint.GetAccountEvaluationStatusAsSeriesAndDataFrame(account_no)이 중에 함수 호출 결과 중 테이블성 정보들은pandas.DataFrame타입으로 제공해 이후 분석 및 처리가 유용하게끔 했습니다.개발과정에서 라이브러리 밖을 드나들 필요가 없도록 자주 확인이 필요한 여러가지 메타 정보들을 함께 제공일반적으로 인터넷 등지에서 접하기 쉬운 관련 대부분 예시들은 사용자가 OpenAPI+ 에 대한
여러 가지 메타정보들을 이미 다 알고 있다는 걸 가정하고, 아니면 적어도 외부 참고자료를
확인하는 것을 가정하고 작성되어 있는 경우가 많습니다.예를 들어 TR 의 입력과 출력 데이터 구조, 실시간 데이터별 FID 목록, 에러코드에 대한
설명문 등이 이러한 메타정보들에 해당되는데요. 앞서 함수 호출 방식에서의 이슈와 비슷하게,
이러한 정보들을 매번 참고 자료를 확인하고 그에 맞춰 개발하는 방식에는 어느 정도 한계가
있습니다.따라서 KOAPY 에서는 이러한 정보들을 개발하는 과정에서 언어 내 라이브러리에서 바로 조회
및 활용이 가능하도록 포함시켜 제공합니다. 이로 인해 일차적으로 사용자 입장에서는 매번매뉴얼이나KOAStudio를 열어서 참고하고 이후 일일이 하나씩 하드코딩할 필요가
없어졌습니다.fromkoapyimportKiwoomOpenApiPlusTrInfotr_info=KiwoomOpenApiPlusTrInfo.get_trinfo_by_code("opt10001")fromkoapyimportKiwoomOpenApiPlusRealTyperealtype_info=KiwoomOpenApiPlusRealType.get_realtype_info_by_name("주식시세")fromkoapyimportKiwoomOpenApiPlusErrorerror_message=KiwoomOpenApiPlusError.get_error_message_by_code(-101)덧붙여서 TR 관련 정보나 실시간 데이터 관련 정보들은 OpenAPI+ 가 설치되어 있는 경우
해당 경로의 데이터를 참고해 동적으로 생성하도록 되어있는데요. 이로 인해 직접 하드코딩
등을 했을 때 발생할 수 있는 이슈 없이, 매번 업데이트 시 변경된 내용이 바로바로 적용될
수 있는 이점 또한 가지고 있습니다.라이브러리 호환성으로 인해 특정 환경이 강제되는 것을 우회할 수 있도록 시스템 구성키움증권의 OpenAPI+ 는 32bit 환경만 제공하고 있기 때문에 이를 사용하는 쪽도 자연스럽게
32bit 기반이 되어야 합니다.여기서는Python을 32bit 로 사용해야 하는 조건이 붙게 되는 것인데요. 몇몇 외부
서드파티들에서는 더 이상 32bit 를 지원하지 않는 경우도 많아 다양한 서드파티 기능들과
접목시키기에는 32bit 제약이 번거로운 점이 많습니다.KOAPY 에서는 이를 해소하기 위해gRPC서버-클라이언트 형태의 구성을 잡아 서버에서는
32bit 기반으로 OpenAPI+ 의 핵심 기능만 제공하도록 하고, 클라이언트에서는 이런 32bit
제약 없이 결과들을 받아서 이후 여러 서드파티 기능들과 함께 활용할 수 있도록 했습니다.앞에서는 주로 32bit 제약을 가지고 이야기했지만 더 나아가서는gRPC의 많은 언어들에
대한 확장성을 활용하여 Python 이외에gRPC에서 지원하는 다른 언어들로 클라이언트를
작성해 사용하는 방식으로도 확장이 가능합니다.또한Python에서Qt를 사용하기 위해서는PyQt5혹은PySide2를 사용해야 하는데요.
KOAPY 에서는 라이선스 등을 고려해서 기본값으로PySide2를 사용하도록 되어있지만,
사용자의 필요성에 따라PySide2대신PyQt5를 사용하려 할 때 쉽게 변경할 수 있도록qtpy를 통해서 지원하고 있습니다.키움증권의 OpenAPI+ 기능 자체 이외에 부수적으로 필요할만한 다양한 기능들을 추가로 제공KOAPY 는 키움증권의 OpenAPI+ 핵심 기능 이외에 전체적인 개발 및 활용에 필요한 다양한
부가기능들을 추가로 제공합니다.TR 호출 시 호출 횟수 제한 회피KRX 거래소 휴장일 확인 (exchange_calendarsAPI 활용)알람 및 메시지 기능 (discord.pyAPI 활용)라이브러리 뿐만 아니라 관련 기능들을 추가적인 코드 구현없이 쉽게 사용해볼 수 있도록 (+ 개념 증명 목적으로서) CLI 제공굳이 Python 코드를 작성하지 않더라도 기본적인 기능들을 활용해 볼 수 있도록 여러
커맨드를 포함하는 CLI 를 제공합니다.CLI 를 활용하면 마켓별 코드 목록 확인, 주식 기본 정보 확인, 일봉/분봉 데이터 확인 및
저장, 실시간 데이터 구독 등 다양한 기능들을 코드 구현 없이 사용할 수 있습니다.$koapygetstockcode--market=0$koapygetstockinfo--code=005930$koapygetdaily--code=005930--output=005930.xlsx$koapywatch--code=005930--realtype="주식시세"서버도 CLI 커맨드로 쉽게 띄울 수 있습니다.$koapyserveLicensingKOAPY 는 다중 라이선스 방식으로 배포되며,
사용자는 자신의 의도 및 사용 방식에 따라 아래 라이선스 옵션들 중 하나를 선택해 사용할 수 있습니다.MIT LicenseApache License 2.0GNU General Public License v3.0or later라이선스 선택과 관련하여 추천하는 가이드라인은 아래와 같습니다.MIT License일반적인 사용자에게 알맞습니다.짧고 단순한 라이선스를 선호하시면 해당 라이선스를 선택하세요.Apache License 2.0MIT 라이선스와 큰 차이는 없지만, 특허와 관련해서 명시적인 허가조항이 있습니다.추후 특허권 침해 소송이 우려되는 경우 MIT 라이선스 대신에 선택하시면 됩니다.GNU General Public License v3.0 or laterFSF/GPL이 추구하는Copyleft의 가치를 따르신다면 선택 가능한 옵션중 하나입니다.이외에backtrader관련 기능들을 활용하시는 경우, KOAPY 는반드시GPLv3+ 로만 배포되어야 합니다.구체적으로koapy.backtrader모듈 하위의 기능들을 사용한다면 GPLv3+ 배포 조건에 해당됩니다.이것은backtrader가 GPLv3+ 로 배포되고 있으며,
해당 라이선스의 요구사항에 따라 그것을 사용하는 소프트웨어 또한 GPLv3+ 로 배포되어야 하기 때문입니다.각 라이선스의 허가 및 요구사항과 관련해서 쉽게 정리된 내용은tl;drLegal에서 참고하실 수 있습니다.다만 위의 내용이 법률적 조언은 아닌 점 참고 바랍니다.Credits이 패키지는Cookiecutter와elbakramer/cookiecutter-poetry프로젝트 탬플릿을 사용하여 생성되었습니다.