딥러닝모델6 (A31) 설계

카테고리 없음 2016. 9. 30. 04:18

Bigdata-trader.com의 31번째 알고리즘(모델번호 A31이며 6번째 딥러닝 모델)을 개발하기 위한 연구 노트

목적
딥러닝 기술을 이용하여 급등주의 사전 조짐을 학습 가능한가 테스트 하기 위함. 여기서 급등주란 일반적인 우상향주가 아닌 장기간 소외되던 종목이 5일간 연속 으로 하루평균 10%이상의 가격 상승을 경험 한 종목으로 정의 하기로 함.

가설
주가의 급변(급 상승)은 새로운 호재 나 수익성 개선에 따른 예측 불가의 시장의 자연스러운 가격 변동이 아닌 특정 매수 세력의 의도된 행위의 결과이고, 매수 세력이 사전에 수년에서 수 개월간 해당 종목에서 준비를 한 후 행한 행위의 결과임을 가정. 이러한 준비 행위는 급등 직전 몇 달간의 거래 데이터를 기계 학습함으로써 포착 할 수 있는 특이한 패턴을 갖음을 가정 함. 

방법
과거 데이터에서 급등주를 필터링 및 수집함. 세력주 지수를 이용하여 20일 눌림목 지수 특정값 이상 종목중 급등주 정의에 해당하는 것만 선택. 급등전 강기간 소외 되었음을 확인 하는 루트 추가 필요. 1차 수집정보는 (종목번호와 급등 시작 날짜). 1차 수집 정보만을 ann_builder를 이용하여 2차 수집 정보를 수집함. 2차 수집 정보(시간, 주가, 국내외 인덱스, 외인 거래량, 외인 포션등)는 시계열 데이터로 생성하며 수집기간을 파라미터 입력으로 받아 디비에서 추출하여 ann_builder 입력 폼으로 변형. 어느정도의 수집 기간이 보장되어야 하므로 신규 종목은 제외되어야함 (수집 시작일에 데이터 시작일보다 이전인 종목 제외). 
네거티브 클래쓰 데이터로 급등주 외의 일반적 우상향주, 우하향주 등도 같이 모아야함.

서비스를 위해서는 트레이닝이 끝난 네트워크를 종목별로 파일로 저장하여 가지고 있어야 하는데 cafe24에서는 그들의 정책상 keras를 수행할 수 없을 듯. 자바만 가능하므로 A26~A30과 같이 A31과 관련된 모든 코드는 dl4j로 작성해야 할 듯.

추가적으로 개발해야 할 툴. 패키지에 util_rapidSoaringANNBuilder.java 추가. 박스권 상향 이탈과 동시에 급등하는 패턴을 찾는 유틸리티. 급등주의 조건이 까다로우므로 퀄리파이하는 루틴필요. 다음과 같은 순서로..

1) 새로운 테이블 추가: 다른 쪽에서도 공유할 수 있도록 패턴 이름으로 분리하여 저장 

mysql>create table patternfound
(
  patternname varchar(30) not null,
  itemcode varchar(8) not null,
  a varchar(10) not null,         // start date of soaring
  b varchar(10),    
  c varchar(10),    
  d varchar(10),
  primary key (patternname, itemcode, a) 
);

2) 매일 자동 업데이트시 세력지수 테이블내 모든 종목 추출 => 후보들

3) 후보들 중 원하는 패턴인가 qualify

4) qualify 리턴 값은 soaring starting date 임. 테이블의 a 에 저장

5) 장기간 수집 후 patternfound 테이블을 이용 디비 재검색하여 2차 데이터 수집

6) 2차 데이터이용 학습 데이터 생성

7) 학습 데이터 생성시 중복 체크 필수. 같은 "종목+startdate" 혹은 같은 종목코드인테 startdate가 근소하게 무의미하게 차이가 나는 레코드가 존재할 수 있으므로 확인 필요

 

 

 

posted by Dr.Deeeep

나만의 로보 어드바이저(robo-advisor) 만들기 [2]

금융 2016. 8. 30. 15:37

Python을 이용한 주가 데이터 크롤링

 

