[스크랩] 핑거스탁 어플 개발자 인터뷰

출처: http://www.zdnet.co.kr/news/news_view.asp?artice_id=20131210162123


외국인이 살때 사고 기관이 팔 때 판다?

개미들의 주식 투자전략은 보통 '감', 좋게 말하면 직관에 의존한다. 데이터 기반 주식 투자는 애널리스타가 아닌 개미들이 쉽게 넘볼 수 없는 영역이었다.

이런 가운데 20년 동안 쌓아온 주가 데이터를 기반으로 자신이 산 주식이 5일 동안 얼마나 오를지 예측해 주는 서비스가 그것도 무료로 제공되고 있어 주목된다.

모바일 솔루션 전문 업체 티그레이프가 지난 3월 공개한 모바일 앱 '핑거스톡(Finger Stock)'이 그것이다. 핑거스톡은 기존 주가 등락율을 통해 매수, 유지, 매도를 분석한 예측결과를 제공한다. 적용된 예측방법은 기계학습(Machine Learning)을 통한 분석이다. 기계학습은 과거 데이터 흐름을 보고 훈련과정을 통해서 앞으로를 예측하는 방법이다.

주가를 예측해 주는 서비스와 알고리즘이 없었던 건 아니다. 이미 증권사에서는 이런 고도화된 기능을 가진 시스템트레이딩 프로그램을 사용중이다. 하지만 우리나라 개미 투자자들이 데이터에 기반해 투자하란 쉽지않다. 해외에서는 다양한 시스템트레이딩 툴이 보편화돼 있지만 국내 상황은 다르다.
핑거스톡
핑거스톡 개발자 유인관 티그레이프 기술고문 박사는 증권사 애널리스트들은 경험 및 노하우와 함께 고도화된 시스템트레이딩 툴을 사용하는 반면 개미 투자자들은 투자를 결정하는데 사용할 만한 데이터 분석 자료가 없다. 주식차트를 보더라도 감으로 보는 경향이 있다 며 개미 투자자들도 데이터에 기반해 투자할 수 있도록 돕기 위해서 주가예측 서비스를 개발하게 됐다 고 말했다.

핑거스톡 앱에서는 3개의 기계학습 알고리즘을 골라 내일 주가 오름세(종가기준)와 예측 데이터에 대한 정확도를 보여준다.

각각의 알고리즘은 SVM, MARS, NN으로 이뤄진다. 알고리즘 설명은 앱 도움말에 상세히 나와있는데, 수학에 능통하지 않으면 이해하기 어렵다. 요약하자면 3개 알고리즘에서 예측값과 정확도가 모두 높은 종목이 추천 종목이라고 생각하면 된다.

예측을 위해서는 우선 과거에 어떤 일이 있었는지 '훈련'해야 한다. 유 박사는 1990년대 이후부터 쌓아온 데이터를 갖고 40여개의 주식관련 지표 중 3개~10개 정도를 사용해 최근 6개월 동안 실제 주가와 가장 잘 맞는 수치를 찾아 내는 최적화 과정이 훈련 이라고 설명했다.

또 사용하는 지수가 너무 많거나 과거 데이터를 너무 많이 쓰면 오히려 정확도가 떨어지기 때문에 가장 정확도를 높일 수 있는 변수들로 최적화하는 것이 핑거스톡만의 기술 이라고 덧붙였다.

훈련후에는 오늘 마감한 주식 데이테를 계산해 내일 보여줄 데이터를 예측하는 과정이 진행된다. 오늘 마감한 데이터는 코스콤 증권 전산에서 공개된 데이터를 받아와 사용한다. 거래 종료 후 2천개 종목의 각종 주가 데이터를 모으기 시작해 8시부터 훈련된 정보를 기반으로 계산을 시작한다. 10시쯤 계산이 끝나고 12시에는 새로 나온 예측 결과를 보여준다.

유 박사는 예측은 매일하지만 훈련은 시간이 오래걸리기 때문에 일주일에 한번씩, 금요일에 시작해 월요일에 끝난다 며 가장 신선한 데이터로 계산한 수치는 화요일에 나온다 고 사용팁을 전했다.

핑거스톡에서 주가 분석에 사용되는 지수에는 가격정보외에 환경적 요인들도 이미 포함됐다고 볼 수 있다.
그래도 주가에 영향을 미치는 요인인 사건은 포함되지 않은 만큼, 100% 앱에 의존해 투자하는 것은 부적합하다. 핑거스톡측도 실제 투자시 참고자료로만 사용하길 권한다 는 입장이다.

