모든 프로그램들은 Call Flow가 존재하며, 사용자 지향적인 프로그램일수록 사용자가 어떻게 프로그램을 사용해 나갈지, 예를 들면, 로그인부터 해서 특정 기능을 사용하기 위해 어떤 것들을 설정해야 하며, 얻어낸 결과를 어떻게 저장하고 프로그램을 종료하는지까지의 시나리오가 존재한다. 

 

프로그램 제작 전에 완성된 내용이지만, 나중에 사용자 매뉴얼 작성 시에 도움이 될 수 있도록 지금 기록을 해놓는 게 좋을 것 같다. 물론 Flow Chart 기반의 시나리오 정리이며, 필요할 경우 지속적으로 업데이트될 것이다.

 


L-ATS 사용자 시나리오

 

L-ATS 사용자 관점 시나리오

 

 

실은 어떤 프로그램이든 사용자 관점에서 정의하는 시나리오는 복잡하지 않다. 

사용자는 프로그램의 기능이 직관적이며 단순해야(단순하다는 어감이 조금 좋지 않은데 Simple하다가 의도하는 바와 가까운 단어다.) 잘 사용하게 된다. 

 

개발자라면 잘 알겠지만 단순해 보이는 하나하나의 과정마다 수가지의 예외처리와 백그라운드 프로세스 작업이 존재한다는 것을 알 것이다. 

사용자의 시선에서는 당연히 신경 쓸 필요 없다. 모든 기능이 오류 없이 정상적으로 처리되어야 하니 말이다.

즉, 위의 시나리오는 프로그램의 모든 기능이 정상적일 때의 시나리오이다. 

 

설계된 L-ATS 2.0의 기능은 크게 4가지로 구분된다. 

  1. 이베스트 증권 계좌 선택
  2. 스탑로스 조건 설정
  3. 자동 매매 시작
  4. 종목별 처리할 스탑로스 종류 선택

실제론 대부분의 자동매매 프로그램들이 1.~3.번 기능이 전부이다. 2.번 기능이 프로그램마다의 특징을 갖는 기능이며, 자동으로 매수하는 기능이 있는 프로그램도 있다. (L-ATS 1.0에도 존재했던 기능이나 2.0에서는 스탑로스만...)

 

기능 자체는 간단해 보이지만, 돈이 왔다갔다하는 프로그램이기에 얕은 지식으로 간단하게 만들 수 있는 프로그램의 종류는 아니다. 

기능 구현보다 Exception 처리에 더 많은 공을 들여야 한다. 

사용자는...더구나 GUI 환경에서의 사용자는 개발자가 예측하지 못한 돌발 행동을 많이 한다.

 

Posted by [ 브랜든 ]
,

라즈베리파이 3에 CentOS 설치 후, MariaDB, 그리고 Python3을 설치하려고 하는데...

디스크 용량 부족 메시지가 떳다.

 

???? 

 

내 SD카드는 분명 64G짜리인데....

설마 하는 마음에 Disk 사이즈를 확인해 보았다.

df -h 명령어로 OS 디스크 용량 확인.

응..?? root에 3.7GB로 잡혀있다. 나머지 나의 60GB는 어디로 사라졌느뇨....

 

이래저래 구글링 해보니... 최초 디스크 용량이 자동으로 작게 잡힌다고 하는데... 생각해보니 처음 CentOS 부팅했을 때 Desktop에 CentOS 설치했을 때와는 달리 파티션 설정하는 부분이 존재하지 않았었다. 

 

Partition을 다시 설정해야 할 듯하다. 


위에서 boot 공간이 '/dev/mmcblk0p1'로 잡혀 있을 것을 볼 수 있다.

즉, mmcblk0 중에서 p1(Partition1)이 해당 영역으로 잡혀있다는 것이다. 그럼 나머지 공간은....?

 

lsblk 명령어로 살펴보자.

'mmcblk0'의 partition 분리 정보.

boot 가 Partition 1, Swap이 Partition 2, 그리고 root가 Partition 3으로 잡혀있다. 

그리고 나머지 59.6 GB는 할당되지 않은 공간으로 되어있다. (참... 이런 것까지 수동으로 해보긴 처음...)

 

'parted /dev/mmcblk0' 명령어로 mmcblk0에 대한 Partition 작업 모드로 전환한다.

print free 실행 시 현재 할당된, 그리고 할당되지 않은 Partition 정보를 볼 수 있다.

 

소중한 59.2GB의 FREE 영역이 보인다.

구글링 해보니... 이미 할당되어 있는 root Partition(Partition 3)을 삭제하고! 다시 생성하는 방식인데... 이미 시스템 파일들이 잡혀있는 공간인데 괜찮을지 걱정이 되지만... 방법이 없으니 강행해야 한다.

 

'fdisk /dev/mmcblk0' 명령어로 partition 작업을 진행한다.

 