기본적으로 로보 어드바이저는 대용량의 주가 및 환경 데이터 + 지능적 트레이딩 알고리즘에 의해 구동된다. 따라서 나만의 로보 어드바이저를 만들기 위해서는 나만의 트레이딩 알고리즘을 구현할 수 있는 프로그램 능력과 대용량 데이터를 분석할 수 있는 분석 능력뿐 아니라 데용량 데이터를 수집할 수 있는 수집 능력이 필수 적이다. 따라서 주가 데이터의 크롤러가 필수적이다. 이 글에서는 주가 데이터의 크롤러 제작에 필요한 기술과 구현 방법에 대해 살펴보겠다.

 

공학도라면 서론을 길게 말하는것을 싫어한다. 결론 먼저, 설명 나중이므로. 먼저 쿨하게 내가 제작한 주가 데이터 크롤러 소스를 밑에 붙여 놓았다. 바쁜 사람은 그냥 카피해가서 바로 사용하면 된다. 안 바쁜 독자라면 계속 읽어보자.

 

이 코드는 파이썬으로 제작한 주가 데이터 크롤러이다. 로보 어드바이저는 두가지 크롤러가 필요한데, 롱텀 크롤러와 실시간 크롤러가 그것이다. 롱텀 크롤러는 처음 로보 어드바이저를 기동하기 위해 최초 한번은 몇 년치 주가 데이터를 한꺼번에 크롤링 하는 작업이 필요한데 그때 사용하기 위한 크롤러 이다. 밑에 소스는 롱텀 크롤러 소스이다. 이 후에는 변경(추가)된 데이터만을 매일매일, 혹은 실시간으로, 가져오는 간략화된(속도가 빠른) 실시간 크롤러가 필요한데 그것은 나중에 올리기로 한다. 물론 롱텀 그롤러와 실시간 크롤러는 비슷한 코드로 구성된다. 단지 용도에 맞게 프로그램 흐름도가 조금 다를뿐이다.

 

이 크롤러는 CybosPlus와 Python으로 구현되었다. CybosPlus는 대신증권에서 제공하는 시스템 트레이딩을 위한 API이다. CybosPlus에 대한 정보는 쉽게 찾아 볼 수 있으므로 생략하기로 한다.

 

(임시저장...)

 

 

 

 

#
# Developed by "Dr.Deeeep"
#
# intelligent version of crawler, in this version
#   - it check the last day of item in the database and crawling from the last day.
#   - the data of last day will be overwritten because they may are not the final value
#

 

import time
import mysql.connector
import win32com.client

config = {
  'user': 'USERID',
  'password': 'PASSWORD',
  'host': 'yourhost.com',
  'database': 'DBNAME',
  'raise_on_warnings': True,
}
# Don't forget to change the server setting to arrow remote connection to MySQL.
# mysql examples are available at
# https://dev.mysql.com/doc/connector-python/en/connector-python-examples.html
cnx = mysql.connector.connect(**config)
cursor = cnx.cursor()

 

cpcybos = win32com.client.Dispatch("CpUtil.CpCybos")

if cpcybos.IsConnect == 1:
    print("Cybos connection succeeded")
else:
    print("Cybos connection failed")

   
inStockCode = win32com.client.Dispatch("CpUtil.CpStockCode")    # general stock item info
inStockMst = win32com.client.Dispatch("dscbo1.StockMst")        # Current data
inStockChart = win32com.client.Dispatch("CpSysdib.StockChart")  # Past Data

totalItemNumInCybosPlus = inStockCode.GetCount()
print("Total number of items = ",totalItemNumInCybosPlus)

# print all items in BT format
# Some variables, such as changerate, fortramt, totaltraceprice, should be calculated on the fly, thus filled with dummy '-999.0'

 

#itemcode
finalpriceArray = []        #inStockChart.SetInputValue(5, 5)
startpriceArray = []        #inStockChart.SetInputValue(5, 2)
highpriceArray = []         #inStockChart.SetInputValue(5, 3)
lowpriceArray = []          #inStockChart.SetInputValue(5, 4)
changerateArray = []         #inStockChart.SetInputValue(5, 6)       may need to calculate from (today final / yesterday final)
tramtArray = []             #inStockChart.SetInputValue(5, 8)
orgtramtArray = []          #inStockChart.SetInputValue(5, 20)      THIS data is not complete in cybosdb. cannot use..
fortramtArray = []          # -999.0 #inStockChart.SetInputValue(5, ???) may need to cal from (today fortotal - yesterday fortotal)
fortotalArray = []          #inStockChart.SetInputValue(5, 16)
forportionArray = []        #inStockChart.SetInputValue(5, 17)
totaltradepriceArray = []   # -999.0    #inStockChart.SetInputValue(5, 0) may need to cal from (tramt * final price)

