본문 바로가기

퀀트투자 A to Z

QQQ 실시간 주가 예측 모델을 이용한 데이트레이딩 도전기: 게임처럼 느껴지는 전략과 모델 테스트

반응형

기존에 1,2,3편으로 블로그가 나누어져있었는데 하나로 합쳤습니다.

1편 (초기계획)

투자에 입문한 이래 투자가 성공했을때 수익이 발생하는것에서 느끼는 기쁨도 있지만 내가 만드는 새로운 투자전략과 투자에사용하는 모델을 테스트하는 것이 나에게는 게임에서 퀘스트를 하나씩 클리어 하는것과 비슷한 감정을 느끼게 해준다. 다음 퀘스트로 도전해보려고하는것은 QQQ 주가예측모델을 이용한 데이트레이딩이다. 

원하는 output

telegram봇을 통해 현재가, 등락률, 오를확률을 N초단위로 notify한다.

QQQ-머신러닝-당일등락률예측
머신러닝 모델을 활용한 주가예측

투자전략 아이디어

  • 데이트레이딩 목적
  • QQQ 예측모델로 TQQQ에 투자할지 SQQQ에  투자할지 결정하여 투자한다.
  • 주식 N개씩 분할 매수한다. 
  • 투자는 미래에셋증권 MTS를 이용하고 Trailing Stop(추적손절매)를 사용하여 자동 매도한다

Trailing Stop(추적손절매) 상승추세시 매도하지 않으며, 상승시 고점에 대비하여 N% 지점으로 자동매도 손절가를 점차 높여서 셋팅 된다. 사실 지금까지는 Trailing Stop기능을 사용하지 않고 수동으로 자동매도 손절가격을 변경해 주었었는데...... 검색해보니 추적손절매 기능이 내가 수동으로 감시가격을 변경하던것을 자동으로 처리해준다는 것을 오늘 알게되었다..... 아직 추적손절매 기능을 사용한적이 없어서 실제로 내가 이해한 작동방식이 맞는지는 한번더 테스트할 필요성이 있어보인다. 확실하게하기위해 미래에셋에 전화해서 확인하려고한다.

 

미래애셋증권-자동매매설정화면
미래에셋 MTS 자동매도화면

 

왜 QQQ예측인가?

  • SQQQ와TQQQ가 존재하므로 상승장과 하락장에 모두 사용할수있는 장점이 있다.
  • 미국 나스닥 100 지수를 추종하는 ETF이기 때문에, 미국 주식 시장의 전체적인 흐름을 반영합니다. 따라서 QQQ의 흐름을 예측함으로써 미국 주식 시장의 전체적인 흐름을 예측할 수 있다. 기존 퀀트 백테스트로 선택한 주식종목에 투자시기가 모호한 경우, QQQ 예측 모델을 활용하면 전체 시장의 움직임을 예측하여 주식을 사는 타이밍을 더 적절하게 조절할 수 있다고 생각한다.

왜 미래에셋증권인가?

신규 계좌개설 이벤트로 미래에셋과 하이투자증권 모두 수수료무료로 이용가능한데(둘다 테스트 해본결과 sec fee까지도 모두 면제되는듯하다) 하이투자증권이 환율우대 조건이 더 좋음에도 불구하고 해외주식의 자동매수/매도 기능을 지원하지 않아서 미래에셋증권을 선택하였다.(나에게는 매우 중요한 기능) 특히 이번에 테스트할 추적손절매 기능은 매우 유용하게 쓰일수 있다고 생각한다. 미래에셋증권의 경우 현재 매수/매도 현재 모두 무료이지만 2023년10월6일 부터는 이벤트 적용기간이 지나 매수 수수료만 무료가 2023년 말까지 적용이된다. 그러므로 수수료가 무료일때 최대한 빠르게 테스트해볼 생각이다. 

 

예측모델의 목표