Linux에 해당하는 /dev/mmcblk0p3을 삭제하고 다시 생성해준다.
d(delete) > 3 명령어로 Partition 3이 삭제된 것을 확인한다.

이제 n(add a new) 명령어로 다시 partition을 잡아준다.

 

n(new) > 3 (partition number) > start block size > end block size를 입력해서 새로운 Partition을 만든다.

새로 만들어진 Partition 3 (/dev/mmcblk0p3)을 확인해 보면 용량이 대폭 늘어났다.

 

위 작업에서 중요한 건 Partition 3의 Start Block 값을 기존과 같이 Partition 2 (/dev/mmcblk0p2)의 다음 값으로 지정해야 한다는 것이다. (default가 2048로 되어 있기 때문에 무심코 Enter를 누르면 안 된다.)

 

이제 저장을 하면 재부팅을 하라는 경고문이 뜬다.

 

reboot을 하라는 경고문이 뜬다.

시스템 Reboot을 진행해볼까... 잘하고 있는 것인가... 자꾸 의문이 든다...

걱정과는 달리 재부팅이 잘 된다. 변경사항이 반영이 되지 않았으니... 당연히 재부팅엔 문제가 없었...

아직 /dev/root의 사이즈가 변경되지 않았다.

이제 resize2fs 명령어를 실행시켜 새로 할당한 partition 사이즈를 적용한다.

적용 후 15306168 block들이 늘어났다.

뭔가가 되어가는 거 같다.... 이제 용량이 정말 늘어났는지 확인해 보자.

54GB로 대폭 늘어난 /dev/root/ Partion 용량.

이제야 소중한 Disk 용량을 전부 사용할 수 있게 되었다.

 

 

Posted by [ 브랜든 ]
,

L-ATS는 한순간에 한 사람의 사용자(하나의 계정)만 사용할 수 있도록 운영할 예정이니 프로그램이 종료되는 시점까지 '사용자 정보'는 하나의 데이터 셋만 생성될 것이다. 

 

그럼 프로그램이 동작하는 동안 사용자는 어떤 정보들을 관리하여야 할까?

 

우선 기본 사용자 정보는 아래 두 가지 형태로 구분할 수 있다. 

  • L-ATS 사용자 정보
  • 이베스트 증권 사용자 정보

좀 더 Detailed 정보들을 나열해 보자.


[ L-ATS 사용자 정보 ]

 

 1. L-ATS 가입자 ID : 비밀번호 찾기와 연계하기 위해 E-Mail Type으로 정함.

 2. 가입자 Pricing Grade : L-ATS 가입자의 가격 정책 등급 정보.

 3. Auto Trading 여부 : 현재 자동 매매 처리 중인지 여부 정보.

 4. 현재 접속 단말 MAC : 한 계정당 한 명만 사용할 수 있도록 MAC 인증을 위한 정보.

 

[ 이베스트 증권 사용자 정보 ]

 

 1. 현재 접속 HTS 정보 : '모의투자' 또는 '실투자' 접속 서버 정보와 현재 접속 여부 정보.

 2. 이베스트 가입자 ID : 이베스트 증권 ID 정보.

 3. 현재 계좌 : 증권 사용자는 여러 개의 계좌를 가질 수 있기 때문에, 1개의 계좌를 선택하여 사용할 수 있음.


우선 이정도면 될 것 같다. 

 


 

사용자 정보는 프로그램이 시작된 순간부터 종료될 때까지 단 하나(!)만 존재하게 되므로 프로그램 어디에서도 사용할 수 있도록 Global 형태로 선언했다.

 

아래는 사용자 정보를 관리하는 Class다.

public class User_Info
{
    public static User_Info gUser_Info = new User_Info();

    public bool IsUserLogin;            // 프로그램 로그인 여부
    public bool IsAutoTrading;          // 자동매매 진행 여부

    private string Id;                  // L-ATS 사용자 ID
    private string Grade;               // 회원등급
    private string MacAddr;             // 현재 접속 단말 MAC Address

    public DateTime Last_Login;

    //---------------------------------------------------------------

    public bool IsHTSLogin;             // HTS 로그인 여부

    private string EbestId;             // 이베스트 ID
    private string UserName;            // 사용자 이름
    private string CurAccount;          // 현재 사용 계좌 번호

    // 생성자
    public User_Info()
    {
        IsUserLogin = false;
        IsAutoTrading = false;
        IsHTSLogin = false;
        
        Id = string.Empty;
        Grade = string.Empty;
        MacAddr = string.Empty;

        EbestId = string.Empty;
        UserName = string.Empty;
        CurAccount = string.Empty;
    }

    // 소멸자
    ~User_Info()
    {

    }
    
    ... 생략 ...
}

bool Type의 변수를 제외한 모든 정보들은 private으로 선언하여 Set/Get 함수를 사용하도록 했다. 

참고로 나는 변수의 초기화를 매우 중요하게 생각하는 개발자다. 

 

