직장인에게 유용한 사이트 모음

<직장인에게 유용한 사이트 모음 - Ver2020>

직장내일 : https://www.facebook.com/jikjangnaeil (직장인 커뮤니티 - 유머, 이벤트, 할인 정보 등)
인생공부 : https://www.facebook.com/인생공부-1927599617465292 (고영성/신영준님이 운영하는 인생상담 채널)
연직모: http://www.salary-up.kr/ (직장인 커뮤니티 - 연봉 높여가는 직장인들 모임, 연봉UP/재테크/투잡 중심)
고민해우소 : https://cafe.naver.com/smartphonefamily (업무 외 고민 상담하기 좋은 분노해소 커뮤니티)
성남산업진흥원 : http://magazine.snventure.net/main.asp(전자잡지들을 무료로 볼 수 있음)
대한상공회의소 전자매거진 : http://magazine.korcham.net/main.asp(전자잡지들을 무료로 볼 수 있음)
직장인 탐구생활 : https://cafe.naver.com/workee(직장인 커뮤니티 - 네이버 최대 직장인 커뮤니티, 일상 중심)
월급쟁이 부자들 : https://cafe.naver.com/wecando7(재테크 커뮤니티 - 네이버 재테크 커뮤니티)
페이퍼슨 : https://cafe.naver.com/paperson(다양한 문서 서식을 구할 수 있는 네이버 카페)
네이버 아름다운 한글문서 서식 : https://hangeul.naver.com/2014/document (네이버가 제공하는 문서 서식 사이트)

픽사 베이 : https://pixabay.com/ko/ (무료 고화질 이미지를 구할 수 있는 사이트)
unsplash : https://unsplash.com/ (무료 고퀄리티 이미지를 구할 수 있는 곳)
아이콘 파인더 : https://www.iconfinder.com/ (무료 아이콘을 구할 수 있는 사이트. 검색 조건의 Free를 이용)
The Noun Project : https://thenounproject.com/ (무료 아이콘을 구할 수 있는 사이트. royalty–free)
눈누 : https://noonnu.cc/ (무료한글폰트를 구할 수 있는 사이트)
네이버 나눔고딕글꼴 : https://hangeul.naver.com/2017/nanum (네이버가 제공하는 나눔고딕 폰트)
이미지 파일 용량 : http://imgpresso.co.kr/ (웹 상에서 이미지 용량을 줄여주는 서비스를 제공함)
이미지 변환 : https://allinpdf.com/kr/convert/fileconvert/fileconvert-start-image (pdf, jpg, png, gif, tiff 간 변환 제공)
=> 이미지 변환은 구글에 xxx to xxx로 검색해보면 다 나옴.

픽슬러 : https://pixlr.com/pro/editor (웹 상의 이미지 편집기)
BackGround Burner : https://burner.bonanza.com/ (이미지의 배경을 투명하게 만들어 줌. png 파일 제작 유용)
imgur : https://imgur.com/vidgif (비디오를 이미지로 변환해 주는 사이트)

친절한 혜강씨 : http://leehyekang.com/ (PPT 만들기 강좌)
프레젠테이션 매거진 : http://www.presentationmagazine.com (PPT 서식을 구할 수 있는 곳)
슬라이드 쉐어 : http://www.slideshare.net (PPT 서식을 구할 수 있는 곳)
하늘지기 베가스 영상공방 : https://blog.naver.com/7andsoul (영상편집 관련 정보들이 많은 곳)

구글 번역 : http://translate.google.com/ (할 말이 없음. 그냥 필요.)
네이버 어학사전 : https://endic.naver.com/krenEntry.nhn?sLn=kr&entryId=21e6235c79ba4abbba46b23934c1f94f

<업무에 필요한 무료 소프트웨어(회사에서도 무료)>

알캡쳐 : https://www.altools.co.kr/download/alcapture.aspx
(알 시리즈를 그리 선호하진 않지만 네이버캡쳐 서비스가 중단되었기에 설치하여 사용. 무료 캡쳐 프로그램들은 큰 차이 없음)

Foxit PDF Reader : https://www.foxitsoftware.com/kr/downloads/
(PDF Printer. 문서를 PDF로 출력할 때 사용하는 프로그램)

Notepad++ : https://notepad-plus-plus.org/download
(텍스트 편집기. 기능이 굉장히 많음.)

반디집 : https://www.bandisoft.com/
7-Zip : https://www.7-zip.org/
(개인적으로는 빵집을 추천하지만 개발 중단되었으므로 두 개 도구 추천)

FileZilla : https://filezilla-project.org/
(FTP Client. 아마 대부분 이것을 사용하고 있지 않을까 싶다. FTP Server도 제공함)

SMemo : http://www.smemo.co.kr/
(윈도우용 포스트잇. 점점 광고가 늘어나고 있긴 하지만 기능도 같이 개발되는 중)

Photoscape : http://www.photoscape.org/ps/main/index.php
(무료 도구 중 강추하는 프로그램. 이미지 편집과 관련하여 다양한 기능을 제공한다)

Unlocker : https://unlocker.kr.uptodown.com/windows
(종료되지 않는 프로세스들을 찾아서 Kill 해주는 프로그램)

DaView : http://datools.kr/Down7_1.htm
(이미지 뷰어 + Hwp 뷰어를 포함하고 있다. HWPViewer를 따로 갈 필요가...)

Putty : https://www.putty.org/
(원격 Shell 접속 프로그램)

에버노트 : https://evernote.com/intl/ko/
(노트 필기용 프로그램. 요새는 조금 힘이 떨어져 가는 듯하지만...)

Slack : https://slack.com/
(업무 협업 도구. 팀 워크 올리기에 유용한 도구)

Virtual Box : https://www.virtualbox.org/
(가상 공간을 제공하여 별도 OS를 설치할 수 있도록 해주는 프로그램. 확장팩은 유료)

UltraVNC : https://www.uvnc.com/
(원격 제어 도구. VNC Server가 설치된 PC에 접속해서 화면을 미러링 한 상태에서 제어 가능)

UltraViewer : https://ultraviewer.net/en/
(원격 제어 도구. VNC Server와 비슷. Team Viewer에 비해 단점은 파일전송이 되지 않음)

WinMerge : http://winmerge.org/?lang=en
(Text 파일 병합기. 다른 점을 비교해주고 통합할 때 유용한 도구)

PDFSAM : https://pdfsam.org/
(PDF 파일을 쪼개거나 합칠 때 사용하는 도구)

Gimp : https://www.gimp.org/
(포토샵 무료 버전이라고 많이 소개 되지만 사실 많이 부족함. 간단한 이미지 편집은 다른 도구를 쓰는 듯)

Xmind : http://www.xmindkorea.net/download.asp?code=3
(무료 마인드맵 프로그램)

http://www.hantools.co.kr/sub_index.asp?dcode=d&pcode=o
(알툴즈와 비슷한 느낌의 무료 프로그램들을 제공하는 사이트)

<직장인에게 유용한 앱>
블라인드 : 익명 커뮤니티 제공. 분노발생 주의
리멤버 : 명함을 찍으면 알아서 내용을 저장해주는 앱
슬랙 : 위에 설명한 슬랙의 모바일 버전
에버노트 : 위에 설명한 에버노트의 모바일 버전
푸시불렛(PushBullet) : 스마트폰의 메시지들을 PC에서 확인가능 한 앱. 특히 SMS 문자를 받고 보내기에 매우 유용함.
무음무음 : 기본 카메라에 연동되어 카메라 셔터 소리를 없애줌.
깜박하지마 : 자꾸 깜박하는 분들을 위한 유용한 앱
금연시작 : 금연하면서 아낄 수 있는 돈, 몸의 변화 상태를 위젯으로 알려줌.