핑거스톡의 수익 모델은 아직 구체적이지 않다. 현재로선 개미 투자자들이 데이터에 기반한 주식 투자로 공생할 수 있는 환경을 만들어 보자는데 초점을 맞췄다.

유 박사는 매일 3~4GB 정도의 주가 관련 데이터가 발생하는데 여기에는 고가나 종가 외에도 상당히 다양한 데이터가 있기 때문에 이를 이용해서 주식 연관 분석이나 이 주식이 왜 올랐는 이유도 알 수 있게 하고 싶다 고 말했다.

또 이런 데이터분석 툴은 이미 대형 증권사나 펀드회사는 다 가지고 있지만 개미들이 접근하기에는 한계가 있다. 앞으로 비즈니스 모델을 좀더 고민해봐야겠지만, 지금으로선 개미들도 함께 공생해보자는게 목표다 고 덧붙였다.






주가예측어플 - 핑거스탁




Finger Stock은 기계 학습을 사용하여 주가 예측을 하는 어플리케이션이다.

사용하는 feature나 기계학습 알고리즘이 다르긴 하지만 

지금 개발중인 어플 역시 기계 학습을 사용하여 주가 예측을 하는 어플이기 때문에 

참고용으로 기록해둔다. 



주가 예측 기간 : 5일후의 주가 예측

사용 알고리즘: SVM, MARS, NN

사용 feature: ATR, SMI, ADX, EMV, MACD, SAR

전체 예측 정확도: 공개하지 않음 

(개별 종목의 예측 정확도는 공개, 각 종목별로 훈련 및 테스트 하는듯)

기계학습기간:2012년 12월~ 2015년 1월 (대략 2년)


기계학습기간이 조금 예전이고 예측만 업데이트되고 있어  

이제는 유지보수만 하는 듯 하다. 



아래는 어플의 메인화면이다. 

전체 회사의 기계학습별 예측 주가등락률을 보거나 

종목을 즐겨찾기 하여 예측 결과를 확인할 수 있다. 






예측에 사용하는 알고리즘에 대한 설명은 아래와 같다. 






메인에서 회사이름을 누르면 더 자세한 예측 결과를 보여주고 있다. 

아래 한국사이버결제와 지스마트글로벌은 같은 SVM을 예측 알고리즘을 사용하지만

기계학습 예측정확도와 기계학습에 사용한 자료가 다른 것으로 보아 

회사별로 다른 예측 알고리즘을 사용한 것으로 보인다. 







마지막으로 사용한 feature들에 대한 설명이다. 







대신증권 API - cybos marketeye 사용하기 (C#)

MarketEye class

 

 MarketEye

 

설명

주식,지수,선물/옵션 등의 여러종목의 필요 항목들을 한번에 수신합니다.

통신종류

Request/Reply

연속여부

X

관련 SB/PB

StockCur, FutureCurOnly, OptionCurOnly

관련CYBOS

[7059] MarketEye

모듈 위치

cpsysdib.dll

Method

object.SetInputValue(type,value)

type 해당하는 입력 데이터를 value 값으로 지정합니

  • type: 입력 데이터

0 - (long or long array) 필드 또는 필드 배열. 최대 64개의 필드까지 요청가

필드

0:종목코드(string)

1:시간( ulong) - hhmm

2:대비부호(char)

코드

내용

'1'

상한

'2'

상승

'3'

보합

'4'

'5'

3:전일대비(long or float) - 주의) 반드시 대비부호(2) 같이 요청을 하여야

4:현재가(long or float)

5:시가(long or float)

6:고가(long or float)

7:저가(long or float)

8:매도호가(long or float)

9:매수호가(long or float)

10:거래량( ulong)

11:거래대금(ulonglong) - 단위:

12:장구분(char or empty)

코드

내용

'0'

장전

'1'

동시호가

'2'

장중

13:총매도호가잔량(ulong)

14:총매수호가잔량(ulong)

15:최우선매도호가잔량(ulong)

16:최우선매수호가잔량(ulong)

17:종목명(string)

20:총상장주식수(ulonglong) - 단위:

21:외국인보유비율(float)

22:전일거래량(ulong)

23:전일종가(long or float)

24:체결강도(float)

25:체결구분(char or empty)

코드

내용

'1'

매수체결

'2'

매도체

27:미결제약정(long)

28:예상체결가(long)

29:예상체결가대비(long) - 주의) 반드시 예샹체결가대비부호(30) 같이 요청을 하여야