그리고 언제든 바로 프로그램 상의 사용자 상태 정보를 확인할 수 있는 메뉴를 만들었다. 즉, 위의 User_Info() 클래스의 정보를 확인하는 메뉴이다. 


 

'메인메뉴 > 사용자 정보'  메뉴에서 User_Info() 클래스 정보 표시

 

먼저 L-ATS 로그인 후 사용자 정보를 보면 아래처럼 알 수 있는 정보만 표시가 된다.

 

L-ATS 로그인 후 User_Info() 정보

 

회원가입시 입력했던 Database의 정보들과 로그인 시에 입력한 HTS Server 정보 (모의투자/실투자)가 표시된다. 

 

이베스트 HTS를 로그인하고 보유계좌까진 선택한 후 '사용자 정보'를 확인해 보자.

이베스트 HTS 로그인. 모의투자기 때문에 공인인증번호는 입력하지 않아도 된다.
이베스트 HTS 로그인이 정상 처리되면, 보유한 계좌의 목록을 확인할 수 있다.

 

이제 계좌의 목록 중 하나를 골라서 '선택' 버튼을 클릭하면 비로소 User_Info()의 모든 정보가 완성된다.

 

모든 정보가 채워진 User_Info(). 하단의 StatusBar에도 함께 표시하여 사용자 인지성을 향상시켰다.

 

사실 '사용자 정보' 메뉴는 디버깅 용으로 만들었던 건데... 메뉴가 되어 버렸다.

'Trading' 카테고리의 다른 글

[Trading] XingAPI - DevCenter 사용하기  (0) 2020.08.14
[Trading] L-ATS 사용자 시나리오  (0) 2020.08.02
[Trading] HTS 로그인 설계, 구현  (0) 2020.07.08
[Trading] 프로그램 로그인  (0) 2020.06.21
[Trading] 두번째 프로그램  (0) 2020.06.07
Posted by [ 브랜든 ]
,

처음 라즈베리파이를 구매했던 이유는 내 개인적인 개발 서버가 필요했기 때문이었다. 

C 컴파일이나 쉘 스크립트, 그리고 Python 정도만 돌아가면 됐었기에 라즈베리파이로도 충분했다.

(STT 처리 모듈 테스트를 위해 값 비싼 GPU도 있으면 좋겠지만...회사 서버를 사용하는 걸로...)

 

가끔 On-Premise 사업을 진행하면서 운영에 필요한 Utility들을 짬짬히 개발하거나 내 Library 소스를 관리하는데에 많이 이용한다. 

 

Database를 설치해두면 개인적으로 매우 유용한 '서버'로써의 라즈베리파이를 쓸 수 있다. 게다가 공유기 Port Fowarding과 외부 접근 가능 계정을 할당하여 사용한다면 언제 어디서는 사용할 수 있는 DB 서버가 된다. 

 

나는 가장 널리 사용하는 MySQL과 동일한 소스코드 기반으로 동작하는 MariaDB(무료니까...)를 설치해 사용하도록 해야겠다. 

 

https://ko.wikipedia.org/wiki/MariaDB

 

MariaDB - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. MariaDB는 오픈 소스의 관계형 데이터베이스 관리 시스템(RDBMS)이다. MySQL과 동일한 소스 코드를 기반으로 하며, GPL v2 라이선스를 따른다. 오라클 소유의 현재 불��

ko.wikipedia.org


[ Step 1 ] MariaDB yum 'repository' 등록

 

'repository'는 패키지들을 모아 놓은 저장소라고 생각하면 될 듯하다.  작업은 당연히 root 권한으로 해야한다.

 

/etc/yum.repos.d/MriaDB.repo 파일 생성

10.3 버전을 base로 설정했는데 원하는 버전으로 변경해도 된다.

 

[ Stem 2 ] yum 업데이트 실행

 

MariaDB.repo 파일 생성 확인 후, yum update 명령어를 실행

MariaDB repository 설정 추가 후 'yum update'를 실행하면 mariadb 관련 update가 진행됨을 볼 수 있다.

그리고 'yum repolist' 명령어로 MariaDB repository가 등록되어 있는지 확인한다.

 

중간에 mariadb 관련 repository 등록 상태를 확인할 수 있다.

 

[ Step 3 ] MariaDB 설치 및 확인

 

yum install mariadb-server 명령어로 MariaDB를 설치한다.

 

mariadb-server만 설치가 된다. 다른 블로그를 찾다보면 mariadb-client도 같이 입력하도록 한 사람들이 많다.

 

설치가 완료된 후에는 rpm -qa 명령어로 잘 설치가 되었는지 확인한다.

설치된 MariaDB 관련 패키지 목록.

 

[ Step 4 ] MariaDB 실행 및 접속 확인

 

systemctl 명령어로 MariaDB를 실행한다. 

 

'active' 상태의 MariaDB 확인.

 

root로 MariaDB 접속을 확인한다.

 

