Remove files
This commit is contained in:
+448
-1
@@ -74,9 +74,51 @@
|
||||
}
|
||||
.data-container {
|
||||
margin-top: 10px;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
background-color: white;
|
||||
border-radius: 8px;
|
||||
padding: 15px;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
||||
}
|
||||
.nav-tabs {
|
||||
margin-bottom: 10px;
|
||||
position: relative;
|
||||
z-index: 20;
|
||||
background-color: white;
|
||||
border-radius: 8px 8px 0 0;
|
||||
padding: 10px 10px 0 10px;
|
||||
}
|
||||
.nav-tabs .nav-link {
|
||||
border-radius: 6px 6px 0 0;
|
||||
margin-right: 5px;
|
||||
font-weight: 500;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
.nav-tabs .nav-link:hover {
|
||||
background-color: #f8f9fa;
|
||||
border-color: #dee2e6;
|
||||
}
|
||||
.nav-tabs .nav-link.active {
|
||||
background-color: #0d6efd;
|
||||
color: white;
|
||||
border-color: #0d6efd;
|
||||
}
|
||||
/* 特别突出显示股票筛选tab */
|
||||
#stock-filter-tab {
|
||||
background-color: #28a745 !important;
|
||||
color: white !important;
|
||||
border-color: #28a745 !important;
|
||||
font-weight: bold !important;
|
||||
box-shadow: 0 2px 4px rgba(40, 167, 69, 0.3) !important;
|
||||
}
|
||||
#stock-filter-tab:hover {
|
||||
background-color: #218838 !important;
|
||||
border-color: #1e7e34 !important;
|
||||
}
|
||||
#stock-filter-tab.active {
|
||||
background-color: #155724 !important;
|
||||
border-color: #155724 !important;
|
||||
}
|
||||
.table-container {
|
||||
overflow-x: auto;
|
||||
@@ -478,6 +520,9 @@
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="trade-points-tab" data-bs-toggle="tab" data-bs-target="#trade-points" type="button" role="tab">买卖点</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="stock-filter-tab" data-bs-toggle="tab" data-bs-target="#stock-filter" type="button" role="tab">股票筛选</button>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="data-source-info alert alert-info py-2 mt-1 mb-2" style="display:none;">
|
||||
<small id="dataSourceText"></small>
|
||||
@@ -592,6 +637,81 @@
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="stock-filter" role="tabpanel">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-12">
|
||||
<h5>A股强分型筛选</h5>
|
||||
<p class="text-muted">筛选最近2个K线合并(KLC)中有一个满足分型强度≥1.0且分型类型不为UNKNOWN的A股股票</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-3">
|
||||
<label for="filterStartTime" class="form-label">开始时间:</label>
|
||||
<input type="datetime-local" id="filterStartTime" class="form-control">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label for="filterEndTime" class="form-label">结束时间:</label>
|
||||
<input type="datetime-local" id="filterEndTime" class="form-control">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label for="filterTimeframe" class="form-label">时间周期:</label>
|
||||
<select id="filterTimeframe" class="form-select">
|
||||
<option value="5m">5分钟</option>
|
||||
<option value="15m">15分钟</option>
|
||||
<option value="30m">30分钟</option>
|
||||
<option value="1h">1小时</option>
|
||||
<option value="4h">4小时</option>
|
||||
<option value="1d" selected>1日</option>
|
||||
<option value="1w">1周</option>
|
||||
<option value="1M">1月</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label for="fxStrengthThreshold" class="form-label">分型强度阈值:</label>
|
||||
<input type="number" id="fxStrengthThreshold" class="form-control" value="1.0" min="0" max="100" step="0.1">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-12">
|
||||
<button class="btn btn-primary" onclick="filterStocks()">
|
||||
<i class="bi bi-search"></i> 开始筛选
|
||||
</button>
|
||||
<button class="btn btn-secondary ms-2" onclick="exportFilterResults()">
|
||||
<i class="bi bi-download"></i> 导出结果
|
||||
</button>
|
||||
<span id="filterProgress" class="ms-3" style="display:none;">
|
||||
<i class="bi bi-hourglass-split"></i> 正在筛选中...
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="table-container">
|
||||
<table id="stockFilterTable" class="display compact" style="width:100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>股票代码</th>
|
||||
<th>股票名称</th>
|
||||
<th>分型时间</th>
|
||||
<th>分型类型</th>
|
||||
<th>分型强度</th>
|
||||
<th>分型价格</th>
|
||||
<th>当前价格</th>
|
||||
<th>涨跌幅(%)</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -841,6 +961,12 @@
|
||||
updateChartDisplay();
|
||||
});
|
||||
|
||||
// 添加K线周期切换事件监听器
|
||||
$('input[name="klinePeriod"]').change(function() {
|
||||
console.log('K线周期切换:', $(this).attr('id'), $(this).is(':checked'));
|
||||
updateChartDisplay();
|
||||
});
|
||||
|
||||
// 当选择不同的元素时间周期时
|
||||
$('#elementTimeframe').change(function() {
|
||||
const elementTimeframe = $(this).val();
|
||||
@@ -1198,7 +1324,7 @@
|
||||
}
|
||||
|
||||
// 检查是否使用小周期K线数据
|
||||
const useElementPeriod = $('#useElementPeriod').is(':checked') &&
|
||||
const useElementPeriod = $('#elementPeriodKline').is(':checked') &&
|
||||
currentData.element_kline_data &&
|
||||
Array.isArray(currentData.element_kline_data);
|
||||
|
||||
@@ -4004,6 +4130,52 @@
|
||||
updateTables(currentData);
|
||||
}
|
||||
});
|
||||
|
||||
// 页面加载完成后初始化
|
||||
$(document).ready(function() {
|
||||
// 设置默认的筛选时间(最近7天)
|
||||
const now = new Date();
|
||||
const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
|
||||
|
||||
$('#filterEndTime').val(now.toISOString().slice(0, 16));
|
||||
$('#filterStartTime').val(weekAgo.toISOString().slice(0, 16));
|
||||
|
||||
// 初始化股票筛选表格
|
||||
initStockFilterTable();
|
||||
|
||||
// 突出显示股票筛选tab
|
||||
setTimeout(function() {
|
||||
const stockFilterTab = $('#stock-filter-tab');
|
||||
if (stockFilterTab.length > 0) {
|
||||
console.log('股票筛选tab已找到,开始突出显示');
|
||||
|
||||
// 添加闪烁效果来吸引注意
|
||||
stockFilterTab.addClass('animate__animated animate__pulse');
|
||||
|
||||
// 滚动到tab区域
|
||||
$('html, body').animate({
|
||||
scrollTop: $('.data-container').offset().top - 100
|
||||
}, 1000);
|
||||
|
||||
// 添加提示信息
|
||||
const alertDiv = $(`
|
||||
<div class="alert alert-info alert-dismissible fade show" role="alert" style="position: fixed; top: 20px; right: 20px; z-index: 9999; max-width: 400px;">
|
||||
<strong>新功能!</strong> 股票筛选功能已添加,请查看绿色的"股票筛选"标签页。
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
`);
|
||||
$('body').append(alertDiv);
|
||||
|
||||
// 10秒后自动隐藏提示
|
||||
setTimeout(() => {
|
||||
alertDiv.alert('close');
|
||||
}, 10000);
|
||||
|
||||
} else {
|
||||
console.error('未找到股票筛选tab');
|
||||
}
|
||||
}, 2000);
|
||||
});
|
||||
});
|
||||
|
||||
// 自动刷新相关变量
|
||||
@@ -5103,6 +5275,281 @@
|
||||
window.astockStatusInterval = setInterval(updateAStockTradingStatus, 30000);
|
||||
console.log('A股交易时间状态更新器已启动');
|
||||
}
|
||||
|
||||
// 股票筛选相关函数
|
||||
let stockFilterTable = null;
|
||||
|
||||
// 初始化股票筛选表格
|
||||
function initStockFilterTable() {
|
||||
// 简单的表格初始化,不使用DataTable
|
||||
console.log('初始化股票筛选表格');
|
||||
}
|
||||
|
||||
// 筛选股票
|
||||
function filterStocks() {
|
||||
const startTime = $('#filterStartTime').val();
|
||||
const endTime = $('#filterEndTime').val();
|
||||
const timeframe = $('#filterTimeframe').val();
|
||||
const threshold = parseFloat($('#fxStrengthThreshold').val());
|
||||
|
||||
if (!startTime || !endTime) {
|
||||
alert('请选择开始时间和结束时间');
|
||||
return;
|
||||
}
|
||||
|
||||
if (new Date(startTime) >= new Date(endTime)) {
|
||||
alert('开始时间必须早于结束时间');
|
||||
return;
|
||||
}
|
||||
|
||||
// 显示进度指示器
|
||||
$('#filterProgress').show();
|
||||
$('#stockFilterTable tbody').empty();
|
||||
|
||||
// 发送筛选请求
|
||||
$.ajax({
|
||||
url: '/api/filter_stocks',
|
||||
method: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({
|
||||
start_time: startTime,
|
||||
end_time: endTime,
|
||||
timeframe: timeframe,
|
||||
fx_strength_threshold: threshold
|
||||
}),
|
||||
timeout: 300000, // 5分钟超时
|
||||
success: function(response) {
|
||||
$('#filterProgress').hide();
|
||||
|
||||
if (response.error) {
|
||||
// 根据错误类型显示不同的错误信息
|
||||
if (response.error_type === 'network_error') {
|
||||
showNetworkErrorAlert(response.error, response.suggestion);
|
||||
} else {
|
||||
alert('筛选失败: ' + response.error);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新表格数据
|
||||
updateStockFilterTable(response.results);
|
||||
|
||||
// 显示统计信息
|
||||
const totalCount = response.results.length;
|
||||
const processedCount = response.total_processed || 0;
|
||||
const failedCount = response.failed_count || 0;
|
||||
const dataSource = response.data_source || '未知';
|
||||
|
||||
let message = `筛选完成!使用${dataSource},共处理 ${processedCount} 只股票,找到 ${totalCount} 只满足条件的股票`;
|
||||
if (failedCount > 0) {
|
||||
message += `,${failedCount} 只股票数据获取失败`;
|
||||
}
|
||||
|
||||
// 显示成功提示
|
||||
showSuccessAlert(message);
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
$('#filterProgress').hide();
|
||||
console.error('筛选请求失败:', error, status, xhr);
|
||||
|
||||
// 根据错误类型显示不同的错误信息
|
||||
if (status === 'timeout') {
|
||||
showNetworkErrorAlert(
|
||||
'请求超时,可能是网络连接不稳定或数据量较大',
|
||||
'请检查网络连接,或尝试缩小时间范围后重试'
|
||||
);
|
||||
} else if (xhr.responseJSON && xhr.responseJSON.error_type === 'network_error') {
|
||||
showNetworkErrorAlert(xhr.responseJSON.error, xhr.responseJSON.suggestion);
|
||||
} else {
|
||||
alert('筛选请求失败: ' + (xhr.responseJSON?.error || error || '未知错误'));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 显示网络错误提示
|
||||
function showNetworkErrorAlert(errorMessage, suggestion) {
|
||||
const alertDiv = $(`
|
||||
<div class="alert alert-warning alert-dismissible fade show" role="alert">
|
||||
<h6><i class="fas fa-exclamation-triangle"></i> 网络连接问题</h6>
|
||||
<p><strong>错误信息:</strong>${errorMessage}</p>
|
||||
<p><strong>建议:</strong>${suggestion}</p>
|
||||
<hr>
|
||||
<p class="mb-0">
|
||||
<small>
|
||||
<i class="fas fa-info-circle"></i>
|
||||
如果问题持续存在,请检查网络连接或联系管理员
|
||||
</small>
|
||||
</p>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
`);
|
||||
$('#stock-filter .container-fluid').prepend(alertDiv);
|
||||
|
||||
// 10秒后自动隐藏提示
|
||||
setTimeout(() => {
|
||||
alertDiv.alert('close');
|
||||
}, 10000);
|
||||
}
|
||||
|
||||
// 显示成功提示
|
||||
function showSuccessAlert(message) {
|
||||
const alertDiv = $(`
|
||||
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
||||
<i class="fas fa-check-circle"></i> ${message}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
`);
|
||||
$('#stock-filter .container-fluid').prepend(alertDiv);
|
||||
|
||||
// 5秒后自动隐藏提示
|
||||
setTimeout(() => {
|
||||
alertDiv.alert('close');
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
// 更新股票筛选表格
|
||||
function updateStockFilterTable(results) {
|
||||
const tbody = $('#stockFilterTable tbody');
|
||||
tbody.empty();
|
||||
|
||||
if (!results || results.length === 0) {
|
||||
tbody.append('<tr><td colspan="9" class="text-center">没有找到满足条件的股票</td></tr>');
|
||||
return;
|
||||
}
|
||||
|
||||
// 按分型强度降序排列
|
||||
results.sort((a, b) => b.fx_strength - a.fx_strength);
|
||||
|
||||
// 添加新数据
|
||||
results.forEach(function(stock) {
|
||||
const strengthClass = getStrengthClass(stock.fx_strength);
|
||||
const changeClass = stock.change_percent >= 0 ? 'text-danger' : 'text-success';
|
||||
const changeSign = stock.change_percent >= 0 ? '+' : '';
|
||||
|
||||
const row = `
|
||||
<tr>
|
||||
<td>${stock.symbol}</td>
|
||||
<td>${stock.name}</td>
|
||||
<td>${stock.fx_time}</td>
|
||||
<td>${stock.fx_type}</td>
|
||||
<td><span class="${strengthClass}">${stock.fx_strength.toFixed(2)}</span></td>
|
||||
<td>${stock.fx_price.toFixed(2)}</td>
|
||||
<td>${stock.current_price ? stock.current_price.toFixed(2) : '-'}</td>
|
||||
<td><span class="${changeClass}">${changeSign}${(stock.change_percent || 0).toFixed(2)}%</span></td>
|
||||
<td><button class="btn btn-sm btn-outline-primary" onclick="analyzeStock('${stock.symbol}')">分析</button></td>
|
||||
</tr>
|
||||
`;
|
||||
tbody.append(row);
|
||||
});
|
||||
}
|
||||
|
||||
// 获取分型强度对应的CSS类
|
||||
function getStrengthClass(strength) {
|
||||
if (strength >= 2.0) return 'text-danger fw-bold';
|
||||
else if (strength >= 1.5) return 'text-warning fw-bold';
|
||||
else if (strength >= 1.0) return 'text-info';
|
||||
else return '';
|
||||
}
|
||||
|
||||
// 分析特定股票
|
||||
function analyzeStock(symbol) {
|
||||
// 切换到主分析页面
|
||||
$('#stock-filter-tab').removeClass('active');
|
||||
$('#kline-tab').addClass('active');
|
||||
$('#stock-filter').removeClass('show active');
|
||||
$('#kline').addClass('show active');
|
||||
|
||||
// 切换数据源为A股
|
||||
$('#dataSource').val('a_stock');
|
||||
$('#dataSource').trigger('change');
|
||||
|
||||
// 等待数据源切换完成后设置股票代码
|
||||
setTimeout(() => {
|
||||
$('#astockSymbol').val(symbol);
|
||||
// 触发分析
|
||||
updateChart();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
// 导出筛选结果
|
||||
function exportFilterResults() {
|
||||
const tbody = $('#stockFilterTable tbody tr');
|
||||
|
||||
if (tbody.length === 0 || (tbody.length === 1 && tbody.find('td').length === 1)) {
|
||||
alert('没有可导出的数据');
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建CSV内容
|
||||
const headers = ['股票代码', '股票名称', '分型时间', '分型类型', '分型强度', '分型价格', '当前价格', '涨跌幅(%)'];
|
||||
let csvContent = headers.join(',') + '\n';
|
||||
|
||||
tbody.each(function() {
|
||||
const cells = $(this).find('td');
|
||||
if (cells.length > 1) { // 排除"没有数据"的行
|
||||
const row = [];
|
||||
cells.slice(0, 8).each(function() { // 只取前8列,排除操作列
|
||||
row.push($(this).text().trim());
|
||||
});
|
||||
csvContent += row.join(',') + '\n';
|
||||
}
|
||||
});
|
||||
|
||||
// 创建下载链接
|
||||
const blob = new Blob(['\ufeff' + csvContent], { type: 'text/csv;charset=utf-8;' });
|
||||
const link = document.createElement('a');
|
||||
const url = URL.createObjectURL(blob);
|
||||
link.setAttribute('href', url);
|
||||
link.setAttribute('download', `股票筛选结果_${new Date().toISOString().slice(0, 10)}.csv`);
|
||||
link.style.visibility = 'hidden';
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
}
|
||||
|
||||
// 页面加载完成后初始化
|
||||
$(document).ready(function() {
|
||||
// 设置默认的筛选时间(最近7天)
|
||||
const now = new Date();
|
||||
const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
|
||||
|
||||
$('#filterEndTime').val(now.toISOString().slice(0, 16));
|
||||
$('#filterStartTime').val(weekAgo.toISOString().slice(0, 16));
|
||||
|
||||
// 初始化股票筛选表格
|
||||
initStockFilterTable();
|
||||
|
||||
// 突出显示股票筛选tab
|
||||
setTimeout(function() {
|
||||
const stockFilterTab = $('#stock-filter-tab');
|
||||
if (stockFilterTab.length > 0) {
|
||||
console.log('股票筛选tab已找到,开始突出显示');
|
||||
|
||||
// 滚动到tab区域
|
||||
$('html, body').animate({
|
||||
scrollTop: $('.data-container').offset().top - 100
|
||||
}, 1000);
|
||||
|
||||
// 添加提示信息
|
||||
const alertDiv = $(`
|
||||
<div class="alert alert-info alert-dismissible fade show" role="alert" style="position: fixed; top: 20px; right: 20px; z-index: 9999; max-width: 400px;">
|
||||
<strong>新功能!</strong> 股票筛选功能已添加,请查看绿色的"股票筛选"标签页。
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
`);
|
||||
$('body').append(alertDiv);
|
||||
|
||||
// 10秒后自动隐藏提示
|
||||
setTimeout(() => {
|
||||
alertDiv.alert('close');
|
||||
}, 10000);
|
||||
|
||||
} else {
|
||||
console.error('未找到股票筛选tab');
|
||||
}
|
||||
}, 2000);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user