#beyond BT Format
circulationrateArray = []   #inStockChart.SetInputValue(5, 25)
totalstocknumArray = []     #inStockChart.SetInputValue(5, 12)
sichongArray = []           #inStockChart.SetInputValue(5, 13)


###################################################
#
#   This number represents the number of record to crawl for each cybosplus access
#   Must be large enough to cover the gap between the last date in my db and today while keep small enough to prevent the waste of speed of cybosplus access.
numOfCrawling = 200        # n days
#
#   This string number is the starting itemcode for the case of resuming suspened, quitted, crawling job
startingItemCode = "000000"    # 000000 for new start
#
#
###################################################


currentItemIndex = -1
for aItemcode in range(0, inStockCode.GetCount()):   # for each itemcode
    currentItemIndex = currentItemIndex + 1
    print("### progress = ", ((currentItemIndex * 100) / totalItemNumInCybosPlus), " %")
                     
    dateToCrawlArray = []       #inStockChart.SetInputValue(5, 0)

    # this line print just the item code and name
    # print(inStockCode.GetData(0,i), inStockCode.GetData(1,i), inStockCode.GetData(2,i))

    itemcode = inStockCode.GetData(0,aItemcode)

    # this can be used for resuming suspended process
    # THIS may not necessary for intelligent version of crawler
    if itemcode < "A"+startingItemCode:
        print("Skipping "+itemcode)
        continue

    inStockChart.SetInputValue(0, itemcode)

    ## retrieve LAST DATE in DB of this itemcode ==========================
    ## if no data for this item, set the last date to 20050101
   
    print ("itemcode = ", itemcode)
    shortItemcode = itemcode[1:]

    sqlStr = ("select max(date) from datatable where itemcode='"+ shortItemcode+ "'")

    #print("sqlStr = ", sqlStr, ", newItemcode = ", shortItemcode)
    cursor.execute(sqlStr)

 

    #######################################
    # modified source
    row = cursor.fetchone()
    if row[0]:
        lastDateInMyDB = row[0]
    else:                           # Null. number of returned row is 0. no data in DB.
        print ("itemcode = ", itemcode, " is added newly... skipping..")
        print ("TODO:  add code here to handle newly added items. !!!!!!!!!!!!")
        continue
    #######################################

 


    ## retrieving LAST DATE in CybosPlus ========================
    inStockChart.SetInputValue(1, '2')  # retrieve by num of records
    inStockChart.SetInputValue(4, 1)    # num of record to retrive is. Just the last one
    inStockChart.SetInputValue(5, 0)    # field type, tr amt(8), finalprice(5), date(0)
    inStockChart.SetInputValue(6, ord('D')) # chart type,  by Day
    inStockChart.SetInputValue(9, '0')  # modified price? yes. 0 for no
    inStockChart.BlockRequest()
    lastDateInCybosPlus = inStockChart.GetDataValue(0,0)
    print("in itemcode = ", itemcode, ", The latest data in CybosPlus = ", lastDateInCybosPlus)


#TODO:
#    dateToCrawlArray = retieve DATE array from lastDateInMyDB to lastDateInCybosPlus

