hc.
← 모든 프로젝트
TIME SERIES / FINANCIAL DATA

Windmill

TimeLLM으로 주가를 예측하고,
개인화 포트폴리오를 구성하다.

TimeLLM 기반 주가 예측과 연령 및 위험감수도별 포트폴리오 추천 시스템을 개발했습니다.

PORTFOLIO EXPLORER

상위 5개 프로필 vs. S&P 500

2025.06.20 — 2025.07.18 / 20거래일 과거 가격 기반 비교

순위는 이 기간의 최종 수익률 기준입니다. 처음에는 상위 5개가 선택됩니다.

선택한 5개 평균—
S&P 500—
시장 대비—
선택한 프로필 평균S&P 500가는 선: 개별 프로필
55개 프로필에서 직접 선택 5개 선택
선택 / 순위연령위험감수도최종 수익률

선택한 프로필의 누적 수익률을 동일 비중으로 평균합니다. 전체 결과: 연령 11구간 × 위험감수도 5단계, 총 55개 프로필.

수익률 데이터를 불러오는 중입니다.

PERIOD2025.07 — 2025.08
TEAM4인 팀
MY ROLEAI 개발, 모델 실험 및 평가
TimeLLMNeuralForecastGPT-2PyTorchyfinanceFlaskGemma3
AI 소스 코드 ↗모델 구조 보기 ↓실험 결과 보기 ↓
01 / PROBLEM & OWNERSHIP

가격 예측을 사용자가 활용할 수 있는 기능으로.

초기 목표는 사용자가 종목과 예측 기간, 참고할 지표를 선택하면 미래 주가를 확인할 수 있는 웹 서비스를 만드는 것이었습니다. S&P 500 구성 종목을 대상으로 예측 모델을 평가하고 종목별 오차를 분석했습니다.

직접 담당한 작업

  • 주가와 금리, 재무지표를 정리하는 데이터 전처리
  • TimeLLM 기반 예측 코드와 입력 설정 실험
  • 종목별 예측 오차 분석과 결과 저장
  • 예측 결과를 활용한 추천 로직과 Flask AI 서버 연동

팀에서 함께 완성한 서비스

4명이 AI 개발, 프론트엔드 디자인, 프론트엔드 개발, 백엔드와 DB를 나눠 맡았습니다. 제가 담당한 AI 처리 결과를 React 화면과 FastAPI 백엔드에서 사용할 수 있도록 연결했습니다.

02 / TIME SERIES MODELING

핵심 모델은 TimeLLM, 예측 대상은 종가.

NeuralForecast의 TimeLLM을 사용하고 백본으로 openai-community/gpt2를 지정했습니다. TimeLLM은 시계열을 패치로 나누고 언어 모델의 표현 공간에 연결한 뒤, 출력층에서 수치 예측으로 변환하는 방식입니다. 이 프로젝트에서는 해당 모델을 금융 시계열에 적용하는 데이터 처리와 실험, 서비스 호출 흐름을 구현했습니다.

01종가 시계열yfinance 수집
unique_id / ds / y 정리
02패치와 표현 변환TimeLLM
Reprogramming
03GPT-2 백본종목과 업종 설명
프롬프트 문맥
04수치 예측예측 기간 h
날짜별 종가 출력

데이터와 프롬프트를 구성했습니다.

주가 데이터를 종목 ID, 날짜, 종가로 정리하고 선택된 거래량, OHLC, 금리, 재무지표의 날짜를 맞췄습니다. PER, PBR, PSR은 선택 여부에 따라 종목 및 업종 설명과 함께 prompt_prefix에 넣었습니다.

서비스 모델 설정

예측 길이
사용자가 지정하는 h
입력 창
h × 12
학습 한도
100 steps
배치 크기
16
검증 구간
h개 관측값

종목별 평가 설정: 예측 길이 30, 입력 창 365, 검증 구간 60.

03 / EXPERIMENT & DIAGNOSIS

한 종목의 곡선보다, 499종목의 오차 분포.

