Langchain을 활용하여 미국주식 투자하기

2010년부터 시작한 미국주식의 투자경험을 바탕으로, 매년 가트너에서 발표하는 10대 전략기술을 투자의 선행지표로 활용하여 투자하는 아이디어를 구상해 보았습니다.

목차

  1. Langchain을 활용한 미국주식 투자하기 개요

    1. 왜 미국 IT주식인지?

    2. 시장을 초과하는 섹터는?

  2. 분석 내용

    1. 가트너 10대전략기술(2010-2024) 불러오기

    2. 랭체인을 활용하여 제 나름의 카테고리로 분류, 투자선정 기준 만들기

    3. 랭체인을 활용하여 매년 카테고리의 대장종목 뽑아내기

    4. 티커처리 등을 통해서 야후파이낸스 활용 투자수익률 분석(1년 투자)

    5. 1천만원 투자 시뮬레이션을 통해 연평균 수익률(복리, 단리) 확인


1. Langchain을 활용한 미국주식 투자하기

1. 왜 미국 주식인지?

위 그래프에서 보는 바와 같이 미국 주식시장은 중국과 한국 대비 압도적인 퍼포먼스를 보여줍니다. 한국과 중국은 10여년간 거의 제자리인 반면 미국은 300%가 넘는 누적 수익을 가져왔습니다.

2. 시장을 초과하는 섹터는?

위 그래프에서 보는 바와 같이 최근 10년간 it 종목의 수익률은 500%로 타 섹터에 비해 압도적이므로, 지수 수익률을 상회 하는 미국 IT주식에 세부 투자 전략을 만들고자 하였습니다.

2. 분석내용

1. 가트너 10대전략기술(2010-2024) 불러오기

IT섹터의 선행지표로 매년 10대 전략기술을 발표하는 가트너의 자료를 활용(2010-2024)하여, IT카테고리를 세부 분류하기 위한 데이터를 준비하였습니다.

2. 랭체인을 활용하여 제 나름의 카테고리로 분류, 투자선정 기준 만들기

10여년 간 미국 IT주식을 투자한 경험을 바탕으로, 아래의 카테고리를 만들고 가트너 10대 트렌드를 랭체인을 활용하여 각각 분류합니다. 이를 통해 출력한 결과는 코드의 맨 아래와 같습니다.

import pandas as pd
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate

# GPT 모델 설정
model = ChatOpenAI(model="gpt-4")
output_parser = StrOutputParser()

# 분류할 기술 목록에서 '기타인프라'를 제거
tech_categories = ["클라우드 인프라", "데이터분석 및 AI","블록체인", "엣지", "모바일", "가상증강현실", "3d프린팅", "디지털트윈", "보안", "기타", 'AI Hardware']

# 실제 가트너 데이터프레임 불러오기
actual_file_path = 'cleaned_gartner2022_transformed.xlsx'
actual_df = pd.read_excel(actual_file_path)

# 프롬프트 템플릿
prompt_template = ("다음 기술 트렌드를 주어진 기술 분류 중 하나로 분류하세요: {trend}\n"
                   "기술 분류 목록: {categories}\n"
                   "분류 결과만 출력해 주세요.")

def classify_trend(trend):
    prompt = ChatPromptTemplate.from_template(prompt_template.format(trend=trend, categories=", ".join(tech_categories)))
    chain = prompt | model | output_parser
    try:
        result = chain.invoke({})
        return result.strip()
    except Exception as e:
        print(f"오류가 발생했습니다 (트렌드: {trend}): {e}")
        return "기타"

# 데이터프레임에 "기술분류" 열 추가
actual_df['기술분류'] = actual_df['Trend'].apply(classify_trend)

# 'ai data'로 분류되지 않았지만 'ai'라는 단어가 포함된 트렌드에 대해 추가 분류
# def add_ai_data_category(row):
#     if 'ai data' not in row['기술분류'].split(', ') and 'ai' in row['Trend'].lower():
#         return row['기술분류'] + ', ai data'
#     return row['기술분류']

# actual_df['기술분류'] = actual_df.apply(add_ai_data_category, axis=1)

# 변환된 데이터 확인
print("기술분류가 추가된 데이터프레임 확인:")
print(actual_df.head())

# 엑셀 파일로 저장
actual_df.to_excel("classified_gartner2022_revised.xlsx", index=False)
print("기술분류가 추가된 데이터프레임이 'classified_gartner2022_revised.xlsx' 파일로 저장되었습니다.")

# 출력 결과
기술분류가 추가된 데이터프레임 확인:
   Year  Number       Trend        기술분류