중간에 mysql.sock 관련해서 많은(?) 우여곡절이 있었지만, MySql과 MariaDB는 조금만 구글링해보아도 많은 솔루션이 있기 때문에 설치 자체는 어렵지 않다. 

 

다음 포스팅은 외부접속 계정 생성과 실제 외부 접속을 진행해 보도록 해야겠다. 

 

 

Posted by [ 브랜든 ]
,

그저 라즈베리파이3에 주식 자동매매 프로그램을 위한 DB 서버용 리눅스 설치를 하려고 했을 뿐인데

이런 글을 쓰고 있게 될 줄은 몰랐다. 

 

리눅스 재설치때 마다 블로그 보면서 다시 설치하면 되니 그냥 기록해 두자. 

 

나는 원래 Server-Side C언어 개발자였기 때문에 개인적으로 만들어서 갖고 있는 C언어 라이브러리들이 

조금 있다. (Logger, Statistic, DB Handler, Transaction Manager 등등...)

언제 사용할 기회가 있을지 모르니 C/C++ 컴파일러를 설치해 둬야겠다. 

(실은 지금도 실시간 STT(음성인식) 처리를 위한 RTP 패킷 캡쳐 모듈을 C++로 만들어놔서 C++ 컴파일러가 필요하긴 하다. 최근 동일 기능의 Python 모듈을 새로 설계해서 개발하고 있긴 하지만...)

 


 

Step 1.  Available Group 확인

 

현재 시스템의 Available Group에 Development Tools가 존재하는지 확인한다.

'Available Group'의 'Development Tools' 확인.

 

Step 2. Development Tools 설치

 

yum group install "Development Tools" 명령어로 C/C++ 컴파일러 관련 모든 패키지들을 한번에 설치한다.

 

설치할 패키지들이 매우 많다. 56개....

Step 3. 컴파일러 설치 확인

 

설치가 완료된 후에는 gcc --version 명령어로 설치된 버전을 확인한다. (gcc/g++ 동일하다.)

 

 

Step 4. 예제를 통해 소스 컴파일 하기

 

아래와 같이 C/C++ 언어 예제 소스를 만들어 컴파일을 해보자.

 

프로그래밍의 기본, "Hello, World!" 출력 프로그램 작성. 

 

컴파일~~

 

출력된 "Hello, World!" 문자열.

gcc를 통해 test.c 파일을 컴파일 하면, a.out 파일이 생성되고, 이 파일을 실행시키면 "Hello, World!"가 출력된다.

 

오랫만에 짧게 C언어 끄적였는데 (요즘엔 Python을 주로 쓰고 있어서...) 그래도 손가락이 기억하나 보다.

 

 

Posted by [ 브랜든 ]
,

라즈베리파이에 설치한 CentOS 7의 기본 셋팅을 하려고 한다. 

 

실은 이미 한번 진행했다. minimal 버전을 설치했기 때문에...

결국 실패하고...아니 포기하고....(하나하나 설정해 주는게 이렇게 빡셀 줄이야...)

다시 GNOME 버전으로 설치했다.

 

2020/07/12 - [Whatever] - 라즈베리파이(Raspberry-Pi) 3B+에 CentOS 7 설치하기

 

라즈베리파이(Raspberry-Pi) 3B+에 CentOS 7 설치하기

작년에 구매하여 간이 서버로 사용하고 있는 '라즈베리 파이'가 하나 있다. 개인적인 개발 서버가 필요하여 구매하였고, 집 공유기에 물려 365일 24시간 돌아가고 있는 아주 고마운 녀석이다. 이 �

brandon-dev.tistory.com

 

어찌나 편하던지...

친절하게 X window로 바로 부팅해준다. 

 

라즈베리파이에서 실행된 X-Window

먼저 root 비번부터 변경해 보자. 

 

su - passwd 명령어를 통해 root의 비밀번호를 변경한다. 참고로 초기 root 비밀번호는 'centos'로 되어 있다. 

 

다음은 yum 의 update 이다. 

 

yum update는 X-Window에서 'Application Update' 항목을 통해 진행할 수도 있고, 콘솔에서 'yum update -y' 명령어를 사용해서 진행할 수도 있다. 콘솔의 경우 당연히 root 권한으로 실행해야 한다.

 

나는 X-Window에서 바로 OS update 알림이 떠서 실행한 후에, 콘솔에서 다시 update를 실행했다. (당연히 콘솔에서는 설치되는게 없었다.)

Hostname을 변경해 볼까. Default 값인 'localhost'가 썩 맘에 들지 않는다. 

라즈베리파이니까 'raspberry'로 바꿔 보자.

 

방법 1. hostname 명령어

hostname 명령어를 사용하여 raspberry로 바꿨지만...OS 재부팅을 하면 다시 초기화 된다. 

 

방법 2. /etc/sysconfig/network 파일 수정

해당 파일에 HOSTNAME 필드가 없다면, 추가해주면 된다. 재부팅을 해보자.

엇...변경안됐다....