#    for aDate in dateArray:
#        do the same with other crawlers


    ## retireve dateToCrawlArray
    print("in itemcode = ", itemcode, ", Now retrieving Date2Crawl array...")
    inStockChart.SetInputValue(1, '1')  # retrieve by num of specified date
    inStockChart.SetInputValue(3, lastDateInMyDB) # starting date
    inStockChart.SetInputValue(2, lastDateInCybosPlus) # ending date
    inStockChart.SetInputValue(4, numOfCrawling) # get some data which number is given
    inStockChart.SetInputValue(5, 0)    # field type, tr amt(8), finalprice(5), date(0)
    inStockChart.SetInputValue(6, ord('D')) # chart type,  by Day
    inStockChart.BlockRequest()

    numofdate2Crawl = inStockChart.GetHeaderValue(3)    # num of rec retrieved
    print("in itemcode = ", itemcode, ", Num of DATE to crwal = ", numofdate2Crawl, " From = ", lastDateInMyDB, " to = ", lastDateInCybosPlus)
    for i in range(numofdate2Crawl):
        volumn = inStockChart.GetDataValue(0,i)
        dateToCrawlArray.insert(0, volumn)
        if int(volumn) <= int(lastDateInMyDB):
            break

    print("in itemcode = ", itemcode, ", dateToCrawArray = ", dateToCrawlArray)

    for aCrawlDate in dateToCrawlArray:
       
        ## retrieving FINALPRICE =========================
        inStockChart.SetInputValue(1, '1')  # retrieve by num of specified date
        inStockChart.SetInputValue(3, aCrawlDate) # starting date
        inStockChart.SetInputValue(2, aCrawlDate) # ending date
        inStockChart.SetInputValue(4, 1) # get a data
        inStockChart.SetInputValue(5, 5)    # finalprice(5)
        inStockChart.SetInputValue(6, ord('D')) # chart type,  by Day
        inStockChart.SetInputValue(9, '0')  # modified price? yes. 0 for no
        inStockChart.BlockRequest()
        numofreturned_finalprice = inStockChart.GetHeaderValue(3)    # num of rec retrieved
        #print(" Num of retrieved record (FP) = ", numofreturned_finalprice)
        if (numofreturned_finalprice > 0):
            finalprice = inStockChart.GetDataValue(0,0)  
            #print("     final price was ", finalprice)
        else:
            finalprice = '-999.0'
            print(itemcode, "     No data. default final price: -999.0")


        ## retrieving STARTPRICE ============================
        inStockChart.SetInputValue(1, '1')  # retrieve by num of specified date
        inStockChart.SetInputValue(3, aCrawlDate) # starting date
        inStockChart.SetInputValue(2, aCrawlDate) # ending date
        inStockChart.SetInputValue(4, 1) # get a data
        inStockChart.SetInputValue(5, 2)    # startprice
        inStockChart.SetInputValue(6, ord('D')) # chart type,  by Day
        inStockChart.SetInputValue(9, '0')  # modified price? yes. 0 for no
        inStockChart.BlockRequest()
        numofreturned_startprice = inStockChart.GetHeaderValue(3)    # num of rec retrieved
        #print(" Num of retrieved record (SP) = ", numofreturned_startprice)
        if (numofreturned_startprice > 0):
            startprice = inStockChart.GetDataValue(0,0)      
            #print("    start price was ", startprice)
        else:
            startprice = '-999.0'
            print(itemcode, "              No data. default START PRICE : -999.0")


        ## retrieving HIGHPRICE ============================
        inStockChart.SetInputValue(1, '1')  # retrieve by num of specified date
        inStockChart.SetInputValue(3, aCrawlDate) # starting date
        inStockChart.SetInputValue(2, aCrawlDate) # ending date
        inStockChart.SetInputValue(4, 1) # get a data
        inStockChart.SetInputValue(5, 3)    # highprice
        inStockChart.SetInputValue(6, ord('D')) # chart type,  by Day
        inStockChart.SetInputValue(9, '0')  # modified price? yes. 0 for no
        inStockChart.BlockRequest()
        numofreturned_highprice = inStockChart.GetHeaderValue(3)    # num of rec retrieved
        #print(" Num of retrieved record (HP) = ", numofreturned_highprice)
        if (numofreturned_highprice > 0):
            highprice = inStockChart.GetDataValue(0,0)      
            #print("    high price was ", highprice)
        else:
            highprice = '-999.0'
            print(itemcode, "                 No data. default HIGH PRICE: -999.0")

 

        ## retrieving LOWPRICE ============================
        inStockChart.SetInputValue(1, '1')  # retrieve by num of specified date
        inStockChart.SetInputValue(3, aCrawlDate) # starting date
        inStockChart.SetInputValue(2, aCrawlDate) # ending date
        inStockChart.SetInputValue(4, 1) # get a data
        inStockChart.SetInputValue(5, 4)    # lowprice
        inStockChart.SetInputValue(6, ord('D')) # chart type,  by Day
        inStockChart.SetInputValue(9, '0')  # modified price? yes. 0 for no
        inStockChart.BlockRequest()
        numofreturned_lowprice = inStockChart.GetHeaderValue(3)    # num of rec retrieved
        #print(" Num of retrieved record (LowP) = ", numofreturned_lowprice)
        if (numofreturned_lowprice > 0):
            lowprice = inStockChart.GetDataValue(0,0)      
            #print("    low price was ", lowprice)
        else:
            lowprice = '-999.0'
            print(itemcode, "                   No data. default LOW PRICE: -999.0")

 

        ## retrieving CHANGERATE ============================
        changerate = '-999.0'     
        #print("    changerate was ", changerate)


        ## retrieving TRAMT ============================
        inStockChart.SetInputValue(1, '1')  # retrieve by num of specified date
        inStockChart.SetInputValue(3, aCrawlDate) # starting date
        inStockChart.SetInputValue(2, aCrawlDate) # ending date
        inStockChart.SetInputValue(4, 1) # get a data
        inStockChart.SetInputValue(5, 8)    # tramt
        inStockChart.SetInputValue(6, ord('D')) # chart type,  by Day
        inStockChart.SetInputValue(9, '0')  # modified price? yes. 0 for no
        inStockChart.BlockRequest()
        numofreturned_tramt = inStockChart.GetHeaderValue(3)    # num of rec retrieved
        #print(" Num of retrieved record (TRAMT) = ", numofreturned_tramt)
        if (numofreturned_tramt > 0):
            tramt = inStockChart.GetDataValue(0,0)      
            #print("    tramt was ", tramt)
        else:
            tramt = '-999.0'
            print(itemcode, "                     No data. default TRAMT: -999.0")

 

 

        ## retrieving ORGTRAMT ============================
        inStockChart.SetInputValue(1, '1')  # retrieve by num of specified date
        inStockChart.SetInputValue(3, aCrawlDate) # starting date
        inStockChart.SetInputValue(2, aCrawlDate) # ending date
        inStockChart.SetInputValue(4, 1) # get a data
        inStockChart.SetInputValue(5, 20)    # org tramt
        inStockChart.SetInputValue(6, ord('D')) # chart type,  by Day
        inStockChart.SetInputValue(9, '0')  # modified price? yes. 0 for no
        inStockChart.BlockRequest()
        numofreturned_orgtramt = inStockChart.GetHeaderValue(3)    # num of rec retrieved
        #print(" Num of retrieved record (ORG TRAMT) = ", numofreturned_orgtramt)
        if (numofreturned_orgtramt > 0):
            orgtramt = inStockChart.GetDataValue(0,0)      
            #print("    orgtramt was ", orgtramt)
        else:
            orgtramt = '-999.0'
            print(itemcode[1:], "                      No data. default ORG TRAMT: -999.0")
           

        ## retrieving FORTRAMT ============================
        fortramt = '-999.0'     
        #print("    fortramt was ", fortramt)

 

        ## retrieving FORTOTAL ============================
        inStockChart.SetInputValue(1, '1')  # retrieve by num of specified date
        inStockChart.SetInputValue(3, aCrawlDate) # starting date
        inStockChart.SetInputValue(2, aCrawlDate) # ending date
        inStockChart.SetInputValue(4, 1) # get a data
        inStockChart.SetInputValue(5, 16)    # startprice
        inStockChart.SetInputValue(6, ord('D')) # chart type,  by Day
        inStockChart.SetInputValue(9, '0')  # modified price? yes. 0 for no
        inStockChart.BlockRequest()
        numofreturned_fortotal = inStockChart.GetHeaderValue(3)    # num of rec retrieved
        #print(" Num of retrieved record (FORTOTAL) = ", numofreturned_fortotal)
        if (numofreturned_fortotal > 0):
            fortotal = inStockChart.GetDataValue(0,0)      
            #print("    fortotal was ", fortotal)
        else:
            fortotal = '-999.0'
            print(itemcode, "                          No data. default FORTOTAL: -999.0")

       

        ## retrieving FORPORTION ============================
        inStockChart.SetInputValue(1, '1')  # retrieve by num of specified date
        inStockChart.SetInputValue(3, aCrawlDate) # starting date
        inStockChart.SetInputValue(2, aCrawlDate) # ending date
        inStockChart.SetInputValue(4, 1) # get a data
        inStockChart.SetInputValue(5, 17)    # startprice
        inStockChart.SetInputValue(6, ord('D')) # chart type,  by Day
        inStockChart.SetInputValue(9, '0')  # modified price? yes. 0 for no
        inStockChart.BlockRequest()
        numofreturned_forportion = inStockChart.GetHeaderValue(3)    # num of rec retrieved
        #print(" Num of retrieved record (FORPORTION) = ", numofreturned_forportion)
        if (numofreturned_forportion > 0):
            forportion = inStockChart.GetDataValue(0,0)
            forportion = float("{0:.4f}".format(forportion))
            #print("    forportion was ", forportion)
        else:
            forportion = '-999.0'
            print(itemcode, "                          No data. default FORPORTION: -999.0")

       

        ## retrieving TOTALTRADEPRICE ============================
        totaltradeprice = '-999.0'   
        #print("    total trade price was ", totaltradeprice)


        ## retrieving CIRCULATIONRATE ============================
        circulationrate = '-999.0'   
        #print("    circulation rate was ", circulationrate)
       

        ## retrieving TOTALSTOCKNUM ============================
        inStockChart.SetInputValue(1, '1')  # retrieve by num of specified date
        inStockChart.SetInputValue(3, aCrawlDate) # starting date
        inStockChart.SetInputValue(2, aCrawlDate) # ending date
        inStockChart.SetInputValue(4, 1) # get a data
        inStockChart.SetInputValue(5, 12)    # startprice
        inStockChart.SetInputValue(6, ord('D')) # chart type,  by Day
        inStockChart.SetInputValue(9, '0')  # modified price? yes. 0 for no
        inStockChart.BlockRequest()
        numofreturned_totalstocknum = inStockChart.GetHeaderValue(3)    # num of rec retrieved
        #print(" Num of retrieved record (TOTALSTOCKNUM) = ", numofreturned_totalstocknum)
        if (numofreturned_totalstocknum > 0):
            totalstocknum = inStockChart.GetDataValue(0,0)      
            #print("    totalstocknum was ", totalstocknum)
        else:
            totalstocknum = '-999.0'
            print(itemcode, "                     No data. default TOTALSTOCKNUM: -999.0")
           


        ## retrieving SICHONG ============================
        inStockChart.SetInputValue(1, '1')  # retrieve by num of specified date
        inStockChart.SetInputValue(3, aCrawlDate) # starting date
        inStockChart.SetInputValue(2, aCrawlDate) # ending date
        inStockChart.SetInputValue(4, 1) # get a data
        inStockChart.SetInputValue(5, 13)    # startprice
        inStockChart.SetInputValue(6, ord('D')) # chart type,  by Day
        inStockChart.SetInputValue(9, '0')  # modified price? yes. 0 for no
        inStockChart.BlockRequest()
        numofreturned_sichong = inStockChart.GetHeaderValue(3)    # num of rec retrieved
        #print(" Num of retrieved record (SICHONG) = ", numofreturned_sichong)
        if (numofreturned_sichong > 0):
            sichong = inStockChart.GetDataValue(0,0)      
            #print("    sichong was ", sichong)
        else:
            sichong = '-999.0'
            print(itemcode, "                No data. default SICHONG: -999.0")
       

        #sqlStr = ("insert into cybosplus date="+str(aCrawlDate)+", itemcode="+itemcode[1:]+", finalprice="+str(finalprice)+", startprice="+str(startprice))
        #print("insert sqlStr = ", sqlStr)

        add_record = ("insert into datatable "
                      "(date, itemcode, finalprice, startprice, highprice, lowprice, changerate, tradeamount, orgtradeamount, fortradeamount, fortotalamount, forportion, totaltradeprice, totalstocknum, sichong) "
                      "values (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) "
                      "on duplicate key update "
                      "finalprice=%s, startprice=%s, highprice=%s, lowprice=%s, changerate=%s, tradeamount=%s, orgtradeamount=%s, fortradeamount=%s, fortotalamount=%s, forportion=%s, totaltradeprice=%s, totalstocknum=%s, sichong=%s")
             
        data_record = (aCrawlDate, itemcode[1:], finalprice, startprice, highprice,
                       lowprice, changerate, tramt, orgtramt, fortramt,
                       fortotal, forportion, totaltradeprice, totalstocknum, sichong,
                       finalprice, startprice, highprice,
                       lowprice, changerate, tramt, orgtramt, fortramt,
                       fortotal, forportion, totaltradeprice, totalstocknum, sichong)

        cursor.execute(add_record, data_record)
        cnx.commit()       