Rmarkdown 에서 html출력물, 컬러글씨 인쇄하기

Rmarkdown은 보고서 작성을 위해 매우 훌륭한 툴이다.

  • 보통 outfile을 html 로 정하고 이를 pdf로 변환하여 사용한다.
  • 이 경우 그래프나 이미지는 컬러로 인쇄되는데 글씨는 흑백으로 변환되어 출력된다.
  • 이는 Rmarkdown에서 출력포멧을 흑백으로 바꾸어주는 스타일 코드를 기본으로 심어져 있기 때문이다.
  • 만일 프린터로 출력할 경우도 컬러로 인쇄하고자 한다면 현재로서는 출력물인 html의 소스코드를 수정해야 한다.
    - @media print {} 항목을 모두 삭제하여야 하는데

    • 그러기 위한 쉬운 방법 중에 하나는 @media 코드를 일괄적으로 삭제하는 방법
  • Rmarkdown 에서 print style 옵션을 설정하는 기능이 있을 듯 한데 아직 못 찾고 있다.

OpenAPI+ 메뉴얼 – 조회 및 실시간 데이터 처리

조회와 실시간 데이터 처리

[조회처리(조회요청)]

OpenAPI가 제공하는 데이터중에서 원하는 데이터를 서버에 요청해서 가져오는 것을 말하는데 TR(Transaction)단위로 처리됩니다. TR이란 서버와 데이터를 주고받을때 정의한 약속된 규약이며 입력부분(Input)과 데이터를 수신하는 출력부분(Output)을 가지고 있습니다. 입력부분은 요청하는 데이터에 따라 입력갯수(입력항목)가 달라지며 출력부분은 보통 데이터갯수(출력항목)가 여러개로 구성됩니다.
출력부분은 출력항목이 한번씩만 전달되는 싱글데이터와 복수로 전달되는 멀티데이터가 있고 TR에 따라 싱글데이터(또는 멀티데이터)만 있거나 둘다 있는 경우도 있습니다. OpenAPI가 제공하는 TR은 KOA Studio의 TR목록 탭에서 찾아볼 수 있고 각 TR별로 조회도 가능합니다.

  • OPT10070 : 당일주요거래원요청 - 싱글데이터
  • OPT10081 : 주식일봉차트조회요청 - 싱글 + 멀티데이터

[계좌비밀번호 설정]

잔고나 주문가능금액,수량등 계좌관련 조회나 주문전에 미리 계좌비밀번호를 설정해야 오류 알림창과 -301 오류코드없이 사용하실수 있습니다. 계좌비밀번호 설정은 계좌비밀번호 입력창에서만 가능하며 이 입력창은 메뉴나 함수로 출력하실수 있습니다.

  • 메뉴이용 : 로그인후 트레이 메뉴(모니터 오른쪽 하단)에서 "계좌비밀번호 저장"선택
  • 함수이용 : 로그인후 OpenAPI.KOA_Functions(_T("ShowAccountWindow"), _T(""))호출

[조회제한]

OpenAPI 조회는 1초당 5회로 제한되며 복수종목 조회와 조건검색 조회 횟수가 합산됩니다. 가령 1초 동안 시세조회2회 관심종목 1회 조건검색 2회 순서로 조회를 했다면 모두 합쳐서 5회이므로 모두 조회성공하겠지만 조건검색을 3회 조회하면 맨 마지막 조건검색 조회는 실패하게 됩니다.

[조회제한 강화]

기존 1초당 5회 조회제한외에 분당, 시간당 유동적 조회제한이 2017년 4월 6일 17:00이후 반영되었습니다. (OpenAPI 게시판 조회제한 관련 공지내용을 참고하세요.)
조회제한 강화 발생시 에러코드(-200)리턴과 알림 메시지가 표시되며 조회제한 강화가 발생한 프로그램은 다시 로그인해야 조회기능을 다시 이용할 수 있으며 구체적인 조회제한 기준은 비공개로 운영하고 있습니다. 이 조회제한 강화는 거래시간, 거래일에 관계없이 OpenAPI프로그램 실행시 항상 점검합니다. 점검방법은 CommRqData()함수와 CommKwRqData()함수를 이용한 조회횟수를 합산하는 것으로 연속조회 역시 CommRqData()를 이용므로 합산됩니다.
이외 SetRealReg()함수호출이나 나머지 OpenAPI함수호출은 조회제한 강화와 관련없으며 실시간 시세데이터 사용도 관련없습니다.
조회횟수 합산은 프로그램별로 합산하며 로그인ID 별로는 합산하지 않습니다. 예를들어 같은ID로 로그인한 2개 프로그램에서 각각 10회씩 조회했다면 프로그램별 10회 조회이며 20조회로 합산하지 않습니다.

[연속조회]

TR별로 한번에 전달할 수 있는 데이터 갯수가 정해져 있습니다. 그런데 이 갯수보다 조회데이터가 많을때 연속조회로 모든 데이터를 조회하게 됩니다. 연속조회는 모든 조회처리에 적용되는 공통사항이며 CommRqData()에서 인자값만 바꿔서 처리합니다.
아래처럼 설정해서 맨 처음 조회했을때 추가로 조회할 데이터가 있다면

OpenAPI.CommRqData("일별데이터조회", "OPT10086" , 0, "0001");

OnReceiveTRData()이벤트에서 5번째 인자값(sPrevNext)에 "2"가 전달됩니다. 그렇다면 연속조회하실때는 CommRqData("일별데이터조회", "OPT10086" , 2, "0001"); 3번째 인자값을 2로 설정해서 조회하시면 됩니다.
정리하면 다음과 같습니다.

OpenAPI.CommRqData("일별데이터조회", "OPT10086" , 0, "0001"); // 처음조회시 혹은 연속데이터가 없을때
OpenAPI.CommRqData("일별데이터조회", "OPT10086" , 2, "0001"); // 연속조회시

[실시간 데이터]

시세조회요청이 성공하면 관련 실시간 시세데이터가 발생했을때 서버에서 자동으로 OnReceiveRealData()이벤트로 실시간 타입단위로 전달해줍니다.
KOA Studio의 실시간 탭을 여시면 Real Type과 "주식시세"에서 "종목프로그램매매"까지 나열된 이름을 확인할 수 있습니다.
이들 하나하나를 실시간 타입이라고 하며 관련있는 FID(숫자)와 이름(실시간 항목)를 임의로 모아놓은 것입니다.
예를들어 실시간 타입 "주식시세"는 FID 10 현재가 ~ FID 568 하한가발생시간까지 19개 FID로 구성되며 한꺼번에 전달되는것입니다.
또 실시간 타입 "주식체결"는 FID 20 체결시간 ~ FID 1313 Extra Item까지 35개 FID가 한번에 전달됩니다.

[실시간 데이터 - 주의사항]

실시간 타입 "주문체결", "잔고", "파생잔고"는 주문관련 실시간 데이터를 전달하기 때문에 시세조회한 뒤나 SetRealReg()함수로 등록해서 사용할 수 없습니다. 이 실시간 타입은 주문을 해야 발생하며 주문전용 OnReceiveChejanData()이벤트로 전달됩니다.

아래 실시간 타입은 시스템 내부용으로 사용할수없는 실시간 타입입니다.

  1. 임의연장정보

  2. 시간외종목정보

  3. 주식거래원

  4. 순간체결량

  5. 선물옵션합계

  6. 투자자별매매

[참고 SetRealReg() 함수]

SetRealReg()함수로도 실시간 시세데이터 수신이 가능하며 시세조회요청과 방법만 다를뿐 수신하는 실시간 시세데이터 그리고 데이터 처리 방법은 동일합니다 이 함수는 조건검색 항목에서 사용법을 설명하고 있습니다.