0  2010       1     클라우드컴퓨팅    클라우드 인프라
1  2010       2  어드밴스드 애널리틱  데이터분석 및 AI
2  2010       3   클라이언트 컴퓨팅   클라이언트 컴퓨팅
3  2010       4       그린 IT          기타
4  2010       5  데이터센터의 재구성    클라우드 인프라
기술분류가 추가된 데이터프레임이 'classified_gartner2022_revised.xlsx' 파일로 저장되었습니다.

이러한 기술 분류를 기반으로, 어떤 기준으로 기술 카테고리를 투자해야 할지 고민해 보았습니다.

가급적 보수적이고 안전한 투자를 위해, 기술분류 중 3년 연속 선정되고 해당연도 2회 이상 선정된 기술분류와 4년 연속 선정되고 해당연도 2회 이상 선정된 기술분류 두가지를 아래와 같이 뽑아보았습니다.

 Year                  3년연속_1년2회                  4년연속_1년2회
0   2010                                                      
1   2011                                                      
2   2012  클라우드 인프라, 모바일, 데이터분석 및 ai                           
3   2013  클라우드 인프라, 모바일, 데이터분석 및 ai  클라우드 인프라, 모바일, 데이터분석 및 ai
4   2014              클라우드 인프라, 모바일              클라우드 인프라, 모바일
5   2015       클라우드 인프라, 데이터분석 및 ai       클라우드 인프라, 데이터분석 및 ai
6   2016  클라우드 인프라, 모바일, 데이터분석 및 ai  클라우드 인프라, 모바일, 데이터분석 및 ai
7   2017                 데이터분석 및 ai                 데이터분석 및 ai
8   2018                 데이터분석 및 ai                 데이터분석 및 ai
9   2019                 데이터분석 및 ai                 데이터분석 및 ai
10  2020           블록체인, 데이터분석 및 ai           블록체인, 데이터분석 및 ai
11  2021   클라우드 인프라, 보안, 데이터분석 및 ai             보안, 데이터분석 및 ai
12  2022   클라우드 인프라, 보안, 데이터분석 및 ai   클라우드 인프라, 보안, 데이터분석 및 ai
13  2023       클라우드 인프라, 데이터분석 및 ai       클라우드 인프라, 데이터분석 및 ai
14  2024       클라우드 인프라, 데이터분석 및 ai       클라우드 인프라, 데이터분석 및 ai

위 기술분류를 살펴보면 2000년대 IT 트렌드를 이끌었던 모바일이 2010년 초반에도 등장하고 있고, 2010년대에 들어서면서 빅데이터 분석이 화두가 되고, 이를 처리하기 위한 클라우드가 등장하고 있음을 확인할 수 있습니다. 간간이 보안, 블록체인 등의 이슈 또한 등장하지만, 2010년대와 2020년대는 클라우드 인프라와 데이터분석이 테크 트렌드의 중심으로 자리하고 있음을 확인할 수 있습니다.

3. 랭체인을 활용하여 매년 카테고리의 대장종목 뽑아내기

보수적인 투자를 위해 4년연속 해당년도 1년2회 선정된 기술분류에 대한 해당년도 대장종목을 뽑아내려고 합니다. 랭체인을 활용하여 해당종목과 티커를 추출합니다.

import pandas as pd
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate

# GPT 모델 설정
# model = ChatOpenAI(model="gpt-3.5-turbo")
model = ChatOpenAI(model="gpt-4")
output_parser = StrOutputParser()

# 프롬프트 템플릿
prompt_template = ("현재를 {year}년이라고 생각하고, {category} 분야에서 미국 상장주식 대장 기업 3개를 반드시 추천해줘. \
                    예를 들어 Amazon web service나 Microsoft Ajure와 같이 하나의 서비스라면 Amazon, Microsoft와 같이 모회사를 바로 알려줘"
                   "목록으로 만들어서 데이터 분석하려고 하니까 각각의 이름만 말해주되, 이름을 말했으면 ticker는 말하지마.")

def get_top_stocks(year, category):
    prompt = ChatPromptTemplate.from_template(prompt_template.format(year=year, category=category))
    chain = prompt | model | output_parser
    try:
        result = chain.invoke({})
        companies = [line.strip().split('.')[1].strip() for line in result.split('\n') if line.strip()]
        return companies
    except Exception as e:
        print(f"오류가 발생했습니다 (연도: {year}, 카테고리: {category}): {e}")
        return []

def get_stock_ticker(company):
    prompt = ChatPromptTemplate.from_template(f"{company}의 주식 티커를 알려줘. 티커만 말해줘.")
    chain = prompt | model | output_parser
    try:
        result = chain.invoke({})
        ticker = result.split(',')[0].strip()  # 여러 티커가 나올 경우 첫 번째 티커만 선택
        return ticker
    except Exception as e:
        print(f"오류가 발생했습니다 (기업: {company}): {e}")
        return "Unknown"

