본문 바로가기
주식 자동매매 프로그램 제작/국내주식 자동매매

[C# 주식자동매매제작] 계좌 조회 및 예수금상세현황 조회하기

by 타임박스 2022. 4. 25.
반응형


✔ 키움증권 TR 요청하기, Open API 이벤트 수신



이번 포스트에서는 내 계좌들을 불러오고 내 계좌의 잔고현황 데이터를 가져오는 방법입니다.

이전 샘플프로젝트에 어느정도 구현이 다 되어있습니다.

이전 포스트에서 받은 샘플프로젝트에서 Form1.cs를 엽니다.

함수 axKHOpenAPI_OnEventConnect 부분을 찾아가봅니다.

로그인되었을때 처리되는 부분이 나타나있습니다.

Open API의 원리키움증권에 데이터 요청 (TR) -> 키움증권에서 데이터 전송 -> Open API 이벤트 수신

이런 원리 입니다. TR을 송신하면 키움증권에서 데이터를 전송합니다.

하지만 TR의 제약사항이 많아 TR 제약사항에 대해서는 따로 설명드리겠습니다.

 

● 로그인했을경우 자동으로 계좌조회

계좌정보의 경우에는 로그인 요청을 했을때 정보가 다 포함되어서 따로 데이터 요청(TR)은 필요없습니다.

이미 아래의 함수가 샘플프로젝트에는 구현이 되어있습니다.

private void 계좌조회ToolStripMenuItem_Click(object sender, EventArgs e)
{
    lbl아이디.Text = axKHOpenAPI.GetLoginInfo("USER_ID");
    lbl이름.Text = axKHOpenAPI.GetLoginInfo("USER_NAME");

    string[] arr계좌 = axKHOpenAPI.GetLoginInfo("ACCNO").Split(';');

    cbo계좌.Items.AddRange(arr계좌);
    cbo계좌.SelectedIndex = 0;
}

로그인 후 계좌조회를 따로따로 클릭하기가 번거로워 한번에 처리하는 것이 필요해보입니다.

private void 로그인ToolStripMenuItem_Click(object sender, EventArgs e)
{
    if (axKHOpenAPI.CommConnect() == 0)
    {
        Logger(Log.일반, "로그인창 열기 성공");
        //추가
        계좌조회ToolStripMenuItem.PerformClick();
    }
    else
    {
        Logger(Log.에러, "로그인창 열기 실패");
    }
}

로그인이 성공했을때 계좌조회 버튼을 강제로 활성화합니다.

이제 로그인 버튼 한번만 누르면 계좌조회까지 알아서 되네요.

 

●예수금상세현황 조회 함수 추가

예수금상세현황 조회를 하는 이유는 자동으로 매매를 하면 지금 예수금이 얼마고 정산되는 돈을 얼마인지 알고있어야

주식을 몇개를 매매할지 알 수 있기 때문입니다.

1. 키움증권에 데이터 요청(TR)

Form1.cs 의 Form1 클래스에 예수금상세현황요청 함수를 추가합니다.

//키움증권에 예수금상세현황을 요청(TR)을 한다.
public void 예수금상세현황요청()
{
    axKHOpenAPI.SetInputValue("계좌번호", cbo계좌.Text.Trim());
    axKHOpenAPI.SetInputValue("비밀번호", "");
    axKHOpenAPI.SetInputValue("비밀번호입력매체구분", "00");
    axKHOpenAPI.SetInputValue("조회구분", "3");

    int nRet = axKHOpenAPI.CommRqData("예수금상세현황요청", "OPW00001", 0,GetScrNum());

}

 

2. 이벤트로 데이터 수신

위에서 우리가 요청했던 데이터는 axKHOpenAPI_OnReceiveTrData 이벤트를 통해서 수신받게됩니다.

기존 코드에서 else if로 예수금상세현황요청을 추가했습니다.

private void axKHOpenAPI_OnReceiveTrData(object sender, AxKHOpenAPILib._DKHOpenAPIEvents_OnReceiveTrDataEvent e)
{
    if (e.sRQName == "주식주문")
    {
        string s원주문번호 = axKHOpenAPI.GetCommData(e.sTrCode, "", 0, "").Trim();

        long n원주문번호 = 0;
        bool canConvert = long.TryParse(s원주문번호, out n원주문번호);

        if (canConvert == true)
            txt원주문번호.Text = s원주문번호;
        else
            Logger(Log.에러, "잘못된 원주문번호 입니다");

    }
    // OPT1001 : 주식기본정보
    else if (e.sRQName == "주식기본정보")
    {
        Logger(Log.조회, "{0} | 현재가:{1:N0} | 등락율:{2} | 거래량:{3:N0} ",
               axKHOpenAPI.GetCommData(e.sTrCode, e.sRQName, 0, "종목명").Trim(),
               Int32.Parse(axKHOpenAPI.GetCommData(e.sTrCode, "", 0, "현재가").Trim()),
               axKHOpenAPI.GetCommData(e.sTrCode, "", 0, "등락율").Trim(),
               Int32.Parse(axKHOpenAPI.GetCommData(e.sTrCode, "", 0, "거래량").Trim()));
    }
    // OPT10081 : 주식일봉차트조회
    else if (e.sRQName == "주식일봉차트조회")
    {
        int nCnt = axKHOpenAPI.GetRepeatCnt(e.sTrCode, e.sRQName);

        for (int i = 0; i < nCnt; i++)
        {
            Logger(Log.조회, "{0} | 현재가:{1:N0} | 거래량:{2:N0} | 시가:{3:N0} | 고가:{4:N0} | 저가:{5:N0} ",
                axKHOpenAPI.GetCommData(e.sTrCode, "", i, "일자").Trim(),
                Int32.Parse(axKHOpenAPI.GetCommData(e.sTrCode, "", i, "현재가").Trim()),
                Int32.Parse(axKHOpenAPI.GetCommData(e.sTrCode, "", i, "거래량").Trim()),
                Int32.Parse(axKHOpenAPI.GetCommData(e.sTrCode, "", i, "시가").Trim()),
                Int32.Parse(axKHOpenAPI.GetCommData(e.sTrCode, "", i, "고가").Trim()),
                Int32.Parse(axKHOpenAPI.GetCommData(e.sTrCode, "", i, "저가").Trim()));
        }
    }
    //예수금상세현황 요청 추가
    else if (e.sRQName == "예수금상세현황요청")
    {
        int 예수금 = Int32.Parse(axKHOpenAPI.GetCommData(e.sTrCode, e.sRQName, 0, "예수금").Trim());
        int 출금가능금액 = Int32.Parse(axKHOpenAPI.GetCommData(e.sTrCode, e.sRQName, 0, "d+2출금가능금액").Trim());
    }
}

이제 예수금과 d+2출금가능금액을 얻어왔습니다.

지역변수로 놔두지말고 계좌클래스를 생성하여 예수금과 출금가능금액을 관리해야할 것 같네요.

자동으로 매매하면 예수금을 줄이고 d2출금가능금액도 변경을 해줘야하니까요.

Q : 왜 우리가 예수금, 출금가능금액을 매매할때마다 변경해줘야하죠?

A : 왜냐면 키움증권에 TR은 제약사항이 많습니다. 많은 TR요청을 사용할시 Open API 시스템 자체가 응답하지 않아요.

그래서 최소한으로 TR요청을 줄여야합니다.

public static class MyWallet
{
    int 예수금;
    int d2출금가능금액;
}
//예수금상세현황 요청 추가
else if (e.sRQName == "예수금상세현황요청")
{
    MyWallet.예수금 = Int32.Parse(axKHOpenAPI.GetCommData(e.sTrCode, e.sRQName, 0, "예수금").Trim());
    MyWallet.d2출금가능금액 = Int32.Parse(axKHOpenAPI.GetCommData(e.sTrCode, e.sRQName, 0, "d+2출금가능금액").Trim());
}

 

감사합니다.

반응형

댓글