CentOS 7에서는 아래 방법으로 변경해야한다.

 

방법 3. hostnamectl set-hostname 명령어 사용

귀찮지만...다시 재부팅해보자.

이제 변경된 Hostname으로 표시됨을 확인할 수 있다. 

Posted by [ 브랜든 ]
,

작년에 구매하여 간이 서버로 사용하고 있는 '라즈베리 파이'가 하나 있다.

 

개인적인 개발 서버가 필요하여 구매하였고, 집 공유기에 물려 365일 24시간 돌아가고 있는 

아주 고마운 녀석이다. 

이 녀석 덕분에 사업 진행에 있어 필요한 간단한 유틸이나 배치 프로그램을 어디서든, 생각날 때마다 바로바로

개발하고 테스트할 수 있어서 많은 시간을 절약할 수 있었다. 

 

처음에는 CentOS가 설치되지 않는 줄 알고...(처음 샀을때 우분투MATE 얘기만 나와서...)

우분투MATE를 설치하여 사용하고 있었는데

최근 이녀석을 포맷할 일이 생겨 이왕 설치할거 익숙한 CentOS를 설치하기로 했다. 


 

 

[ 라즈베리 파이에 설치 가능한 CentOS 찾기 ]

 

https://wiki.centos.org/action/show/Manuals/ReleaseNotes/CentOS7.2003?action=show&redirect=Manuals%2FReleaseNotes%2FCentOS7

 

Manuals/ReleaseNotes/CentOS7.2003 - CentOS Wiki

Manuals/ReleaseNotes/CentOS7.2003 (2020-06-01 21:42:53에 TrevorHemsley가(이) 마지막으로 수정)

wiki.centos.org

위에 링크에서 '찾기' -> RaspberryPi를 입력하면 라즈베리파이용 CentOS가 보이게 된다.

 

라즈베리 파이 3용 CentOS. 중간에 URL 부분으로 들어가면 된다.

참고로 CentOS는 아직 라즈베리파이 3에서만 설치되는 것 같다. 

라즈베리파이 4에 설치하려는 블로거를 본적이 있는데, 지금은 어떨지 모르겠지만 그때는 실패했었다는 걸 봤었다.

 

라즈베리 파이용 CentOS Minimal로 설치한다.

 

나는 부팅 USB 만들때 주로 'Rufus'를 사용하는데, 여러가지 프로그램들이 있겠지만 내가 생각하기엔 이 프로그램이 가장 편하다. 

 

Rufus로 마이크로SD 카드에 CentOS 굽기.

이제 라즈베리파이 3B+에 USB를 꽂고, 전원을 껴보자.

별 다른 조작 없이 USB를 먼저 꽂고 전원만 꽂으면 자동으로 설치를 시작한다.

라즈베리파이에 CentOS 설치 화면

정상적으로 설치가 잘 되어가고 있다. (캡쳐가 안되서....아니 할 줄 몰라서...사진으로...)

 

CentOS 설치 후 로그인 완료 화면

설치가 완료 되면 로그인 화면이 뜨게 되고 minimal 설치라 사전에 사용자 정보를 등록하지 않아

root 계정으로 로그인 해야한다. 

  • 계정 : root

비밀번호  : centosCentOS 7 설치는 완료 되었고...minimal 설치 후 필수 설치 요소들은 다음 포스팅에서

다시 시작해야겠다.

 

근데 아래처럼 메시지가 계속 찍힌다...

전력부족...

지금 사용하는 놈은 5V / 2A인데...

우분투 사용할때는 문제 없었는데 CentOS가 전력을 더 많이 먹네...

 

사실 라즈베리파이 3의 권장 어댑터는 5V / 3A 다. 바로 새로 구매해야겠다.

 

 

Posted by [ 브랜든 ]
,

이베스트에서 제공하는 XingAPI에 의한 로그인 기능은 키움API에서 제공하는 기능과는 사뭇 다르다.

 

먼저 키움API의 경우에는 로그인 할때 키움 HTS에서 로그인하는 것과 같은 방식을 제공한다.

로그인과 동시에 HTS 서버에 접속하고 업데이트 버전이 있을 경우 업데이트를 진행하고 그 다음 로그인까지

완료하는 과정을 거친다.

 

L-ATS v1.0을 통해 확인해 보자.

 

'로그인' API를 호출하면 위와 같이 키움 HTS 로그인 화면을 제공한다. 

 

이베스트 XingAPI는 'HTS 서버 연결'과 'HTS 로그인'이 별개로 동작한다.

즉, HTS 서버 연결 상태를 고려하여 로그인/로그아웃 처리를 진행해야 한다. 

물론 HTS 서버에 연결이 되어야 로그인이 될 것이다. 아래 두 경우는 분명 다르게 동작해야 한다.

 

  • 서버가 연결되어 있지 않은 상태에서의 로그인/로그아웃 시도
  • 서버가 연결되어 있는 상태에서의 로그인/로그아웃 시도