def clean_company_name(name):
    return ''.join([c for c in name if c.isalnum() or c.isspace()]).strip()

def save_top_stocks_to_excel_and_df(investment_df):
    all_top_stocks = []
    for _, row in investment_df.iterrows():
        year = row['Year']
        tech_categories = row['4년연속_1년2회'].split(', ')
        for category in tech_categories:
            if category:  # 카테고리가 있는 경우만 처리
                top_stocks = get_top_stocks(year, category)
                for rank, stock in enumerate(top_stocks, start=1):
                    cleaned_stock = clean_company_name(stock)
                    ticker = get_stock_ticker(cleaned_stock)
                    all_top_stocks.append({'Year': year, 'Category': category, 'Rank': rank, 'Stock': cleaned_stock, 'Ticker': ticker})

    top_stocks_df = pd.DataFrame(all_top_stocks)
    top_stocks_df.to_excel("top_stocks_by_year_with_tickers_final.xlsx", index=False)
    print("대장기업 목록이 'top_stocks_by_year_with_tickers_final.xlsx' 파일로 저장되었습니다.")
    
    return top_stocks_df

# 기존에 로드된 투자대상 기술분류 데이터프레임
investment_df = investment_df_4y

# 대장기업 목록 저장 및 데이터프레임 반환
top_stocks_df = save_top_stocks_to_excel_and_df(investment_df)

# 데이터프레임 확인
print("최종 결과물 데이터프레임 확인:")
print(top_stocks_df.head())

# 데이터프레임을 변수로 저장하여 향후 사용
final_top_stocks_df = top_stocks_df

최종 결과물 데이터프레임 확인:
   Year  Category  Rank      Stock               Ticker
0  2013  클라우드 인프라     1     Amazon                 AMZN
1  2013  클라우드 인프라     2  Microsoft                 MSFT
2  2013  클라우드 인프라     3        IBM  IBM의 주식 티커는 IBM입니다.
3  2013       모바일     1      Apple                 AAPL
4  2013       모바일     2     Google                GOOGL

위의 결과를 확인해보면 IBM은 티커만 뽑아내지 못한 것을 확인할 수 있습니다. 티커를 추가로 가공하여 아래와 같은 결과를 얻을 수 있었습니다.

티커 추가 가공 후 데이터프레임 확인:
   Year  Category  Rank      Stock Ticker
0  2013  클라우드 인프라     1     Amazon   AMZN
1  2013  클라우드 인프라     2  Microsoft   MSFT
2  2013  클라우드 인프라     3        IBM    IBM
3  2013       모바일     1      Apple   AAPL
4  2013       모바일     2     Google  GOOGL
                   .....
2023	클라우드 인프라	1	Amazon	AMZN
2023	클라우드 인프라	2	Microsoft	MSFT
2023	클라우드 인프라	3	Google	GOOGL
2023	데이터분석 및 ai	1	Alphabet Inc	GOOGL
2023	데이터분석 및 ai	2	Amazon Inc	AMZN
2023	데이터분석 및 ai	3	Microsoft Corporation	MSFT
2024	클라우드 인프라	1	Amazon	AMZN
2024	클라우드 인프라	2	Microsoft	MSFT
2024	클라우드 인프라	3	Google	GOOGL
2024	데이터분석 및 ai	1	Amazon	AMZN
2024	데이터분석 및 ai	2	Microsoft	MSFT
2024	데이터분석 및 ai	3	Alphabet 	GOOGL

2010년대 초반 IBM은 클라우드 업계에서 3위를 차지하고 있지만, 시간이 지남에 따라 그 자리를 google에게 물려주어 대장주로 등장하지 않게 됩니다. gpt가 업계의 변화에 따라 해당년도에 걸맞는 대장종목을 잘 선정하고 있음을 알 수 있습니다.

4. 티커처리 등을 통해서 야후 파이낸스 활용 각 종목 투자수익률 분석(1년씩 투자)

야후 파이낸스 라이브러리를 불러와, 해당 티커가 있는지 확인한 후, 선정된 기술분류 당 3개의 종목을 해당년도에 투자(1월초 매수, 12월말 매도)하는 전략의 각종목 투자수익율을 계산합니다.

import pandas as pd
import yfinance as yf

# final_top_stocks_df 데이터프레임 사용 (기존 데이터프레임 활용)
# 이미 존재하는 ticker_counts 데이터프레임을 사용
# ticker_counts = final_top_stocks_df.groupby(['Year', 'Ticker']).size().reset_index(name='Count')