S&P 500 구성 종목을 순회하며 예측과 실제 값을 비교하고 MSE, MAE, 정규화 오차를 CSV로 저장했습니다. 완료된 종목은 건너뛰도록 해 중단된 실험을 이어갈 수 있게 했습니다. 499종목 평가에서 정규화 MAE 중앙값은 8.29%, 오차 20% 초과 종목은 76개였습니다.

종목별 정규화 오차 분포 499종목 평가
5% 미만
15330.7%
5% 이상, 10% 미만
13827.7%
10% 이상, 20% 이하
13226.5%
20% 초과
7615.2%
중앙값 8.29%평균 11.99%최댓값 110.46%

정규화 MAE = MAE ÷ 평가 구간 실제 종가의 평균 × 100.

7월 18일 교수님도 가격 예측 정확도의 한계를 짚고 변화량을 활용한 위험도 기반 추천을 제안했습니다. 팀은 이 피드백을 반영해 목표를 조정했고, 저는 예측 결과를 추천에 사용할 수 있는 지표와 처리 흐름으로 구체화했습니다.

04 / FROM FORECAST TO RECOMMENDATION

시계열 예측을 출발점으로, 추천 파이프라인을 확장했습니다.

TimeLLM이 생성한 가격 경로에서 일별 변화율과 표준편차, 첫 예측 가격 대비 최대 및 최소 변화율을 계산했습니다. 이를 사용자 나이와 손실 허용 수준, 뉴스 정보와 결합하는 후속 단계를 만들었습니다. Gemma3는 이 단계에서 후보 선택과 설명 생성을 담당합니다.

  1. 01

    예측 가격을 위험 지표로 변환

    종목별 예측 CSV를 날짜 기준으로 합치고, 일별 변화율의 표준편차를 기준으로 5단계 위험 등급을 구성했습니다.

  2. 02

    사용자 성향에 맞는 후보 선정

    나이와 손실 허용 수준을 함께 입력했습니다. 전체 종목 표가 길어지면 문자열 길이 기준으로 나눠 분석하고 후보를 합쳤습니다.

  3. 03

    뉴스 문맥 추가

    후보 종목의 뉴스 제목과 설명을 수집해 감성을 분석했습니다. 같은 뉴스의 반복 요청을 줄이도록 날짜별 CSV 캐시를 두었습니다.

  4. 04

    종목, 비중, 추천 이유 생성

    최종 5종목과 배분 비중, 이유를 생성하고, 추천 종목이 보유 데이터 목록에 있는지 대조했습니다. 형식이나 종목 검증이 실패하면 최대 5회 시도하도록 구현했습니다.

05 / DELIVERY & CONSTRAINTS

노트북의 실험을 웹 요청으로 연결했습니다.

React종목과 기간 선택
예측 및 추천 결과 표시
→
FastAPI웹 요청 처리
AI 서버 호출
→
Flask AI 서버별도 Conda 환경 호출
TimeLLM / 포트폴리오 처리

Flask가 요청을 받아 예측과 추천 스크립트를 별도 환경에서 실행하고 결과를 JSON으로 반환하도록 연결했습니다. 웹 애플리케이션과 로컬 GPU의 실행 환경을 분리하면서 팀 백엔드가 AI 결과를 사용할 수 있는 인터페이스를 만들었습니다.

시계열 예측 API

종목, 예측 기간, 입력 설정을 받아 TimeLLM을 실행하고 날짜별 예측값을 JSON으로 반환했습니다.

포트폴리오 추천 API

사용자의 연령과 손실 허용 수준을 받아 후보 종목 분석, 뉴스 감성 분석, 배분 비중과 추천 이유 생성을 연결했습니다.

06 / PERFORMANCE

55개 사용자 프로필의 평균 수익률 6.62%.

연령 11구간과 위험감수도 5단계를 조합한 55개 프로필로 포트폴리오를 구성했습니다. 2025년 6월 20일부터 7월 18일까지의 과거 가격을 적용한 수익률 평균은 6.62%였고, 같은 기간 S&P 500은 5.51% 상승했습니다.

평균 수익률6.62%
시장 대비 차이+1.11%p
시장 상회 프로필32 / 55
← 다른 프로젝트 보기