[CommRqData() 함수]

CommRqData(
  BSTR sRQName,    // 사용자 구분명
  BSTR sTrCode,    // 조회하려는 TR이름
  long nPrevNext,  // 연속조회여부
  BSTR sScreenNo   // 화면번호
)

조회요청함수이며 빈번하게 조회요청하면 시세과부하 에러값으로 -200이 전달됩니다.
리턴값 0이면 조회요청 정상 나머지는 에러

  • -200 : 시세과부하
  • -201 : 조회전문작성 에러

[SetInputValue() 함수]

SetInputValue(
BSTR sID,     // TR에 명시된 Input이름
BSTR sValue   // Input이름으로 지정한 값
)

조회요청시 TR의 Input값을 지정하는 함수이며 조회 TR 입력값이 많은 경우 이 함수를 반복적으로 호출합니다.

[OPT10081 : 주식일봉차트조회요청예시]

SetInputValue("종목코드"  ,  "039490"); // 첫번째 입력값 설정
SetInputValue("기준일자"  ,  "20160101");// 두번째 입력값 설정
SetInputValue("수정주가구분"    ,  "1"); // 세번째 입력값 설정
LONG lRet = CommRqData( "RQName","OPT10081", "0","0600");// 조회요청

[DisconnectRealData() 함수]

DisconnectRealData(
BSTR sScnNo // 화면번호
)

화면번호 설정한 실시간 데이터를 해지합니다.

[GetRepeatCnt() 함수]

GetRepeatCnt(
BSTR sTrCode, // TR 이름
BSTR sRecordName // 레코드 이름
)

조회수신한 멀티데이터의 갯수(반복)수를 얻을수 있습니다. 예를들어 차트조회는 한번에 최대 900개 데이터를 수신할 수 있는데 이렇게 수신한 데이터갯수를 얻을때 사용합니다. 이 함수는 반드시 OnReceiveTRData()이벤트가 호출될때 그 안에서 사용해야 합니다.

[OPT10081 : 주식일봉차트조회요청예시]

OnReceiveTrDataKhOpenAPIctrl(...)
{
  if(strRQName == _T("주식일봉차트"))
  {
    int nCnt = OpenAPI.GetRepeatCnt(sTrcode, strRQName);
    for (int nIdx = 0; nIdx < nCnt; nIdx++)
    {
      strData = OpenAPI.GetCommData(sTrcode, strRQName, nIdx, _T("종목코드"));   strData.Trim();
      strData = OpenAPI.GetCommData(sTrcode, strRQName, nIdx, _T("거래량"));   strData.Trim();
      strData = OpenAPI.GetCommData(sTrcode, strRQName, nIdx, _T("시가"));   strData.Trim();
      strData = OpenAPI.GetCommData(sTrcode, strRQName, nIdx, _T("고가"));   strData.Trim();
      strData = OpenAPI.GetCommData(sTrcode, strRQName, nIdx, _T("저가"));   strData.Trim();
      strData = OpenAPI.GetCommData(sTrcode, strRQName, nIdx, _T("현재가"));   strData.Trim();
    }
  }
}

[CommKwRqData() 함수]

CommKwRqData(
BSTR sArrCode,    // 조회하려는 종목코드 리스트
BOOL bNext,   // 연속조회 여부 0:기본값, 1:연속조회(지원안함)
int nCodeCount,   // 종목코드 갯수
int nTypeFlag,    // 0:주식 관심종목, 3:선물옵션 관심종목
BSTR sRQName,   // 사용자 구분명
BSTR sScreenNo    // 화면번호
)

한번에 100종목을 조회할 수 있는 관심종목 조회함수인데 영웅문HTS [0130] 관심종목 화면과는 이름만 같은뿐 전혀관련이 없습니다. 함수인자로 사용하는 종목코드 리스트는 조회하려는 종목코드 사이에 구분자';'를 추가해서 만들면 됩니다. 조회데이터는 관심종목정보요청(OPTKWFID) Output을 참고하시면 됩니다. 이 TR은 CommKwRqData()함수 전용으로 임의로 사용하시면 에러가 발생합니다.

[GetCommData() 함수]

GetCommData(
BSTR strTrCode,   // TR 이름
BSTR strRecordName,   // 레코드이름
long nIndex,      // TR반복부
BSTR strItemName) // TR에서 얻어오려는 출력항목이름

OnReceiveTRData()이벤트가 호출될때 조회데이터를 얻어오는 함수입니다. 이 함수는 반드시 OnReceiveTRData()이벤트가 호출될때 그 안에서 사용해야 합니다.

[OPT10081 : 주식일봉차트조회요청예시]

OnReceiveTrDataKhOpenAPIctrl(...)
{
  if(strRQName == _T("주식일봉차트"))
  {
    int nCnt = OpenAPI.GetRepeatCnt(sTrcode, strRQName);
    for (int nIdx = 0; nIdx < nCnt; nIdx++)
    {
      strData = OpenAPI.GetCommData(sTrcode, strRQName, nIdx, _T("종목코드"));   strData.Trim();
      strData = OpenAPI.GetCommData(sTrcode, strRQName, nIdx, _T("거래량"));   strData.Trim();
      strData = OpenAPI.GetCommData(sTrcode, strRQName, nIdx, _T("시가"));   strData.Trim();
      strData = OpenAPI.GetCommData(sTrcode, strRQName, nIdx, _T("고가"));   strData.Trim();
      strData = OpenAPI.GetCommData(sTrcode, strRQName, nIdx, _T("저가"));   strData.Trim();
      strData = OpenAPI.GetCommData(sTrcode, strRQName, nIdx, _T("현재가"));   strData.Trim();
    }
  }
}

[GetCommRealData() 함수]

GetCommRealData(
BSTR strCode,   // 종목코드
long nFid   // 실시간 타입에 포함된FID
)

OnReceiveRealData()이벤트가 호출될때 실시간데이터를 얻어오는 함수입니다.
이 함수는 반드시 OnReceiveRealData()이벤트가 호출될때 그 안에서 사용해야 합니다.

[주식체결 실시간 데이터 예시]

if(strRealType == _T("주식체결"))
{
  strRealData = m_KOA.GetCommRealData(strCode, 10);   // 현재가
  strRealData = m_KOA.GetCommRealData(strCode, 13);   // 누적거래량
  strRealData = m_KOA.GetCommRealData(strCode, 228);    // 체결강도
  strRealData = m_KOA.GetCommRealData(strCode, 20);  // 체결시간
}

[GetCommDataEx() 함수]

GetCommDataEx(
BSTR strTrCode,   // TR 이름
BSTR strRecordName  // 레코드이름
)

조회 수신데이터 크기가 큰 차트데이터를 한번에 가져올 목적으로 만든 전용함수입니다.

[차트일봉데이터 예시]

OnReceiveTrDataKhOpenAPIctrl(...)
{
  if(strRQName == _T("주식일봉차트"))
  {
    VARIANT   vTemp = OpenAPI.GetCommDataEx(strTrCode, strRQName);
    long    lURows, lUCols;
    long    nIndex[2]
    COleSafeArray saMatrix(vTemp);
    VARIANT vDummy;
    VariantInit(&vDummy);
    saMatrix.GetUBound(1, &lURows); // 데이터 전체갯수(데이터 반복횟수)
    saMatrix.GetUBound(2, &lUCols); // 출력항목갯수

    for(int nRow = 0; nRow <= lURows; nRow ++)
    {
      for(int nCol = 0; nCol <= lUCols; nCol ++)
      {
        nIndex[0] = lURows;
        nIndex[1] = lUCols;
        saMatrix.GetElement(nIndex, &vDummy);
        ::SysFreeString(vDummy.bstrVal);
      }
    }
    saMatrix.Clear();
    VariantClear(&vTemp);
  }
}

