test1 / data /technicals.py
davidkim205's picture
1์ฐจ ๊ฐœ๋ฐœ ์ฝ”๋“œ ์™„๋ฃŒ
83efdfc
import yfinance as yf
def calc_rsi(close, period=14):
delta = close.diff()
gain = delta.clip(lower=0).rolling(period).mean()
loss = (-delta.clip(upper=0)).rolling(period).mean()
return float((100 - 100 / (1 + gain / loss)).iloc[-1])
def calc_macd_histogram(close):
ema12 = close.ewm(span=12).mean()
ema26 = close.ewm(span=26).mean()
macd = ema12 - ema26
signal = macd.ewm(span=9).mean()
return float((macd - signal).iloc[-1])
def calc_bb_position(current, close):
bb_mid = close.rolling(20).mean().iloc[-1]
bb_std = close.rolling(20).std().iloc[-1]
bb_upper = float(bb_mid + 2 * bb_std)
bb_lower = float(bb_mid - 2 * bb_std)
pos = (current - bb_lower) / (bb_upper - bb_lower) * 100 \
if (bb_upper - bb_lower) > 0 else 50
if pos > 80:
label = f"์ƒ๋‹จ ๊ทผ์ ‘ ({pos:.0f}%)"
elif pos < 20:
label = f"ํ•˜๋‹จ ๊ทผ์ ‘ ({pos:.0f}%)"
else:
label = f"์ค‘๊ฐ„ ๊ตฌ๊ฐ„ ({pos:.0f}%)"
return bb_upper, bb_lower, label
def fetch_technicals(ticker, period="6mo"):
hist = yf.Ticker(ticker).history(period=period)
if len(hist) < 30:
return {}
close = hist["Close"]
volume = hist["Volume"]
current = float(close.iloc[-1])
ma20 = close.rolling(20).mean().iloc[-1]
ma50 = close.rolling(50).mean().iloc[-1] if len(close) >= 50 else None
ma200 = close.rolling(200).mean().iloc[-1] if len(close) >= 200 else None
rsi = calc_rsi(close)
macd_hist = calc_macd_histogram(close)
bb_upper, bb_lower, bb_pos = calc_bb_position(current, close)
def rsi_signal(r):
if r < 30: return "๊ณผ๋งค๋„ (๋ฐ˜๋“ฑ ๊ฐ€๋Šฅ)"
if r > 70: return "๊ณผ๋งค์ˆ˜ (์กฐ์ • ๊ฐ€๋Šฅ)"
return "์ค‘๋ฆฝ"
return {
"ma20": round(float(ma20), 2),
"ma50": round(float(ma50), 2) if ma50 is not None else None,
"ma200": round(float(ma200), 2) if ma200 is not None else None,
"price_vs_ma20": "์œ„" if current > float(ma20) else "์•„๋ž˜",
"rsi_14": round(rsi, 1),
"rsi_signal": rsi_signal(rsi),
"macd_histogram": round(macd_hist, 4),
"macd_signal": "์ƒ์Šน ๋ชจ๋ฉ˜ํ…€" if macd_hist > 0 else "ํ•˜๋ฝ ๋ชจ๋ฉ˜ํ…€",
"bb_upper": round(bb_upper, 2),
"bb_lower": round(bb_lower, 2),
"bb_position": bb_pos,
"volume_ratio": round(float(volume.iloc[-1]) / float(volume.tail(20).mean()), 2),
}