L-ATS 3.0은 지난 10월 초 모든 서비스 구현이 완료되어 서비스의 기능 테스트 진행중이다.

투자 프로그램 개발 시 유의 사항
프로그램을 테스트 하기 위해 보통 모의투자를 사용한다. 
모의투자를 통해 프로그램을 테스트 하는 것은 본인 생각보다 실투자와는 많은 차이가 있다. 
먼저 증권사에서 제공하는 API TR은 결과물이 실투자와 모의투자가 다른 경우가 있다. (예를 들어, 같은 TR이지만 실투자에서만 결과물을 보여주는 경우)
그리고 모의투자는 매수/매도 타이밍이 매우 늦는다. 내가 만든 프로그램은 빠른 매수와 빠른 매도가 핵심이기 때문에 이러한 성격의 프로그램에는 모의투자가 적절하지 않다. 
그래서 테스트도 소량의 현금으로 진행....한....다....

 

테스트를 현금으로 [실투자]에서 진행하고 있으므로, 실 운영과 기능 테스트를 함께 진행하고 있는 셈이다. 

 

기능적인 소소한 버그가 존재하긴 하지만 기획했던 서비스의 전체적인 흐름은 생각했던대로 정상적으로 운영되는 것을 확인했다. 더구나 시스템은 수일간 증권 시장이 운영되는 시간동안 장애없이 잘 운영되었다. 

 

이제 준비는 끝난 것일까...?


 

처음 L-ATS 3.0의 서비스를 기획할 때 캡쳐된 글자 이미지를 OCR 처리하여 종목명을 추출하는 것을 생각해내고 선택한 이유는 현재 내가 인공지능 전문 솔루션 회사에 재직중이었기 때문이었다. 

무언가 내가 만든 이 서비스에도 인공지능적인 요소를 넣고 싶었기 때문이다. 그렇게 선택한 것이 OCR 이었고, 최근 큰 이슈가 되었던 ChatGPT를 활용하는 방법을 찾고 싶었지만 서비스 기능들을 아무리 살펴봐도 ChatGPT가 할만한 일은 없었다. 

물론 저 생각은 [기획] 단계에서의 생각이었다.

 

[운영] 단계에서의 발견

 

인공지능에는 100%는 없다.

이 말은 즉, 글자 이미지가 OCR 처리된 결과물은 100% 정확하지 않을 수 있다는 것이다. 

 

내가 사용한 OCR 엔진인 Tessaract는 한국어 언어 모델을 지정해서 사용했는데 그 때문인지 영어 알파벳이 포함된 종목정보는 영어 알파벳이 아라비아 숫자로 인식되었다.

예를 들면, SK하이닉스는 59하이닉스와 같이 인식되어 결과물을 생성했다.

 

여기서 ChatGPT가 문득 떠올랐다. 

 

OCR로부터 잘못 인식된 종목정보를 ChatGPT에게 물어서 교정할 수 있지 않을까?

 

ChatGPT는 아주 다양한, 많은 업무를 해결해주니까 가능할 것이라 생각하긴 했지만, 과연 1750억개의 파라미터에 우리 한국 증권 시장의 KOSPI, KOSDAQ 정보가 있을지는 의문이긴 했다. 

 

그래서 프롬프트 작성에 열을 올리기 시작했다. 

프롬프트란? ChatGPT와 같은 LLM 모델에게 질문을 할 때, 더 나은, 더 좋은 답변을 억기 위해서 질문을 최적화 하는 기법을 말한다.
좋은 프롬프트를 만들수록 더 좋고 간결한 정보를 획득할 수 있다. 

 

처음에는 심플하게 ChatGPT에게 물어봤다.

ChatGPT Input 프롬프트
ChatGPT 응답

음...역시나 내가 원하는 답변을 얻지는 못했다.

 

ChatGPT를 잘 활용하는 방법 중에 가장 좋은 방법은 컨텍스트를 명확하게 하는 것인데

예를 들면, 부가적인 정보들을 주어주는 것이다. (갑자기 ChatGPT 활용법으로 길이 새는것 같은데.....)

 

내가 필요한 정보는 한국 증권 시장에 속한 종목 이름에 대한 것이니 좀 더 정확한 답변을 얻기 위해 Role Prompt 기법을 사용해본다. (ChatGPT에게 역할을 주어주는것!)

더 나은 ChatGPT Input 프롬프트
ChatGPT 응답

 

ChatGPT가 해야할 일을 보다 더 자세하게 지시해주면 이렇게 내가 원하는 답변을 정확하게 얻을 수 있다. 

 

이제 이것을 내 서비스에 녹아들게 하면 보다 더 많은 종목들에 대해 자동 매매을 처리할 수 있게 되고, 좀 더 인공지능적인 서비스가 되지 않을까? 

 

더 나은 L-ATS를 위해 ChatGPT를 접목시킬 수 있는 서비스의 시스템 설계를 조금씩 진행해 봐야겠다.

Posted by [ 브랜든 ]
,

L-ATS 3.0 시스템은 크게 아래 두 가지 프로그램으로 구성된다.

Windows Application
OS : Windows 11
개발 환경 : 개인 데스크탑, MS Visual Studio 2019, 이베스트 투자증권 XingAPI
개발 언어 : C#, Winform
운영 환경 : AWS Cloud
LINUX Server Program
OS : CentOS 8.x
개발 환경 : Raspberry Pi, Vim Editor, MariaDB
개발 언어 : python3
운영 환경 : AWS Cloud

 

시스템의 큰 구성은 기존 L-ATS 2.0의 구조를 승계했다.

Windows Application은 매수할 종목의 자동 인식실제 매매 업무를 담당하고 LINUX Server Program은 매수를 위한 종목 정보관리 업무를 담당한다.

 

L-ATS 3.0의 큰 흐름을 도식화 하면 다음과 같다.


L-ATS 3.0.exe
Windows Application
  • 화면 캡처 처리
    • Visual Studio를 통해 C# 프로그래밍으로 화면을 캡쳐하는 방식을 구현하기는 쉽지 않았다.
    • 관련된 예시나 소스는 많지만 원하는 크기, 원하는 위치의 화면을 캡쳐하는 방식의 화면 캡쳐 구현은 존재하지 않았다.
    • 그래서 유용한 정보들을 수집해서 몇가지의 예시 기능을 결합해서 구현했다.
  • 캡쳐된 문자 이미지의 OCR 처리
    • 캡쳐된 화면을 바로 OCR 요청해서 Text로 변환하는 기능을 한다.
    • Apple이나 Google, NAVER에서 제공하는 OCR은 한국어 인식능력이 뛰어나지만 비용적인 측면의 문제가 있었다.
    • 때문에 무료로 사용 가능한 Tessaract OCR을 사용했다. (인식률이 많이 좋아지긴 했지만...부족하다...)