30:예상체결가대비부호(char or empty)

코드

내용

'1'

상한

'2'

상승

'3'

보합

'4'

'5'

31:예상체결수량(ulong)

32:19일종가합(long or float)

33:상한가(long or float)

34:하한가(long or float)

35:매매수량단위(ushort)

36:시간외단일대비부호(char or empty)

코드

내용

'+'

양수

'-'

음수

37:시간외단일전일대비(long) - 주의) 반드시 시간외단일대비부호(36) 같이 요청을 하여야

38:시간외단일현재가(long)

39:시간외단일시가(long)

40:시간외단일고가(long)

41:시간외단일저가(long)

42:시간외단일매도호가(long)

43:시간외단일매수호가(long)

44:시간외단일거래량(ulong)

45:시간외단일거래대금(ulonglong) - 단위:

46:시간외단일총매도호가잔량(ulong)

47:시간외단일총매수호가잔량(ulong)

48:시간외단일최우선매도호가잔량(ulong)

49:시간외단일최우선매수호가잔량(ulong)

50:시간외단일체결강도(float)

51:시간외단일체결구분(char or empty)

코드

내용

'1'

매수체결

'2'

매도체

53:시간외단일예상/실체결구분(char)

코드

내용

'1'

예상체결

'2'

54:시간외단일예상체결가(long)

55:시간외단일예상체결전일대비(long) - 주의) 반드시 시간외예상체결대비부호(56) 같이 요청을 하여야

56:시간외단일예상체결대비부호(char or empty)

코드

내용

'1'

상한

'2'

상승

'3'

보합

'4'

하락

'5'

하한

57:시간외단일예상체결수량(ulong)

59:시간외단일기준가(long)

60:시간외단일상한가(long)

61:시간외단일하한가(long)

62:외국인순매매(long)

63:52주최고가(long or float)

64:52주최저가(long or float)

65:연중주최저가(long or float)

66:연중최저가(long or float)

67:PER(float)

68:시간외매수잔량(ulong)

69:시간외매도잔량(ulong)

70:EPS(ulong)

71:자본금(ulonglong)- 단위:백만

72:액면가(ushort)

73:배당률(float)

74:배당수익률(float)

75:부채비율(float)

76:유보율(float)

77:자기자본이익률(float)

78:매출액증가율(float)

79:경상이익증가율(float)

80:순이익증가율(float)

81:투자심리(float)

82: VR(float)

83:5 회전율(float)

84:4 종가합(ulong)

85:9 종가합(ulong)

86:매출액(ulonglong) - 단위: 백만

87:경상이익(ulonglong) - 단위:

88:당기순이익(ulonglog) - 단위:

89:BPS(ulong) - 주당순자

90:영업이익증가율(float)

91:영업이익(ulonglong) - 단위:

92:매출액영업이익률(float)

93:매출액경상이익률(float)

94:이자보상비율(float)

95:결산년월(ulong) - yyyymm

96:분기BPS(ulong) - 분기주당순자

97:분기매출액증가율(float)

98:분기영업이액증가율(float)

99:분기경상이익증가율(float)

100:분기순이익증가율(float)

101:분기매출액(ulonglong) - 단위:

102:분기영업이익(ulonglong) - 단위:

103:분기경상이익(ulonglong) - 단위:

104:분기당기순이익(ulonglong) - 단위:

105:분개매출액영업이익률(float)

106:분기매출액경상이익률(float)

107:분기ROE(float) - 자기자본순이익

108:분기이자보상비율(float)

109:분기유보율(float)

110:분기부채비율(float)

111:최근분기년월(ulong) - yyyymm

112:BASIS(float)

113:현지날짜(ulong) - yyyymmdd

114:국가명(string) - 해외지수 국가

 

1 - (string or string array) 종목코드 또는 종목코드 배열. 최대 200종목까지 가능.
주의) 해외지수와 환율은 심볼코드를 입력하여야 ) JP#NI225:니케이지

 

2 - (char) 체결비교방식

코드

내용

'1'

체결가비교방식(default)

'2'

호가비교방

 

  • value: 새로 지정할

value = object.GetHeaderValue(type)

type 해당하는 헤더 데이터를 반환합니

  • type: 데이터

0 - (long) 필드

1 - (string array) 필드명의 배열 - 필드는 요청한 필드 값의 오름차순으로 정렬되어

2 - (long) 종목

  • 반환값: 데이터 종류에 해당하는

value = object.GetDataValue (Type,index)

