203 lines
11 KiB
HTML
203 lines
11 KiB
HTML
{% extends "base.html" %}
|
||
|
||
{% block title %}交易信号 - AI 智能选股大师{% endblock %}
|
||
|
||
{% block content %}
|
||
<!-- 页面标题和筛选 -->
|
||
<div class="row mb-4">
|
||
<div class="col-12">
|
||
<div class="d-flex justify-content-end align-items-center">
|
||
<!-- 筛选表单 -->
|
||
<form method="GET" class="d-flex gap-2 align-items-center">
|
||
<select name="strategy" class="form-select form-select-sm">
|
||
<option value="">所有策略</option>
|
||
<option value="K线形态策略" {% if strategy_name == 'K线形态策略' %}selected{% endif %}>K线形态策略</option>
|
||
</select>
|
||
|
||
<select name="timeframe" class="form-select form-select-sm">
|
||
<option value="">所有周期</option>
|
||
<option value="daily" {% if timeframe == 'daily' or not timeframe %}selected{% endif %}>日线</option>
|
||
<option value="weekly" {% if timeframe == 'weekly' %}selected{% endif %}>周线</option>
|
||
<option value="1h" {% if timeframe == '1h' %}selected{% endif %}>1小时</option>
|
||
</select>
|
||
|
||
<select name="days" class="form-select form-select-sm">
|
||
<option value="7" {% if days == 7 %}selected{% endif %}>最近7天</option>
|
||
<option value="15" {% if days == 15 %}selected{% endif %}>最近15天</option>
|
||
<option value="30" {% if days == 30 %}selected{% endif %}>最近30天</option>
|
||
<option value="90" {% if days == 90 %}selected{% endif %}>最近90天</option>
|
||
</select>
|
||
|
||
<select name="per_page" class="form-select form-select-sm">
|
||
<option value="20" {% if per_page == 20 %}selected{% endif %}>每页20条</option>
|
||
<option value="50" {% if per_page == 50 %}selected{% endif %}>每页50条</option>
|
||
<option value="100" {% if per_page == 100 %}selected{% endif %}>每页100条</option>
|
||
</select>
|
||
|
||
<button type="submit" class="btn btn-primary btn-sm text-nowrap">
|
||
<i class="fas fa-filter me-1"></i>筛选
|
||
</button>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<!-- 信号表格 -->
|
||
<div class="row">
|
||
<div class="col-12">
|
||
<div class="card fade-in">
|
||
<div class="card-header">
|
||
<h5 class="mb-0 text-primary fw-bold">
|
||
<i class="fas fa-table me-2"></i>详细信号数据
|
||
</h5>
|
||
</div>
|
||
<div class="card-body p-0">
|
||
{% if signals_grouped %}
|
||
<div class="table-container">
|
||
{% for scan_hour, signals in signals_grouped.items() %}
|
||
<!-- 扫描时间分组标题 -->
|
||
<div class="scan-date-header bg-light px-3 py-2">
|
||
<h6 class="mb-0 text-primary fw-bold">
|
||
<i class="fas fa-clock me-2"></i>扫描时间: {{ scan_hour.strftime('%Y-%m-%d %H:%M') }}
|
||
<span class="badge bg-primary ms-2">{{ signals|length }} 条信号</span>
|
||
</h6>
|
||
</div>
|
||
|
||
<!-- 该扫描时间下的信号表格 -->
|
||
<div class="table-responsive">
|
||
<table class="table table-hover mb-0">
|
||
<thead class="table-light">
|
||
<tr>
|
||
<th>股票</th>
|
||
<th>策略</th>
|
||
<th>周期</th>
|
||
<th>信号日期</th>
|
||
<th>突破价格</th>
|
||
<th>阴线高点</th>
|
||
<th>突破幅度</th>
|
||
<th>实体比例</th>
|
||
<th>换手率</th>
|
||
<th>扫描时间</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{% for signal in signals %}
|
||
<tr>
|
||
<td>
|
||
<div class="d-flex align-items-center">
|
||
<a href="https://xueqiu.com/S/{% if signal.stock_code.endswith('.SZ') %}SZ{% elif signal.stock_code.endswith('.SH') %}SH{% elif signal.stock_code.startswith('0') or signal.stock_code.startswith('3') %}SZ{% else %}SH{% endif %}{{ signal.stock_code.split('.')[0] }}" target="_blank" class="stock-code-link me-2">
|
||
<div class="stock-code-badge">{{ signal.stock_code }}</div>
|
||
</a>
|
||
<div class="stock-name text-truncate">{{ signal.stock_name or '未知' }}</div>
|
||
</div>
|
||
</td>
|
||
<td>
|
||
<span class="badge badge-light-primary">{{ signal.strategy_name }}</span>
|
||
</td>
|
||
<td>
|
||
<span class="badge bg-{% if signal.timeframe == 'daily' %}primary{% elif signal.timeframe == '1h' %}info{% else %}success{% endif %}">
|
||
{{ '日线' if signal.timeframe == 'daily' else ('1小时' if signal.timeframe == '1h' else '周线') }}
|
||
</span>
|
||
</td>
|
||
<td class="text-muted">{{ signal.signal_date | datetime_format('%Y-%m-%d') }}</td>
|
||
<td class="text-success fw-bold">{{ signal.breakout_price | currency }}元</td>
|
||
<td class="text-muted">{{ signal.yin_high | currency }}元</td>
|
||
<td>
|
||
<span class="badge bg-{% if signal.breakout_pct and signal.breakout_pct > 3 %}success{% elif signal.breakout_pct and signal.breakout_pct > 1 %}warning{% else %}secondary{% endif %}">
|
||
{{ signal.breakout_pct | percentage }}
|
||
</span>
|
||
</td>
|
||
<td class="text-muted">{{ signal.final_yang_entity_ratio | percentage }}</td>
|
||
<td class="text-muted">{{ signal.turnover_ratio | percentage }}</td>
|
||
<td class="text-muted small">{{ signal.scan_time | datetime_format('%m-%d %H:%M') }}</td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
{% endfor %}
|
||
</div>
|
||
|
||
<!-- 分页 -->
|
||
{% if total_pages > 1 %}
|
||
<nav aria-label="信号分页" class="mt-4">
|
||
<ul class="pagination justify-content-center">
|
||
<!-- 上一页 -->
|
||
<li class="page-item {% if not has_prev %}disabled{% endif %}">
|
||
<a class="page-link" href="{% if has_prev %}{{ url_for('signals', page=current_page-1, strategy=strategy_name, timeframe=timeframe, days=days, per_page=per_page) }}{% else %}#{% endif %}">
|
||
<i class="fas fa-chevron-left"></i> 上一页
|
||
</a>
|
||
</li>
|
||
|
||
<!-- 页码 -->
|
||
{% set start_page = [1, current_page - 2]|max %}
|
||
{% set end_page = [total_pages, current_page + 2]|min %}
|
||
|
||
{% if start_page > 1 %}
|
||
<li class="page-item">
|
||
<a class="page-link" href="{{ url_for('signals', page=1, strategy=strategy_name, timeframe=timeframe, days=days, per_page=per_page) }}">1</a>
|
||
</li>
|
||
{% if start_page > 2 %}
|
||
<li class="page-item disabled"><span class="page-link">...</span></li>
|
||
{% endif %}
|
||
{% endif %}
|
||
|
||
{% for page_num in range(start_page, end_page + 1) %}
|
||
<li class="page-item {% if page_num == current_page %}active{% endif %}">
|
||
<a class="page-link" href="{{ url_for('signals', page=page_num, strategy=strategy_name, timeframe=timeframe, days=days, per_page=per_page) }}">{{ page_num }}</a>
|
||
</li>
|
||
{% endfor %}
|
||
|
||
{% if end_page < total_pages %}
|
||
{% if end_page < total_pages - 1 %}
|
||
<li class="page-item disabled"><span class="page-link">...</span></li>
|
||
{% endif %}
|
||
<li class="page-item">
|
||
<a class="page-link" href="{{ url_for('signals', page=total_pages, strategy=strategy_name, timeframe=timeframe, days=days, per_page=per_page) }}">{{ total_pages }}</a>
|
||
</li>
|
||
{% endif %}
|
||
|
||
<!-- 下一页 -->
|
||
<li class="page-item {% if not has_next %}disabled{% endif %}">
|
||
<a class="page-link" href="{% if has_next %}{{ url_for('signals', page=current_page+1, strategy=strategy_name, timeframe=timeframe, days=days, per_page=per_page) }}{% else %}#{% endif %}">
|
||
下一页 <i class="fas fa-chevron-right"></i>
|
||
</a>
|
||
</li>
|
||
</ul>
|
||
</nav>
|
||
{% endif %}
|
||
|
||
{% else %}
|
||
<div class="empty-state">
|
||
<i class="fas fa-signal"></i>
|
||
<h4>暂无信号数据</h4>
|
||
<p>请尝试调整筛选条件或稍后再试</p>
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{% endblock %}
|
||
|
||
{% block extra_js %}
|
||
<script>
|
||
$(document).ready(function() {
|
||
// 表格行点击高亮
|
||
$('tbody tr').on('click', function() {
|
||
$(this).toggleClass('table-active');
|
||
});
|
||
|
||
// 工具提示
|
||
$('[data-bs-toggle="tooltip"]').tooltip();
|
||
|
||
// 如果没有timeframe参数,自动设置为daily并重新加载
|
||
const urlParams = new URLSearchParams(window.location.search);
|
||
if (!urlParams.has('timeframe')) {
|
||
urlParams.set('timeframe', 'daily');
|
||
window.location.search = urlParams.toString();
|
||
}
|
||
});
|
||
</script>
|
||
{% endblock %} |