Tessaract OCR의 정확도가 낮지만 그래도 효용성이 있다고 판단한 이유는 하루에 많은 뉴스 종목들 중에 정확히 인식되는 몇몇개 종목에 대해 데이터 분석을 통해 높은 확률로 수익을 낼수 있는 조건을 만든다면 사용해도 무방하다고 생각했다.
  • 이베스트 투자증권 API를 사용한 Trading 처리
    • OCR 결과 Text에서 패턴 분석을 통해 종목명을 추출한다.
패턴 분석을 위해서는 해당 뉴스방에서 어떤 형태의 문자열로 뉴스를 알려주는지 공통점을 찾아내야 한다. 동일한 방법으로 많은 수의 뉴스 분석이 가능하고 종목추출이 가능한 패턴을 분석한다.
    • 추출된 종목명은 LINUX Server Program으로 전송하여 Database에 저장된 종목의 Code 정보를 가져온다.
    • Code 정보를 확보하면 증권사 API를 사용하여 매수 요청한다.
    • 매매 결과 정보를 LINUX Server Program으로 전송하여 파일에 기록할 수 있게 한다.
L-ATS-3.0-Server.py
LINUX Python Program
  • OCR 결과에서 추출한 종목명을 수신한다.
  • 수신한 종목명으로 Database를 조회하여 종목의 존재 여부를 확인하고 존재할 경우 종목 코드를 Windows Application으로 전달한다.
  • 수신한 매매 결과 정보를 모니터링 가능하도록 로그로 기록한다.
stocks_collector.py
LINUX Python Program
  • KRX의 국내 주식 정보를 스크래핑 해온다. (pykrx 모듈 사용)
  • KOSPI, KOSDAQ 주식 정보를 Database에 저장한다.
  • crontab에 등록하여 정해진 시간에 정기적으로 수행하도록 한다.
L-ATS Monitoring (v3.5 구현 예정)
LINUX Python Program | Mobile APP
  • 일일 매매 결과를 요청하고 수신하여 표시한다.
  • 실시간 시스템 처리 로그를 표시한다.

대략적인 시스템 구조와 구현해야 할 기능, 그리고 어떤 모듈들을 사용할지 선정을 완료했다.

현재 Windows 화면 캡쳐와 OCR 처리 테스트 프로그램을 만들고 있는데 테스트가 완료되면 바로 서비스 구축에 들어갈 예정이다. 테스트 프로그램 완성에 따라 하반기에는 전체 솔루션 검증을 진행할 예정이다.

 

Posted by [ 브랜든 ]
,

벌써 세 번째 L-ATS 사용자 화면을 설계한다.

 

첫번째 L-ATS 1.0 사용자 화면의 Focus는 '수익과 손실의 설정' 부분이었고,

두번째 L-ATS 2.0 사용자 화면의 Focus는 '매매 처리중인 종목의 표시' 부분이었다.

 

세번째 L-ATS 3.0 사용자 화면의 핵심은 이것이다.

캡쳐된 화면 표시와 OCR 처리된 문자열

 

L-ATS 2.0에서 Flexible 스탑로스를 통한 매도의 자동화를 완성한 상태에서

L-ATS 3.0에서는 매수 행위의 자동화를 구현하여  매매의 완전 자동화 를 완성하는 것이 서비스 기획의 핵심 부분이다.

 

그렇기 때문에 사용자가 보기 편하도록 캡쳐된 화면과 해당 이미지의 OCR 결과를 실시간으로 표시하는 부분에 Focus를 맞췄다.

3.0 버전의 핵심 기능 부분을 부각시키는 것이 사용자 관점에서 서비스의 장점을 직접적으로 잘 나타낼 수 있기 때문에 그때 그때 이미지 캡쳐한 화면과 OCR 처리된 내용을 즉각적으로 표시해줌으로써 사용자의 만족감을 더 높여 줄수 있다.

 

① 메인 메뉴

메뉴의 구조는 [HTS 로그인], [시스템 설정], [프로그램 종료]로 구성된다.

  • HTS 로그인 : 이베스트 증권에 로그인할 수 있도록 기능을 제공한다.
  • 시스템 설정 : 메인 화면에는 보이지 않는 시스템적으로 Critical한 값(예; OCR 엔진 정보, 예외처리 문자열, 문자열 파싱 패턴 등)들을 설정할 수 있는 화면을 제공한다.
  • 프로그램 종료 : 시스템의 안정적인 운영을 위해 비정상 종료 Case를 없애고 이 버튼으로만 종료될 수 있도록 했다.
② 상태 확인
  • HTS 서버 연동 : 증권사(이베스트 증권) API를 통해 HTS와 연동 상태 표시
  • 서버 연결 : LINUX Server의 L-ATS Main Server와 연동 상태 표시
③ 프로그램 조작
  • 캡쳐 영역 [Button]: 캡쳐할 화면의 영역을 설정할 수 있는 투명한 Form 생성
  • 시작 [Button] : 사용자 설정 값으로 자동 매매를 시작하고 정지하는 버튼
  • 캡쳐타임(초) : 실시간으로 화면을 캡쳐할 시간 간격
[ 캡쳐 타임이 필요했던 이유 ]
자동매매의 최초 서비스 기획의 핵심은 '누군가' 실시간으로 특정 종목을 언급해 주는 조건이 되어야 하는 것이었다. 근데 과연 누가...? 
그렇게 찾고 찾아 선택한 것이 카카오톡텔레그램의 일명 뉴스방이었다. 
무료로 불특정 다수에게 특정 종목의 당일 Good/Bad 뉴스를 실시간으로(?) 알려주는 고마운 곳.
하지만 이 방들은 소프트웨어적으로 개인이 메시지를 받을 수 없었다. (캡쳐 + OCR 방식을 선택한 이유.)
때문에 이 뉴스방에 새로운 뉴스가 올라온 것을 알 수 있는 방법이 없다. 그래서 일정 간격으로 화면을 지속적으로 캡쳐해서 OCR 결과를 처리하는 방식으로 처리했다. (OCR 기술이 많이 발전했듯 이런것도 해결이 가능한 좋은 방향의 방법이 곧 생기길...)
  • 스탑로스(%) : 자동 매도를 위한 손실률 설정
④ 자동매수 설정
  • 보유계좌 : 자동 매매에 사용할 사용자의 증권사 계좌
  • 매수금 : 자동으로 매수할 경우 1회 매수가
1회 매수가가 10만원일 경우, 1주당 10만원 이상인 종목은 매수하지 않는다. 
1주당 10만원 이하인 종목은 10만원 이내에서 최대 매수량을 계산하여 매수한다.
예) 1주당 9천원인 종목이면 11주 매수
⑤ 잔고조회
  • 자산총액 : 현재 선택된 사용자 증권사 계좌의 잔고 확인
  • 예수금 : 현재 선택된 사용자 증권사 계좌의 예수금 확인
