AUTO TRADE/[대신증권] CYBOS PLUS

대신증권 CYBOS PLUS 프로그램 구현 (2) - 자동로그인 구현하기 ②

프로그램 구현 목표

  • CYBOS PLUS 자동 로그인 기능 구현하기 (바로가기 링크)
  • 접속을 시도하기 전에 접속 여부 구분하기 (현재 게시글)
  • 로그인 결과 확인하기 (현재 게시글)

지난 게시글에서는 프로그램이 실행되는 동시에 Cybos Plus를 실행시켜 서버에 접속하도록 하는 클래스인 `class login:`을 생성해주고 해당 클래스가 호출되면 자동적으로 접속이 이루어지는지에 대해 살펴보았다. 이번 게시글에서는 이미 접속이 되어 있는 경우에는 해당 클래스를 호출하지 않도록 하고, 접속 요청 후에는 접속이 성공했는지 그 여부를 판단하도록 하는 코드를 구현해보고자 한다.

 

(2) 접속을 시도하기 전에 접속 여부 구분하기

접속 여부를 확인할 수 있는 함수는 `class cybos:` 클래스 내부의 `self.cybos` 모듈이 갖고 있는 `_IsConnect()` 함수를 통해 확인할 수 있었다. 접속 여부를 구분하는 함수의 실행 결과로 1이 전달되면 서버와의 연결에 성공한 것이고 0이 전달되면 서버와의 연결에 실패한 것이었다. 다만 코드를 구현하기 전에 앞서 `_IsConnect()` 함수를 조금 수정해줘야 하는 부분이 있는데, 바로 해당 함수로부터 결과값을 전달받아야 한다는 것이다. 즉, `print()` 구문으로 되어 있는 부분은 그렇다 치고 우리는 접속 결과 여부를 `return`을 활용하여 그 결과값을 전달받아야 한다.

예를 들어, 아래와 같이 해당 함수의 인자로 전달된 값에 5를 더한 값을 반환하는 함수가 있을 때, `plus_5` 함수는 단순히 계산한 후에 그 값을 출력하고 끝나는 반면, `return_plus_5` 함수는 출력한 후에 그 결과값을 `return`하는 기능이 포함되어 있다. 이 둘의 차이점은 바로 '함수가 계산한 결과값을 우리가 전달받아 사용할 수 있는가 ?'이다.

def plus_5(value):
    result = value + 5
    print(result)
    
def return_plus_5(value):
    result = value + 5
    print(result)
    return result

 

아래와 같이 두 함수에 10을 전달해준 후, 그 결과값을 `result_value`라는 변수에 입력하여 그 결과값을 출력해보자. 아래의 결과값을 보면 어렵지 않게 확인할 수 있는데, 함수가 계산한 결과값을 `return`을 통해 반환해주어야만 우리가 그 값을 활용할 수 있다.

>>> result_value = plus_5(10)
15
>>> print(result_value)
None
>>> result_value = return_plus_5(10)
15
>>> print(result_value)
15

 

같은 논리에서 우리는 `_IsConnect()` 함수의 결과값에 있어서 `return`을 통해 서버와의 접속 여부가 어떻게 되었는지를 반환해주어야 한다. 아래와 같이 서버와의 연결에 성공한 경우에는 True를, 실패한 경우에는 False를 반환하도록 코드를 아래와 같이 변경해주도록 하자.
※ Line: 10, 13

## CpUtil.py ##
class CpCybos:
    def __init__(self):
        self.cybos = win32com.client.Dispatch("CpUtil.CpCybos")           ## COM 연결

    def _IsConnect(self):
        value = self.cybos.IsConnect
        if value == 1:
            print(f"[통신결과:{value}] 서버와의 연결에 성공했습니다.")
            return True
        elif value == 0:
            print(f"[통신결과:{value}] 서버와의 연결에 실패했습니다.")
            return False

