Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -7,7 +7,7 @@ from vnstock import Vnstock
|
|
| 7 |
st.set_page_config(page_title="Vietnam Stock Market Insight", layout="wide")
|
| 8 |
st.title("📈 Vietnam Stock Market Insight")
|
| 9 |
|
| 10 |
-
# Nhập
|
| 11 |
symbol = st.text_input("Nhập mã cổ phiếu (ví dụ: VNM, FPT, VCB):", value="VNM")
|
| 12 |
col1, col2 = st.columns(2)
|
| 13 |
with col1:
|
|
@@ -16,21 +16,29 @@ with col2:
|
|
| 16 |
end_date = st.date_input("Ngày kết thúc", pd.to_datetime("2024-12-31"))
|
| 17 |
|
| 18 |
# Tabs cho các chức năng
|
| 19 |
-
tab1, tab2, tab3, tab4 = st.tabs([
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 20 |
|
|
|
|
| 21 |
with tab1:
|
| 22 |
if st.button("Phân tích kỹ thuật"):
|
| 23 |
-
with st.spinner("Đang tải dữ liệu
|
| 24 |
try:
|
| 25 |
stock = Vnstock().stock(symbol=symbol, source='VCI')
|
| 26 |
-
df = stock.quote.history(
|
| 27 |
-
|
| 28 |
-
|
|
|
|
|
|
|
| 29 |
df['date'] = pd.to_datetime(df['time'])
|
| 30 |
df.set_index('date', inplace=True)
|
| 31 |
df.sort_index(inplace=True)
|
| 32 |
|
| 33 |
-
# Tính
|
| 34 |
df['EMA12'] = df['close'].ewm(span=12, adjust=False).mean()
|
| 35 |
df['EMA26'] = df['close'].ewm(span=26, adjust=False).mean()
|
| 36 |
df['MACD'] = df['EMA12'] - df['EMA26']
|
|
@@ -40,7 +48,6 @@ with tab1:
|
|
| 40 |
df['BB_Upper'] = df['BB_Middle'] + (2 * df['BB_Std'])
|
| 41 |
df['BB_Lower'] = df['BB_Middle'] - (2 * df['BB_Std'])
|
| 42 |
|
| 43 |
-
# Tính RSI
|
| 44 |
delta = df['close'].diff()
|
| 45 |
gain = delta.where(delta > 0, 0)
|
| 46 |
loss = -delta.where(delta < 0, 0)
|
|
@@ -49,57 +56,65 @@ with tab1:
|
|
| 49 |
rs = avg_gain / avg_loss
|
| 50 |
df['RSI'] = 100 - (100 / (1 + rs))
|
| 51 |
|
| 52 |
-
|
| 53 |
-
st.subheader("Dữ liệu giá cổ phiếu")
|
| 54 |
st.dataframe(df[['open', 'high', 'low', 'close', 'volume']].dropna().tail(10))
|
| 55 |
|
| 56 |
-
st.subheader("
|
| 57 |
fig_bb = go.Figure()
|
| 58 |
fig_bb.add_trace(go.Scatter(x=df.index, y=df['close'], name='Close'))
|
| 59 |
fig_bb.add_trace(go.Scatter(x=df.index, y=df['BB_Upper'], name='Upper Band'))
|
| 60 |
fig_bb.add_trace(go.Scatter(x=df.index, y=df['BB_Lower'], name='Lower Band'))
|
| 61 |
st.plotly_chart(fig_bb, use_container_width=True)
|
| 62 |
|
| 63 |
-
st.subheader("
|
| 64 |
fig_rsi = go.Figure()
|
| 65 |
fig_rsi.add_trace(go.Scatter(x=df.index, y=df['RSI'], name='RSI'))
|
| 66 |
fig_rsi.update_layout(yaxis=dict(range=[0, 100]))
|
| 67 |
st.plotly_chart(fig_rsi, use_container_width=True)
|
| 68 |
|
| 69 |
-
st.subheader("
|
| 70 |
fig_macd = go.Figure()
|
| 71 |
fig_macd.add_trace(go.Scatter(x=df.index, y=df['MACD'], name='MACD'))
|
| 72 |
fig_macd.add_trace(go.Scatter(x=df.index, y=df['MACD_Signal'], name='Signal'))
|
| 73 |
st.plotly_chart(fig_macd, use_container_width=True)
|
| 74 |
|
| 75 |
except Exception as e:
|
| 76 |
-
st.error(f"Lỗi khi phân tích kỹ thuật: {e}")
|
| 77 |
|
|
|
|
| 78 |
with tab2:
|
| 79 |
if st.button("Phân tích cơ bản"):
|
| 80 |
-
with st.spinner("Đang tải
|
| 81 |
try:
|
| 82 |
stock = Vnstock().stock(symbol=symbol, source='VCI')
|
| 83 |
df_financial = stock.finance.income_statement(period='quarter', lang='vi', dropna=True)
|
| 84 |
-
st.subheader("Báo cáo tài chính quý")
|
| 85 |
st.dataframe(df_financial)
|
| 86 |
except Exception as e:
|
| 87 |
-
st.error(f"Lỗi khi lấy dữ liệu
|
| 88 |
|
|
|
|
| 89 |
with tab3:
|
| 90 |
-
st.subheader(f"Thông tin cơ bản về doanh nghiệp {symbol}")
|
| 91 |
try:
|
| 92 |
stock = Vnstock().stock(symbol=symbol, source='VCI')
|
| 93 |
company_info = stock.company.overview()
|
|
|
|
| 94 |
st.dataframe(company_info)
|
| 95 |
except Exception as e:
|
| 96 |
-
st.error(f"Lỗi khi lấy thông tin doanh nghiệp: {e}")
|
| 97 |
|
|
|
|
| 98 |
with tab4:
|
| 99 |
-
st.subheader(f"Giao dịch khối ngoại, tự doanh và cổ đông lớn của {symbol}")
|
| 100 |
try:
|
| 101 |
stock = Vnstock().stock(symbol=symbol, source='VCI')
|
| 102 |
-
|
| 103 |
-
st.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 104 |
except Exception as e:
|
| 105 |
-
st.error(f"Lỗi khi lấy dữ liệu giao dịch: {e}")
|
|
|
|
| 7 |
st.set_page_config(page_title="Vietnam Stock Market Insight", layout="wide")
|
| 8 |
st.title("📈 Vietnam Stock Market Insight")
|
| 9 |
|
| 10 |
+
# Nhập mã cổ phiếu và ngày
|
| 11 |
symbol = st.text_input("Nhập mã cổ phiếu (ví dụ: VNM, FPT, VCB):", value="VNM")
|
| 12 |
col1, col2 = st.columns(2)
|
| 13 |
with col1:
|
|
|
|
| 16 |
end_date = st.date_input("Ngày kết thúc", pd.to_datetime("2024-12-31"))
|
| 17 |
|
| 18 |
# Tabs cho các chức năng
|
| 19 |
+
tab1, tab2, tab3, tab4 = st.tabs([
|
| 20 |
+
"📉 Phân tích kỹ thuật",
|
| 21 |
+
"📊 Phân tích cơ bản",
|
| 22 |
+
"🏢 Thông tin doanh nghiệp",
|
| 23 |
+
"📈 Giao dịch khối ngoại & cổ đông lớn"
|
| 24 |
+
])
|
| 25 |
|
| 26 |
+
# --- Tab 1: Phân tích kỹ thuật ---
|
| 27 |
with tab1:
|
| 28 |
if st.button("Phân tích kỹ thuật"):
|
| 29 |
+
with st.spinner("Đang tải dữ liệu..."):
|
| 30 |
try:
|
| 31 |
stock = Vnstock().stock(symbol=symbol, source='VCI')
|
| 32 |
+
df = stock.quote.history(
|
| 33 |
+
start=start_date.strftime("%Y-%m-%d"),
|
| 34 |
+
end=end_date.strftime("%Y-%m-%d"),
|
| 35 |
+
interval='1D'
|
| 36 |
+
)
|
| 37 |
df['date'] = pd.to_datetime(df['time'])
|
| 38 |
df.set_index('date', inplace=True)
|
| 39 |
df.sort_index(inplace=True)
|
| 40 |
|
| 41 |
+
# Tính các chỉ báo kỹ thuật
|
| 42 |
df['EMA12'] = df['close'].ewm(span=12, adjust=False).mean()
|
| 43 |
df['EMA26'] = df['close'].ewm(span=26, adjust=False).mean()
|
| 44 |
df['MACD'] = df['EMA12'] - df['EMA26']
|
|
|
|
| 48 |
df['BB_Upper'] = df['BB_Middle'] + (2 * df['BB_Std'])
|
| 49 |
df['BB_Lower'] = df['BB_Middle'] - (2 * df['BB_Std'])
|
| 50 |
|
|
|
|
| 51 |
delta = df['close'].diff()
|
| 52 |
gain = delta.where(delta > 0, 0)
|
| 53 |
loss = -delta.where(delta < 0, 0)
|
|
|
|
| 56 |
rs = avg_gain / avg_loss
|
| 57 |
df['RSI'] = 100 - (100 / (1 + rs))
|
| 58 |
|
| 59 |
+
st.subheader("📊 Dữ liệu giá cổ phiếu")
|
|
|
|
| 60 |
st.dataframe(df[['open', 'high', 'low', 'close', 'volume']].dropna().tail(10))
|
| 61 |
|
| 62 |
+
st.subheader("📈 Bollinger Bands")
|
| 63 |
fig_bb = go.Figure()
|
| 64 |
fig_bb.add_trace(go.Scatter(x=df.index, y=df['close'], name='Close'))
|
| 65 |
fig_bb.add_trace(go.Scatter(x=df.index, y=df['BB_Upper'], name='Upper Band'))
|
| 66 |
fig_bb.add_trace(go.Scatter(x=df.index, y=df['BB_Lower'], name='Lower Band'))
|
| 67 |
st.plotly_chart(fig_bb, use_container_width=True)
|
| 68 |
|
| 69 |
+
st.subheader("📉 RSI (Relative Strength Index)")
|
| 70 |
fig_rsi = go.Figure()
|
| 71 |
fig_rsi.add_trace(go.Scatter(x=df.index, y=df['RSI'], name='RSI'))
|
| 72 |
fig_rsi.update_layout(yaxis=dict(range=[0, 100]))
|
| 73 |
st.plotly_chart(fig_rsi, use_container_width=True)
|
| 74 |
|
| 75 |
+
st.subheader("📉 MACD")
|
| 76 |
fig_macd = go.Figure()
|
| 77 |
fig_macd.add_trace(go.Scatter(x=df.index, y=df['MACD'], name='MACD'))
|
| 78 |
fig_macd.add_trace(go.Scatter(x=df.index, y=df['MACD_Signal'], name='Signal'))
|
| 79 |
st.plotly_chart(fig_macd, use_container_width=True)
|
| 80 |
|
| 81 |
except Exception as e:
|
| 82 |
+
st.error(f"❌ Lỗi khi phân tích kỹ thuật: {e}")
|
| 83 |
|
| 84 |
+
# --- Tab 2: Phân tích cơ bản ---
|
| 85 |
with tab2:
|
| 86 |
if st.button("Phân tích cơ bản"):
|
| 87 |
+
with st.spinner("Đang tải dữ liệu..."):
|
| 88 |
try:
|
| 89 |
stock = Vnstock().stock(symbol=symbol, source='VCI')
|
| 90 |
df_financial = stock.finance.income_statement(period='quarter', lang='vi', dropna=True)
|
| 91 |
+
st.subheader("📊 Báo cáo tài chính quý")
|
| 92 |
st.dataframe(df_financial)
|
| 93 |
except Exception as e:
|
| 94 |
+
st.error(f"❌ Lỗi khi lấy dữ liệu tài chính: {e}")
|
| 95 |
|
| 96 |
+
# --- Tab 3: Thông tin doanh nghiệp ---
|
| 97 |
with tab3:
|
|
|
|
| 98 |
try:
|
| 99 |
stock = Vnstock().stock(symbol=symbol, source='VCI')
|
| 100 |
company_info = stock.company.overview()
|
| 101 |
+
st.subheader(f"🏢 Thông tin doanh nghiệp: {symbol}")
|
| 102 |
st.dataframe(company_info)
|
| 103 |
except Exception as e:
|
| 104 |
+
st.error(f"❌ Lỗi khi lấy thông tin doanh nghiệp: {e}")
|
| 105 |
|
| 106 |
+
# --- Tab 4: Giao dịch khối ngoại & cổ đông lớn ---
|
| 107 |
with tab4:
|
|
|
|
| 108 |
try:
|
| 109 |
stock = Vnstock().stock(symbol=symbol, source='VCI')
|
| 110 |
+
|
| 111 |
+
st.subheader("🔹 Giao dịch khối ngoại")
|
| 112 |
+
foreign_df = stock.holder.foreign()
|
| 113 |
+
st.dataframe(foreign_df)
|
| 114 |
+
|
| 115 |
+
st.subheader("🔸 Cổ đông lớn")
|
| 116 |
+
major_df = stock.holder.major()
|
| 117 |
+
st.dataframe(major_df)
|
| 118 |
+
|
| 119 |
except Exception as e:
|
| 120 |
+
st.error(f"❌ Lỗi khi lấy dữ liệu giao dịch: {e}")
|