확실히 해두자면 내가 원하는것은 정확한 주가 예측이아니다. 또한 api를 이용한 자동매매 프로그램도 아니다. 단지 필요한 정보는 확률적으로 오를 확률이 더 높은지 내릴 확률이 더 높은지 실시간으로 확인하는 것이다. 

 

계획

우선순위를 높여서 개발을 진행할 생각이다. 데이트레이딩의 경우 매수매도 수수료가 없을때 최대의효과가 발휘한다고 생각되기때문이다. 

 

P.S.

왜 나는 TQQQ보다 SQQQ에 애증이 가는지 모르겠다.

 

추가글(20230907)

(실제output은 개발중 오를 확률에서 예측등락률로 변경하였다. ) 다른 우선순위가 있어서 개발을 미루고 미루다가 마음먹은지 1일도 안걸려서 prototype version이 완성되어버렸다. 추후 실제 어떻게 개발했는지 간략하게 설명하는 글을 쓰도록 하겠다. 추후 여러가지 feature를 테스트 할 예정이다.

QQQ-머신러닝-당일등락률예측-2
메시지내용: 주식 Ticker 현재가(등락률) 예측가(예측등락률)

 

2편(분석&모델링)

혹시 내용을 보고 무슨 5분만에 데이터습득을 하고 5분만에 분석을 하고 하루만에 개발을 끝내냐고 생각하는분들이 있을까봐 추가로 설명하자면 장기간 아이디어와 개념을 정리하고 메모를 매일매일 하는 노력에대한 설명이 없을뿐이지 많은 노력을 하여 만드는 결과물이라는것을 알아주셨으면 좋겠다. 

 

feature 선정 기준

  • 실제 사용할 feature의 real time 데이터를 구할수있는가? api든 스크래핑이든 최대 1분 이내에 갱신 가능하여야 한다.
  • 과거 일자별 데이터를 최소 N 년치를 구할 수 있는가? 
  • qqq주가와 상관관계가 있는가?
  • 얼마나 독립적인가?
  • feature는 qqq주가에 비해 얼마나 선행되는 지표라고 생각하는가?
  • 나의 가설(실제 qqq주가는 OOO이 주도한다)에 근거하여 feature선정

feature 5분 초간단 데이터 습득

  • 누구나 5분 만에 습득가능한 데이터로 준비하였다. 습득방법은 영업비밀이다. 하지만 힌트는 '구글은 신이다'로 하겠다. 혹시라도 힌트를 듣고도 모르겠고 궁금하시다면 댓글을 주시면 알려드리도록 하겠다.

feature 5분 초간단 분석

  • 구글 시트상에서 피어슨 상관관계로 초간단 분석진행(5년 치 데이터를 확보할 수 있는 약 20개 정도의 feature에 대해 분석하였다.)
  • 구글시트의 CORREL함수는  피어슨상관관계 함수이며 -1 ~ 1을 리턴한다. 두 행렬의 개수가 똑같아야 하며 한쪽에 빈셀이 있다면 계산 시에는 무시하니 데이터가 있는 행전체를 선택해도 무관하다. 굳이 R이나 python까지 쓰지 않아도 충분히 간단히 분석 가능하다. 

구글시트-피어슨상관관계-QQQ-주가예측

산점도(scatter plot) 확인

상관관계가 있다고 나와도 실제데이터는 아웃라이어가 존재한다거나 선형이 아니라거나 하는 경우가 있기 때문에 산점도를 직접 눈으로 확인하였다. (초스피드 산점도 확인하는 방법 = tablaeu를 이용 ) 

tableau-산점도-qqq-주가예측
tablaeu를 이용한 산점도(scatter plot)체크

물론 구글시트에서도 아래 그림과 같이 산점도 확인이 가능하다.

구글시트-산점도-qqq-주가예측
구글시트 산점도(scatter plot)체크

신경망모델 저장