⑥ 캡쳐 이미지
  • 캡쳐 영역으로 선택된 화면의 캡쳐된 이미지를 표시
⑦ OCR 결과
  • 캡쳐된 이미지의 OCR 변환 결과를 표시
⑧ 실시간 잔고
  • 매수가 완료되서 현재 계좌에 보유하고 있는 종목 리스트 표시
표시되는 종목 리스트들은 실시간으로 현재가를 갱신하여 표시하고 스탑로스를 계산

 

⑨ 거래 완료
  • 당일 거래 완료된 종목 리스트 표시
정말 이베스트 증권의 거래 완료 종목 표시를 위한 API는 최악이다.
HTS나 MTS에서 확인할 수 있는 '잔고 조회'의 화면에서 조회되는 값들과 동일한 값들을 표시하기 위해 정말 많은 시행착오를 겼었다. 이 내용은 따로 포스팅 예정이다.
⑩ 종목 추출 결과
  • OCR 결과에서 패턴 분석으로 종목명을 추출하고 LINUX Server program으로 전달하여 매수를 위한 해당 종목의 Code 정보를 요청/수신하여 표시
⑪ 실시간 건수
  • 현재 계좌에 보유하고 있는 종목의 갯수와 당일 거래 완료된 종목의 갯수 표시
⑫ 거래 완료
  • 당일 거래 완료된 종목들의 금액 정보 표시
⑬ 접속 정보
  • 사용자의 증권사 계정 접속 정보 표시

 

L-ATS 시스템이 버전업 되면서 UX/UI는 일부분들이 계승되어 구성되는것 같다. 

아무래서 버전 마다 기획하고 설계하고 구현하고 운영하다보면 배우는 것이 있기때문에 버릴건 버리고, 활용할 건 활용하게 되는것 같다.

 

새로 도전할 캡쳐 및 OCR 처리 부분 개발을 위해 부지런히 손을 움직여야겠다.

Posted by [ 브랜든 ]
,

L-ATSLim's Automatic Trading System의 약자로 2016년 성(임씨)이 같은 나(프로그램 개발)와 내 친구(검색식 생성)의 합작으로 시작된 프로젝트였다.

 

Trading 프로그램들은 모두 같은 목적을 갖고 있다. 

[ 매매의 자동화 ]

 

프로그램을 필요로하는 사람들마다 매매의 자동화의 방식, 기준은 다 제각각이다

L-ATS은 매매의 자동화를 위해 이러한 기능들을 제공했다.

 

2016년 L-ATS 1.0

2020.05.24 - [Trading] - [Trading] 첫번째 프로그램

 

[Trading] 첫번째 프로그램

