def userinfo(port, verbose): set_verbosity(verbose) import pandas as pd from koapy import KiwoomOpenApiPlusEntrypoint with KiwoomOpenApiPlusEntrypoint(port=port, client_check_timeout=client_check_timeout, verbosity=verbose) as context: context.EnsureConnected() result = {} result["보유계좌수"] = context.GetLoginInfo("ACCOUNT_CNT") account_numbers = context.GetLoginInfo("ACCLIST").rstrip(";").split( ";") for i, accno in enumerate(account_numbers): result["계좌번호 (%d/%s)" % (i + 1, result["보유계좌수"])] = accno result["사용자 ID"] = context.GetLoginInfo("USER_ID") result["사용자 명"] = context.GetLoginInfo("USER_NAME") result["키보드보안 해지 여부"] = { "0": "정상", "1": "해지", }.get(context.GetLoginInfo("KEY_BSECGB"), "알수없음") result["방화벽 설정 여부"] = { "0": "미설정", "1": "설정", "2": "해지", }.get(context.GetLoginInfo("FIREW_SECGB"), "알수없음") result["접속서버 구분"] = { "1": "모의투자", }.get(context.GetServerGubun(), "실서버") click.echo(pd.Series(result).to_markdown())
def stockname(codes, port): from koapy import KiwoomOpenApiPlusEntrypoint with KiwoomOpenApiPlusEntrypoint(port=port, client_check_timeout=client_check_timeout) as context: context.EnsureConnected() def get_codes(): if codes: if '-' in codes: with click.open_file('-', 'r') as f: for code in f: yield code.strip() else: for code in codes: yield code else: while True: try: code = click.prompt('code', prompt_suffix=' >>> ') code = code.strip() if code == 'exit': break if code: yield code except EOFError: break for code in get_codes(): name = context.GetMasterCodeName(code) click.echo(name)
def minute(code, interval, output, format, start_date, end_date, port, verbose): # pylint: disable=redefined-builtin if (code, interval, output, start_date, end_date) == (None, None, None, None, None): fail_with_usage() set_verbosity(verbose) if interval is None: fail_with_usage("Interval is not set.") if output is None: output = "%s.%s" % (code, format) from koapy import KiwoomOpenApiPlusEntrypoint with KiwoomOpenApiPlusEntrypoint(port=port, client_check_timeout=client_check_timeout, verbosity=verbose) as context: context.EnsureConnected() df = context.GetMinuteStockDataAsDataFrame(code, interval, start_date, end_date) if format == "xlsx": df.to_excel(output) elif format == "sqlite3": from sqlalchemy import create_engine engine = create_engine("sqlite:///" + output) df.to_sql("A" + code, engine)
def userinfo(port, verbose): set_verbosity(verbose) import pandas as pd from koapy import KiwoomOpenApiPlusEntrypoint with KiwoomOpenApiPlusEntrypoint(port=port, client_check_timeout=client_check_timeout, verbosity=verbose) as context: context.EnsureConnected() result = {} result['보유계좌수'] = context.GetLoginInfo('ACCOUNT_CNT') account_numbers = context.GetLoginInfo('ACCLIST').rstrip(';').split(';') for i, accno in enumerate(account_numbers): result['계좌번호 (%d/%s)' % (i + 1, result['보유계좌수'])] = accno result['사용자 ID'] = context.GetLoginInfo('USER_ID') result['사용자 명'] = context.GetLoginInfo('USER_NAME') result['키보드보안 해지 여부'] = { '0': '정상', '1': '해지', }.get(context.GetLoginInfo('KEY_BSECGB'), '알수없음') result['방화벽 설정 여부'] = { '0': '미설정', '1': '설정', '2': '해지', }.get(context.GetLoginInfo('FIREW_SECGB'), '알수없음') result['접속서버 구분'] = { '1': '모의투자', }.get(context.GetServerGubun(), '실서버') click.echo(pd.Series(result).to_markdown())
def orders( account, date, reverse, executed_only, not_executed_only, stock_only, bond_only, sell_only, buy_only, code, starting_order_no, port, verbose, ): set_verbosity(verbose) if account is None: logger.info("Account not given. Using first account available.") sort_type = "1" if reverse: sort_type = "2" if executed_only: sort_type = "3" if not_executed_only: sort_type = "4" asset_type = "0" if stock_only: asset_type = "1" if bond_only: asset_type = "2" order_type = "0" if sell_only: order_type = "1" if buy_only: order_type = "2" from koapy import KiwoomOpenApiPlusEntrypoint with KiwoomOpenApiPlusEntrypoint(port=port, client_check_timeout=client_check_timeout, verbosity=verbose) as context: context.EnsureConnected() if account is None: account = context.GetFirstAvailableAccount() df = context.GetOrderLogAsDataFrame1(account) click.echo("[실시간미체결요청]") click.echo(df.to_markdown()) click.echo() df = context.GetOrderLogAsDataFrame2(account) click.echo("[실시간체결요청]") click.echo(df.to_markdown()) click.echo() df = context.GetOrderLogAsDataFrame3(account, date, sort_type, asset_type, order_type, code, starting_order_no) click.echo("[계좌별주문체결내역상세요청]") click.echo(df.to_markdown())
def modulepath(port, verbose): set_verbosity(verbose) from koapy import KiwoomOpenApiPlusEntrypoint with KiwoomOpenApiPlusEntrypoint(port=port, client_check_timeout=client_check_timeout, verbosity=verbose) as context: click.echo(context.GetAPIModulePath())
def autologin(port, verbose): set_verbosity(verbose) from koapy import KiwoomOpenApiPlusEntrypoint with KiwoomOpenApiPlusEntrypoint( port=port, client_check_timeout=client_check_timeout) as context: context.EnsureConnected() context.ShowAccountWindow()
def login(port, verbose): set_verbosity(verbose) from koapy import KiwoomOpenApiPlusEntrypoint with KiwoomOpenApiPlusEntrypoint(port=port, client_check_timeout=client_check_timeout) as context: state = context.GetConnectState() if state == 0: click.echo('Logging in...') else: click.echo('Already logged in.') context.EnsureConnected() gubun = context.GetServerGubun() if gubun == '1': click.echo('Logged into Simulation server.') else: click.echo('Logged into Real server.')
def deposit(account, port, verbose): set_verbosity(verbose) if account is None: logging.info('Account not given. Using first account available.') from koapy import KiwoomOpenApiPlusEntrypoint with KiwoomOpenApiPlusEntrypoint(port=port, client_check_timeout=client_check_timeout, verbosity=verbose) as context: context.EnsureConnected() if account is None: account = context.GetAccountList()[0] result = context.GetDepositInfo(account) click.echo(result.to_markdown(floatfmt='.2f'))
def stockinfo(code, output, format, port, verbose): # pylint: disable=redefined-builtin if (code, output) == (None, None): fail_with_usage() set_verbosity(verbose) if output is None: if format is None: format = "md" else: if format is None: format = "xlsx" if format == "xlsx": if not output.endswith(".xlsx"): output += ".xlsx" elif format == "md": if not output.endswith(".md"): output += ".md" elif format == "json": if not output.endswith(".json"): output += ".json" import pandas as pd from koapy import KiwoomOpenApiPlusEntrypoint with KiwoomOpenApiPlusEntrypoint(port=port, client_check_timeout=client_check_timeout, verbosity=verbose) as context: context.EnsureConnected() dic = context.GetStockBasicInfoAsDict(code) series = pd.Series(dic) if not output: if format == "md": click.echo(series.to_markdown()) elif format == "json": click.echo(series.to_json()) else: if format == "xlsx": series.to_excel(output, header=False) elif format == "json": with open(output, "w") as f: click.echo(series.to_json(), file=f)
def evaluation(account, include_delisted, exclude_delisted, for_each, as_summary, port, verbose): set_verbosity(verbose) if account is None: logger.info("Account not given. Using first account available.") if exclude_delisted: include_delisted = False if as_summary: for_each = False lookup_type = "1" elif for_each: lookup_type = "2" from koapy import KiwoomOpenApiPlusEntrypoint with KiwoomOpenApiPlusEntrypoint(port=port, client_check_timeout=client_check_timeout, verbosity=verbose) as context: context.EnsureConnected() if account is None: account = context.GetAccountList()[0] single, multi = context.GetAccountEvaluationStatusAsSeriesAndDataFrame( account, include_delisted) click.echo("[계좌평가현황요청] : [계좌평가현황]") click.echo(single.to_markdown(floatfmt=".2f")) click.echo() click.echo("[계좌평가현황요청] : [종목별계좌평가현황]") click.echo(multi.to_markdown()) click.echo() single, multi = context.GetAccountEvaluationBalanceAsSeriesAndDataFrame( account, lookup_type) click.echo("[계좌평가잔고내역요청] : [계좌평가결과]") click.echo(single.to_markdown(floatfmt=".2f")) click.echo() click.echo("[계좌평가잔고내역요청] : [계좌평가잔고개별합산]") click.echo(multi.to_markdown())
def daily(code, output, format, start_date, end_date, port, verbose): # pylint: disable=redefined-builtin if (code, output, start_date, end_date) == (None, None, None, None): fail_with_usage() set_verbosity(verbose) if output is None: output = '%s.%s' % (code, format) from koapy import KiwoomOpenApiPlusEntrypoint with KiwoomOpenApiPlusEntrypoint(port=port, client_check_timeout=client_check_timeout, verbosity=verbose) as context: context.EnsureConnected() df = context.GetDailyStockDataAsDataFrame(code, start_date, end_date) if format == 'xlsx': df.to_excel(output) elif format == 'sqlite3': from sqlalchemy import create_engine engine = create_engine('sqlite:///' + output) df.to_sql('A' + code, engine)
import pandas as pd from koapy import KiwoomOpenApiPlusEntrypoint from koapy import CybosPlusEntrypoint kiwoom = KiwoomOpenApiPlusEntrypoint() cybos = CybosPlusEntrypoint() kiwoom.EnsureConnected() cybos.EnsureConnected() kiwoom_codes = kiwoom.GetGeneralCodeList() cybos_codes = cybos.GetGeneralCodeList() cybos_codes = [code[1:] for code in cybos_codes] kiwoom_codes = pd.DataFrame(kiwoom_codes, columns=['code']) kiwoom_codes['kiwoom'] = 'TRUE' cybos_codes = pd.DataFrame(cybos_codes, columns=['code']) cybos_codes['cybos'] = 'TRUE' df = pd.merge(kiwoom_codes, cybos_codes, how='outer', on='code') df.to_excel('output.xlsx')
from koapy import KiwoomOpenApiPlusEntrypoint with KiwoomOpenApiPlusEntrypoint() as context: context.EnsureConnected() account_nos = context.GetAccountList() print("전체 계좌 목록: %s" % account_nos) account_no = account_nos[0] print("사용할 계좌번호: %s" % account_no) print() series = context.GetDepositInfo(account_no) print("예수금상세현황요청 : 예수금상세현황") print(series.to_markdown()) print() df = context.GetAccountRateOfReturnAsDataFrame(account_no) print("계좌수익률요청 : 계좌수익률") # TR 이름에서 그대로 따왔긴 한데, 정작 수익률은 그 어디에도 없음.. print(df.to_markdown()) print() summary, foreach = context.GetAccountEvaluationStatusAsSeriesAndDataFrame( account_no) print("계좌평가현황요청 : 계좌평가현황") print(summary.to_markdown()) print("계좌평가현황요청 : 종목별계좌평가현황") print(foreach.to_markdown()) print() # 위와 아래의 차이는 수수료/세금 영향을 고려하냐 안하냐의 차이인듯, 위는 고려하지 않고 아래는 모두 고려하는것으로 보임
# Test this example script with two different scenarios # # 1. External-Server-Process scenario # 1. Run 4_koapy_tray_application.py script in 32bit environment # => Server will start with tray application # 2. Open another console and run 5_koapy_entrypoint.py script (this one), in 32bit or 64bit environment # => Client will connect to the existing server # # 2. Server-In-Subprocess scenario # 1. Just run 5_koapy_entrypoint.py script (this one) in 32bit environment # => Server will start in subprocess and Client will connect to it from koapy import KiwoomOpenApiPlusEntrypoint entrypoint = KiwoomOpenApiPlusEntrypoint() APIModulePath = entrypoint.GetAPIModulePath() print(APIModulePath)
# 7. 실시간 데이터 처리 예시 # TR 관련 메타정보 확인 # KOAPY 임포트 from koapy import ( KiwoomOpenApiPlusEntrypoint, KiwoomOpenApiPlusRealType, KiwoomOpenApiPlusTrInfo, ) logging.basicConfig( format="%(asctime)s [%(levelname)s] %(message)s - %(filename)s:%(lineno)d", level=logging.DEBUG, ) # 1. 엔트리포인트 객체 생성 entrypoint = KiwoomOpenApiPlusEntrypoint() # 모듈 경로 확인 (기본 함수 사용 예시) module_path = entrypoint.GetAPIModulePath() print(module_path) # 2. 로그인 예시 logging.info("Logging in...") entrypoint.EnsureConnected() logging.info("Logged in.") # 3. 기본 함수 실행 예시 # 접속 상태 확인 (기본 함수 호출 예시) logging.info("Checking connection status...") status = entrypoint.GetConnectState()
def order(request_name, screen_no, account_no, order_type, code, quantity, price, quote_type, original_order_no, format, port, verbose): # TODO: 주문 취소시 기존 주문에 대한 이벤트 스트림 종료되도록 """ \b [주문유형] 1 : 신규매수 2 : 신규매도 3 : 매수취소 4 : 매도취소 5 : 매수정정 6 : 매도정정 \b [거래구분] 모의투자에서는 지정가 주문과 시장가 주문만 가능합니다. 00 : 지정가 03 : 시장가 05 : 조건부지정가 06 : 최유리지정가 07 : 최우선지정가 10 : 지정가IOC 13 : 시장가IOC 16 : 최유리IOC 20 : 지정가FOK 23 : 시장가FOK 26 : 최유리FOK 61 : 장전시간외종가 62 : 시간외단일가매매 81 : 장후시간외종가 """ if (request_name, screen_no, account_no, order_type, code, quantity) == (None, None, None, None, None, None): fail_with_usage() if order_type is None: fail_with_usage() set_verbosity(verbose) from koapy import KiwoomOpenApiPlusEntrypoint from google.protobuf.json_format import MessageToDict if format == 'json': import json def print_message(message): click.echo(json.dumps(MessageToDict(message))) else: import pprint pp = pprint.PrettyPrinter() def print_message(message): click.echo(pp.pformat(MessageToDict(message))) with KiwoomOpenApiPlusEntrypoint(port=port, client_check_timeout=client_check_timeout, verbosity=verbose) as context: context.EnsureConnected() if order_type in ['3', '4'] and (account_no is None or code is None): for account_no_candidate in context.GetAccountList(): df = context.GetOrderLogAsDataFrame1(account_no_candidate) if '주문번호' in df.columns: rows = df.loc[df['주문번호'] == original_order_no,:] if rows.shape[0] > 0: row = rows.iloc[0,:] if account_no is None: account_no = row['계좌번호'] if code is None: code = row['종목코드'] break if account_no is None: logging.info('Account not given. Using first account available.') account_no = context.GetFirstAvailableAccount() responses = context.OrderCall( request_name, screen_no, account_no, order_type, code, quantity, price, quote_type, original_order_no) for response in responses: print_message(response)
def watch(codes, input, fids, realtype, output, format, port, verbose): if (codes, fids, realtype) == (tuple(), tuple(), None): fail_with_usage() set_verbosity(verbose) codes_len = len(codes) if codes_len == 0: if input is None: fail_with_usage('Either code or input should be given.') if not os.path.exists(input): fail_with_usage('Given input does not exist.') if os.path.isfile(input): if input.endswith('.xlsx'): import pandas as pd df = pd.read_excel(input, dtype=str) code_column = '종목코드' if code_column in df: codes = df[code_column] else: codes = df.iloc[0] codes_len = len(codes) elif input.endswith('.txt'): with open(input) as f: codes = [line.strip() for line in f] codes_len = len(codes) else: fail_with_usage('Unrecognized input type.') else: fail_with_usage('Unrecognized input type.') if realtype is not None: from koapy import KiwoomOpenApiPlusRealType fids_from_realtype = KiwoomOpenApiPlusRealType.get_fids_by_realtype(realtype) fids = list(set(fids).union(set(fids_from_realtype))) if not codes: fail_with_usage('No codes to watch. Set --code or --input.') if not fids: fail_with_usage('Cannot infer fids to watch. Set either --fid or --realtype.') import datetime import pandas as pd from koapy import KiwoomOpenApiPlusEntrypoint from koapy import KiwoomOpenApiPlusRealType def parse_message(message): fids = event.single_data.names names = [KiwoomOpenApiPlusRealType.Fid.get_name_by_fid(fid, str(fid)) for fid in fids] values = event.single_data.values dic = dict((name, value) for fid, name, value in zip(fids, names, values) if name != fid) series = pd.Series(dic) return series if format == 'json': def print_message(message): click.echo(parse_message(message).to_json(), file=output) else: def print_message(message): code = event.arguments[0].string_value name = event.arguments[1].string_value click.echo('[%s] [%s]' % (code, name), file=output) click.echo('[%s]' % datetime.datetime.now(), file=output) click.echo(parse_message(message).to_markdown(), file=output) with KiwoomOpenApiPlusEntrypoint(port=port, client_check_timeout=client_check_timeout, verbosity=verbose) as context: context.EnsureConnected() for event in context.GetRealDataForCodesAsStream(codes, fids, infer_fids=True): print_message(event)
def stockcode(names, markets, port): """ \b Possible market codes are: 0 : 장내 10 : 코스닥 3 : ELW 8 : ETF 50 : KONEX 4 : 뮤추얼펀드 5 : 신주인수권 6 : 리츠 9 : 하이얼펀드 30 : K-OTC \b Possible market code aliases are: all: All possible market codes. """ markets_option = markets if (markets, names) == (tuple(), tuple()): # fail_with_usage() pass from koapy import KiwoomOpenApiPlusEntrypoint with KiwoomOpenApiPlusEntrypoint(port=port, client_check_timeout=client_check_timeout) as context: context.EnsureConnected() if not names and not markets: markets = ['0'] if 'all' in markets: markets = market_codes codes = set() for market in markets: codes = codes.union(set(context.GetCodeListByMarketAsList(market))) codes = sorted(list(codes)) if markets_option: for code in codes: click.echo(code) else: def get_names(): if names: if '-' in names: with click.open_file('-', 'r') as f: for name in f: yield name.strip() else: for name in names: yield name else: while True: try: name = click.prompt('name', prompt_suffix=' >>> ') name = name.strip() if name == 'exit': break if name: yield name except EOFError: break all_names = [context.GetMasterCodeName(code) for code in codes] codes_by_name = dict(zip(all_names, codes)) for name in get_names(): code = codes_by_name.get(name, None) if code: click.echo(code) else: click.echo('Cannot find code for given name: %s.' % name)