앞서 포스팅한 xingAPI의 여러 데이터 조회 방법 중 [단일 데이터 조회]에 대해 포스팅 해본다.

보면 알겠지만 C#을 사용해서 자동 매매 프로그램을 만들고 있기 때문에 C#으로 코드를 짤 것이다. 

xingAPI COM 개발 가이드에는 엑셀 VBA를 이용한 프로그램의 코드가 소개되어 있다.

 

개발이 익숙한 사람이라면 COM 형식의 개발은 라이브러리 참조 후 객체의 함수들을 보면 대충 어떤 경우에 어떤 함수를 사용하면 될지 감이 온다. 

 

우선 xingAPI 가이드에 나온 내용부터 보자. 아래는 가이드에서 정리한 [단일 데이터 조회] 순서이다.

 

단일데이터 조회는 XAQuery 객체를 사용.

 

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

물론 가이드에는 위의 과정들이 엑셀 VBA로 되어 있어서 엑셀 VBA로 프로그램을 만들 예정이면 가이드를 보고 따라 하면 된다. 나는 C#으로 위의 과정들을 만들어 본다.

 

xingAPI Test 프로그램 화면


우선 단일데이터 조회를 위해 [자산현황 조회] 기능을 사용한다. 

해당 버튼을 클릭할 때마다 1회, 단일적으로 데이터를 요청하고 수신하는 방식이다.

 

xingAPI의 요청-응답은 요청하는 함수, 그리고 서버로부터 데이터를 수신하는 함수의 두 개의 함수가 쌍을 이루는 형태로 구성된다. 

 

하나의 TR 구성은 요청과 수신의 두 개 함수가 쌍을 이루게 된다.

즉, xingAPI에서 제공되는 모든 TR 처리는 요청하는 함수와 응답을 수신하는 함수, 두 개의 함수를 구현해야지만 완성이 된다. 

 

먼저 [자산현황 조회]를 위한 TR을 찾기 위해 'DevCenter'에 접속하여 TR을 찾아보자. 

'DevCenter' 사용 법은 아래에...

2020/08/14 - [Trading] - [Trading] XingAPI - DevCenter 사용하기

 

[Trading] XingAPI - DevCenter 사용하기

키움증권 API도 마찬가지지만 이베스트 XingAPI에서도 개발할 때 유용한 도구를 제공한다. 이베스트 XingAPI에서는 'DevCenter'라는 것인데, XingAPI에서 제공하는 다양한 TR(Transaction)들을 실제로 내가 보�

brandon-dev.tistory.com

'DevCenter'의 TR 목록 중, 계좌 자산 현황 정보를 볼 수 있을 것 같은 TR은 아래처럼 4가지가 가능해 보인다.

계좌 자산 정보 조회 TR 목록

위의 4가지 종류의 TR을 하나하나 눌러가며 'OutBlock'의 항목들을 잘 살펴보고 내가 필요한 정보들을 모두 획득할 수 있는 TR을 선택한다. 

 

내가 필요로 하는 정보들은 아래와 같다.

  • 실자산총액
  • D+1 예수금
  • D+2 예수금
  • 총 매입금액
  • 평가손익
  • 평가금액
  • 손익률

나는 저 위의 4가지 TR을 모두 사용해보고 많은 시간을 삽질(?)하며 결국 [CSPAQ12200] TR을 선택했다.

나와 같은 삽질을 하지 않도록...각 TR에 대한 내용을 조금 정리해 본다.


1. CSPAQ12200 현물계좌 예수금/주문가능금액/총평가조회(API)

 

이름만 보면...내가 필요한 정보들이 다~있을 것만 같은 TR 이름이다. 하지만 '총 매입금액'과 '평가손익'에 대한 정보는 존재하지 않아 존재하는 나머지 정보들을 이용해서 두 개 정보를 얻어냈다. 간단한 수학 공식으로 얻어낼 수 있다. 

다시 CSPAQ12200에 대해 얘기해 보자. 나의 경우는 이 TR을 내가 원할 때 1회 조회함으로써 내 자산 정보를 확인할 수 있도록 하는 하는데에 사용하였는데, 의외로 주기적으로 이 정보를 요청하도록 개발하는 사람이 많은지 TR 요청 폭주로 인해서 잦은 장애가 발생한다고 한다. 그래서 이베스트 측에서는 이 TR 대신 CSPAQ22200을 새로 만들어 사용하게 했다고 했다. 하지만....CSPAQ22200은 정말 적은 정보를 제공하여 나에게는 적합하지 않은 TR이었다. 

 

2. CSPAQ12300 현물계좌 잔고내역 조회(API)

 

이 TR이야말로 내가 원하는 정보들을 다~ 제공해주는 TR이다. 하지만 공교롭게도 이 TR은 모의투자에서만 지원하고 실투자에서는 지원하지 않는다. 이유는 나도 모르겠다. 이것은 이베스트에서 공식적으로 실투자에서는 제공되지 않는다고 한 사항이며, 그걸 알기 전까지 정말 엄청난 시간 소모와 삽질을 했다...실투자용 자동매매 프로그램을 만들 경우 이 TR은 사용하지 않는다.

 

3. t0424 주식잔고2

 

이 TR도 CSPAQ12300과 마찬가지로 내가 원하는 정보들은 다~ 제공해 주는 TR이다. t0424 TR 정보를 보면 알겠지만, 이 TR 하나로 자산현황과 해당 계좌에 존재하는 체결된 종목 리스트들을 함께 전달해 준다. 설계한 내 프로그램의 기능상 이 두 가지 기능이 분리되어 사용되어야 하기에 이 TR은 자산현황 조회 시 사용하지 않고 오로지 계좌 잔고 조회에만 사용하였다. 설계한 프로그램이 굳이 이 두 가지 기능을 따로 분리할 필요가 없다면, t0424 TR을 사용하는 것을 추천한다. 이 TR을 사용하는 법은 다음 포스팅에...

 


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

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;        // 자산현황 조회

        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의 응답 메시지를 수신할 함수 등록
        }
        
        // HTS 서버 접속
        private void Btn_Conn_Server_Click(object sender, EventArgs e)
        {
            string serverType = "hts.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)
        {


        }
    }
}

TR을 사용할 때 어떤 값을 입력해야 하는지, 그리고 응답 메시지에서 어떤 값을 추출해야 하는 지는 'DevCenter'에서 TR 정보를 보면 쉽게 알 수 있다. 

 

빨간색 표시 부분에서 InBlock과 OutBlock의 필드 값들을 확인하여 사용.

TR을 사용하기 전에 반드시 해야하는 작업이 있다.
바로 res 파일들을 다운로드하여 저장해 두고 있어야 하는데 해당 작업은 'DevCenter'에서 제공한다.

필요한 TR만 다운로드할 수 있긴 하지만, 그냥 전부다 다운로드하여두면 편하다.
다운로드하면 아래 경로에 자동적으로 저장이 되고, 개발할 때 해당 경로의 .res 파일을 ResFileName에 넣어 주면 된다.

 

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

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

 

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

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

brandon-dev.tistory.com

위 상태에서 [자산현황 조회] 버튼을 누르면 메시지 박스에 결과가 표시될 것이다.

 

xingAPI의 기본 TR 요청/응답처리를 구현해 봤다. 모든 TR이 이와 같은 원리로 동작하니 이것만 할 수 있다면 다른 TR들에 대한 구현도 어렵지 않을 것이다.

Posted by [ 브랜든 ]
,