간단해 보이지만 쉽게 생각할 수 없는 부분이다. 

 

이베스트 API의 경우 사용자 Form을 이용해서 별도의 로그인이 필요하다.


[ 대략적인 동작 과정 ]

 

1. 프로그램 실행 후 먼저 프로그램 로그인을 시도한다.

 

2. '이베스트 HTS 서버' 연결을 시도한다.

   2-1. 연결이 완료 될 경우, 해당 연결 서버의 정보를 표시한다.

   2-2. 연결이 되지 않을 경우, 환경 설정 값에 의해 서버 연결을 재시도 한다.

      2-2-1. 환경 설정 값에 의한 재연결 시도 횟수 초과 시 자동으로 프로그램을 종료한다.

 

3. '이베스트 HTS 서버' 연결을 별도로 관리한다.

   3-1. HTS 서버와의 연결 상태를 주기적으로 확인하고, 연결 유실 시 재연결을 시도하도록 관리한다.

   3-2. 화면 한편에 현재 HTS 서버와의 연결 상태를 한번에 확인 할 수 있도록 표시한다.

 

LOGIN Flow Chart

 

가장 신중하게 생각해야할 부분은 'Connection 관리' 부분이다. 

 

네트워크 개발을 하던 첫 회사에서 'Connection 관리'가 생각보다 단순하지 않고 쉽지 않다는 것을 많이 느꼈다.

지금 로직을 구성한다 해도 100% 완벽하게 할 수 있을지 의문이다.

 

Connection 관리는 아래 두 개의 환경 설정 값에 의해 동작하도록 해야한다.

  • Connection Check Interval (확인 시간 간격)
  • Connection Check Count (최대 확인 횟수)

솔직히 Connection 관리는 실시간(Realtime)성이 가장 중요한 시스템에서 필수적인 것이지만

Trading 시스템에서는 크게 중요하지 않을 수도 있다. 

때문에 'HTS 로그인' 상태에서 'HTS 서버' Connection이 끊길 경우(네트워크 장애 등) 프로그램을 자동 종료하여도 크리티컬하진 않을 것이다.

 

'L-ATS 로그인 -> HTS 접속 -> HTS 로그인' 까지 완료된 화면.

 

보유 계좌 리스트 조회 완료.

다음 포스팅은 '자산현황' 조회와 '잔고현황' 불러오기가 될 예정이다.

'Trading' 카테고리의 다른 글

[Trading] L-ATS 사용자 시나리오  (0) 2020.08.02
[Trading] 사용자 정보 구조  (0) 2020.07.18
[Trading] 프로그램 로그인  (0) 2020.06.21
[Trading] 두번째 프로그램  (0) 2020.06.07
[Trading] 첫번째 프로그램  (0) 2020.05.24
Posted by [ 브랜든 ]
,

C언어만 사용하던 나는 솔직히 OOP 개념이 익숙하거나 크게 와 닿지 않는다.

 

중복된 기능의 함수나 DB Handler, Logger 등의 기능 단위를 구분할 수 있는 것들을 모듈화하여

Library 형태로 만들어 컴파일 할 때 추가하여 사용하곤 했다. 

 

C#에서는 하나의 프로젝트 안에 여러 클래스를 생성하여 사용하는 것 같으니 방법을 정리해 보자.

 

delegate 테스트했던 프로젝트에 추가해서 진행하면 좋을것 같다.

