ChatGPT로 기술적 분석하기
최근 ChatGPT를 활용하여 주식 투자에 관한 다양한 시도가 증가하고 있습니다.
그 중 하나의 예시로, 2023년 8월 7일에 Medium에 게시된 기사를 국내 주식 시장에 맞게 수정하여 활용해보았습니다.
원래 글의 ChatGPT를 활용하는 아이디어도 참신하지만, 이 기사를 통해 pandas_ta 패키지와 이 패키지의 기술적 분석(TA) 지표를 시각화하는 코드는 매우 유용해 보입니다.
아래는 원문 기사의 내용입니다.
Stocks Technical Analysis (TA) with Python & ChatGPT: A Comprehensive Guide
Unlock stock insights using Python & ChatGPT. Analyze TA indicators, forecast trends, and gain valuable market sentiment.
medium.com
다음은 원문 기사를 국내 주식 종목 중 올 여름 가장 주목받는 에코프로 주식에 대한 분석으로 변형한 내용입니다. 이를 위해 OHLCV 데이터를 얻는 방법을 yfinance 패키지를 이용하던것에서 pykrx로 변경하였습니다.
OHLCV 데이터 얻기
google colab에서 수행하기 위해서 패키지를 설치합니다.
!pip install pandas_ta
!pip install pykrx
종목 데이터를 얻고난후에는 pandas_ta 분석 도구가 영문 OHLCV 컬럼이름을 사용하기 때문에 컬럼 이름 변경이 필요합니다.
import matplotlib.pyplot as plt
import pandas as pd
from pykrx import stock
import pandas_ta as ta
import matplotlib.dates as mdates
from datetime import datetime, timedelta
# 에코프로 종목 현재일 기준으로 120일 전부터의 종목 데이터 얻음
symbol = "086520"
end_date = datetime.today()
start_date = end_date - timedelta(days=120) # 4 달전
# 시작일과 종료일 사이의 symbol의 OHLCV 데이터를 얻음
stock_data = stock.get_market_ohlcv(start_date, end_date, symbol)
# 한글 컬럼과 인덱스 이름을 TA 라이브러리를 사용하기 위해 영문으로 바꿈
stock_data.rename(columns={
'시가': 'Open',
'고가': 'High',
'저가': 'Low',
'종가': 'Close',
'거래량': 'Volume',
'등락률': 'Change'
}, inplace=True)
# Index 이름을 'Date'로 변경
stock_data.rename_axis('Date', inplace=True)
위 코드를 실행하면 `stock_data`에는 다음과 같은 데이터가 얻어집니다.
DataFrame에 기술적 분석 지표 넣기
`pandas_ta` 패키지 설치시 pandas DataFrame에 래퍼를 제공해서 stock_data.ta 형식으로 TA API 접근이 가능합니다.
# Calculate technical indicators using pandas-ta
stock_data.ta.macd(append=True)
stock_data.ta.rsi(append=True)
stock_data.ta.bbands(append=True)
stock_data.ta.obv(append=True)
# Calculate additional technical indicators
stock_data.ta.sma(length=20, append=True)
stock_data.ta.ema(length=50, append=True)
stock_data.ta.stoch(append=True)
stock_data.ta.adx(append=True)
# Calculate other indicators
stock_data.ta.willr(append=True)
stock_data.ta.cmf(append=True)
stock_data.ta.psar(append=True)
#convert OBV to million
stock_data['OBV_in_million'] = stock_data['OBV']/1e7
stock_data['MACD_histogram_12_26_9'] = stock_data['MACDh_12_26_9'] # not to confuse chatGTP
# Summarize technical indicators for the last day
last_day_summary = stock_data.iloc[-1][['Close',
'MACD_12_26_9','MACD_histogram_12_26_9', 'RSI_14', 'BBL_5_2.0', 'BBM_5_2.0', 'BBU_5_2.0','SMA_20', 'EMA_50','OBV_in_million', 'STOCHk_14_3_3',
'STOCHd_14_3_3', 'ADX_14', 'WILLR_14', 'CMF_20',
'PSARl_0.02_0.2', 'PSARs_0.02_0.2'
]]
print("에코프로 종목 가장 최근의 기술적 분석 자료:")
print(last_day_summary)
ChatGPT 프롬프트 만들기
ChatGPT 채팅창에 입력할 프롬프트를 생성하는 코드입니다.
## 프롬프트 작성
sys_prompt = """
아래는 한국 에코프로 종목의 가장 최근의 기술적 분석 자료입니다. 이 분석 자료를 통해 1주일후의 주가 전망을 말해주기 바랍니다.
에코프로 종목 가장 최근의 기술적 분석 자료:
{}""".format(last_day_summary)
print(sys_prompt)
위 코드가 생성한 프롬프트 입니다.
아래는 한국 에코프로 종목의 가장 최근의 기술적 분석 자료입니다. 이 분석 자료를 통해 1주일후의 주가 전망을 말해주기 바랍니다.
에코프로 종목 가장 최근의 기술적 분석 자료:
Close 901000.000000
MACD_12_26_9 -55587.564421
MACD_histogram_12_26_9 -5199.206170
RSI_14 39.140796
BBL_5_2.0 844817.428309
BBM_5_2.0 919400.000000
BBU_5_2.0 993982.571691
SMA_20 982200.000000
EMA_50 992085.869665
OBV_in_million 0.979703
STOCHk_14_3_3 11.040074
STOCHd_14_3_3 16.975701
ADX_14 28.374610
WILLR_14 -80.254777
CMF_20 -0.141652
PSARl_0.02_0.2 NaN
PSARs_0.02_0.2 985000.000000
Name: 2023-09-27 00:00:00, dtype: float64
ChatGPT에게 분석 의뢰하기
생성된 프롬프트의 제일 마지막 라인을 제외하고 내용 전체를 클립보드에 복사하여 ChatGPT 채팅창에 붙여넣기를 합니다.
다음은 ChatGPT의 위 프롬프트에 대한 답변입니다.
참고로 구글 bard에게도 동일하게 물었더니 짧은 답변을 줍니다.
둘 다 대답이 단기적으로 하락한다고 하니 1주일후 주가가 어떻게 되는지 추후 이 포스트에 업데이트 하겠습니다.
분석 결과 시각화
좌측 상단에 주가와 설정했던 지표 값을 차례대로 시각화 하는 코드입니다.
# Plot the technical indicators
plt.figure(figsize=(14, 8))
# Price Trend Chart
plt.subplot(3, 3, 1)
plt.plot(stock_data.index, stock_data['Close'], label='Close', color='blue')
plt.plot(stock_data.index, stock_data['EMA_50'], label='EMA_50', color='green')
plt.plot(stock_data.index, stock_data['SMA_20'], label='SMA_20', color='orange')
plt.title("Price Trend")
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%b%d')) # Format date as "Jun14"
plt.xticks(rotation=45, fontsize=8) # Adjust font size
plt.legend()
# On-Balance Volume Chart
plt.subplot(3, 3, 2)
plt.plot(stock_data['OBV'], label='On-Balance Volume')
plt.title('On-Balance Volume (OBV) Indicator')
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%b%d')) # Format date as "Jun14"
plt.xticks(rotation=45, fontsize=8) # Adjust font size
plt.legend()
# MACD Plot
plt.subplot(3, 3, 3)
plt.plot(stock_data['MACD_12_26_9'], label='MACD')
plt.plot(stock_data['MACDh_12_26_9'], label='MACD Histogram')
plt.title('MACD Indicator')
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%b%d')) # Format date as "Jun14"
plt.xticks(rotation=45, fontsize=8) # Adjust font size
plt.title("MACD")
plt.legend()
# RSI Plot
plt.subplot(3, 3, 4)
plt.plot(stock_data['RSI_14'], label='RSI')
plt.axhline(y=70, color='r', linestyle='--', label='Overbought (70)')
plt.axhline(y=30, color='g', linestyle='--', label='Oversold (30)')
plt.legend()
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%b%d')) # Format date as "Jun14"
plt.xticks(rotation=45, fontsize=8) # Adjust font size
plt.title('RSI Indicator')
# Bollinger Bands Plot
plt.subplot(3, 3, 5)
plt.plot(stock_data.index, stock_data['BBU_5_2.0'], label='Upper BB')
plt.plot(stock_data.index, stock_data['BBM_5_2.0'], label='Middle BB')
plt.plot(stock_data.index, stock_data['BBL_5_2.0'], label='Lower BB')
plt.plot(stock_data.index, stock_data['Close'], label='Close', color='brown')
plt.title("Bollinger Bands")
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%b%d')) # Format date as "Jun14"
plt.xticks(rotation=45, fontsize=8) # Adjust font size
plt.legend()
# Stochastic Oscillator Plot
plt.subplot(3, 3, 6)
plt.plot(stock_data.index, stock_data['STOCHk_14_3_3'], label='Stoch %K')
plt.plot(stock_data.index, stock_data['STOCHd_14_3_3'], label='Stoch %D')
plt.title("Stochastic Oscillator")
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%b%d')) # Format date as "Jun14"
plt.xticks(rotation=45, fontsize=8) # Adjust font size
plt.legend()
# Williams %R Plot
plt.subplot(3, 3, 7)
plt.plot(stock_data.index, stock_data['WILLR_14'])
plt.title("Williams %R")
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%b%d')) # Format date as "Jun14"
plt.xticks(rotation=45, fontsize=8) # Adjust font size
# ADX Plot
plt.subplot(3, 3, 8)
plt.plot(stock_data.index, stock_data['ADX_14'])
plt.title("Average Directional Index (ADX)")
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%b%d')) # Format date as "Jun14"
plt.xticks(rotation=45, fontsize=8) # Adjust font size
# CMF Plot
plt.subplot(3, 3, 9)
plt.plot(stock_data.index, stock_data['CMF_20'])
plt.title("Chaikin Money Flow (CMF)")
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%b%d')) # Format date as "Jun14"
plt.xticks(rotation=45, fontsize=8) # Adjust font size
# Show the plots
plt.tight_layout()
plt.show()