[OnReceiveTrData() 이벤트]

void OnReceiveTrData(
BSTR sScrNo,       // 화면번호
BSTR sRQName,      // 사용자 구분명
BSTR sTrCode,      // TR이름
BSTR sRecordName,  // 레코드 이름
BSTR sPrevNext,    // 연속조회 유무를 판단하는 값 0: 연속(추가조회)데이터 없음, 1:연속(추가조회) 데이터 있음
LONG nDataLength,  // 사용안함.
BSTR sErrorCode,   // 사용안함.
BSTR sMessage,     // 사용안함.
BSTR sSplmMsg     // 사용안함.
)

조회요청 응답을 받거나 조회데이터를 수신했을때 호출됩니다.
조회데이터는 이 이벤트내부에서 GetCommData()함수를 이용해서 얻어올 수 있습니다.

[OnReceiveRealData()이벤트]

OnReceiveRealData(
BSTR sCode,        // 종목코드
BSTR sRealType,    // 리얼타입
BSTR sRealData    // 실시간 데이터 전문
)

실시간 데이터 수신할때마다 호출되며 SetRealReg()함수로 등록한 실시간 데이터도 이 이벤트로 전달됩니다.
GetCommRealData()함수를 이용해서 실시간 데이터를 얻을수 있습니다.

[OnReceiveMsg()이벤트]

OnReceiveMsg(
BSTR sScrNo,   // 화면번호
BSTR sRQName,  // 사용자 구분명
BSTR sTrCode,  // TR이름
BSTR sMsg     // 서버에서 전달하는 메시지
)

서버통신 후 수신한 메시지를 알려줍니다.
메시지에는 6자리 코드번호가 포함되는데 이 코드번호는 통보없이 수시로 변경될 수 있습니다. 따라서 주문이나 오류관련처리를
이 코드번호로 분류하시면 안됩니다.

OpenAPI+ 메뉴얼 – 로그인과 버전처리

개요

  • OpenAPI(Application Programing Interface)

    • 국내주식상품과
    • 코스피200 지수선물/옵션,
    • 주식선물을 거래할 수 있는

    거래/분석프로그램을 개발 할 수 있도록 하는 일종의 프로그램으로, COM형태로 제공합니다.

  • 주요기능은

    • 시세데이터 조회와 실시간 데이터제공,
    • 주문기능,
    • 조건검색기능(주식만 가능)

    을 제공하며 모두 로그인 이후 가능합니다.

[통신동작]

  • OpenAPI함수호출과 이벤트는 모두 비동식 방식으로 서버에 시세조회나 주문등을 함수호출로 요청하면 처리 결과를 전용 이벤트를 호출해서 전달합니다.
  • 여기서 수신데이터를 가져오려면 반드시 이벤트 리턴전에 적절한 데이터 획득함수를 사용해서 얻어와야 합니다.
  • 이벤트가 호출하기 전에 데이터 획득함수를 사용하거나 이벤트 리턴후에 호출하게 되면 혹은 임의로 이벤트를 호출하면 정상적인 데이터를 얻을수 없습니다.
  • 지금까지 설명을 조회요청을 예를들어 정리하면 다음과 같습니다. 이외 OpenAPI기능도 관련 함수와 이벤트 차이가 있을뿐 전체 동작은 동일합니다.
기능요청(조회함수 CommRqData, CommKwRqData 호출)  ---> 이벤트 호출(OnReceiveTRData ) ---> 데이터 획득 (GetCommData함수)

[화면번호]

  • 화면번호는 서버에 조회나 주문등 필요한 기능을 요청할때 이를 구별하기 위한 키값으로 이해하시면 됩니다.
  • 0000(혹은 0)을 제외한 임의의 숫자를 사용하시면 되는데 갯수가 200개로 한정되어 있기 때문에 이 갯수를 넘지 않도록 관리하셔야 합니다.
  • 만약 사용하는 화면번호가 200개를 넘는 경우 조회결과나 주문결과에 다른 데이터가 섞이거나 원하지 않는 결과를 나타날 수 있습니다.

[이벤트]

  • 시세조회나 조건검색요청등 관련함수 호출로 요청하면 서버에서 이를 처리해서 결과를 OpenAPI의 특정함수를 호출해서 알려주는데 이 함수를 이벤트라고 합니다.
  • 조회를 예로 들면 SetInputValue(), CommRqData()함수로 조회를 하면 조회결과를 만들어서 OpenAPI로 전달하고 조회한 사용자의 OnReceiveTRData를 호출하게 됩니다.
  • 이벤트는 일반함수와 구별하기 위해 이름앞에 On~에 있으며 OnEventConnect, OnReceiveTRData, OnReceiveRealData등이 있습니다.
  • 로그인, 조회, 주문, 조건검색등 기능별로 함수와 이벤트가 분류되어 있으니 용도에 맞는 함수와 이벤트를 사용해야 합니다.

로그인과 버전처리

[로그인 개요]

  • 로그인은 CommConnect()함수를 호출하며 OnEventConnect 이벤트 인자값으로 로그인 성공여부를 알수 있습니다.
  • 이 값이 0이면 성공이고 나머지는 실패로 오류코드값을 참고해서 실패원인을 파악할수 있습니다.
  • 실서버와 동일한 시세데이터로 주문테스트를 할 수 있는 모의투자서버를 제공하는데 로그인창에서 "모의투자 서버"을 선택해서 간단히 접속하실수 있습니다.

[수동 로그인]

  • 로그인창에 로그인ID와 비밀번호를 직접입력해서 로그인을 하는것을 말하며 기본적으로 이 로그인방법을 사용하게 됩니다.
  • 수동 로그인중에 버전처리내용이 있는 경우 버전처리도 함께 진행됩니다.

[자동 로그인]

  • 로그인한 다음 계좌비밀번호 입력창을 통해 자동로그인을 설정할 수 있습니다.
  • 트레이 메뉴(모니터 오른쪽 하단)에서 "계좌비밀번호 저장" 메뉴를 선택하면 화면이 표시되는데 여기서 로그인 이후 사용할 계좌와 계좌비밀번호를 입력하고 등록버튼을 눌러서 저장한 다음 계좌번호 아래에 있는 AUTO 체크 박스를 선택하시면 자동 로그인을 위한 설정이 모두 끝납니다.
  • 로그인 설정을 자동으로 하면 종목정보를 제외한 버전처리를 모두 무시하게 되며 버전처리를 다시 받으려면 AUTO 버튼을 체크 해지하고 프로그램을 재 실행 하시면 됩니다.

[계좌비밀번호 설정]

  • 잔고나 주문가능금액, 수량등 계좌관련 조회나 주문전에 미리 계좌비밀번호를 설정해야 오류 알림창과 -301 오류코드없이 사용하실수 있습니다.
  • 계좌비밀번호 설정은 계좌비밀번호 입력창에서만 가능하며 이 입력창은 메뉴나 함수로 출력하실수 있습니다.

    • 메뉴이용 - 로그인후 트레이 메뉴(모니터 오른쪽 하단)에서 "계좌비밀번호 저장"선택
    • 함수이용 - 로그인후 OpenAPI.KOA_Functions(_T("ShowAccountWindow"), _T(""))호출

[버전 처리]

  • 로그인할때 버전처리가 필요한 경우 버전처리 알림창이 출력될수 있습니다.
  • 이 알림창이 표시되면 OpenAPI프로그램을 먼저 모두 종료한다음 알림창에 있는 닫기버튼을 누르셔야 합니다.
  • 그렇지 않으면 버전처리가 정상적으로 끝나지 않아서 로그인할때 또 버전처리 알림창이 표시됩니다.
  • 그리고 알림창이 표시되었을때 KOA Studio도 실행중이면 역시 함께 종료시켜주셔야 합니다.
  • 이렇게 OpenAPI프로그램을 모두 종료하신 다음 알림창을 닫아주시면 버전처리가 자동으로 진행되고 프로그램을 재실행 해주시면 됩니다.

