import streamlit as st from streamlit_autorefresh import st_autorefresh import pandas as pd import requests import yfinance as yf from datetime import datetime, timedelta # Hàm lấy danh sách cổ phiếu có Volume > Avg Vol (3M) từ Yahoo Finance def get_active_stocks(): url = "https://finance.yahoo.com/markets/stocks/most-active/?start=0&count=100" headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)", "Accept-Language": "en-US,en;q=0.9" } response = requests.get(url, headers=headers, timeout=10) tables = pd.read_html(response.text) stocks_df = tables[0] stocks_df['Volume'] = stocks_df['Volume'].replace({'M': '*1e6', 'k': '*1e3'}, regex=True).map(pd.eval).astype(int) stocks_df['Avg Vol (3M)'] = stocks_df['Avg Vol (3M)'].replace({'M': '*1e6', 'k': '*1e3'}, regex=True).map(pd.eval).astype(int) result = stocks_df[stocks_df['Volume'] > stocks_df['Avg Vol (3M)']] result_df = result[['Symbol', 'Price', 'Change', 'Change %', 'Volume', 'Avg Vol (3M)']] result_df.columns = ['Symbol', 'Price', 'Change', 'Change %', 'Volume', 'Avg Vol (3M)'] # Chuẩn hóa dữ liệu result_df['Price'] = result_df['Price'].str.split(' ').str[0] result_df['Volume'] = result_df['Volume'].apply(lambda x: f"{x:,}") result_df['Avg Vol (3M)'] = result_df['Avg Vol (3M)'].apply(lambda x: f"{x:,}") result_df['Price'] = result_df['Price'].astype(float).apply(lambda x: f"${x:.2f}") result_df['Change'] = result_df['Change'].astype(float).apply(lambda x: f"+{x:.2f}" if x > 0 else f"{x:.2f}") return result_df # Hàm lấy dữ liệu Open, High, Close từ yfinance def get_stock_data(symbols): stock_data = [] for symbol in symbols: try: stock = yf.Ticker(symbol) hist = stock.history(period="1d") # Lấy dữ liệu trong 1 ngày gần nhất live_price = stock.info.get("regularMarketPrice", None) if not hist.empty: open_price = hist['Open'].iloc[-1] high_price = hist['High'].iloc[-1] close_price = hist['Close'].iloc[-1] low_price = hist['Low'].iloc[-1] stock_data.append({ "Symbol": symbol, "Open": round(open_price, 2), "High": round(high_price, 2), "Close": round(close_price, 2), "Low": round(low_price, 2), "Live Price": round(live_price, 2) if live_price else "N/A" }) except Exception as e: print(f"Không lấy được dữ liệu của {symbol}: {e}") return pd.DataFrame(stock_data) # Hàm tính ATR def compute_atr(ticker): end_date = datetime.today() start_date = end_date - timedelta(days=30) df = yf.download(ticker, start=start_date, end=end_date, progress=False) if df.empty or len(df) < 15: return None df['H-L'] = df['High'] - df['Low'] df['H-PC'] = abs(df['High'] - df['Close'].shift(1)) df['L-PC'] = abs(df['Low'] - df['Close'].shift(1)) df['TR'] = df[['H-L', 'H-PC', 'L-PC']].max(axis=1) df['ATR'] = df['TR'].rolling(window=14).mean() return round(df['ATR'].iloc[-1], 2) # Main logic with st.spinner("Đang tải dữ liệu..."): df = get_active_stocks() df['ATR (14)'] = df['Symbol'].apply(compute_atr) st.dataframe(df.dropna(subset=["ATR (14)"]).reset_index(drop=True)) # Ứng dụng Streamlit st.title("Stocks with Volume > Avg Vol (3M) and Price Data") # Cập nhật tự động mỗi 60 giây st_autorefresh(interval=60000, key="price_refresh") # Hiển thị thời gian cập nhật mới nhất st.write("🔄 **Lần cập nhật gần nhất:**", pd.Timestamp.now()) if st.button("Get Stocks Data"): with st.spinner('Fetching data...'): df = get_active_stocks() # Lấy danh sách cổ phiếu có volume cao symbols = df["Symbol"].tolist() # Lấy danh sách mã cổ phiếu stock_prices = get_stock_data(symbols) # Lấy giá Open, High, Close, Low, Live Price từ yfinance # Kết hợp hai bảng dữ liệu merged_df = pd.merge(df, stock_prices, on="Symbol", how="left") st.dataframe(merged_df) # Hiển thị dữ liệu trên Streamlit