2020/06/20 - [C#] - [C#] delegate, 폼 간의 DATA 공유

[C#] delegate, 폼 간의 DATA 공유

Trading 시스템을 내가 아닌 제 3자의 사용자적 입장에서 사용하도록 시뮬레이션 해 보았을 때 자식 Form을 새로 띄워서 값을 입력 받거나 확인할 수 있게 하는 작업이 많이 필요하단 것을 알게 되��

brandon-dev.tistory.com

Form2에서 입력했던 '아이디'와 '비밀번호'를 Form1에서 바로 출력하지 않고

새로운 클래스 파일(.cs)의 객체에 저장한 후에 그 값을 읽어와서 출력하는 방법으로 진행해 보자.

 

오른쪽 솔루션 탐색기에서 프로젝트 명의 오른쪽 클릭 후 [ 추가(D) ] - [ 새 항목(W) ]을 선택한다.

 

 

프로젝트 오른쪽 클릭 - [ 추가(D) ] - [ 새 항목(W) ]

 

 

클래스를 선택 후에 입력할 사용자 정보를 관리할 'User_Info.cs' 파일을 추가한다.

 

 

User_Info.cs 파일 추가

 

User_Info Class는 ID와 Password, 두 개의 변수를 갖고, 각각의 값을 Set/Get하는 함수를 갖게 될 것이다.

 

ID와 비밀번호는 사용하는 Class에서 직접 접근할 수 없도록 'private' 접근 제한자를 사용하고, 각각의 값을 Handling 할 수 있는 'public' 함수를 만들어 사용할 수 있도록 한다. (이게 객체지향 방법이라는데...나는 익숙치 않아서....Anyway)

 

[ User_Info.cs ]

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace delegate_test
{
    class User_Info
    {
        private string Id;             // 사용자 ID
        private string Password;       // 사용자 비밀번호

        // 생성자
        public User_Info()
        {
            Id = string.Empty;
            Password = string.Empty;
        }

        public void SetId(string Id)
        {
            this.Id = Id;
        }

        public string GetId()
        {
            return this.Id;
        }

        public void SetPassword(string Password)
        {
            this.Password = Password;
        }

        public string GetPassword()
        {
            return this.Password;
        }
    }
}

참고로 나는 변수의 초기화를 굉~~장히 중요하게 생각하는 개발자다. (생성자에서 변수 초기화는 무조건 필수!!)

 

이제 User_Info Class를 어떻게 사용하는가...

두 가지의 방법이 있는데, 하나는 User_Info Class 내에 static 객체를 하나 생성해두고 다른 곳에서 호출해서 쓰는 방식이고 다른 하나는 User_Info Class를 사용할 곳에서 객체를 직접 생성해서 사용하는 방식이 있다. 

 

< 방법 1> - Static 객체

[User_Info.cs]

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace delegate_test
{
    class User_Info
    {
        // static 객체
        public static User_Info gUser_Info = new User_Info();

        private string Id;             // 사용자 ID
        private string Password;       // 사용자 비밀번호

        // 생성자
        public User_Info()
        {
            Id = string.Empty;
            Password = string.Empty;
        }

        public void SetId(string Id)
        {
            this.Id = Id;
        }

        public string GetId()
        {
            return this.Id;
        }

        public void SetPassword(string Password)
        {
            this.Password = Password;
        }

        public string GetPassword()
        {
            return this.Password;
        }
    }
}

어디서든 접근 가능하도록 public으로 만든 static 객체를 만들어 둔다.

 

사용하는 방법은 간단하다.

User_Info 객체를 사용하고 싶은 곳에서 [클래스명].[객체명].[함수/변수]와 같은 형태로 사용하면 된다.

[Form1.cs]

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;

namespace delegate_test
{
    public delegate void LoginGetEventHandler(string id, string password); // 자식 Form EventHandler

    public partial class Form1 : Form
    {
        static string static_id = "brandon";
        Form2 Child = new Form2(static_id);

        public Form1()
        {
            InitializeComponent();
            Form2.LoginGetEvent += new LoginGetEventHandler(this.Login_Process); // EventHandler 등록
        }

        private void 로그인ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Child.Owner = this;
            Child.ShowDialog();                     
        }

        private void Login_Process(string id, string password) // Event 발생 시, 처리할 함수 선언
        {
            // User_Info 객체에 입력 받은 정보 저장
            User_Info.gUser_Info.SetId(id);
            User_Info.gUser_Info.SetPassword(password);


            // User_Info 객체에서 값 가져오기
            string test_result = string.Empty;
            //test_result = String.Format("ID : {0}, PW : {1}", id, password);
            test_result = String.Format("ID : {0}, PW : {1}", User_Info.gUser_Info.GetId(), User_Info.gUser_Info.GetPassword())
            textBox1.Text = test_result;  // 자식 Form에서 수신한 값 표시
        }
    }
}

 

이전과 동일하게 비밀번호를 'asdf1234!@#$'로 입력 후 로그인 버튼 클릭

 

전과 동일하게 아이디랑 비밀번호가 출력되면 정상적으로 User_Info Class를 사용하는 셈.

 

 

자식 Form에서 입력한 값을 부모 Form에서 받아 User_Info 객체에 Set/Get 후 출력 

 

 

사용자 정보의 경우, 프로그램내에서 단 하나만(!) 존재하는 것이기에 위의 예제처럼 static 객체로 선언해서 쓰는것이 좋을 것 같다. 상황에 따라 여러개의 객체가 필요한 경우는 아래처럼 사용하면 된다.

 

[Form1.cs]

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;

namespace delegate_test
{
    public delegate void LoginGetEventHandler(string id, string password); // 자식 Form EventHandler

    public partial class Form1 : Form
    {
        // User_Info 객체 생성
        User_Info gUser_Info = new User_Info();

        static string static_id = "brandon";
        Form2 Child = new Form2(static_id);

        public Form1()
        {
            InitializeComponent();
            Form2.LoginGetEvent += new LoginGetEventHandler(this.Login_Process); // EventHandler 등록
        }

        private void 로그인ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Child.Owner = this;
            Child.ShowDialog();                     
        }

        private void Login_Process(string id, string password) // Event 발생 시, 처리할 함수 선언
        {
            // User_Info 객체에 입력 받은 정보 저장
            gUser_Info.SetId(id);
            gUser_Info.SetPassword(password);


            // User_Info 객체에서 값 가져오기
            string test_result = string.Empty;
            //test_result = String.Format("ID : {0}, PW : {1}", id, password);
            test_result = String.Format("ID : {0}, PW : {1}", gUser_Info.GetId(), gUser_Info.GetPassword());
            textBox1.Text = test_result;  // 자식 Form에서 수신한 값 표시
        }
    }
}

 