[모의투자]

  • 로그인 창에서 모의투자접속을 선택을 체크하면 모의투자로 접속하며 이 체크를 풀면 실서버(운영서버)로 접속합니다.
  • KOA Studio 프로그램은 항상 모의투자로만 접속가능해서 모의투자접속 체크 해지가 않됩니다.
  • 모의투자로 로그인하시려면 당사 홈페이지에서 미리 모의투자 사용신청을 하셔야 하며 상세한 내용은 당사 홈페이지를 참고하시기 바랍니다.
  • 모의투자 계좌번호, 주문 가능종목, 수수료등 정책은 실서버와 차이가 있으므로 상세한 내용은 홈페이지 내용을 꼭 참고해 주세요.

[중복로그인]

  • 실서버에서는 중복로그인을 허용하지 않기 때문에 동일PC나 다른PC나 관계없이 마지막에 로그인한 경우만 유지되고 이전에 로그인한 프로그램은 자동으로 로그오프됩니다.
  • 그러나 모의투자서버는 중복로그인이 가능해서 얼마든지 로그인 하실수 있습니다.

[LONG CommConnect()]

  • 수동 로그인설정인 경우 로그인창을 출력해서 로그인을 시도하거나 자동로그인 설정인 경우 로그인창 출력없이 로그인을 시도합니다.

[LONG GetLoginInfo()]

  • 로그인 후 사용할 수 있으며 인자값에 대응하는 정보를 얻을 수 있습니다. 인자는 다음값을 사용할 수 있습니다.

    • "ACCOUNT_CNT"
      : 보유계좌 수를 반환합니다.

    • "ACCLIST" 또는 "ACCNO"
      : 구분자 ';'로 연결된 보유계좌 목록을 반환합니다.

    • "USER_ID"
      : 사용자 ID를 반환합니다.

    • "USER_NAME"
      : 사용자 이름을 반환합니다.

    • "KEY_BSECGB"
      : 키보드 보안 해지여부를 반환합니다.(0 : 정상, 1 : 해지)

    • "FIREW_SECGB"
      : 방화벽 설정여부를 반환합니다.(0 : 미설정, 1 : 설정, 2 : 해지)

    • "GetServerGubun"
      : 접속서버 구분을 반환합니다.(1 : 모의투자, 나머지 : 실서버)

    • 리턴값
      : 인자값에 대응하는 정보를 얻을 수 있습니다.

[보유계좌 목록 예시]

CString   strAcctList = GetLoginInfo("ACCLIST");

여기서 strAcctList는 ';'로 분리한 보유계좌 목록임 예) "3040525910;567890;3040526010"

[OnEventConnect()이벤트]

OnEventConnect(
  long nErrCode   // 로그인 상태를 전달하는데 자세한 내용은 아래 상세내용 참고
)

로그인 처리 이벤트입니다. 성공이면 인자값 nErrCode가 0이며 에러는 다음과 같은 값이 전달됩니다.

nErrCode별 상세내용

  • 100 사용자 정보교환 실패
  • 101 서버접속 실패
  • 102 버전처리 실패

[OnReceiveMsg()이벤트]

OnReceiveMsg(
  BSTR sScrNo,   // 화면번호
  BSTR sRQName,  // 사용자 구분명
  BSTR sTrCode,  // TR이름
  BSTR sMsg      // 서버에서 전달하는 메시지
)

서버통신 후 수신한 메시지를 알려줍니다.
메시지에는 6자리 코드번호가 포함되는데 이 코드번호는 통보없이 수시로 변경될 수 있습니다. 따라서 주문이나 오류관련처리를
이 코드번호로 분류하시면 안됩니다.

파이썬으로 배우는 알고리즘 트레이딩 정리

파이선 기초

설치

윈도우 7 기반, 파이썬은 아나콘다 배포판으로 설치, 아나콘다는 반드시 32비트용으로 설치해야 함. 국내 증권사 api 가 32비트 프로그램이기 때문인 것으로 사료됨. 책은 아나콘다 파이썬 3.6 32비트 버전임. 아나콘다 설치시 관리자 권한으로 설치.

파이썬 인터프리터 바탕화면에 바로가기 만들기.

C:\Anaconda3\Lib\idlelib\idle.bat 를 바탕화면에 바로가기 만듬. windows10에서는 c:\ProgramData\Anaconda3\Lib\idlelib\idle.bat 로 되어 있음.

변수

변수는 데이터의 주소를 담고 있음. 실제 데이터를 객체라고 함. 변수에 담긴 실제 데이터의 주소를 알고 싶으면 id(변수명).

>>> x = 100
>>> x
100
>>> id(x)
1845813952
>>> y = x
>>> y
100
>>> id(x), id(y)
(1845813952, 1845813952)

문자열

파이썬은 문자와 문자열을 구분하지 않음. 작은따옴표, 큰따옴표 모두 사용가능. 문자열은 리스트임. 리스트 사용문법과 같음.
len(문자열) : 문자 개수
문자변수명[시작위치:끝위치] : 문자열 일부만 자르기, 시작위치, 끝위치 중 하나는 생략가능. 시작위치 생략하면 0으로 간주, 끝위치 생략하면 마지막 위치로 간주.위치를 음수로 지정. 음수로 지정되면 맨마지막위치부터 오는쪽으로 가면서 -1, -2 ...

문자열 나누기

>>> my_jusik = "naver daum"
>>> my_jusik.split(' ')
['naver', 'daum']
>>> my_jusik.split(' ')[0]
'naver'
>>> split_jusik = my_jusik.split(' ')
>>> split_jusik
['naver', 'daum']
>>> split_jusik[0]
'naver'

문자열 합치기

>>> daum = "Daum"
>>> kakao = "Kakao"
>>> daum + ' ' + kakao
'Daum Kakao'

데이터 타입 확인하기

>>> type(x)
<class 'int'>
>>> type(id(x))
<class 'int'>
>>> type(4000)
<class 'int'>
>>> type(3.14159)
<class 'float'>
>>> type('안녕하새요')
<class 'str'>

리스트

>>> myList = [23,345,'sdfasd','fghfh',444]
>>> myList2 = []
>>> myList[3]
'fghfh'
>>> myList[-3]
'sdfasd'
>>> myList[1:3]
[345, 'sdfasd']

리스트 생성할 때 사용한 각괄호 와 인덱스의 곽괄호는 다른 개념임.

리스트의 인덱스 사용문법

각괄호내부의 숫자로 사용. [0], [3], [-2], [1:6], [3:-1]
양수 인덱스: 0 첫원소의 앞, 1 첫원소 뒤 둘째원소 앞, ...
음수 인덱스: -1 마지막원소 앞 마지막에서 둘째원소 뒤, ...

리스트에 데이터 삽입

리스트변수명.append('삽입될 데이터') : 리스트 마지막에 삽입됨
리스트변수명.insert(인덱스, '삽입될 데이터') : 인덱스 위치에 삽입됨

리스트데이터 삭제

del 리스트변수명[인덱스]

이차원리스트의 인덱싱

리스트변수명[2][4] 처럼 사용.

튜플

리스트는 각괄호사용, 튜플은 둥글괄호 사용.
리스트는 원소를 변경할 수 있지만, 튜플은 변경할 수 없다.
튜플은 대신 속도가 빠르다.
튜플원소에 접근하는 방법은 [인덱스]를 사용한다. 이를통해 [시작위치:끝위치]를 사용해 튜플원소 일부를 가져올 수 도 있음.