Jupyter에서 텐서플로우 신경망 모델을 작성하여 local에 저장한다. 저장하면 directory가 생성된다.

model.save('first_model')

텐서플로우-신경망-모델-directory
모델 local 저장

모델로드 샘플

model = tf.keras.models.load_model('first_model')
new_record={'X1': ['0.1447739066'], 'X2': ['0.03'], 'X3': ['-0.002426623527'], 'X4': ['0'], 'X5': ['0'], 'X6': [-0.024736537399210702]}
new_df = pd.DataFrame(new_record)
test_predictions = model.predict(new_df.astype(np.float32))
print(test_predictions[0][0])

 

실시간 예측 샘플

def predict(features, worksheet, model):
    feature_keys = worksheet.row_values(1)
    feature_values = worksheet.row_values(4)
    new_record = {key: [value] for key, value in zip(feature_keys[1:], feature_values[1:])}
    new_record['F1'] = [features["F1"]]
    new_df = pd.DataFrame(new_record)
    prediction = model.predict(new_df.astype(np.float32))
    features.update({"modbel1_rate": prediction[0][0]})
    features.update({"model1_sqqq_price": (prediction[0][0]+1)*features["SQQQ_base_price"]})
    features.update({"model1_tqqq_price": (prediction[0][0]*-1+1)*features["TQQQ_base_price"]})
    features.update({key: value for key, value in zip(feature_keys[1:], feature_values[1:])})
    return features

while True:
    try:
        features = getFeatures1()
        features = predict(features, worksheet, model)
        writeToCSV(features)
        time.sleep(10)
    except Exception as e:
        print(e)
        send_telegram_message("123456", "sqqq 예측 에러발생")

실시간 데이터의 일부는 scrapping이 필요하여 scrapper를 별도 제작하였고 습득한 데이터는 구글시트에 업데이트되도록 설정하였다.

그래서 feature 중일부는 google sheet에서 가져오며 feature중 일부는 특정 api를 통하여 습득하고 있다.

 

투자전략

실제 1~2일 정도 사용해 본 결과 예측치와 실제등락률 사이에 gap이 존재하고 gap이 커졌다 작아졌다를 반복한다. 이 갭은 보통 절대값 기준으로 1이상은 거의 발생하진 않았다. gap 커지고 작아지는특징을 이용하여 매수/매도를 해보려고한다. 갭이 0으로 회귀되는 특징을 이용하는것이 페어트레이딩의 개념과 흡사하다고 생각한다. 또한 기본적으로 미국 주식 시장의 흐름에 대한 분석포함 되므로 기본적인 투자를 할 때 하나의 지표로서 활용할 생각이다. 추후 시스템트레이딩 이용할수 있는 모델로 확장할수있지 않을까 하는생각이다. 실제로 직접 매수/매도를 하는 방식보다는 시스템 트레이딩에 더 접한한 모델이란 생각이든다.

qqq주가실시간예측차트1
실시간 예측차트

추가분석/개발 예정

해당 데이터를 활용하여 매수포인트와 매도 포인트를 분석 및 백테스팅을 진행할 계획이다. 

분석한 결과를 토대로 telegram으로 push 할 예정이다. 예측등락률과 실제등락률의 gap이 N이상 벌어졌을 때 push 하려고 한다.

가설이 생길 때마다 모델을 추가해서 모델들끼리 경쟁시켜 볼 생각이다. 참고로 예측치와 feature로 사용한 데이터를 log개념으로 csv로 저장하게 되어있는데 이걸 tablaeu에서 가져와서 실시간분석 중이다. (단... 매번 data refresh를 눌러줘야 하는 번거로움이 있다. 심지어 단축키가 있는데 어떤이유에서인지 안먹힐때가 있다. 개선할 방법 연구 중인며 데이터를 실시간 동기화해줄수있는 무료의 다른 툴이 있다면 사용해볼 생각이다.) 사실 포워드테스팅(실시간주가를 반영한 자동 전략패턴 매수/매도)을 준비하고있는데 포워드테스팅준비가 우선순위가 더높아 추가분석과 개발은 당분간 없을것같다. 

 

 

