Compare commits
8 Commits
67ae4fe038
...
aaf7d0afd1
| Author | SHA1 | Date | |
|---|---|---|---|
| aaf7d0afd1 | |||
| 77ffb150c6 | |||
| 73ff3f7089 | |||
| 8fb3949fac | |||
| dce017fbf2 | |||
| 58e3e98031 | |||
| e65661ef94 | |||
| 5e88a1ce24 |
@@ -1,4 +1,4 @@
|
||||
from datetime import date
|
||||
from datetime import date, timedelta
|
||||
from fastapi import APIRouter, Depends, Request
|
||||
from fastapi.responses import HTMLResponse
|
||||
from sqlalchemy.orm import Session
|
||||
@@ -59,7 +59,7 @@ def contract_detail(request: Request, contract: str, db: Session = Depends(get_d
|
||||
bars = (
|
||||
db.query(DailyBar)
|
||||
.filter(DailyBar.contract == contract.upper())
|
||||
.order_by(DailyBar.date)
|
||||
.order_by(DailyBar.date.desc())
|
||||
.all()
|
||||
)
|
||||
|
||||
@@ -77,8 +77,18 @@ def contract_detail(request: Request, contract: str, db: Session = Depends(get_d
|
||||
"has_amp": bar.amp_5d is not None,
|
||||
})
|
||||
|
||||
latest = bars[-1] if bars else None
|
||||
latest = bars[0] if bars else None
|
||||
|
||||
# Predict next trading day amplitude: mean of latest 5 diffs
|
||||
# Compute next trading date
|
||||
next_date = latest.date + timedelta(days=1) if latest else None
|
||||
if next_date and next_date.weekday() >= 5:
|
||||
next_date += timedelta(days=7 - next_date.weekday())
|
||||
|
||||
# Predict next trading day amplitude
|
||||
next_amp = None
|
||||
if len(bars) >= 5:
|
||||
next_amp = round(sum(b.diff for b in bars[:5]) / 5)
|
||||
template = request.app.state.templates.get_template("contract.html")
|
||||
return HTMLResponse(
|
||||
template.render(
|
||||
@@ -88,6 +98,9 @@ def contract_detail(request: Request, contract: str, db: Session = Depends(get_d
|
||||
contracts=active_contracts,
|
||||
rows=rows,
|
||||
latest=latest,
|
||||
next_amp=next_amp,
|
||||
next_date=next_date.strftime("%Y/%-m/%-d") if next_date else None,
|
||||
next_weekday=WEEKDAY_ZH.get(next_date.weekday(), "") if next_date else "",
|
||||
row_count=len(rows),
|
||||
)
|
||||
)
|
||||
|
||||
@@ -12,27 +12,45 @@
|
||||
<div class="trend">日期 {{ latest.date }}</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="label">当日振幅</div>
|
||||
<div class="value">{{ latest.amp_5d|int if latest.amp_5d else '—' }}</div>
|
||||
<div class="trend">日波幅 {{ latest.diff|int }} 点</div>
|
||||
<div class="label">次日预测振幅</div>
|
||||
<div class="value" style="color:var(--accent);">{{ next_amp if next_amp else '—' }}</div>
|
||||
<div class="trend">近5日均波幅</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="label">数据条数</div>
|
||||
<div class="value">{{ row_count }}</div>
|
||||
<div class="label">最新波幅</div>
|
||||
<div class="value">{{ latest.diff|int }} 点</div>
|
||||
<div class="trend">{{ latest.date }}</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="section-title">日线数据</div>
|
||||
<p style="font-size:0.78rem;color:var(--sub);margin-bottom:12px;">
|
||||
振幅 = 近 5 日 (最高−最低) 均值取整 · 点击振幅值查看计算过程
|
||||
</p>
|
||||
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:10px;">
|
||||
<p style="font-size:0.78rem;color:var(--sub);margin:0;">
|
||||
振幅 = 近 5 日 (最高−最低) 均值取整 · 点击振幅值查看计算过程
|
||||
</p>
|
||||
{% if rows|length > 7 %}
|
||||
<button id="toggle-all" class="btn" style="font-size:0.78rem;padding:4px 14px;background:var(--surface);color:var(--accent);border:1px solid var(--accent);border-radius:5px;cursor:pointer;" onclick="toggleAll()">显示全部 ({{ rows|length }}条)</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="table-wrap">
|
||||
<table id="bars-table">
|
||||
<tr><th>日期</th><th>星期</th><th>开盘</th><th>收盘</th><th>最高</th><th>最低</th><th>波幅</th><th>5日均振幅</th></tr>
|
||||
{% if next_date %}
|
||||
<tr style="background:var(--accent-light);font-weight:500;">
|
||||
<td>{{ next_date }}</td>
|
||||
<td>{{ next_weekday }}</td>
|
||||
<td class="na">—</td>
|
||||
<td class="na">—</td>
|
||||
<td class="na">—</td>
|
||||
<td class="na">—</td>
|
||||
<td class="na">—</td>
|
||||
<td><span style="color:var(--accent);font-weight:700;">{{ next_amp }}</span></td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% for row in rows %}
|
||||
<tr data-index="{{ loop.index0 }}" data-diff="{{ row.diff }}" data-date="{{ row.date }}" data-weekday="{{ row.weekday }}">
|
||||
<tr data-index="{{ loop.index0 }}" data-diff="{{ row.diff }}" data-date="{{ row.date }}" data-weekday="{{ row.weekday }}"{% if loop.index0 >= 7 %} class="extra-row" style="display:none;"{% endif %}>
|
||||
<td>{{ row.date }}</td>
|
||||
<td>{{ row.weekday }}</td>
|
||||
<td>{{ row.open }}</td>
|
||||
@@ -53,21 +71,32 @@
|
||||
</div>
|
||||
|
||||
<script>
|
||||
|
||||
var allShown = false;
|
||||
function toggleAll() {
|
||||
allShown = !allShown;
|
||||
var btn = document.getElementById('toggle-all');
|
||||
var rows = document.querySelectorAll('.extra-row');
|
||||
rows.forEach(function(r) { r.style.display = allShown ? '' : 'none'; });
|
||||
btn.textContent = allShown ? '收起' : '显示全部 ({{ rows|length }}条)';
|
||||
}
|
||||
document.querySelectorAll('.amp-cell').forEach(function(cell) {
|
||||
cell.addEventListener('click', function() {
|
||||
var row = cell.parentElement.parentElement;
|
||||
var tbl = document.getElementById('bars-table');
|
||||
var rows = tbl.querySelectorAll('tr');
|
||||
// Only rows with data-index (skip header + next-day row)
|
||||
var dataRows = tbl.querySelectorAll('tr[data-index]');
|
||||
var idx = parseInt(row.dataset.index);
|
||||
if (idx < 5) return;
|
||||
// Need 5 older rows (higher index, since newest first)
|
||||
if (idx + 5 >= dataRows.length) return;
|
||||
|
||||
document.getElementById('drawer-title').textContent = '{{ contract }}';
|
||||
document.getElementById('drawer-date').textContent = '目标: ' + row.dataset.date + ' ' + row.dataset.weekday + ' 振幅 ' + cell.textContent.trim();
|
||||
|
||||
var html = '<tr><td>日期</td><td>最高−最低</td></tr>';
|
||||
var sum = 0;
|
||||
for (var j = idx - 5; j < idx; j++) {
|
||||
var r = rows[j + 1];
|
||||
for (var j = idx + 1; j <= idx + 5; j++) {
|
||||
var r = dataRows[j];
|
||||
html += '<tr><td>' + r.dataset.date + ' ' + r.dataset.weekday + '</td><td>' + r.dataset.diff + '</td></tr>';
|
||||
sum += parseInt(r.dataset.diff);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user