그리고 다시 Boss.py 파일로 돌아와서, `self.cybos._IsConnect()` 부분을 단순히 실행하는 것 뿐만 아니라 그 결과값을 하나의 변수에 입력하도록 한 후에 그 변수를 한 번 출력해보도록 하자. 아래의 코드를 참고하면 되는데, 결과값을 입력할 변수 이름을 `result`으로 설정한 후에 `print()` 구문을 통해 `_IsConnect()` 함수의 결과값을 확인해보도록 하자. 서버에 접속이 되어 있다면 True를, 접속되어 있지 않다면 False를 반환해줄 것이다.
※ Line: 30, 31

## Boss.py ##
import win32com.client
from pywinauto import application
from COM import CpSysDib
from COM import CpUtil
from COM import CpTrade
from COM import DsCbo1

class login:
    def __init__(self):
        self.Id = ""
        self.Password = ""
        self.Cert = "*"
        self.run()

    def run(self):
        app = application.Application()
        executable_path = "C:\\DAISHIN\\STARTER\\ncStarter.exe"
        args = f" /prj:cp /id:{self.Id} /pwd:{self.Password} /pwdcert:{self.Cert} /autostart"
        app.start(f"{executable_path}{args}")

class cybos:
    def __init__(self):
        self.cybos = CpUtil.CpCybos()
        self.stockchart = CpUtil.CpStockCode()
        self.trade = CpTrade.CpTdUtil()
        self.codemgr = CpUtil.CpCodeMgr()
        self.stockmst = DsCbo1.StockMst()
        self.stockchart = CpSysDib.StockChart()
        result = self.cybos._IsConnect()
        print(result)

if __name__ == "__main__":
    cybos()

▶ 실행 결과 확인하기

더보기

[통신결과:1] 서버와의 연결에 성공했습니다.
True

 

그렇다면 우리는 왜 서버와 접속이 되어 있는지 여부를 확인한 후에 로그인을 시도해야 할까 ? 이에 대한 답은 간단하게도 접속되어 있는 상황에서 재접속을 시도해보면 된다. 아래와 같은 오류를 직면할 수 있을 것이다. 우리가 구현하고자 하는 기능이 기본적으로 자동 매매 프로그램임에도 불구하고 아래와 같은 팝업창이 떴을 때 우리가 직접 "예" 또는 "아니오"를 클릭해서 팝업창을 꺼주는 것보다는 사전에 서버와 연결되어 있는지를 확인한 후에 연결되어 있지 않다면 로그인을 시도하도록 하는 것이 합리적이기 때문이다. 

※ Line: 31~35

## Boss.py ##
import win32com.client
from pywinauto import application
from COM import CpSysDib
from COM import CpUtil
from COM import CpTrade
from COM import DsCbo1

class login:
    def __init__(self):
        self.Id = ""
        self.Password = ""
        self.Cert = "*"
        self.run()

    def run(self):
        app = application.Application()
        executable_path = "C:\\DAISHIN\\STARTER\\ncStarter.exe"
        args = f" /prj:cp /id:{self.Id} /pwd:{self.Password} /pwdcert:{self.Cert} /autostart"
        app.start(f"{executable_path}{args}")

class cybos:
    def __init__(self):
        self.cybos = CpUtil.CpCybos()
        self.stockchart = CpUtil.CpStockCode()
        self.trade = CpTrade.CpTdUtil()
        self.codemgr = CpUtil.CpCodeMgr()
        self.stockmst = DsCbo1.StockMst()
        self.stockchart = CpSysDib.StockChart()

        if self.cybos._IsConnect() == True: ## 연결되어 있는 경우
            pass
        elif self.cybos._IsConnect() == False:
            ## 로그인 함수를 실행하여 로그인 시작
            pass

if __name__ == "__main__":
    cybos()

이제 Line 34에서 로그인 함수를 실행할 코드를 작성해주면 되는데, 우리는 이미 `class login:`이라는 이름으로 로그인 기능을 수행하는 클래스를 생성해주었으므로 해당 클래스를 호출해주기만 하면 된다.
※ Line: 32, 35, 36

## Boss.py ##
import win32com.client
from pywinauto import application
from COM import CpSysDib
from COM import CpUtil
from COM import CpTrade
from COM import DsCbo1

