danghungithp's picture
Upload 1398 files
bec48e1 verified
from flask import Blueprint, render_template, request, jsonify
import os
import pandas as pd
from datetime import datetime, timedelta
from vnstock import Vnstock
from modules.utils import (
detect_candlestick_patterns, calculate_fibonacci_levels, calculate_money_flow,
find_double_top_bottom, detect_w_double_bottom, detect_m_double_top, detect_cup_and_handle,
plot_candlestick_with_fibo_patterns, get_financial_valuation,
fetch_vietstock_news, analyze_news_with_groq
)
home_bp = Blueprint('home', __name__)
@home_bp.route('/')
def home():
symbol = 'VNINDEX'
vnindex_csv = os.path.join(os.path.dirname(__file__), '../vnindex.csv')
today = datetime.now().date()
start_3y = (today - timedelta(days=3*365)).strftime('%Y-%m-%d')
end_today = today.strftime('%Y-%m-%d')
if not os.path.exists(vnindex_csv):
stock = Vnstock().stock(symbol=symbol, source='VCI')
df = stock.quote.history(start=start_3y, end=end_today, interval='1D')
df.to_csv(vnindex_csv, index=False)
else:
df_old = pd.read_csv(vnindex_csv)
if 'time' in df_old.columns:
last_date = pd.to_datetime(df_old['time']).max().date()
else:
last_date = today - timedelta(days=3*365)
if last_date < today:
stock = Vnstock().stock(symbol=symbol, source='VCI')
df_new = stock.quote.history(start=(last_date + timedelta(days=1)).strftime('%Y-%m-%d'), end=end_today, interval='1D')
if not df_new.empty:
df_new = df_new[df_new['time'] > str(last_date)]
df_full = pd.concat([df_old, df_new], ignore_index=True)
df_full = df_full.drop_duplicates(subset=['time']).sort_values('time')
df_full.to_csv(vnindex_csv, index=False)
else:
df_full = df_old
else:
df_full = df_old
df = df_full
candlestick_patterns = detect_candlestick_patterns(df)
fibonacci_levels = calculate_fibonacci_levels(df)
df = calculate_money_flow(df)
double_tops, double_bottoms = find_double_top_bottom(df)
w_double_bottoms = detect_w_double_bottom(df)
m_double_tops = detect_m_double_top(df)
CHART_PATH_CANDLE_VNINDEX = "static/images/vnindex_candle.png"
CHART_PATH_MONEY_VNINDEX = "static/images/vnindex_money.png"
os.makedirs(os.path.dirname(CHART_PATH_CANDLE_VNINDEX), exist_ok=True)
plot_candlestick_with_fibo_patterns(
df, fibonacci_levels, candlestick_patterns, symbol, chart_path=CHART_PATH_CANDLE_VNINDEX,
double_tops=double_tops, double_bottoms=double_bottoms,
cup_handle_patterns=None, w_double_bottoms=w_double_bottoms, m_double_tops=m_double_tops
)
# Vẽ biểu đồ dòng tiền
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 6))
plt.plot(df['time'], df['money_flow'], label='Money Flow')
plt.plot(df['time'], df['money_flow_20d_avg'], label='20-Day Avg Money Flow', linestyle='--')
plt.xlabel('Time')
plt.ylabel('Money Flow')
plt.title('Money Flow for VNINDEX')
plt.legend()
plt.grid()
plt.savefig(CHART_PATH_MONEY_VNINDEX)
plt.close()
cup_handle_patterns = detect_cup_and_handle(df)
stock = Vnstock().stock(symbol=symbol, source='VCI')
financial_valuation = get_financial_valuation(stock)
# Lấy 30 phiên gần nhất
df_recent = df.tail(30)
# Chuẩn bị dữ liệu bảng cho prompt
table_rows = []
for _, row in df_recent.iterrows():
table_rows.append(f"{row['time']}: Giá={row['close']}, KL={row['volume']}, Dòng tiền={row.get('money_flow', '')}, MA20 dòng tiền={row.get('money_flow_20d_avg', '')}")
data_table = "\n".join(table_rows)
# Tổng hợp marker mẫu hình giá
pattern_summary = []
if double_tops:
pattern_summary.append(f"Đỉnh: {', '.join([str(x['time']) for x in double_tops])}")
if double_bottoms:
pattern_summary.append(f"Đáy: {', '.join([str(x['time']) for x in double_bottoms])}")
if w_double_bottoms:
pattern_summary.append(f"W-Double Bottom: {', '.join([str(x['time']) for x in w_double_bottoms])}")
if m_double_tops:
pattern_summary.append(f"M-Double Top: {', '.join([str(x['time']) for x in m_double_tops])}")
if cup_handle_patterns:
pattern_summary.append(f"Cup & Handle: {', '.join([str(x['time']) for x in cup_handle_patterns])}")
pattern_text = " | ".join(pattern_summary) if pattern_summary else "Không có mẫu hình đặc biệt."
# Tạo prompt động cho Groq AI
groq_prompt = (
f"Dưới đây là dữ liệu giao dịch VNINDEX 30 phiên gần nhất (thời gian, giá đóng cửa, khối lượng, dòng tiền, MA20 dòng tiền):\n"
f"{data_table}\n\n"
f"Các mẫu hình nhận diện: {pattern_text}\n\n"
"Hãy phân tích dòng tiền theo phương pháp VSA, nhận diện trạng thái hiện tại (đỉnh, đáy, phân phối, tăng tốc/bứt phá), và dự báo xu hướng ngắn hạn. Trình bày ngắn gọn, súc tích, sát thực tế giao dịch."
)
# Gọi Groq AI backend để lấy kết quả phân tích khi load trang
try:
from modules.utils import client, GROQ_MODEL
groq_ai_result = client.chat.completions.create(
model=GROQ_MODEL,
messages=[{"role": "user", "content": groq_prompt}],
max_tokens=600, temperature=0.2
).choices[0].message.content.strip()
except Exception as exc:
groq_ai_result = f"[Lỗi AI] {exc}"
# Fetch and analyze news
news_items = fetch_vietstock_news()
news_analysis = analyze_news_with_groq(news_items)
# Truyền context vào template
return render_template(
'home.html',
symbol=symbol,
chart_path_candle_vnindex=CHART_PATH_CANDLE_VNINDEX,
chart_path_money_vnindex=CHART_PATH_MONEY_VNINDEX,
vnindex_fibonacci_levels=fibonacci_levels,
vnindex_pattern_results=candlestick_patterns,
vnindex_double_tops=double_tops,
vnindex_double_bottoms=double_bottoms,
vnindex_cup_handle_patterns=cup_handle_patterns,
financial_valuation=financial_valuation,
vnindex_w_double_bottoms=w_double_bottoms,
vnindex_m_double_tops=m_double_tops,
groq_prompt=groq_prompt,
groq_ai_result=groq_ai_result,
news_items=news_items,
news_analysis=news_analysis,
)
@home_bp.route('/api/groq_analyze', methods=['POST'])
def groq_analyze():
from flask import jsonify
data = request.get_json()
prompt = data.get('prompt', '')
question = data['question'] if 'question' in data else ''
full_prompt = prompt
if question:
full_prompt += f"\n\nCâu hỏi thêm của người dùng: {question}"
try:
from modules.utils import client, GROQ_MODEL
result = client.chat.completions.create(
model=GROQ_MODEL,
messages=[{"role": "user", "content": full_prompt}],
max_tokens=600, temperature=0.2
).choices[0].message.content.strip()
except Exception as exc:
result = "[Lỗi AI] " + str(exc)
return jsonify({"result": result})