>>> a = (1,2,3,'하하하','호호호',4,5)
>>> a[2:4]
(3, '하하하')

딕셔너리

{키:값, 키:값 ...}
딕셔너리는 인덱스를 지원하지 않음. 인덱스가 아니라 키를 사용해야 함.

>>> aa = {1:10, 2:20, '삼':30}
>>> aa[1]
10
>>> aa['삼']
30
>>> aa[1:2]
Traceback (most recent call last):
  File "<pyshell#51>", line 1, in <module>
    aa[1:2]
TypeError: unhashable type: 'slice'

키값으로 숫자, 문자, 모두 사용가능.

딕셔너리 데이터 추가

딕셔너리변수명[키] = 데이터

딕셔너리 데이터 삭제

del 딕셔너리변수명[키]

딕셔너리 키 찾기, 값 찾기

>>> aa = {1:10, 0.3:30}
>>> aa[0.3]
30
>>> aa.keys()
dict_keys([1, 0.3])
>>> type(aa.keys())
<class 'dict_keys'>
>>> list(aa.keys())
[1, 0.3]
>>> aaKeys = list(aa.keys())
>>> aaKeys
[1, 0.3]
>>> aaValus = list(aa.values())
>>> aaValus
[10, 30]
>>> 0.3 in aa.keys()
True

파이썬 비교연산자

==, !=, >, <, <=, >=

if 문 사용문법

   if 조건식 :
        실행문
    elif:
        실행문
    else:
        실행문

for문 사용문법

for 변수명 in 리스트 :
    실행문

리스트 원소가 하나씩 변수명에 바인딩 되어 실행문을 반복함.

리스트 대신 range()이용 해도 됨

for 변수명 in range(1,10)
    실행문

여기서 range는 1 <= range(1,10) < 10 로 해석. 그러므로 변수명에는 1 부터 9까지 차레대로 바인딩 됨.

리스트 대신 튜플을 사용해도 됨.
for 변수명 in 튜플

for문에 딕셔너리 사용문법

for 키변수명,값변수명 in 딕셔너러변수명.ltems():
또는
for 키변수명 in 딕셔너리변수명.keys():
또는
for 값변수명 in 딕셔너리변수명.values():

while 문 사용법

while 조건문 :
    실행문

break 문 과 continue 문

루프 내부에 사용. break는 루프를 빠져 나가고, continue문은 그 다음 실행문을 실행하지 않고 계속 루프를 실행.

함수만들기

def 함수명(파라미터들):
    함수내 명령문
    return 반환값

모듈

모듈은 함수들과 데이터들을 모듈명.py 라는 파일로 만들어 놓은것.
이를 파이썬에서 임포트 하여 재사용 할 수 있음.
import 모듈명

임포트 된 모듈의 함수를 사용하고 싶으면
모듈명.함수명()

임포트 된 모듈의 변수를 사용하고 싶으면
모듈명.변수명

모듈을 제작하는 과정에서 모듈을 테스트 하기 위해 모듈 마지막에 다음과 같은 코드를 삽입한다.

...
if __name__ == "__main__"
    print(내부함수명(필요한파라미터))
    print(__name__)

이렇게 함으로써 모듈을 직접 실행 할 때는 위의 if문이 동작하여 함수가 제대로 작동하는지 볼 수 있고, import 할 때는 위의 if 문이 동작되지 않는다. 그 이유는 name 이라는 파이썬 내부변수가 이 모듈을 직접 실행한 경우 "main"으로 바인딩 되고 import 되었을 때는 파일명으로 바인딩 되기 때문이다.

Time 모듈

>>> import time
>>> current_time = time.ctime()
>>> print (current_time)
Thu May 30 22:02:02 2019
>>> dir(time)
['_STRUCT_TM_ITEMS', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'altzone', 'asctime', 'clock', 'ctime', 'daylight', 'get_clock_info', 'gmtime', 'localtime', 'mktime', 'monotonic', 'monotonic_ns', 'perf_counter', 'perf_counter_ns', 'process_time', 'process_time_ns', 'sleep', 'strftime', 'strptime', 'struct_time', 'thread_time', 'thread_time_ns', 'time', 'time_ns', 'timezone', 'tzname']
>>> time
<module 'time' (built-in)>
>>> import random
>>> random
<module 'random' from 'C:\\ProgramData\\Anaconda3\\lib\\random.py'>

dir(모듈명) 은 모듈에 적재된 데이터 및 함수들을 확인 할 수 있다.

import 후 모듈명을 적으면 모듈의 위치를 확인할 수 있다.

os모듈

디랙토리 에 관한 함수들 있다.
현재 디랙토리 구하기 os.getcwd()
디랙토리내 파일명 구하기 os.listdir(패스)
특정디랙토리내 실행파일 찾기

for x in os.listdir('c:\Anaconda3')
    if x.endswith('exe')
        print(x)

임포트하는 방법

import 모듈명
모듈명.변수명
import 모듈명 as 별명
별명.변수명
from 모듈명 import 함수명

함수명을 바로 사용할 수 있다. 다만 기존의 동일한 이름의 함수명을 중복되어 사라짐.

form 모듈명 import *

모듈내 모든 함수 및 데이터를 바로 사용할 수 있음. 다만 기존의 동일한 이름의 것들은 모두 중복되어 사라짐.

클래스

self : 클래스가 인스탄스화 될 때 그 인스탄스명 으로 바인딩 된다.
__init__ :생성자(매쏘드)
__del__ : 소멸자

정의

class 클래스명(상속받을_부모_클래스명):
    클래스변수명 = 0
    def __init__(self, 입력받는인스탄스변수명, ...):
        self.입력받는인스탄스변수명 = 입력받는인스탄스변수명
        self.다른인스탄스변수명 = "호호데이터"
        함수변수명 = "임의데이터"

    def 매쏘드명(self):
        print (self.인스탄스변수명)

   def __del__(self):

상속받을_부모_클래스명 은 생략가능. 상속 받는다면 부모 클래스에 존재하는 메소드를 그대로 사용할 수 있다.
클래스변수명은 인스탄스에서 호출할 수 있으며 모든 인스탄스가 공유한다. C에서 정적 변수랑 비슷
인스탄스변수는 매소드 안에서만 정의될 수 있음. 보통 생성자 안에서 정의함. 그러면 다른 매소드에서도 사용 가능. (단, self. 없이 그냥 변수명으로 정의되면 그 함수에서만 사용되고 소멸되는 로컬 변수임)
인스탄스변수는 인스탄스명.인스탄스변수명 처럼 호출되며, 인스탄스 마다 다른 값을 가진다.
메소드가 self 인자를 가지고 있으면 인스탄스로만 호출이 가능하고,
메소드가 self 인자가 없으면 클래스로만 호출이 가능
클래스명은 대문자로 시작이 관례

인스탄스란 ff = 클래스명() 처럼 클래스가 호출될 때
ff 를 인스탄스라 함.
메소드가 클래스로 호출된다는 것은 클래스명.메소드() 형식으로 호출하는 것을 말함.
메소드가 인스탄스로 호출된다는 것은 인스탄스명.메소드() 형식으로 호출하는 것을 말함.

class 에서 변수 사용 정리

클래스 내부에서 정의
: 클래스변수가 되고 인스탄스 되지 않고 클래스로 직접 호출 가능할 뿐만 아니라 인스탄스에서도 호출가능. java에서 정적변수처럼 동작

매소드 내부에서 self.변수명 처럼 정의
: 인스탄스 변수가 되고 인스탄스의 다른 메소드에서 호출 가능.

매소드 내부에서 self. 없이 변수명으로 정의
: 해당 메소드 내부에서만 호출가능.