프로그램 명 : L-ATS (Lim's Automatic Trading System) 버전 : 1.0 환경 : Visual Basic 주요기능 : 검색식 기반 주식 매수, 설정값 기반 주식 매도, 스탑로스 API : 키움증권 API 제작기간 : 2015.05 ~ 2015.08 키움에서

brandon-dev.tistory.com


  • 키움증권 API 사용
  • 키움증권 [조건검색]의 자체 개발한 검색식을 사용한 자동 매수

손익 수준(%) 및 수량을 단계적으로 커스텀 가능한 자동 매도

 

2020년 L-ATS 2.0

2020.06.07 - [Trading] - [Trading] 두번째 프로그램

 

[Trading] 두번째 프로그램

프로그램 명 : L-ATS (Lim's Automatic Trading System) 버전 : 2.0 환경 : Visual C# 주요기능 : HTS/MTS 매수 종목 정보 실시간 수신, 설정값 기반 주식 매도, Flexable 스탑로스 API : 이베스트 증권 XingAPI 제작기간 : 2

brandon-dev.tistory.com


  • 이베스트증권 XingAPI 사용
  • 자동 매매 프로그램과 텔레그램 봇의 조합으로 텔레그램에서 종목명만 입력하면 설정된 조건으로 알아서 매수해 주는 실시간 매수 자동화
  • 가장 빠르게(!) 매수하는게 주 목적으로 매매를 위한 종목 클릭, 계좌 비번 입력, 매수 수량 입력, 매수 버튼 클릭 등의 작업을 없앤 초 간단 매수
  • 상승하는 종목의 최대 수익을 낼 수 있도록 현재가에 맞춰 유동적으로 변화하는 매도 기준의 실시간 변화
  • 손실을 최소화 할 수 있는 철저한 자동 손절

 

L-ATS 1.0은 사실상 실패한 프로젝트였다. 실패라기 보단 매매의 목적(=수익)을 달성하기에 큰 단점이 있었다.

제대로된 검색식

L-ATS 1.0은 위에 기술했듯이 키움증권의 검색식을 통해 추출된 종목을 즉시 매매하는 방식으로 차트 기반의 수익을 만들어내는 제대로된 검색식을 필요로 했기 때문이다.

아는 사람은 알겠지만...수익을 만들어 내는 제대로된 검색식을 만들기란 정말 쉽지않다. 
제대로된 검색식을 누구나 만들 수 있다면 모든 사람이 부자가 됐겠지...(나 역시도 반년간 검색식에 매달렸지만....)

L-ATS 1.0은 이렇게 약 7개월 정도 운용되다가 폐기되었다.


그렇게 시간이 흘러 2019년.

친구의 권유로 카카x톡 찌라시 매매방에 들어가게 되었고, 약 1년여의 시간동안 관찰해온 찌라시 매매방의 특징으로 나만의 독창적인 매도 방식을 결합하여 L-ATS 2.0을 설계하게 되었다.

 

[ 찌라시 매매방에서 찾아낸 특징 ]

  1. 찌라시 매매방은 진짜 뉴스와 가짜 뉴스가 섞여 나온다.
  2. 찌라시 매매방의 목적 상(= 뉴스 띄우고 개미들이 들러붙어 1~2% 오를때 물량 넘기기 수법) 진짜 뉴스든 가짜 뉴스든 대부분 어느 순간 일정 수준의 상승을 보인다.
  3. 높은 확률로 상한가 직행 종목이 나온다. (=진짜뉴스)
   결론 : 가지 않는 종목을 빠른 손절로 손실을 최소화 하고 상한가 가능 종목 1개만 잡아도 평균적으로 수익이다.

[ 자동 손절로 최대 수익을 낼 수 있는 방법의 추론]

  1. 주식판의 모든 종목은 파형을 그리면서 움직인다.
  2. 세력이 들어와 급등하는 종목도 개미를 떨구거나 더 많은 매물을 모아서 올리기 위해 매량 매도를 통해 순간 가격을 내린다.
  3. 종목의 최고가가 갱신될 때마다 해당 값을 기준으로 일정 수준의 손절 라인을 실시간으로 변경하면서 가져간다면 자동매매로써의 최대 수익을 낼 수 있는 하나의 방법이 된다. (= 내 생각)
절대적 손절 라인을 -5%로 지정했다고 가정해 보자.
내가 1000원에 어떤 종목을 샀으면 그 시점에 손절 라인은 1000원에서 -5%인 950원이다. 
이때 종목이 1000원에서 1100원이 되면 그 시점에 손절 라인은 1045원이 된다. 
이런 식으로 손절 라인을 매 시점의 최고가에 맞게 높여 나간다면 1000원에서 급등했다가 다시 1000원으로 내려와도 무조건 수익이 생기게 된다. 
또한, 급등하는 중간 중간에 세력이 개미를 떨구기 위해 호가를 내리는 경우 설정된 -5% 이내에 들어오면 손절되지 않고 상승 파형을 따라 끝까지 가져갈 수 있는 좋은 조건이 된다.
이것은 고정된 금액. 또는 고정된 수익/손절 %에서 자동 청산 기능을 제공하는 많은 증권사들의 기능과는 확실히 더 나은 차별점이 있다.

이렇게 탄생한 L-ATS 2.0은 약 2년간 기능 업데이트 및 버그 수정을 거듭해가며 나의 증권 계좌를 운용해 주었다.

 

L-ATS 2.0은 찌라시 매매방에서 언급한 종목을 무조건 사는 방식을 채택하였기에 

매수에 한해서는 완전 자동화를 할 수가 없었다.

때문에, 찌라시 매매방에 종목이 올라온 것을 캐치한 후 미리켜둔 증권 앱에서 종목을 검색하여 수동으로 매수를 하였다. 

여기서 L-ATS 2.0의 단점이 발생했다.

 

바로 매수가 느리다는 것.

찌라시 매매방에 올라오는 종목은 말그대로 찌라시에 의한 급등 종목들이기 때문에 빠른 매수가 수익과 직결된다. 

하지만 수동 매수로 인해 증권사 앱에 접속하는 시간, 종목을 검색하는 시간, 계좌 비밀번호를 입력하는 시간, 매수 가격 및 매수금액 입력  시간 등..

 

이를 보완하기 위해 텔레그램 봇을 이용하여 L-ATS 2.0 프로그램과 연동을 통해 수동 매수의 한계점을 극복하였으나

이것 역시 찌라시 매매방의 종목을 내가 인지한 후에 매수가 가능했기에 타이밍을 놓치거나 아예 보지 못해 매수를 하지 못하는 단점들이 생겨났다. 

그래서 결론은,  역시 완전 자동화!!

L-ATS 2.0은 약 7개월 전, 결국 전체 수익률 약 -3% 수준을 기록하고 멈추었다. 

그래도 반자동 매매 치고는 매우 괜찮은 수준이라고 생각한다.

 


최근 애플에서 iOS 업데이트를 하면서 카메라 기능 중 OCR 기능을 기본 탑재하면서 전 세계적으로 인공지능 학습에 의한 OCR 정확도가 평균적으로 매우 상승하였음을 보여주었다. (실제로 써보면 거의 100% 정확하다.)

 

L-ATS 2.0에서 완성하지 못했던 완전 자동화를 이 인공지능 OCR 기능을 통해 구현해 보고자 

다시 Visual Studio를 열게 되었다. (지금 내가 인공지능 회사에 재직 중이니까...)

 

2023년 L-ATS 3.0

L-ATS 3.0은 찌라시 매매방의 채팅 창을 일정 시간 간격으로 캡쳐하여 TEXT만 OCR로 변환 후

종목명을 추출하여 즉시 매수 처리하는 방식으로 구현될 것이다.

 

이 과정에서도 분명 문제점은 있다. 

하지만 완전 자동화가 되는 프로그램을 만드는 것이 우선순위이기 때문에 이슈들은 일단 뒤로 제껴둘 생각이다.

Posted by [ 브랜든 ]
,

이번 포스팅은 단일 데이터 조회에 이어 xingAPI의 [반복 데이터 조회]에 대해 포스팅 해본다.

단일 데이터 조회처럼 C#으로 코드를 짤 것이며, xingAPI COM 개발 가이드에는 엑셀 VBA를 이용한 프로그램의 코드가 소개되어 있다.

 

이름에서 알 수 있듯이 반복적으로 구성되어 있는 데이터를 가져올때 사용하는 TR이다.

자동매매 프로그램에 어떤 기능을 넣느냐에 따라 다르겠지만, 이 TR이 많이 필요해 보이진 않는다.

 

나는 계좌에 매수되어있는 종목들의 정보를 가져오는데에 사용하겠다.

 

사실은 본인이 사용하고 싶다고 하더라도 xingAPI에서 해당 기능을 제고하는 TR에 대해서만 사용 가능하다. 

먼저 원하는 기능에 맞는 TR을 찾아보자. 

 

잔고 정보를 가져오기 위해 xingAPI의 '[t0424] 주식잔고2' TR을 사용하면 되겠다.

적절한 TR을 찾기 위해 DevCenter에 접속한 후 각 TR들을 눌러보면 뒤에 'OCCURS'라고 붙는 TR들이 존재한다. 이 TR들은 반복(OCCUR) 데이터 요청이 가능하다는 얘기다. 

 

이 TR을 사용해서 내 계좌에 매수되어 있는 종목들의 정보를 한번에 받아와 보자.

 

데이터를 수신하는 방법만 다를 뿐 단일데이터 조회 방식과 같다. 

 

반복데이터 조회는 XAQuery 객체를 사용.

 

  1. XAQuery 선언
  2. XAQuery 생성
  3. RES 등록
  4. 입력데이터 설정
  5. 입력데이터를 서버로 전송하기
  6. 서버로부터 데이터 받기

프로그램은 이전 포스팅에 사용한 프로그램에 기능을 추가해 구현해 본다.

 

xingAPI 테스트 프로그램, 종목 출력때문에 가로로 조금 넓혔다.

이제 구현 후 테스트 해보자.

종목이 여러개 있어야하므로 모의투자로 접속해서 테스트 해보자.

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using XA_SESSIONLib;
using XA_DATASETLib;

namespace xingAPI_Test
{
    public partial class xingAPI_Test : Form
    {
        // Global 변수
        bool gIsConnHTS = false;
        string gAccount = string.Empty;

        // xingAPI Session 클래스 선언
        XASessionClass myXASessionClass;

        // xingAPI TR 클래스 선언
        XAQueryClass CSPAQ12200;        // 자산현황 조회
        XAQueryClass t0424Occurs;       // 잔고조회 - 종목리스트

        public xingAPI_Test()
        {
            InitializeComponent();
            // xingAPI Session 객체 생성
            myXASessionClass = new XASessionClass();
        }

        // Form Load될 때 초기화
        private void xingAPI_Test_Load(object sender, EventArgs e)
        {
            Realtime_Log.Items.Add("====== xingAPI Test 프로그램 시작 ======");
            // HTS 로그인 핸들러 등록
            myXASessionClass._IXASessionEvents_Event_Login += new XA_SESSIONLib._IXASessionEvents_LoginEventHandler(myXASessionClass_Login);
            // xingAPI TR 이벤트 등록
            CSPAQ12200 = new XAQueryClass();
            CSPAQ12200.ResFileName = @"C:\eBEST\xingAPI\Res\CSPAQ12200.res";  // xingAPI 서버로부터 수신한 응답 메시지를 COM 버전의 API에서 사용할 수 있도록 Format을 맞춰주는 파일
            CSPAQ12200.ReceiveData += CSPAQ12200ReceiveData;  // xingAPI 서버로부터 CSPAQ12200의 응답 메시지를 수신할 함수 등록

            // xingAPI 반복 데이터 조회 TR 이벤트 등록
            t0424Occurs = new XAQueryClass();
            t0424Occurs.ResFileName = @"C:\eBEST\xingAPI\Res\t0424.res";
            t0424Occurs.ReceiveData += t0424ReceiveData;
        }
        
        // HTS 서버 접속
        private void Btn_Conn_Server_Click(object sender, EventArgs e)
        {
            string serverType = "demo.ebestsec.co.kr";
            gIsConnHTS = myXASessionClass.ConnectServer(serverType, 20001); // 20001은 HTS 서버 고정 Port 값
            if (gIsConnHTS == true)
            {
                Realtime_Log.Items.Add("이베스트 모의투자 서버 접속 완료");
            }
            else // 연결 실패했을 경우
            {
                int ErrCode = myXASessionClass.GetLastError();
                var ErrMsg = myXASessionClass.GetErrorMessage(ErrCode);
                string err_log = String.Format("[서버연결] ERR - {0}({1})", ErrMsg, ErrCode);
            }
        }

        // HTS 서버 로그인
        private void Btn_Login_Click(object sender, EventArgs e)
        {
            if (gIsConnHTS == true) // HTS 서버 로그인은 서버 접속이 완료된 이후에만 가능.
            {
                bool reqLogin = ((XA_SESSIONLib.IXASession)myXASessionClass).Login(TB_User_ID.Text, TB_User_Passwd.Text, 
                    "", 0, false); // 세번째 인자는 공인인증비번을 입력하는 칸이지만 보안을 위해 입력 받지 않고 보안 프로그램에서 입력하는 것이 좋다.
                // reqLogin의 결과 값은 로그인 완료 여부가 아닌, 서버에 로그인 요청을 전송 완료 여부이다. 때문에 Login Handler 함수를
                // 별도 추가하여 요청한 로그인 정보가 정상적으로 성공했는지 확인해야한다.
                if (reqLogin == true)
                {
                    Realtime_Log.Items.Add("HTS 로그인 요청 완료");
                }
                else
                {
                    Realtime_Log.Items.Add("HTS 로그인 요청 실패");
                    int ErrCode = myXASessionClass.GetLastError();
                    var ErrMsg = myXASessionClass.GetErrorMessage(ErrCode);
                    string err_log = String.Format("[로그인] ERR - {0}({1})", ErrMsg, ErrCode);
                }
            }
        }

        // HTS 서버 로그인 결과
        void myXASessionClass_Login(string code, string msg)
        {
            if (code == "0000") // code 0000은 성공을 의미
            {
                Realtime_Log.Items.Add("HTS 로그인 완료");

                // 보유 계좌 정보 Loading
                int AccountCount = myXASessionClass.GetAccountListCount();
                for (int i = 0; i < AccountCount; i++)
                {
                    string AccountNo = string.Empty;
                    string AccountName = string.Empty;
                    string AccountDetailName = string.Empty;
                    string AccountNickName = string.Empty;
                    string AccountFinal = string.Empty;

                    AccountNo = myXASessionClass.GetAccountList(i);
                    AccountName = myXASessionClass.GetAccountName(AccountNo);
                    AccountDetailName = myXASessionClass.GetAcctDetailName(AccountNo);
                    AccountNickName = myXASessionClass.GetAcctDetailName(AccountNo);
                    AccountFinal = AccountNo + "(" + AccountName + ")";
                    Realtime_Log.Items.Add(AccountFinal);
                    CB_Account_List.Items.Add(AccountNo);
                }
                Realtime_Log.Items.Add("보유 계좌 정보 Loading 완료");
            }
        }

        // 보유 계좌 선택
        private void Btn_Input_Account_Click(object sender, EventArgs e)
        {
            if (CB_Account_List.Text != "")
            {
                gAccount = CB_Account_List.Text;
                string str_log = String.Format("[보유계좌선택] {0} 선택완료.", gAccount);
                Realtime_Log.Items.Add(str_log);
            }
        }

        // 자산현황 조회 [단일데이터]
        private void Btn_Get_Balance_Click(object sender, EventArgs e)
        {
            // CSPAQ12200 TR의 InBlock 데이터 세팅
            CSPAQ12200.SetFieldData("CSPAQ12200InBlock1", "RecCnt", 0, "00001");
            CSPAQ12200.SetFieldData("CSPAQ12200InBlock1", "MgmtBrnNo", 0, " ");
            CSPAQ12200.SetFieldData("CSPAQ12200InBlock1", "AcntNo", 0, gAccount);
            CSPAQ12200.SetFieldData("CSPAQ12200InBlock1", "Pwd", 0, "실제계좌비번");
            CSPAQ12200.SetFieldData("CSPAQ12200InBlock1", "BalCreTp", 0, "0");

            // TR 요청
            var result = CSPAQ12200.Request(false);
            if (result > 0)
                MessageBox.Show("CSPAQ12200 요청 완료");
            else
                MessageBox.Show("CSPAQ12200 요청 실패");
        }

        private void CSPAQ12200ReceiveData(string trCode)
        {
            // 요청한 CSPAQ12200 TR에 대한 응답 메시지 수신
            // CSPAQ12200 TR의 OutBlock2에서 필요한 데이터 추출
            // 1. 예탁자산 총액
            var temp_value = CSPAQ12200.GetFieldData("CSPAQ12200OutBlock2", "DpsastTotamt", 0);
            decimal estimated_assets = Convert.ToDecimal(temp_value);
            // 2. D+1 예수금
            temp_value = CSPAQ12200.GetFieldData("CSPAQ12200OutBlock2", "D1Dps", 0);
            decimal d1_deposit = Convert.ToDecimal(temp_value);
            // 3. D+2 예수금
            temp_value = CSPAQ12200.GetFieldData("CSPAQ12200OutBlock2", "D2Dps", 0);
            decimal d2_deposit = Convert.ToDecimal(temp_value);
            // 4. 손익률
            temp_value = CSPAQ12200.GetFieldData("CSPAQ12200OutBlock2", "PnlRat", 0);
            double valuation_rate = Convert.ToDouble(temp_value);
            // 5. 잔고평가금액
            temp_value = CSPAQ12200.GetFieldData("CSPAQ12200OutBlock2", "BalEvalAmt", 0);
            decimal evaluation_amounts = Convert.ToDecimal(temp_value);

            string text = String.Format("[예탁자산총액 : {0:#,0}] [D+1 예수금 : {1:#,0}] [D+2 예수금 : {2:#,0}] [손익률 : {3:f2}%] [잔고평가금액 : {4:#,0}]",
                estimated_assets, d1_deposit, d2_deposit, valuation_rate, evaluation_amounts);
            MessageBox.Show(text);
        }

        // 계좌잔고 조회 [반복데이터]
        private void Btn_Get_Items_Click(object sender, EventArgs e)
        {
            // 잔고 리스트 조회
            string inform = String.Format("-- 잔고 리스트 조회");
            Realtime_Log.Items.Add(inform);

            t0424Occurs.SetFieldData("t0424InBlock", "accno", 0, gAccount);
            t0424Occurs.SetFieldData("t0424InBlock", "passwd", 0, "실제계좌비번");
            t0424Occurs.SetFieldData("t0424InBlock", "prcgb", 0, "1");
            t0424Occurs.SetFieldData("t0424InBlock", "chegb", 0, "2");
            t0424Occurs.SetFieldData("t0424InBlock", "dangb", 0, "0");
            t0424Occurs.SetFieldData("t0424InBlock", "charge", 0, "0");
            t0424Occurs.SetFieldData("t0424InBlock", "cts_expcode", 0, " ");
            int result = t0424Occurs.Request(false);
            if (result < 0)
            {
                inform = string.Format("[보유계좌] 계좌 잔고리스트(t0424) 요청이 실패했습니다. ret={0}", result);
                Realtime_Log.Items.Add(inform);
            }
        }

        private void t0424ReceiveData(string trCod)
        {
            // 전체 잔고 종목 횟수 가져오기
            var count = t0424Occurs.GetBlockCount("t0424OutBlock1");
            string inform = String.Format("잔고조회 종목 리스트 갯수 : {0}", count);
            Realtime_Log.Items.Add(inform);

            Realtime_Log.Items.Add("-------------------------------------------------------------------------------------------------------------------------------");           
            string title = String.Format("| {0,20} | {1,10} | {2,10} | {3,10} | {4,10} | {5,10} | {6,10} | {7,10} | {8,10} |", "종목명", "종목코드", "현재가", "매입가", "잔고수량", "매입금액", "평가금액", "평가손익", "수익률");
            Realtime_Log.Items.Add(title);
            Realtime_Log.Items.Add("-------------------------------------------------------------------------------------------------------------------------------");

            // 가져온 종목 횟수 만큼 반복하면서 실제 종목 정보 가져오기
            for (int index = 0; index < count; ++index)
            {
                var temp_value = t0424Occurs.GetFieldData("t0424OutBlock1", "expcode", index); // 종목코드
                string expcode = Convert.ToString(temp_value);
                temp_value = t0424Occurs.GetFieldData("t0424OutBlock1", "hname", index);       // 종목명
                string hname = Convert.ToString(temp_value);
                temp_value = t0424Occurs.GetFieldData("t0424OutBlock1", "price", index);       // 현재가
                decimal price = Convert.ToDecimal(temp_value);
                temp_value = t0424Occurs.GetFieldData("t0424OutBlock1", "pamt", index);        // 매입가
                decimal pamt = Convert.ToDecimal(temp_value);
                temp_value = t0424Occurs.GetFieldData("t0424OutBlock1", "janqty", index);      // 잔고수량
                int janqty = Convert.ToInt16(temp_value);
                temp_value = t0424Occurs.GetFieldData("t0424OutBlock1", "mamt", index);        // 매입금액
                decimal mamt = Convert.ToDecimal(temp_value);
                temp_value = t0424Occurs.GetFieldData("t0424OutBlock1", "appamt", index);      // 평가금액
                decimal appamt = Convert.ToDecimal(temp_value);
                temp_value = t0424Occurs.GetFieldData("t0424OutBlock1", "dtsunik", index);     // 평가손익
                decimal dtsunik = Convert.ToDecimal(temp_value);
                temp_value = t0424Occurs.GetFieldData("t0424OutBlock1", "sunikrt", index);     // 수익율
                double sunikrt = Convert.ToDouble(temp_value);

                string contents = String.Format("| {0,20} | {1,10} | {2,10} | {3,10} | {4,10} | {5,10} | {6,10} | {7,10} | {8,10} |",
                    expcode, hname, price, pamt, janqty, mamt, appamt, dtsunik, sunikrt);

                Realtime_Log.Items.Add(contents);
            }
            Realtime_Log.Items.Add("-------------------------------------------------------------------------------------------------------------------------------");
        }
    }
}

아래의 이전 포스팅을 참조해서 [서버연결]-[로그인]-[계좌선택]까지 완료해보자.  

2020/08/24 - [Trading] - [Trading] xingAPI - 서버연결, 로그인, 보유계좌 불러오기

 

[Trading] xingAPI - 서버연결, 로그인, 보유계좌 불러오기

오늘은 xingAPI를 사용한 자동매매 프로그램을 만들기 위한 기본 작업들에 대한 포스팅을 하려 한다. 이 내용은 이베스트 투자증권의 xingAPI 소개자료에도 동일하게 소개되어 있는 내용이지만, 엑�

brandon-dev.tistory.com

서버접속 -> 로그인 -> 계좌 선택까지 완료한 화면.

이제 '계좌잔고 조회' 버튼을 누르면 종목 리스트가 표시될 것이다. 

계좌에 매수되어 있는 종목 리스트 표시.

이제 이 정보들을 객체 List로 저장하도록 해서 DataGridView에 Binding하면, 실시간으로 계좌 종목 리스트를 갱신하며 리스트로 보여줄 수 있겠다. 

 

다음은 DataGridView에 Binding하는 법을 포스팅 해보자. 

 

 

Posted by [ 브랜든 ]
,

하나의 시스템/프로그램을 설계하는 것은 상당히 고난도의 작업이다. 

Architecture-Design에 속하는 이 작업은 Front-End의 User Interface(UI)적 편의성과 간결함, 그리고 정확성을 바탕으로 하는 사용자 친화적 경험 및 지식이 필요하며, Back-End의 Call-Flow(메시지 흐름)와 가장 중요한 Data Structure가 가능해야한다. 

 

현재 L-ATS Flex v2.0은 약 50% 정도 완성이 되었지만, 실제 게시글은 그때마다 작성하지 못했다. 이유는 위에서 '가장 중요한'이라고 말한 Data Structure가 불안정했기 때문이다. 

처음 사용해 보는 이베스트 투자증권의 xingAPI에서 얻을 수 있는 Data가 생각보다 제한적이고 API의 사용성 또한 제한적이라 프로그램이 만들어지면서 데이터 구조가 많이 변경되었다. 

 

지금 시점은 xingAPI로부터 얻을 수 있는 데이터가 모두 파악되고, 그 데이터들을 어떤 부분에 사용하고 응용할지 정리가 되었기에, 잠시 개발을 멈추고 글을 작성한다. 


1. L-ATS 화면 구성

L-ATS Flex v2.0 화면 구성

크게 총 15개의 구역으로 구분이 되며, 각 구역 마다의 설명은 아래 정리되어 있다.

L-ATS v1.0과 가장 큰 차이점은 '매수' 기능이 없어져 그에따른 '미체결' 관련 화면 구역이 없어졌다. 그리고 L-ATS v2.0의 핵심 기능인 '스탑로스 Flex' 관련 설정 및 결과 창이 생겼다. 

실은 '스탑로스 Flex'보다 '스탑로스'가 더 표시할 정보가 많이 있는데(설정 조건이 복잡해서...)...결과 창의 위치를 바꾸어야 할 수도 있을 것 같다.

 

2. L-ATS 상세 화면 구성

1~15개의 구역을 가진 L-ATS v2.0

 

① L-ATS v2.0의 주 메뉴 Bar

② L-ATS v2.0 프로그램 사용자 정보 

    : L-ATS v2.0을 사용하기 위한 사용자 가입 정보.

③ 이베스트 투자증권 HTS 서버 접속 정보

    : 접속 (초록색), 미접속 (빨간색)

④ 자동 매매 시작 버튼

    : 이 버튼이 눌리지 않는한 자동매매가 시작되지 않음.

⑤ 프로그램 알림 Bar

    : 프로그램 동작 중 사용자에게 알림이 필요한 수준의 메시지가 표시됨.

⑥ 사용자 계좌 목록

    : 사용자가 보유한 이베스트 투자증권의 계좌 목록 표시. HTS 로그인이 완료되어야 표시됨.

⑦ 실시간 지수 정보

    : 실시간으로 증권 시장의 코스피/코스닥 지수를 표시. 약 3초마다 데이터 수신. HTS 로그인이 완료되어야 표시됨.

⑧ 실시간 매매 처리 종목 현황

    : L-ATS 프로그램 상에서 처리되고 있는 종목들의 갯수를 실시간으로 표시.

     (기존 잔고건수 + 신규 매수 건수) = (거래 완료 건수 + 스탑로스 건수 + 스탑로스 Flex 건수)

⑨ 사용자 계좌의 실시간 자산 현황

⑩ 사용자 계좌의 실시간 잔고 종목 목록

    : 현재 사용자가 보유한 종목들의 목록. 이 목록에서 종목별 스탑로스 처리 여부를 정할 수 있음.

⑪ 자동 스탑로스 환경 설정

    : 자동 매매 시작 이후 적용될 스탑로스 설정 값.

⑫ 스탑로스 처리 종목 목록

    : 실시간 잔고에서 스탑로스 처리를 선택한 종목들에 대한 목록 표시.

⑬ 거래 완료 종목 목록

    : 스탑로스 또는 스탑로스 Flex에서 매도처리가 완료된 종목들에 대한 목록 표시.

⑭ 스탑로스 Flex 처리 종목 목록

    : 실시간 잔고에서 스탑로스 Flex 처리를 선택한 종목들에 대한 목록 표시.

⑮ 이베스트 투자증권 사용자 정보

    : HTS 로그인 후 표시되는 사용자의 이베스트 증권 사용자 정보.

 

3. xingAPI 사용 구역

위의 15개 구역 중 xingAPI를 통해 얻은 데이터를 표시하는 구역에 대한 설명이다.

L-ATS v2.0 화면 내의 xingAPI 사용 구역

생각보다 xingAPI를 사용하는 부분은 많지 않다. 그리고 단순하다. 

실시간으로 계속 데이터를 요청하고 수신하여 반영해야하는 '실시간 잔고' 부분을 제외하고는 단순 Request-Response 처리이기에 크게 어려운 부분은 없다. 

 

xingAPI에서 제공하는 TR처리 기능 중 한번 Binding 해두고 값의 변화가 있을 때마다 서버 측에서 데이터를 내려주는 TR 처리 방식이 있는데 실시간으로 변화되는 잔고 정보를 갱신하는 데에 매우 유용할 것 같지만, 경험상 굳이 세션 유지를 신경 쓰며 보다 세세한 예외처리를 하기 위한 노력을 기울이는 것보다 주기적으로 정보를 요청하여 처리하는 것이 더 심플할 것 같다. 프로그램의 기능은 심플한 것이 최고다. 

 

다음은 실제로 구현한 'HTS 로그인' 부분 포스팅이다.

Posted by [ 브랜든 ]
,

키움증권 API도 마찬가지지만 이베스트 XingAPI에서도 개발할 때 유용한 도구를 제공한다.

 

이베스트 XingAPI에서는 'DevCenter'라는 것인데, XingAPI에서 제공하는 다양한 TR(Transaction)들을 실제로 내가 보유한 계좌를 이용해서 시뮬레이션해볼 수 있도록 해준다. 

 

예를 들면, 계좌 조회를 하는 기능을 개발하고 싶을 경우 어떤 XingAPI TR을 사용해야 하는지, 그리고 해당 TR에 어떤 값들을 입력해서 요청을 해야하는지, 마지막으로 TR에 대한 응답들은 어떤 변수에 어떤 값들이 포함되어 오게 되는지 등이다. 

 

따라서, DevCenter와 HTS/MTS에서 실제 내 계좌의 정보를 비교해가며, 프로그램 개발하면서 내가 필요한 값들이 어떤 것들인지 확인하고 골라내가며 개발을 수월하게 도와준다. 

 


STEP 1. XingAPI 설치

 

우선 XingAPI를 사용하기 위해서는 이베스트 증권에서 제공하는 XingAPI 패키지를 설치해야 한다.

http://www.ebestsec.co.kr/

 

이베스트투자증권

 

www.ebestsec.co.kr

 

xingAPI 다운로드는 이베스트증권 회원가입이 되어있어야 한다.

 

xingAPI 선택

 

xingAPI 패키지 소개부분의 '최신 버전 설치' - 'PC'를 선택하여 설치한다.

 

 

xingAPI 패키지 다운로드

 

설치가 완료되면 바탕화면에 다음과 같은 아이콘이 생긴다. 

 

xingAPI 패키지 설치 후 사용 가능한 프로그램

 

 

STEP 2. XingAPI 실행

 

개발에 필요한 TR 테스트 프로그램으로 'DevCenter'를 사용하면 된다. 그럼 프로그램을 실행시켜 보자.

프로그램을 실행하면 다음과 같은 이베스트 증권 로그인 화면이 뜬다.

 

DevCenter 로그인 화면. 실제 본인 계정, 계좌 정보와 동일하다.

 

접속 서버는 '실서버'와 '모의투자'를 선택할 수 있는데, '모의투자'를 선택할 경우 미리 이베스트 투자증권 사이트에서 본인 계정에 대해 '모의투자' 참여 신청을 완료해야 한다.

 

'DevCenter' 첫 화면. 왼쪽에 다양한 TR 목록을 확인할 수 있다. 

 

첫 로그인 후에 로그 상세, 로그 속성, TR 속성 등이 화면에 표시되지 않을 수 있다. 이때는 메뉴의[보기]-[도구 모음 및 도킹 창]에서 필요한 화면들을 선택, 체크하면 된다.

 

그럼 이제 특정 TR 하나를 선택해 보자. 처리할 수 있는 TR의 종류로는 '단일 데이터', '연속 데이터', '반복 데이터'가 있는데 이 중에서 '단일 데이터'와 '반복 데이터'를 하나의 TR로 제공하는 '[t0424] 주식 잔고 2' TR을 살펴보자.

 

'[t0424] 주식 잔고2' TR의 상세 정보

 

왼쪽 TR 목록에서 '[t0424] 주식 잔고2' TR을 선택하면 위와 같이 해당 TR의 요청 메시지(t0424 inBlock) 그리고 응답 메시지(t0424 OutBlock)에 사용될 각 Data Field 들에 대한 정보를 볼 수 있다. 

 

간략하게 보자면 '[t0424] 주식 잔고 2' TR을 사용하려면 입력에 계좌번호, 비밀번호 등을 넣어야 하고, 수신한 응답에서는 추정 순자산, 실현손익, 매입금액 등의 값을 얻을 수 있는 것으로 되어 있다.

 

또 하나 중요한 것은 바로 'TR 속성' 창의 정보이다. 이곳에 어마어마하게 중요한! 어찌 보면 가장 중요한 것 정보 중의 하나가 있는데 바로 [ 초당 전송 수 ]이다. 

 

'[t0424] 주식 잔고2'의 TR 속성

 

분명하게 '1초당 2건'이라고 명시되어 있다. 

이것은 사용자들이 개발할 프로그램에서 '[t0424 주식 잔고2]' TR을 사용할 경우, 반드시 1초에 최대 2건만 요청할 수 있도록 개발해야 한다는 것이다. (실제로 약 0.1초간 요청을 보내게 하면... 하면 당연히 안된다... 계정 정지당함...)

 

사용자의 프로그램에서 해당 TR을 요청하는 메시지를 만들어야 하는데 그 부분이 바로 't0424InBlock'에 해당된다. 

여러 가지 잘 모르는 것들을 입력해야 하는데 어떤 값을 입력해야 할지 모를 때는 해당 Field를 클릭하면 오른쪽 'TR 속성' 화면의 'Field 정보'에 표시된다.

계좌번호는 사용자의 계좌번호를 입력하면 되고, 비밀번호는 계좌의 비밀번호 4자리... 이외 나머지 것들은 어떤 값을 입력해야 하는지... 당연히 알 수 없다. 단가 구분을 눌러보자.

 

t0424 TR의 '단가구분' Field 상세 정보

 

[TR속성]-[Field 속성] 부분에 '1@평균단가', '2@BEP단가' 라고 쓰여있다. 즉, 평균단가로 잔고를 조회하고 싶으면 '1'이란 값을, BEP단가로 잔고를 조회하고 싶으면 '2'란 값을 넣어야 한다는 것이다. 

다른 Field 들도 위와 같은 방법으로 어떤 값을 넣어야 하는지 확인하면 된다. 

 

또 하나 유심히 봐야 하는 것은 해당 TR이 '단일데이터' 처리인지 '반복데이터'처리인지 확인하는 것이다. 

't0424'를 잘 살펴보면 OutBlock, 즉, 응답 메시지가 두 가지가 존재하는 것을 확인할 수 있다. 

't0424OutBlock'이 단일데이터 응답 메시지이고, 't0424OutBlock1 - OCCURS'가 반복데이터 처리 응답 메시지이다. 

 

풀어 얘기하자면 [t0424 주식 잔고2] TR은 't0424InBlock' 메시지로 계좌번호/비밀번호/단가구분/체결구분/단일가구분/제비용포함여부/CTS_종목번호 값들을 입력받아, 't0424OutBlock'으로 계좌의 일반 정보들을 전달하고, 't0424OutBlock1'로 이 계좌에 존재하는 매수된 종목 리스트(여러개일 수 있으니 동일한 형태의 반복적 데이터들임.)를 전달한다. 는 얘기다.

 

STEP 3. xingAPI TR 실행

xingAPI는 위에서 살펴본 TR에 대해 실제로 테스트해볼 수 있는 기능을 제공한다. 

위에서처럼 사용할 TR을 선택한 다음, 메뉴바 밑의 다양한 아이콘들 중에 푸른 오른쪽 세모(재생 버튼 모양)를 클릭하면 별도의 'TR 확인 창'이 뜬다.

 

[TR 확인 창] 초기 화면

 

TR 확인 창을 실행하면 아까 보았던 InBlock과 OutBlock들의 Field 값들을 볼 수 있고, [In Block]에 해당되는 값들을 입력해서 TR을 실행해 볼 수 있다.

이제 내 계좌의 정보를 입력하고 '조회' 버튼을 클릭하여 이베스트증권 서버로부터 수신한 정보를 확인해 보자.

 

실제 t0424 TR 실행 결과

 

내 실계좌에 대한 잔고 정보 수신이 완료되었다. Out Block의 값들은 실제 내 계좌정보와 동일하니 바로 이베스트증권 HTS/MTS에 접속하여 하나하나 비교하면서 정확한지 확인해보면 된다. 자동매매 프로그램을 만들면서 이 작업이 중요한 이유는... 아무래도 Field의 이름들이 모두 한눈에 어떤 것을 의미하는지 알아보기 힘들고, TR 정보창의 Field 설명이 나와있지만 그 또한 내가 생각한 이름과 다른 게 쓰여있는 것들이 있어 값을 비교해보고 내가 필요한 값과 동일한 값을 가진 Field를 적어 두었다가 사용하면 꽤 효율적이다. 

 

이제 개발을 시작해 보자.

Posted by [ 브랜든 ]
,