class login:
    def __init__(self):
        self.Id = ""
        self.Password = ""
        self.Cert = "*"
        self.run()

    def run(self):
        app = application.Application()
        executable_path = "C:\\DAISHIN\\STARTER\\ncStarter.exe"
        args = f" /prj:cp /id:{self.Id} /pwd:{self.Password} /pwdcert:{self.Cert} /autostart"
        app.start(f"{executable_path}{args}")

class cybos:
    def __init__(self):
        self.cybos = CpUtil.CpCybos()
        self.stockchart = CpUtil.CpStockCode()
        self.trade = CpTrade.CpTdUtil()
        self.codemgr = CpUtil.CpCodeMgr()
        self.stockmst = DsCbo1.StockMst()
        self.stockchart = CpSysDib.StockChart()

        if self.cybos._IsConnect() == True: ## 연결되어 있는 경우
            print(f"로그인되어 있습니다.")
            pass
        elif self.cybos._IsConnect() == False:
            print(f"로그인되어 있지 않습니다. 로그인을 시도합니다.")
            login()
            pass

if __name__ == "__main__":
    cybos()

▶ 실행 결과 확인하기

더보기

[통신결과:0] 서버와의 연결에 실패했습니다.
[통신결과:0] 서버와의 연결에 실패했습니다.
로그인되어 있지 않습니다. 로그인을 시도합니다.

 

 


반응형
728x90

 

 

(3) 로그인 결과 확인하기

앞전에 살펴본 실행 결과를 보면 로그인을 시도한다는 문구까지만 출력되고 그 후에 로그인에 성공하였는지 성공하지 못했는지는 출력되지 않는 찝찝한 결과물을 보여주고 있다. 그렇다면 로그인이 성공되었다면 로그인이 성공되었다는 문구를 출력하도록 하는 기능을 구현할 예정이다. 이 때 가장 중추적인 기능을 수행하는 함수는 바로 `time.sleep()` 구문이다. 이 코드는 인자에 포함되어 있는 시간(단위: 초) 동안 동작을 멈추도록 하는 코드인데, `time.sleep(1)`을 사용하게 되면 해당 코드가 실행된 모든 구간에서 1초씩 멈춘 후에 다음 코드를 수행하게 된다. 아래의 코드를 참고해보도록 하자.

그렇다면 우리는 기본적으로 계속해서 로그인 여부를 확인해주어야 하는데, 그 기능은 `while True:`라는 코드 한 줄만으로 구현이 가능하다. 이 코드는 간단하게 말하면 `break`라는 구문이 작동되기 전까지 그 내부의 코드가 계속해서 동작하는 코드인데, 우리가 구현하게 될 코드를 간략하게 요약하자면 로그인되어 있지 않아서 로그인을 시도하고 그 로그인에 성공한 경우에만 `break`를 사용하도록 하면 된다. 
※ Line: 8, 40~44

실행 결과를 살펴보면 서버와의 연결에 실패했다는 문구와 함께 로그인을 시도한다는 문구가 출력된 이후, 1초마다 서버와의 통신 연결 여부를 확인하게 되므로 서버와의 연결에 실패했다는 문구가 1초마다 계속해서 출력되다가 서버와 연결에 성공한 시점에 "로그인되었습니다. 반복문에서 나갑니다."라는 문구가 출력되고 코드가 종료되는 것을 확인할 수 있다.

## Boss.py ##
import win32com.client
from pywinauto import application
from COM import CpSysDib
from COM import CpUtil
from COM import CpTrade
from COM import DsCbo1
import time

class login:
    def __init__(self):
        self.Id = ""
        self.Password = ""
        self.Cert = "*"
        self.run()

    def run(self):
        app = application.Application()
        executable_path = "C:\\DAISHIN\\STARTER\\ncStarter.exe"
        args = f" /prj:cp /id:{self.Id} /pwd:{self.Password} /pwdcert:{self.Cert} /autostart"
        app.start(f"{executable_path}{args}")

