Spaces:
Runtime error
Runtime error
{% extends "base.html" %} | |
{% block title %} | |
Phân tích {{ symbol if symbol else 'Cổ phiếu' }} - Dữ liệu và Biểu đồ | |
{% endblock %} | |
{% block og_title %}Phân tích {{ symbol if symbol else 'Cổ phiếu' }} - Dữ liệu và Biểu đồ{% endblock %} | |
{% block twitter_title %}Phân tích {{ symbol if symbol else 'Cổ phiếu' }} - Dữ liệu và Biểu đồ{% endblock %} | |
{% block head %} | |
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.11.5/css/jquery.dataTables.min.css"> | |
<script type="text/javascript" src="https://code.jquery.com/jquery-3.5.1.js"></script> | |
<script type="text/javascript" src="https://cdn.datatables.net/1.11.5/js/jquery.dataTables.min.js"></script> | |
<style> | |
.stock-header { | |
background-color: #fff; | |
padding: 20px; | |
border-radius: 8px; | |
margin-bottom: 20px; | |
box-shadow: 0 4px 12px rgba(0,0,0,0.08); | |
text-align: center; | |
} | |
.stock-header form { | |
display: flex; | |
justify-content: center; | |
gap: 10px; | |
margin-top: 15px; | |
} | |
.stock-header input[type="text"] { | |
width: 300px; | |
padding: 10px; | |
border: 1px solid #ccc; | |
border-radius: 4px; | |
} | |
.stock-header button { | |
padding: 10px 20px; | |
background-color: #003366; | |
color: white; | |
border: none; | |
border-radius: 4px; | |
cursor: pointer; | |
} | |
.tabs { | |
display: flex; | |
border-bottom: 2px solid #dee2e6; | |
margin-bottom: 20px; | |
} | |
.tab-link { | |
padding: 10px 20px; | |
cursor: pointer; | |
border: none; | |
background: none; | |
font-size: 16px; | |
border-bottom: 2px solid transparent; | |
margin-bottom: -2px; | |
} | |
.tab-link.active { | |
border-color: #003366; | |
font-weight: bold; | |
} | |
.tab-content { | |
display: none; | |
} | |
.tab-content.active { | |
display: block; | |
} | |
#stockChartContainer { | |
position: relative; | |
height: 60vh; | |
width: 100%; | |
background: #fff; | |
padding: 15px; | |
border-radius: 8px; | |
box-shadow: 0 4px 12px rgba(0,0,0,0.08); | |
} | |
.info-card { | |
background: #fff; | |
border-radius: 8px; | |
padding: 20px; | |
box-shadow: 0 4px 12px rgba(0,0,0,0.08); | |
margin-bottom: 20px; | |
} | |
.financial-tables .table-responsive { | |
max-height: 400px; | |
overflow-y: auto; | |
} | |
.ai-analysis { | |
margin-top: 20px; | |
padding: 15px; | |
background-color: #f9f9f9; | |
border: 1px solid #ddd; | |
border-radius: 4px; | |
} | |
.ai-analysis h4 { | |
margin-top: 0; | |
margin-bottom: 10px; | |
} | |
</style> | |
{% endblock %} | |
{% block header_title %} | |
Phân tích Cổ phiếu - {{ symbol if symbol else 'Nhập mã để bắt đầu' }} | |
{% endblock %} | |
{% block content %} | |
<div id="stock-symbol-data" data-symbol="{{ symbol or '' }}"></div> | |
<div class="stock-header"> | |
<form method="get" action="{{ url_for('stock_analysis') }}"> | |
<input type="text" name="symbol" placeholder="Nhập mã cổ phiếu (VD: FPT, ACB...)" value="{{ symbol or '' }}" required> | |
<button type="submit">Phân tích</button> | |
</form> | |
{% if error %} | |
<div class="alert alert-danger mt-3">{{ error }}</div> | |
{% endif %} | |
</div> | |
{% if symbol %} | |
<div class="tabs"> | |
<button class="tab-link active" data-tab="tab-chart">Biểu đồ kỹ thuật</button> | |
<button class="tab-link" data-tab="tab-financials">Dữ liệu tài chính</button> | |
<button class="tab-link" data-tab="tab-valuation">Phân tích & Định giá</button> | |
</div> | |
<div id="tab-chart" class="tab-content active"> | |
<div class="chart-container" style="height: 60vh;"> | |
<canvas id="stockMainChart"></canvas> | |
</div> | |
<div class="chart-grid"> | |
<div class="chart-item"><canvas id="priceChart"></canvas></div> | |
<div class="chart-item"><canvas id="volumeChart"></canvas></div> | |
<div class="chart-item"><canvas id="pvChart"></canvas> | |
<p><b>Price Volume (PV)</b>: Tích số giá và khối lượng. Đường ngang ở mức 0 là ngưỡng trung bình. PV trên 0 cho thấy dòng tiền vào, dưới 0 cho thấy dòng tiền ra.</p> | |
</div> | |
<div class="chart-item"><canvas id="mfiChart"></canvas> | |
<p><b>Money Flow Index (MFI)</b>: Chỉ số dòng tiền. Đường ngang ở mức 50 là ngưỡng trung bình. MFI trên 50 cho thấy áp lực mua, dưới 50 cho thấy áp lực bán.</p> | |
</div> | |
</div> | |
</div> | |
<div id="tab-financials" class="tab-content financial-tables"> | |
<div class="info-card"> | |
<h3> | |
Bảng dữ liệu tài chính | |
<button type="button" id="reload-financial-data-btn" class="btn btn-sm btn-primary" style="margin-left: 20px;"> | |
Tải dữ liệu mới | |
<span id="financial-loading-spinner" class="spinner" style="display:none; margin-left: 5px;"></span> | |
</button> | |
</h3> | |
<!-- Nav tabs --> | |
<ul class="nav nav-tabs" role="tablist"> | |
<li class="nav-item"><a class="nav-link active" data-bs-toggle="tab" href="#bs-data">Bảng CĐKT</a></li> | |
<li class="nav-item"><a class="nav-link" data-bs-toggle="tab" href="#is-data">Kết quả KD</a></li> | |
<li class="nav-item"><a class="nav-link" data-bs-toggle="tab" href="#cf-data">Lưu chuyển tiền tệ</a></li> | |
<li class="nav-item"><a class="nav-link" data-bs-toggle="tab" href="#ratio-data">Chỉ số TC</a></li> | |
</ul> | |
<!-- Tab panes --> | |
<div class="tab-content"> | |
<div id="bs-data" class="container tab-pane active"><br> | |
<h4>Bảng CĐKT (Năm)</h4> | |
<table id="bs_year_table" class="display" style="width:100%">{{ tables['bs_year']|safe }}</table> | |
<div class="ai-analysis"> | |
<h4>Phân tích AI (Năm)</h4> | |
<p id="bs_year_ai_analysis">Phân tích AI sẽ hiển thị ở đây.</p> | |
<button class="btn btn-primary" onclick="getAiAnalysis('bs_year')">Phân tích</button> | |
</div> | |
<h4>Bảng CĐKT (Quý)</h4> | |
<table id="bs_quarter_table" class="display" style="width:100%">{{ tables['bs_quarter']|safe }}</table> | |
<div class="ai-analysis"> | |
<h4>Phân tích AI (Quý)</h4> | |
<p id="bs_quarter_ai_analysis">Phân tích AI sẽ hiển thị ở đây.</p> | |
<button class="btn btn-primary" onclick="getAiAnalysis('bs_quarter')">Phân tích</button> | |
</div> | |
</div> | |
<div id="is-data" class="container tab-pane fade"><br> | |
<h4>Kết quả KD (Năm)</h4> | |
<table id="is_year_table" class="display" style="width:100%">{{ tables['is_year']|safe }}</table> | |
<div class="ai-analysis"> | |
<h4>Phân tích AI (Năm)</h4> | |
<p id="is_year_ai_analysis">Phân tích AI sẽ hiển thị ở đây.</p> | |
<button class="btn btn-primary" onclick="getAiAnalysis('is_year')">Phân tích</button> | |
</div> | |
<h4>Kết quả KD (Quý)</h4> | |
<table id="is_quarter_table" class="display" style="width:100%">{{ tables['is_quarter']|safe }}</table> | |
<div class="ai-analysis"> | |
<h4>Phân tích AI (Quý)</h4> | |
<p id="is_quarter_ai_analysis">Phân tích AI sẽ hiển thị ở đây.</p> | |
<button class="btn btn-primary" onclick="getAiAnalysis('is_quarter')">Phân tích</button> | |
</div> | |
</div> | |
<div id="cf-data" class="container tab-pane fade"><br> | |
<h4>Lưu chuyển tiền tệ (Năm)</h4> | |
<table id="cf_year_table" class="display" style="width:100%">{{ tables['cf_year']|safe }}</table> | |
<div class="ai-analysis"> | |
<h4>Phân tích AI (Năm)</h4> | |
<p id="cf_year_ai_analysis">Phân tích AI sẽ hiển thị ở đây.</p> | |
<button class="btn btn-primary" onclick="getAiAnalysis('cf_year')">Phân tích</button> | |
</div> | |
</div> | |
<div id="ratio-data" class="container tab-pane fade"><br> | |
<h4>Chỉ số TC (Năm)</h4> | |
<table id="ratio_year_table" class="display" style="width:100%">{{ tables['ratio_year']|safe }}</table> | |
<div class="ai-analysis"> | |
<h4>Phân tích AI (Năm)</h4> | |
<p id="ratio_year_ai_analysis">Phân tích AI sẽ hiển thị ở đây.</p> | |
<button class="btn btn-primary" onclick="getAiAnalysis('ratio_year')">Phân tích</button> | |
</div> | |
<h4>Chỉ số TC (Quý)</h4> | |
<table id="ratio_quarter_table" class="display" style="width:100%">{{ tables['ratio_quarter']|safe }}</table> | |
<div class="ai-analysis"> | |
<h4>Phân tích AI (Quý)</h4> | |
<p id="ratio_quarter_ai_analysis">Phân tích AI sẽ hiển thị ở đây.</p> | |
<button class="btn btn-primary" onclick="getAiAnalysis('ratio_quarter')">Phân tích</button> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<div id="tab-valuation" class="tab-content"> | |
<div class="info-card"> | |
<h3>Phân tích tự động với Groq AI</h3> | |
<form id="groq-form"> | |
<input type="hidden" name="symbol" value="{{ symbol }}"> | |
<input type="text" name="question" placeholder="Nhập câu hỏi về dữ liệu tài chính (tùy chọn)" class="form-control mb-2"> | |
<button type="submit" class="btn btn-info">Phân tích với AI <span class="spinner" style="display:none;"></span></button> | |
</form> | |
<div id="groq-result" class="alert alert-info mt-3" style="white-space: pre-wrap;">Kết quả phân tích sẽ hiển thị ở đây.</div> | |
</div> | |
</div> | |
{% else %} | |
<div class="info-card" style="text-align: center;"> | |
<h4>Chào mừng đến với công cụ Phân tích Cổ phiếu</h4> | |
<p>Vui lòng nhập một mã cổ phiếu vào ô ở trên để bắt đầu xem biểu đồ, dữ liệu tài chính và các phân tích chuyên sâu.</p> | |
</div> | |
{% endif %} | |
{% endblock %} | |
{% block scripts %} | |
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script> | |
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script> | |
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns"></script> | |
<script src="https://cdn.jsdelivr.net/npm/chartjs-chart-financial"></script> | |
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-annotation"></script> | |
<script type="module" src="{{ url_for('static', filename='js/stock_analysis.js') }}"></script> | |
<script> | |
$(document).ready( function () { | |
$('a[data-bs-toggle="tab"]').on('shown.bs.tab', function (e) { | |
if (e.target.getAttribute('href') == '#bs-data') { | |
$('#bs_year_table').DataTable(); | |
$('#bs_quarter_table').DataTable(); | |
} | |
if (e.target.getAttribute('href') == '#is-data') { | |
$('#is_year_table').DataTable(); | |
$('#is_quarter_table').DataTable(); | |
} | |
if (e.target.getAttribute('href') == '#cf-data') { | |
$('#cf_year_table').DataTable(); | |
} | |
if (e.target.getAttribute('href') == '#ratio-data') { | |
$('#ratio_year_table').DataTable(); | |
$('#ratio_quarter_table').DataTable(); | |
} | |
}); | |
} ); | |
function getAiAnalysis(tableId) { | |
var symbol = $('#stock-symbol-data').data('symbol'); | |
$.ajax({ | |
url: '/api/stock_valuation_groq?symbol=' + symbol, | |
type: 'GET', | |
success: function(response) { | |
if (response.groq_valuation) { | |
$('#' + tableId + '_ai_analysis').text(response.groq_valuation); | |
} else if (response.error) { | |
$('#' + tableId + '_ai_analysis').text('Error: ' + response.error); | |
} else { | |
$('#' + tableId + '_ai_analysis').text('No analysis available.'); | |
} | |
}, | |
error: function(error) { | |
$('#' + tableId + '_ai_analysis').text('Error fetching analysis.'); | |
} | |
}); | |
} | |
</script> | |
{% endblock %} | |