type 해당하는 데이터를 반환합니

  • type: 요청한 필드의 index - 필드는 요청한 필드 값으로 오름차순으로 정렬되어

  • index: 요청한 종목의 index

object.Subscribe()

사용하지

object.Unsubscribe()

사용하지

object.Request()

해당하는 데이터를 요청한

object.BlockRequest()

데이터 요청.Blocking Mode

Event

Object.Received

해당하는 데이터를 수신했을 발생하는 이벤

 

 

대신증권의 cybos API를 사용해서 주식에 관련된 다양한 정보들을 수집할 수 있다.

일단 주식에서 수급 및 재무제표의 여러  항목들을 한번에 수신할 수 있는 MarketEye 클래스에 대해 알아보자.

 

사용 언어: C#

개발 툴: visual studio

 

 

static CPSYSDIBLib.MarketEye market = new CPSYSDIBLib.MarketEye();
 

 

 

new를 이용해 MarketEye의 인스턴스를 생성한다.

이제 MarketEye의 함수들을 사용할 수 있다.

물론 해당 라이브러리(CPSYSDIBLib)는 참조추가로 프로젝트에 추가가 되어있어야한다.

 

위 레퍼런스에 적혀있듯이 SetInputValue(type,value) 함수는 두 개의 input을 받는다.

Type은 원하는 정보 type을 지정하는 데 사용되며 long 또는 long array를 입력으로 넣을 수 있다.

각각의 type값은 위 클래스 함수 설명을 참조하기 바란다.

두번째 input은 종목코드 또는 종목코드 배열로 string 이나  string array를 사용한다. 

 

데이터 요청은 BlockRequest함수로 하고 반환받은 데이터는 GetDataValue 함수를 사용해서 사용할 수 있다.

첫번째 input값은 요청한 필드의 인덱스, 두번째 input값은 요청한 회사의 인덱스 값이다.

 

 

케이스 1) 액토즈소프트 회사의 EPS를 알아보자

 

     try
            {
                market.SetInputValue(0, 70);
                market.SetInputValue(1, "A003540");
                market.BlockRequest();
            }
            catch (Exception e)
            {
                return marketList;
            }
          

 

long EPS = market.GetDataValue(0, 0);

 

 

하나의 회사의 하나의 필드 정보만 필요하기에 배열없이 그대로 입력한다.

이럴 경우 GetDataValue의 인풋값은 0,0이 된다.

 

케이스 2) 여러 게임 회사들의 다양한 값들을 배열로 받아온다.

 

요청하는 타입을 배열로 저장하고 회사 종목코드들을 배열로 저장하여 setInputValue의 input값으로 전달한다.

GetHeaderValue 함수로 반환된 타입과 회사의 개수를 알 수 있다. 함수 대신 그냥 요청했던 배열 사이즈로 대신해도 된다.  

GetDataValue (Type,index)는 요청했던 데이터를 돌려주는 함수로

Type배열과 회사코드 배열의 인덱스 값을 인자로 사용하여 해당 회사코드의 타입 값을 리턴한다.  

 

회사 코드별로 파일을 따로 만들어 요일별로 요청했던 데이터를 해당 파일에 추가하려고 한다.

아래 코드를 보면 회사코드로 파일 이름을 만들고 요청했던 필드값들을 , 를 구분자로 하여 하나의 라인으로 만들어 파일에 추가하는 것을 확인할 수 있다.

 

            int[] type_array = { 0, 1, 2, 3, 4, 10, 11, 12, 17, 20, 21, 22, 23, 24, 25, 62, 67, 68, 69 };
            string[] company_array = { "A052790", "A078340", "A112040", "A181710" };
            try
            {
           
                    market.SetInputValue(0, type_array);
                market.SetInputValue(1, company_array);
                market.BlockRequest();

            }
            catch (Exception e)
            {
                string line = string.Format("{0},", e);
                MessageBox.Show(line);
              

            }


            int field_total = market.GetHeaderValue(0);
          int company_total = market.GetHeaderValue(2);


 

             for (int company_num = 0; company_num < company_total; company_num++)
            {
                string company_name = company_array[company_num];
                string filename = string.Format("marketeye_{0}.csv", company_name);
                string total_line = "";
                for (int field_num = 0; field_num < field_total; field_num++)
                {
                    string line = string.Format("{0},", market.GetDataValue(field_num, company_num));
                    total_line += line;

                }
                System.IO.File.AppendAllText(filename, total_line, Encoding.UTF8);
                System.IO.File.AppendAllText(filename, Environment.NewLine);
            
            }