cursor.close()
cnx.close()

 


 

posted by Dr.Deeeep

나만의 로보 어드바이저(robo-advisor) 만들기 [1]

상념 2016. 8. 30. 15:06

로보 어드바이저란? 

 

 

 

 

 

새로운 용어는 아니지만 요즘 뜨고 있는 로보 어드바이저 (robo-advisor)라는 기술. 쉽게 말해 인공지능 기술을 이용하여 자신이 원하는 알고리즘으로 컴퓨터가 주식 거래를 자동으로 수행하도록 하는 기술이다. 물론 이것은 내 나름의 좁은 해석이고 원래는 더 넓고 좋은 의미가 있을것이다. 그런 글은 위키페디아를 참조.

 

빅데이터, 딥러닝, 머신러닝 등등 신조어를 만들기 좋아하는 요즘시대에 로보 어드바이저는 인공지능과 금융이라는 인간의 흥미와 욕망에 부합하여 차세대 대세어로 부족함이 없다. 

 

나는 로보 어드바이저라는 말은 처음 들어본것이 한달 정도 된 듯하다. 처음에는 무슨 신조어인가 했지만 뜻을 알고 나서는.. 흠. 이런 기술은 이미 금융 공학을 공부하거나 데이터 분석을 하는 사람들에게는 오래전부터 있었던 개념이다. 단지 "인공지능"과 "빅데이터"와 같이 현시대 최첨단을 걷는 기술들이 결합되면서 그동안의 데이터 분석에만 집중하던 금융기술이 이제 분석과 기계학습을 이용한 좀더 지능적인 의미로 떠오른 것이다. 

 

