Spaces:
Runtime error
Runtime error
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__) | |
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, | |
) | |
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}) | |