Posted by [ 브랜든 ]
,

앞서 말한바와 같이 이베스트의 XingAPI는 서버 연결과 HTS 연결이 별로도 동작한다. 

때문에 L-ATS 프로그램을 사용하기 위해서는 아래 두 가지 로그인 절차를 거치게 설계했다.

  • Step 1. L-ATS 프로그램 로그인
  • Step 2. 이베스트 HTS 로그인

번거로울 수 있을 것이라 생각할 수도 있겠지만, 이베스트 XingAPI의 로그인 구조와

내가 추구하는 (아무나 내프로그램을 사용할 수 없는...?) 방향과 딱 맞아 떨어졌다 생각할 수 있겠다.

 

L-ATS 첫 실행 화면

지난 '두번째 프로그램' 초기화면 설계와 조금 달라진 모습을 볼 수 있다. 

 

우선, 프로그램 실행과 동시에 'L-ATS 로그인' 화면을 제공하여 프로그램 사용자 로그인과 동시에 

이베스트 HTS 서버 연결을 선택하도록 했다. (덕분에 프로그램 사용자 정보도 관리해야할 것 같다.)

 

먼저 구현된 각 화면의 표시 정보를 보자. (기능이 구현되는 순으로 계속 설명을 써야겠다.)

  1. 사용자 정보 : L-ATS 등록 사용자 정보
  2. HTS : 실시간 이베스트 HTS 연동 상태 표시. 빨 : Disconnect, 녹 : Connected. 
  3. 시작 버튼 : HTS 로그인 후 계좌를 선택해야 하므로, ATS의 모든 기능은 이 버튼이 눌린 시점부터 시작된다.
  4. 알림 : 프로그램에서 Event 발생 시, 텍스트로 표시해 준다. (예] 로그인, 매수, 매도 등)
  5. 하단 Status Bar : 이베스트 HTS 사용자 정보 표시

우선 로그인을 해보자.

내 계정은 이미 등록이 되어 있는 상태이며, 추후 사용자 관리관련 포스팅 예정이다.

ID와 비밀번호를 입력 후, 모의투자/실투자 선택.

그리고 로그인 버튼을 누르면 다음과 같은 L-ATS 시작 화면이 된다.

L-ATS 사용자 로그인 및 이베스트 HTS 접속 상태.

L-ATS 프로그램 사용자의 정보가 왼쪽 상단에 표시되고, 실시간 이베스트 HTS 접속 상태가 'HTS' 부분에 빨간색->초록색으로 표시가 된다. '모의투자'를 선택했을 경우 '모투', '실투자'를 선택했을 경우 '실투'라고 표시된다.

그리고 '알림' 부분에 현재 발생한 로그인 이벤트에 대한 내용이 표시된다. 

여기까지는 아직 이베트스 HTS에 로그인 하긴 전 상태라 계좌정보, 자산현황 등을 알 수 없다. (다음 게시물 예정.)

 

자동 매매 프로그램에 있어서 HTS 연결은 매우 중요하다. 

정전, 네트워크 장애 등등. 어떠한 이유에 있어 프로그램이 돌아가고 있는 상태에서 HTS 연결만 끊기는 경우가 발생할 수 있으므로, HTS 연결 상태를 지속적으로 확인(Heart-Beat)하고 재연결(Reconnect)를 할 수 있도록 개발해야하는 것이 기본이다. 이건 Database 서버와의 연결도 마찬가지이다. 

 

L-ATS v1.0 때보다 많은 기능이 설계에 들어가고 있어...매우 정신이 없다...

 

그래도 재밌는걸 어떡하나 싶다...

 

만들다보니 회원가입 절차가 필요해져서 '비밀번호'는 당연히 입력 즉시(나도 알 수 없도록) 암호화하여 DB에 저장하도록 해야겠다 생각했지만, 이베스트 XingAPI 특징상 HTS 로그인시에 아이디/비번/공인인증서비번을 입력 받도록 되어있다.

 

보안에 굉장히 취약할 수도 있는 부분이라 이 부분을 어떻게 해야 사용자들이 안심하고 사용할 수 있을지 고민이다. 

아니면....내가 예상하는 것과 다를 수도 있고....

'Trading' 카테고리의 다른 글

[Trading] L-ATS 사용자 시나리오  (0) 2020.08.02
[Trading] 사용자 정보 구조  (0) 2020.07.18
[Trading] HTS 로그인 설계, 구현  (0) 2020.07.08
[Trading] 두번째 프로그램  (0) 2020.06.07
[Trading] 첫번째 프로그램  (0) 2020.05.24
Posted by [ 브랜든 ]
,