PANDAS 사용

pasdas는 파이썬의 리스트와 딕셔너리의 개념을 혼합 짬뽕한 것. 매우 유용함.
임포트할 때 Series 와 DataFrame을 로컬네임스페이스 내로 직접 임포트 함.

from pandas import Series, DataFrame

시리즈는 리스트로 부터 변환된다.

kakao = Series([92600, 92400, 92100, 94300, 92300])
print(kakao)

이때 자동적으로 인덱스는 0을 포함한 정수형으로 생김

리스트로 부터 시리즈를 만들 때, 인덱스를 직접 지정할 수 있다.

시리즈변수명 = Series(데이터리스트, index=인덱스리스트)

예)

kakao2 = Series([92600, 92400, 92100, 94300, 92300], 
    index=['2016-02-19', '2016-02-18', '2016-02-17', '2016-02-16','2016-02-15'])

kakao2['2016-02-18'] 처럼 데이터에 접근할 수 있음.
인덱스 전체를 리스트로 얻으려면 kakao2.index
데이터 전체를 리스트로 얻으려면 kakao2.values

시리즈 + 시리즈 하면 같은 키값의 데이터 끼리만 더해짐.

DataFrame은 2차원 데이터 타입임.
딕셔너리로 DataFrame을 정의할 수 있다.

딕셔너리변수명 =    {'컬럼명' : 컬럼데이터리스트,
                    '컬럼명' : 컬럼데이터리스트,
                    '컬럼명' : 컬럼데이터리스트 ...}
데이터프레임변수명 = DataFrame(딕셔너러변수명)

예)

from pandas import Series, DataFrame
daeshin = {'open':  [11650, 11100, 11200, 11100, 11000],
           'high':  [12100, 11800, 11200, 11100, 11150],
           'low' :  [11600, 11050, 10900, 10950, 10900],
           'close': [11900, 11600, 11000, 11100, 11050]}
date = ['16.02.29', '16.02.26', '16.02.25', '16.02.24', '16.02.23']
daeshin_day = DataFrame(daeshin, columns=['open', 'high', 'low', 'close'], index=date)

DataFrame을 생성할 때 columes= 옵션을 써서 컬럼의 순서를 정의 할 수 있다. index= 옵션을 사용해서 인덱스를 지정할 수 있다.
컬럼을 얻어 올 땐, daeshin_day['close']
로우를 얻어 올 땐, daeshin_day.ix['16.02.29']
컬럼명을 리스트로 얻어 올 땐, daeshin_day.columes
인덱스를 리스트로 얻어 올 땐, daeshin_day.index

pyqt5

이벤트처리

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *

class MyWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("PyStock")
        self.setGeometry(300, 300, 300, 400)

        btn1 = QPushButton("Click me", self)
        btn1.move(20, 20)
        btn1.clicked.connect(self.btn1_clicked) # clicked 라는 이벤트가 발생할 때 실행할 함수를 지정함.

    def btn1_clicked(self):
        QMessageBox.about(self, "message", "clicked")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    myWindow = MyWindow()
    myWindow.show()
    app.exec_()

pyqtDesign 으로 만든 ui 사용법

import sys 
from PyQt5.QtWidgets import * 
from PyQt5 import uic 
form_class = uic.loadUiType("main_window.ui")[0] 
class MyWindow(QMainWindow, form_class):  
    def __init__(self): 
        super().__init__() 
        self.setupUi(self) 

if __name__ == "__main__": 
    app = QApplication(sys.argv) 
    myWindow = MyWindow() 
    myWindow.show() 
    app.exec_()

SQLite

  1. sqlite3는 파이썬 표준 라이브러리 임. 별도의 설치과정 없이 바로 사용할 수 있음.
  2. 임포트 하기 import sqlite3
  3. 데이터베이스 커넥트
    • con = sqlite3.connect("파일경로및파일명")
    • 해당경로에 파일이 존재하지 않으면 새로 생성한다.
  4. Cusor 생성 cusor = con.cursor()
  5. sql명령어 실행 cusor.execute("sql명령어")
  6. 작업내용 db에 적용 con.commit()
  7. db 닫기 con.close()
  8. select 문을 execute 한 뒤 데이터 가져오기
    • 로우단위 가져오기 cursor.fetchone() : 리턴값은 튜플
    • 모든 데이터 가져오기 cursor.fetchall(): 리턴값은 리스트
  9. 판다스의 데이터프레임 df와 sqlite db 상호간 데이터 변환
    • 판다스에서 데이터프레임을 디비로 저장하고 읽을 수 있는 메소드 제공.
    • 판다스에서 db로 저장할 때 df.to_sql('테이블명', con)
    • db를 판다스로 읽을 때
      import pandas as pd
      from pandas import Series, DataFrame
      import sqlite3
      con = sqlite3.connect("sdfsdfs.db")
      df = pd.read_sql("select * from kakao", con, index_col='index')
      #db에 인덱스 컬럼이 있는 경우 해당 컬럼명을 쓴다. 없는 경우 none

키움증권 OpenAPI 사용법

OpenApi 연결, 키움이벤트 처리

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QAxContainer import *

class MyWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("PyStock")
        self.setGeometry(300, 300, 300, 150)

        self.kiwoom = QAxWidget("KHOPENAPI.KHOpenAPICtrl.1")  # OpenAPI kiwoom 객체 만들기
        self.kiwoom.dynamicCall("CommConnect()")              # API제공 함수 CommConnect() 호출하기

        self.text_edit = QTextEdit(self)
        self.text_edit.setGeometry(10, 60, 280, 80)
        self.text_edit.setEnabled(False)

        self.kiwoom.OnEventConnect.connect(self.event_connect) #OnEventConnect 이벤트 와 슬롯함수를 연결

    def event_connect(self, err_code):                         #OnEventConnect 이벤트 발생실 실행할 슬롯함수 정의
        if err_code == 0:
            self.text_edit.append("로그인 성공")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    myWindow = MyWindow()
    myWindow.show()
    app.exec_()
  • self.API객체 = QAxWidget("OpenAPI_ProgID") : OpenAPI객체 만들기
  • API객체.dynamicCall("API함수명()") : API 너머 서버에게 주어진 함수를 통해 정보를 요구 응답이 return 값으로 올 수 있음.
  • 응답이 리턴값으로 바로 올 수도 있지만, 이벤트로 실행된 함수 (슬롯함수, 콜백함수)를 통해서 받아야만 되는 경우도 있다.
  • 이벤트 이름은 API에서 제공. 위 예에서는 OnEventConnect
  • 이벤트 발생시 실행할 함수를 구현할 때는 반드시 API에서 미리 정해 논 프로토콜을 지켜야 함. (따라서 API 매뉴얼 참조)

계좌정보 가져오기

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import  *
from PyQt5.QAxContainer import *

class MyWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        # Kiwoom Login
        self.kiwoom = QAxWidget("KHOPENAPI.KHOpenAPICtrl.1")
        self.kiwoom.dynamicCall("CommConnect()")

        # OpenAPI+ Event
        self.kiwoom.OnEventConnect.connect(self.event_connect)

        self.setWindowTitle("계좌 정보")
        self.setGeometry(300, 300, 300, 150)

        btn1 = QPushButton("계좌 얻기", self)
        btn1.move(190, 20)
        btn1.clicked.connect(self.btn1_clicked)

        self.text_edit = QTextEdit(self)
        self.text_edit.setGeometry(10, 60, 280, 80)

    def btn1_clicked(self):
        account_num = self.kiwoom.dynamicCall("GetLoginInfo(QString)", ["ACCNO"])
        self.text_edit.append("계좌번호: " + account_num.rstrip(';'))

    def event_connect(self, err_code):
        if err_code == 0:
            self.text_edit.append("로그인 성공")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    myWindow = MyWindow()
    myWindow.show()
    app.exec_()