# 투자 시작일과 종료일 설정
ticker_counts['Invest Start Date'] = ticker_counts['Year'].apply(lambda x: f"{x}-01-01")
ticker_counts['Invest Final Date'] = ticker_counts['Year'].apply(lambda x: f"{x}-12-31")

# 수익률 계산을 위한 열 추가
ticker_counts['Invest Start Price'] = 0.0
ticker_counts['Invest Final Price'] = 0.0
ticker_counts['Return'] = 0.0

# 주가 데이터 가져오기 및 수익률 계산
for index, row in ticker_counts.iterrows():
    ticker = row['Updated Ticker']
    start_date = row['Invest Start Date']
    final_date = row['Invest Final Date']
    
    try:
        stock_data = yf.download(ticker, start=start_date, end=final_date)
        if not stock_data.empty:
            invest_start_price = stock_data['Adj Close'].iloc[0]
            invest_final_price = stock_data['Adj Close'].iloc[-1]
            ticker_counts.at[index, 'Invest Start Price'] = invest_start_price
            ticker_counts.at[index, 'Invest Final Price'] = invest_final_price
            ticker_counts.at[index, 'Return'] = (invest_final_price - invest_start_price) / invest_start_price
        else:
            print(f"주가 데이터가 없습니다: {ticker}, {start_date} to {final_date}")
    except Exception as e:
        print(f"오류가 발생했습니다: {ticker}, {e}")

# 결과 확인
print("연도별 티커와 수익률 데이터프레임 확인:")
print(ticker_counts.head())

# 엑셀 파일로 저장
ticker_counts.to_excel("ticker_returns_by_year.xlsx", index=False)
print("연도별 티커와 수익률 데이터가 'ticker_returns_by_year.xlsx' 파일로 저장되었습니다.")

#결과 표시
연도별 티커와 수익률 데이터프레임 확인:
   Year Ticker  Count  Exists Updated Ticker Invest Start Date  \
0  2013   AAPL      1    True           AAPL        2013-01-01   
1  2013   AMZN      3    True           AMZN        2013-01-01   
2  2013  GOOGL      1    True          GOOGL        2013-01-01   
3  2013    IBM      2    True            IBM        2013-01-01   
4  2013   MSFT      2    True           MSFT        2013-01-01   

  Invest Final Date  Invest Start Price  Invest Final Price    Return  
0        2013-12-31           16.747730           17.340128  0.035372  
1        2013-12-31           12.865500           19.668501  0.528779  
2        2013-12-31           18.078600           27.732435  0.533992  
3        2013-12-31          118.749161          114.925255 -0.032202  
4        2013-12-31           22.492285           31.285889  0.390961  
연도별 티커와 수익률 데이터가 'ticker_returns_by_year.xlsx' 파일로 저장되었습니다.

5. 최초 1천만원 투자 시뮬레이션을 통해 연평균 수익률(복리, 단리 등) 확인

최초 1천만원을 원금으로 각 종목에 균등하게 투자하여, 총 수익률, 연평균 수익율(단리, 복리)를 구해봅니다. 아래의 결과와 같이 2013년 부터 2024년 까지 위 전략으로 투자하면 총 1,563%의 수익을 거두는 것을 확인하였습니다. 연평균 수익률(복리)로는 26%의 수익률을 거두는 것을 확인할 수 있습니다. 총 1,563%는 해당 기간 미국 주가지수 300%, IT주식 ETF 500%의 수익률임을 감안할 때, 더 나은 투자 결과를 확인 할 수 있었습니다.

투자 전기간 요약 데이터프레임 확인:
  Invest Start Date Invest Final Date  Total Investment Start  \
0        2013-01-01        2024-12-31                10000000   

   Total Investment End  Total Return  Total Return (%)  \
0          1.663838e+08      15.63838       1563.838007   

   Average Annual Return (Simple)  Average Annual Return (Simple %)  \
0                        1.303198                        130.319834   

   Average Annual Return (Compound)  Average Annual Return (Compound %)  
0                          0.264035                           26.403545


막연하게 오래전부터, 확인하고 싶었던 투자전략 이지만, 비정형 분석, 크롤링의 번거로움 등으로 엄두를 내기 어려웠던 분석을 gpt와 랭체인을 통해 쉽게 구현할 수 있다는 사실을 확인하였습니다.

향후 RAG를 활용한 보다 안정적인 분석과, RSI, 재무정보 등 다양한 데이터를 접목하여 단기전략을 만들어 테스트 해보려고 합니다. 감사합니다.

15
3개의 답글

👉 이 게시글도 읽어보세요