로보 어드바이저라는 개념이 원래는 더 넓은 개념의 더 좋은 뜻도 많이 있겠지만, 좁은 의미인 "빅데이터에 기반한 인공 지능 트레이딩 로봇"을 만드는 방법에 대해 연재해보도록 하겠다. 나는 이러한 로봇은 이미 수년전에 개발하여 사용하고 있다. 한때는 실전에 적용하여 트레이딩을 해보기도 했지만 튜닝없이 바로 운영을 하려니 성공률이 낮아 현재는 일단 시뮬레이션만 수행하며 실제 거래는 로봇이 만드는 리포트를 보고 수동으로 수행하고 있다.

 

나만의 로보어드바이저의 개발에 필요한 준비물을 알아보자.

 

Python 

자바

VC++ 6.0 이상

CybosPlus (대신증권계좌필요)

MySQL

 

 

 

CybosPlus 는 대신증권에서 제공하는 개발자를 위한 트레이딩용 API로 자바, python, c++ 등에서 사용할 수 있다. 빠르게는 초당 10회 정도 트레이딩을 할 수 있다. 무엇보다도 실시간 가격을 가져온다든가 처음 수년간의 데이터(빅데이터)를 구축하기 위해 필요하다.

 

일단 여기 까지...

 

 

 

posted by Dr.Deeeep