종목 기본정보 가져오기

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import  *
from PyQt5.QAxContainer import *

class MyWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        # Kiwoom Login
        self.kiwoom = QAxWidget("KHOPENAPI.KHOpenAPICtrl.1")
        self.kiwoom.dynamicCall("CommConnect()")

        # OpenAPI+ Event
        self.kiwoom.OnEventConnect.connect(self.event_connect)
        self.kiwoom.OnReceiveTrData.connect(self.receive_trdata)

        self.setWindowTitle("PyStock")
        self.setGeometry(300, 300, 300, 150)

        label = QLabel('종목코드: ', self)
        label.move(20, 20)

        self.code_edit = QLineEdit(self)
        self.code_edit.move(80, 20)
        self.code_edit.setText("039490")

        btn1 = QPushButton("조회", self)
        btn1.move(190, 20)
        btn1.clicked.connect(self.btn1_clicked)

        self.text_edit = QTextEdit(self)
        self.text_edit.setGeometry(10, 60, 280, 80)
        self.text_edit.setEnabled(False)

    def event_connect(self, err_code):
        if err_code == 0:
            self.text_edit.append("로그인 성공")

    def btn1_clicked(self):
        code = self.code_edit.text()
        self.text_edit.append("종목코드: " + code)

        # SetInputValue
        self.kiwoom.dynamicCall("SetInputValue(QString, QString)", "종목코드", code)

        # CommRqData
        self.kiwoom.dynamicCall("CommRqData(QString, QString, int, QString)", "opt10001_req", "opt10001", 0, "0101")

    def receive_trdata(self, screen_no, rqname, trcode, recordname, prev_next, data_len, err_code, msg1, msg2):
        if rqname == "opt10001_req":
            name = self.kiwoom.dynamicCall("CommGetData(QString, QString, QString, int, QString)", trcode, "", rqname, 0, "종목명")
            volume = self.kiwoom.dynamicCall("CommGetData(QString, QString, QString, int, QString)", trcode, "", rqname, 0, "거래량")

            self.text_edit.append("종목명: " + name.strip())
            self.text_edit.append("거래량: " + volume.strip())

if __name__ == "__main__":
    app = QApplication(sys.argv)
    myWindow = MyWindow()
    myWindow.show()
    app.exec_()

종목코드 및 한글종목명

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import  *
from PyQt5.QAxContainer import *

class MyWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.kiwoom = QAxWidget("KHOPENAPI.KHOpenAPICtrl.1")
        self.kiwoom.dynamicCall("CommConnect()")

        self.setWindowTitle("종목 코드")
        self.setGeometry(300, 300, 300, 150)

        btn1 = QPushButton("종목코드 얻기", self)
        btn1.move(190, 10)
        btn1.clicked.connect(self.btn1_clicked)

        self.listWidget = QListWidget(self)
        self.listWidget.setGeometry(10, 10, 170, 130)

    def btn1_clicked(self):
        ret = self.kiwoom.dynamicCall("GetCodeListByMarket(QString)", ["0"])
        kospi_code_list = ret.split(';')
        kospi_code_name_list = []

        for x in kospi_code_list:
            name = self.kiwoom.dynamicCall("GetMasterCodeName(QString)", [x])
            kospi_code_name_list.append(x + " : " + name)

        self.listWidget.addItems(kospi_code_name_list)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    myWindow = MyWindow()
    myWindow.show()
    sys.exit(app.exec_())

꽃 만들기[04] – 엔트리

지난 작품에 이어서 이번에는 이 작품의 제목을 출력해 보자. 제목은 회전하면서 작은 글씨에서 점차 큰 글씨로 변해간다. 제목이 나타난 후에 플레이어로 부터 화면에 그려질 꽃송이의 갯수를 입력받고 시작 버튼을 클릭하면 장면이 바뀌어 지난 작품에서 만든 꽃이 화면에 그려지도록 한다.

장면 추가하기

꽃만들기300.png


지난 작품을 로드하면 장면 1에 그려져 있는데 + 탭을 클릭하여 장면을 추가한다. 탭을 옮겨 장면의 순서를 바꿀 수 있고 이름도 바꿀 수 있다. 그렇게 하여 과거에 만든 오브젝트들을 장면 2에 담고, 이번 작품에서 새로 추가할 오브젝트들을 장면 1에 담을 수 있도록 준비한다.

배경 만들기

꽃만들기301.png


꽃밭 그림의 배경을 장면 1에 추가한다.

제목 만들기

꽃만들기302.png


글상자 오브젝트를 추가한다. 오브젝트의 이름은 제목 으로 하고 글 내용은 꽃 만들기 로 한다. 글상자 배경색은 투명으로 하고, 글자색은 배경에 비해 눈에 잘 띄는 색으로 정한다. 이번 작품에서는 노란색으로 정했다. 글씨의 크기와 위치를 적당히 설정한다.

신호 추가하기

꽃만들기303.png


사용자입력 이라는 이름으로 신호를 추가한다.

제목 오브젝트의 블럭 코딩

꽃만들기304.png


위 그림과 같이 제목 오브젝트의 블럭코딩을 완성하고 실행해 본다.
제목의 글씨가 회전하면서 점점 커지고 멈출 것이다.

  • 회전 속도를 다르게 하거나,
  • 글씨의 크기를 다르게 하려면 어떻게 해야 할까?

사용자 입력을 위한 변수 추가

꽃만들기305.png


꽃개수라는 이름으로 변수를 추가한다. 슬라이드 속성을 활성화 하여 화면에 슬라이드바를 보이게 한다. 기본값은 10으로 정한다.

시작 버튼 만들기

꽃만들기306.png


시작 이라는 이름으로 글상자 오브젝트를 만든다. 글 내용도 시작으로 한다. 글상자의 배경색과 글자색을 모드 다르게 설정하여 버튼처럼 보이게 한다.

시작 버튼의 블럭코딩

꽃만들기307.png


시작 버튼의 블럭코딩을 그림과 같이 완성하고 실행시킨다.
제목이 등장한 뒤 플레이어가 꽃개수를 정하고 시작 버튼을 클릭할 때 까지 기다린다.

장면 전환 후 꽃 그리기

꽃만들기308.png


장면 2 에 담긴 줄기 오브젝트의 코딩블럭을 수정한다.

꽃 만들기[03] – 엔트리

지난 시간에 이어 꽃을 완성하기로 한다. 지난 시간 까지는 꽃의 줄기와 잎을 생성하였고, 이번 시간에는 그 위에 꽃을 생성하도록 한다.


꽃만들기200.png


모든 코드블럭이 완성되고 실행해 보면 위 그림과 같이 플레이 될 것이다.

신호 및 변수 만들기


꽃만들기201.png


꽃생성잎생성 이라는 이름으로 신호를 만든다.
꽃잎수, 줄기방향, 꽃위치x, 꽃위치y 라는 이름으로 변수를 만든다. 이때, 모든 오브젝트에서 사용 옵션을 선택한다.


줄기 코딩블럭 수정 및 확인


꽃만들기202.png


잎 코딩블럭 수정 및 확인


꽃만들기203.png


꽃 오브젝트 생성


꽃만들기204.png


그림과 같이 꽃 오브젝트를 새로 생성한다. 그리고 꽃잎 한장을 그리고 꽃잎 이라는 이름으로 모양을 생성한다.


꽃만들기205.png


꽃 오브젝트의 이름을 으로 정하고, 이동방향의 값을 0.0 으로 정한다.

꽃 오브젝트 코딩블럭


꽃만들기206.png


위 그림과 같이 꽃 오브젝트의 코딩블럭을 작성하고 실행해 본다.