ostock-backend / model /src /data /economic_data.py
johnaness's picture
Deploy OStock FastAPI backend to HF Space (Docker SDK, port 7860)
4be2d4d
"""
๊ฒฝ์ œ ์ง€ํ‘œ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ๊ด€๋ จ ํ•จ์ˆ˜
"""
import pandas as pd
import yfinance as yf
import FinanceDataReader as fdr
from fredapi import Fred
from statsmodels.tsa.holtwinters import ExponentialSmoothing
def get_economic_data(start_date, end_date, fred_api_key):
"""
๊ฒฝ์ œ ์ง€ํ‘œ์™€ ์‹œ์žฅ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ง‘ํ•˜๋Š” ํ•จ์ˆ˜
"""
# ๊ฒฝ์ œ ์ง€ํ‘œ ๋ฐ์ดํ„ฐ ๋‹ค์šด๋กœ๋“œ (FRED API)
fred = Fred(api_key=fred_api_key)
# ๊ตญ์ฑ„ ์ˆ˜์ต๋ฅ 
DGS = pd.concat([
fred.get_series('DGS2', start_date, end_date),
fred.get_series('DGS5', start_date, end_date),
fred.get_series('DGS10', start_date, end_date)
], axis=1)
DGS.columns = ['2-year', '5-year', '10-year']
# ๊ธฐํƒ€ ๊ฒฝ์ œ ์ง€ํ‘œ
T10Y2Y = fdr.DataReader('FRED:T10Y2Y', start_date, end_date)
VIX = fdr.DataReader('FRED:VIXCLS', start_date, end_date)
Unemployment_Rate = fdr.DataReader('FRED:UNRATE', start_date, end_date)
CPI = fdr.DataReader('FRED:CPIAUCSL', start_date, end_date)
FEDFUNDS = fdr.DataReader('FRED:FEDFUNDS', start_date, end_date)
GDP = pd.DataFrame(fred.get_series('GDP', start_date, end_date), columns=['GDP'])
# ์ฃผ์š” ์ฃผ์‹ ์ง€์ˆ˜
index_tickers = {
"^DJI": "DJI Close",
"NDAQ": "NDAQ Close",
"^GSPC": "SPX Close",
"^RUT": "RUT Close"
}
index_data = {}
for ticker, name in index_tickers.items():
df = yf.download(ticker, start=start_date, end=end_date)
df = df[['Close']].rename(columns={'Close': name})
index_data[name] = df
Index_data = pd.concat(index_data.values(), axis=1)
# ์‚ฐ์—…๋ณ„ ETF
sectors = {
"VDE": "Energy",
"MXI": "Materials",
"VIS": "Industrials",
"VCR": "Consumer Cyclical",
"XLP": "Consumer Staples",
"VHT": "Health Care",
"XLF": "Financials",
"VGT": "Information Technology",
"VOX": "Communication Services",
"XLU": "Utilities",
"VNQ": "Real Estate"
}
sector_data = {}
for etf, sector_name in sectors.items():
df = yf.download(etf, start=start_date, end=end_date)
df.rename(columns={'Close': f'{sector_name} Close'}, inplace=True)
sector_data[sector_name] = df[[f'{sector_name} Close']]
ETF_data = pd.concat(sector_data.values(), axis=1)
# ๋ฐ์ดํ„ฐ ๋ณด๊ฐ„ ๋ฐ ์˜ˆ์ธก
def interpolate_and_forecast(df, col_name, stock_end_date):
df = df.resample('D').asfreq().interpolate()
forecast_steps = (pd.to_datetime(stock_end_date) - df.index[-1]).days
if forecast_steps > 0:
forecast_df = pd.DataFrame(index=pd.date_range(df.index[-1] + pd.Timedelta(days=1), stock_end_date))
model = ExponentialSmoothing(df[col_name], trend='add').fit()
forecast_df[col_name] = model.forecast(steps=forecast_steps)
df = pd.concat([df, forecast_df])
return df
# ๋ชจ๋“  ๊ฒฝ์ œ ๋ฐ ์‹œ์žฅ ์ง€ํ‘œ ๊ฒฐํ•ฉ
econ_df = (
interpolate_and_forecast(DGS, '2-year', end_date)
.join(interpolate_and_forecast(T10Y2Y, 'T10Y2Y', end_date), how='left')
.join(interpolate_and_forecast(VIX, 'VIXCLS', end_date), how='left')
.join(interpolate_and_forecast(Unemployment_Rate, 'UNRATE', end_date), how='left')
.join(interpolate_and_forecast(CPI, 'CPIAUCSL', end_date), how='left')
.join(interpolate_and_forecast(FEDFUNDS, 'FEDFUNDS', end_date), how='left')
.join(interpolate_and_forecast(GDP, 'GDP', end_date), how='left')
)
# ๋ฉ€ํ‹ฐ์ธ๋ฑ์Šค ์ฒ˜๋ฆฌ
if isinstance(Index_data.columns, pd.MultiIndex):
Index_data.columns = Index_data.columns.get_level_values(1)
if isinstance(ETF_data.columns, pd.MultiIndex):
ETF_data.columns = ETF_data.columns.get_level_values(1)
econ_df = econ_df.join(Index_data, how='left').join(ETF_data, how='left')
econ_df.fillna(method='ffill', inplace=True)
econ_df.fillna(method='bfill', inplace=True)
return econ_df