P.S.

블로그에 많은 시간을 투자할 수가 없어서 블로그 쓰는데 드는 시간과 결과물을 어떻게 최적화할지에 대해 잠깐 고민하였는데 일단 블로그 글은 공개게시하고 추가/수정할 아이디어가 있으면 내용을 추가/수정하는 전략을 사용하기로 하였다. 

 

3편(시각화&실제 사용기)

주로 예측결과를 실시간 시각화하는 과정에서 어떤 문제점들이 있었고 어떻게 해결했는지와 실제 하루의 데이트레이딩에 어떻게 활용했는지에 대해서 공유해보려고 합니다.

 

tableau를 이용한 시각화의 문제점

현재 tableau 무료버전인 tableau public을 사용 중이다.(나의 모든 프로젝트가 no cost를 지향한다). 예측결과를 실시간으로 시각화하는 것을 원했지만 차트가 실시간으로 동기화 되어 그려지지 않는다. refresh를 하려면 refresh 버튼을 매번 눌러주어야 한다. refresh 단축키가 있지만 맥북을 사용하는데 단축기가 먹히지 않는 경우가 많아서 refresh를 직접 클릭해주어야 했다.

tableau-데이터-갱신
tableau Refresh

혹시 몰라 데이터를 구글시트에 업데이트하는 식으로 변경하고 구글시트로 data connection을 만들어서 시도해보았지만 이 방법도 역시 refresh를 해주어야 했다. 또한 혹시 몰라 dashboard를 publish(웹에 공개됨)하고 auto update 되는지 확인해 봤지만 가능한 설정은 최대 1일에 한번 업데이트인 것 같다.  

 

잔머리를 굴려보기

그냥 하루에 한두번정도 해결방법을 찾기 위한 아이디어를 생각하였다. 간단하고 서버가 필요 없으며 바로 적용하고 실시간으로 시각화할 수 있는 방법을 찾아보려고 하였다. 그 결과가 구글시트에 chart를 그리기로 하였다. 구글시트의 chart는 새로운 데이터가 입력되면 chart를 자동으로 업데이트해준다. 여기서도 문제점이 하나 있었는데 처음에는 python에서 새로운 레코드를 추가할 때 차트에 반영이 안 되는 것이었다. 확인해 보니 python에서 2023-09-20  04:14:20이라는 값을 입력해 주면 문자로 인식하고 기존의 시간타입의 데이터와 일치하지 않아서 차트상에서 새로운 레코드로 인식하지 않았던 것이다. 구글에 검색해 보니 value_input_option을 'USER_ENTERED'로 설정하라고 한다. 아래 실제 적용한 코드 샘플이다.

row_num = sheet.acell('Z1').value  # 구글시트상에서 Z1에 마지막행의 번호를 자동으로 계산되게 설정해두었다.
update_range = f'A{row_num}:Y{row_num}'
sheet.update(update_range, [list_of_values[0:25]], value_input_option='USER_ENTERED')

 

실제 예측 등락률 실시간 화면

구글시트-qqq주가실시간예측차트

현재 TQQQ예측등락률과 TQQQ예측등락률(F1)과 실제 등락률을 구글시트에서 실시간으로 작성하여 위와 같이 그려주고 있다. TQQQ예측등락률과 TQQQ예측등락률(F1)의 차이는 TQQQ예측등락률은 조금 더 미래예측이고 TQQQ예측등락률(F1)은 좀더 현재 적정가예측에 가깝다. SQQQ도 마찬가지로 차트로 표현하고 있으며 예측등락률과의 갭과 사용되는 feature들에 대해서도 차트로 실시간으로 확인가능한 상태이다. 아직 주간 거래이고 실시간 예측이기때문에 앞으로 N초후의 데이터는 완전히 다른 예측치를 보일가능성이 크다 (주식시장상황등에 따라 변동되는 내용을 실시간 반영한다.)

 