딥러닝 for 트레이딩

금융 2016. 8. 18. 02:38

트래이딩분야에 적용된 딥러닝 기술

 

그 동안 개인적으로 테스트해 본 트래이딩에서의 딥러닝 알고리즘은 그닥 효과가 좋지 못하다. 트래이딩 알고리즘의 시뮬레이션을 위해 구축한 웹페이지 (http://www.bigdata-trader.com/simulation_preview.jsp?month=00000000)에서 확인할 수도 있는데, 딥러닝 모델(현재 A26부터 A30까지 5개 모델이 딥러닝 모델, 나머지는 전통적 트레이딩 알고리즘)의 단타 매매 성공율은 겨우 60퍼센트 정도에 미치고 있다. 물론 딥러닝 모델은 아직 2개월 정도밖에 운영하지 않았지만 몇 년을 돌려도 크게 바뀔거 같지는 않다. 이 정도의 performance는 전통적 방법의 트래이딩 알고리즘(예를 들면 A14나 A4)보다도 훨씬 뒤쳐지는 성적이다.

 

 

 

참고로 각 알고리즘은 DBN을 이용하여 72개월간 다음 데이터를 학습한며, 매일 10거래일 전 발행한 추천 종목의 성적을 평가한다.

A26: 주가

A27: 주가+인덱스

A28: 주가변동률+인덱스변동률

A29: 주가변동률+거래량+외인거래량

A30: 주가변동률+거래량+외인거래량+외인보유portion

 

다양한 딥러닝 아키텍춰를 추가해서 LSTM 등을 이용할 계획이긴 하지만 크게 향상될것 같지는 않다. 아키텍춰보다는 데이터나 모델을 바꿔야 할듯.

 

USC의 Greg Harris 가 트래이딩 분야에 적용된 딥러닝 기술을 잘 정리를 해둔것을 발견하여 정리해본다. 원문은 http://gregharris.info/a-survey-of-deep-learning-techniques-applied-to-trading/

 

(요약 할것)

1. Limit order book modeling

 

2. price-based classification models

 

3. Text-based Classification models

 

4. Volatility Prediction

 

5. Portfolio Optimization

 

각 모델별로 아키텍춰를 달리한 논문들을 소개하고 있는데 내 시스템에 적용 가능한것부터 하나하나 테스트 해볼 생각이다.

 

========== continued..

 

일단 위에 열거된 다른 연구자들의 결과를 보고 놀라운 점은 수익 성공률이 53% 정도 밖에 안된다는 것. 내가 구현한 딥러닝 모델보다도 조금 더 나쁘고 A4나 A14보다도 훨씬 안좋다. 하지만 위 요약을 읽으면서 몇가지 새로운 모델에 대한 구상이 떠올라서 구현해보기로 한다.

 

1. 먼저 리턴(closing price - opening price)이라는 개념. 나의 예측 모델들은 모두 regression problem에 집중한데 반해 리턴이란 개념으로 접근한다면 classification 문제가 된다. + 일것이냐 - 일것이냐의 classification. 사실 class 수를 더 늘려서 regression 처럼 학습할 수 있지만. 어쩄든. 그게 중한게 아니고. return을 계산하기 위해서는 opening price 를 알아야 하는데. 이런식으로 하려면 실시간 시스템이어야 한다. 종가 확인 후 하루 한번 예측을 수행하는 일(daily) 베이스의 bigdata trader 시스템에서는 적용할 수 없다. opening price를 무시한다면 성공률이 50%로 수렴할 것이 뻔하다. 서비스 용도말고 관리자창에 테스트 용도로 장중 opening price를 입력 받아 return을 얻어내는 실험 모듈을 추가해야겠다.

  - 조금 더 생각해보니 "종목 상세 보기"에서는 사용자 입력 후 해당 종목에 한 해 실시간 장중가를 가져 올 수 있으니 그날의 리턴을 계산할 수도 있겠다.

 

2. Text 기반 classification

경제면 headline 들과 개별 종목 등락을 학습한다는 개념. 말그대로 bigdata trader의 기본 개념인데... sns 대신 경제면 headline 을 학습한다는 것.

 

3. moving box learning

DBN 을 써서 oscillating box를 학습 한다는 것인데. 학습이고 뭐고를 떠나 이 전략은 전략 자체의 validation 이 필요하다고 본다. 박스 바닥 뚫고 진입시 매수, 박스 바닥 뚫고 진출수 매도. 그러나 박스권의 설정 자체가 이미 후행적이고 결과론 적이다. oscillating box 이론이 잘 맞는 종목도 있을테니 선택적으로 적용한다면 시도해볼만 하다. 각 종목이 얼마나 oscillating box 이론에 일치하는가 평가하는 모듈이 먼저 필요하다.

 

(임시저장)

 

 

 

 

 

 

 

posted by Dr.Deeeep