class cybos:
    def __init__(self):
        self.cybos = CpUtil.CpCybos()
        self.stockchart = CpUtil.CpStockCode()
        self.trade = CpTrade.CpTdUtil()
        self.codemgr = CpUtil.CpCodeMgr()
        self.stockmst = DsCbo1.StockMst()
        self.stockchart = CpSysDib.StockChart()


        if self.cybos._IsConnect() == True: ## 연결되어 있는 경우
            print(f"로그인되어 있습니다.")
        elif self.cybos._IsConnect() == False:
            print(f"로그인되어 있지 않습니다. 로그인을 시도합니다.")
            login()

            while True:
                if self.cybos._IsConnect() == False:
                    time.sleep(1)
                elif self.cybos._IsConnect() == True:
                    print(f"로그인되었습니다. 반복문에서 나갑니다.")
                    break

if __name__ == "__main__":
    cybos()

▶ 실행 결과 확인하기

더보기

[통신결과:0] 서버와의 연결에 실패했습니다.
[통신결과:0] 서버와의 연결에 실패했습니다.
로그인되어 있지 않습니다. 로그인을 시도합니다.
[통신결과:0] 서버와의 연결에 실패했습니다.
[통신결과:0] 서버와의 연결에 실패했습니다.
[통신결과:0] 서버와의 연결에 실패했습니다.
[통신결과:0] 서버와의 연결에 실패했습니다.
[통신결과:0] 서버와의 연결에 실패했습니다.
[통신결과:0] 서버와의 연결에 실패했습니다.
[통신결과:0] 서버와의 연결에 실패했습니다.
[통신결과:0] 서버와의 연결에 실패했습니다.
[통신결과:0] 서버와의 연결에 실패했습니다.
[통신결과:0] 서버와의 연결에 실패했습니다.
[통신결과:0] 서버와의 연결에 실패했습니다.
[통신결과:0] 서버와의 연결에 실패했습니다.
[통신결과:0] 서버와의 연결에 실패했습니다.
[통신결과:1] 서버와의 연결에 성공했습니다.
[통신결과:1] 서버와의 연결에 성공했습니다.
로그인되었습니다. 반복문에서 나갑니다.

이제 마지막으로 앞서 구현한 로그인 함수들을 `def _open_cybosplus(self):`라는 이름의 함수 안에 넣어서 캡슐로 만들어준 후에, 이 함수를 초기화 함수에서 호출하여 자동으로 Cybos Plus를 실행시키도록 하자.

## Boss.py ##
import win32com.client
from pywinauto import application
from COM import CpSysDib
from COM import CpUtil
from COM import CpTrade
from COM import DsCbo1
import time

class cybos:
    def __init__(self):
        self.cybos = CpUtil.CpCybos()
        self.stockchart = CpUtil.CpStockCode()
        self.trade = CpTrade.CpTdUtil()
        self.codemgr = CpUtil.CpCodeMgr()
        self.stockmst = DsCbo1.StockMst()
        self.stockchart = CpSysDib.StockChart()

        self._open_cybosplus()


    def _open_cybosplus(self):
        if self.cybos._IsConnect() == True: ## 연결되어 있는 경우
            print(f"로그인되어 있습니다.")
        elif self.cybos._IsConnect() == False:
            print(f"로그인되어 있지 않습니다. 로그인을 시도합니다.")
            login()

            while True:
                if self.cybos._IsConnect() == False:
                    time.sleep(1)
                elif self.cybos._IsConnect() == True:
                    print(f"로그인되었습니다. 반복문에서 나갑니다.")
                    break
if __name__ == "__main__":
    cybos()

class login:
    """CYBOS PLUS 실행 함수"""
    def __init__(self):
        self.Id = ""
        self.Password = ""
        self.Cert = "*"
        self.run()

    def run(self):
        app = application.Application()
        executable_path = "C:\\DAISHIN\\STARTER\\ncStarter.exe"
        args = f" /prj:cp /id:{self.Id} /pwd:{self.Password} /pwdcert:{self.Cert} /autostart"
        app.start(f"{executable_path}{args}")

 

 


728x90
반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.