구글시트-qqq주가실시간예측차트2

추가글 18시22분 내가 투자하기로 생각 한 조건에 부합하는 차트가 그려지고 있다. 예측등락률과 실제등락률의 갭이 존재하며, 예측등락률 -> 예측등락률(F1) -> 실제 등락률 순으로 배열되어있다. 해석하면 현재주가가 적정가 예측가보다 저렴하며 또한 앞으로 더 오를 확률이 높다는 것이다.

구글시트-qqq주가실시간예측차트3

추가글2 3시 50분 자다가 잠이 깨서 일어나서 실시간 차트를 확인해보니 배열이 달라진것을 확인하였다. 2시경 TQQQ예측등락률(F1)과 실제 등락률이 교차했다는것을 확인하였다. 매도를 고려한다.내가 원한는 이상적인 차트는 아니다.(손절매 기능을 사용하기에 이미 매도 체결이 되어있는 상태이다)  2시경부터 현재가가 적정가 예측보다 비싸졌다는것을 의미한다. (하지만 아직 예측등락률과 실제등락률의 갭이 약 0.6%정도 존재한다)

 

추가글3

추가글2 작성후 20분뒤 매도신호가 텔레그램을 통하여 알람이 도착했다. 예측등락률과 실제등락률의 차이가 0.2%미만으로 나온다. 종가를 예측을 하는 데이트레이딩 이기때문에 이런패턴의경우 아직까지 매도를 하지 않았다면 매도를 하려고한다.

qqq주가실시간예측알람

 

불편한 점

  • tablaeu처럼 막강한 분석툴을 제공하는 것이 아니므로 분석을 하기 위해서는 한계가 있다.
  • 실시간으로 1시간 이내의 데이터만 필터링하려고 했지만 불가능하였다. 새로 추가되는 데이터는 적용이 안되었다.
    • 블로그 글을 쓰면서 실시간 필터링이 가능하게 할 아이디어가 생각났다. 새로운 시트에 원하는 필터의 데이터만 가지고 오고 그 시트에서 차트를 그리면 될듯하다. 실제 적용한 1시간 이내만 데이터를 가져오는 수식은 =FILTER(realtime!A2:Z, realtime!A2:A>(NOW()-1/24)) 이다.
    • 차트설정에서 타임라인으로 차트로 설정하면 time range가 필터링 가능하다는것을 나중에서야 알게 되었다.

좋은 점

  • 구글시트에 저장해 놓으면 나의 다른 퀀트투자 데이터(나의 경우 모두 구글시트에 있기에)와 연동해서 분석하는 것이 가능해진다.
  • 간단한 추세선(이동평균선) 등도 그릴 수 있다. 예측결과뿐만 아니라 사용되는 feature에 대해서도 데이터를 저장하기에 중요도가 높은 feature의 추세도 확인할 수 있다.
  • 구글 시트를 공유한다면 다른 사용자도 실시간으로 차트를 확인할 수 있다.(그냥 구글시트를 공유해도 되지만, 호기심차원에서 구글시트의 확장기능  App Sheet를 통해서 앱으로 제작해 보고(별도 매뉴얼을 보지 않았는데도 10분 만에 클릭 몇 번으로 앱 배포가 가능할 정도로 쉽다) chart를 작성하여 배포한 뒤 공유하고 테스트해 보았다. 다른 건 다 괜찮지만 실시간 데이터 동기화하여 반영하지 않고 sync 버튼을 눌러주거나 새로고침을 하여야 chart 화면에서 실시간 데이터를 반영하는 것을 알 수 있었다. (참고로 App Sheet는 구글에서 인수한 노코드(No-code) 애플리케이션 개발 플랫폼이다 )