trading: 日内T/长桥/六合彩文档与脚本 + quant-factor-mining 新目录

This commit is contained in:
2026-09-25 01:25:38 +08:00
parent 734b168082
commit 3f17a4eb1f
23 changed files with 1821 additions and 376 deletions
+88 -43
View File
@@ -1,11 +1,15 @@
"""
082 期特码分析 (纯挂牌, 纯挂牌, 不混 Qi 期数据 (Qi 期已开, 用挂牌做前瞻))
088 期特码分析 (纯挂牌, 纯挂牌, 不混 Qi 期数据 (Qi 期已开, 用挂牌做前瞻))
按 user 2026-07-30 实战需求:
1. 不跑频率 (5 期数据无意义)
2. 不混 Qi 期号码 (Qi 期已开, 用挂牌做前瞻, 不算 Nq 资料)
3. 只用挂牌 + 玄机诗 + 红字 推演
4. 输出 5 个候选特码 (有重点, 按挂牌共识排序)
5. 不强行 4 框架 (河洛/梅花/玄空/奇门) 公式 (reference 没推演方法)
🚨 默认期号必须用 v_xg.json Nq (未开下期), 不是 Qi (已开)
(2026-08-13 修过, 详见 SKILL.md 硬规则 4 + 9)
改 main() default period 时只动 Nq + fallback, 别碰 Qi 字段注释
"""
import re
import json
@@ -13,7 +17,7 @@ import sqlite3
import subprocess
import datetime
import os
from collections import Counter
from collections import Counter, defaultdict
DB_PATH = os.path.expanduser('~/.hermes/trading/lottery.db')
@@ -169,7 +173,7 @@ def fetch_sol_detail(path):
return fields
def get_te_ma_candidates(period='082'):
def get_te_ma_candidates(period='088'):
"""特码候选 - 按挂牌共识排序
规则:
@@ -180,10 +184,19 @@ def get_te_ma_candidates(period='082'):
5. 玄机字字型 (权重 × 2)
"""
weights = Counter()
# 同步记录每个号码的来源 (用于输出表格)
src_tracker = defaultdict(list)
def add(n, w, src):
if 1 <= n <= 49:
weights[n] += w
if src not in src_tracker[n]:
src_tracker[n].append(src)
# Step 1: 综合挂牌 列表 + 详情
# 2026-08-20 改: 多抓几页 (3 → 8), 挂牌稀疏时也能拿到更多数据源
gua_html = curl_url('https://sol.2344a.cc/zongheguapai/')
gua_links = re.findall(rf'href="(/zongheguapai/\d+\.html)"[^>]*>.*?{period}期', gua_html)[:3]
gua_links = re.findall(rf'href="(/zongheguapai/\d+\.html)"[^>]*>.*?{period}期', gua_html)[:8]
for link in gua_links:
f = fetch_sol_detail(link)
@@ -191,19 +204,40 @@ def get_te_ma_candidates(period='082'):
if '正版彩图挂' in f:
m = re.search(r'\d+', f['正版彩图挂'])
if m:
weights[int(m.group(0))] += 5 # 彩图挂直接给号最高权重
add(int(m.group(0)), 5, '挂牌 彩图挂直接给号')
# 另版挂 给出号
if '另版挂' in f:
m = re.search(r'\d+', f['另版挂'])
if m:
weights[int(m.group(0))] += 3
add(int(m.group(0)), 3, f'挂牌 另版挂 ({f["另版挂"]})')
# 尾数 (如 1尾,3尾) -> +10, +30
if '尾数' in f:
for m in re.finditer(r'(\d+)尾', f['尾数']):
weights[int(m.group(1))] += 2
weights[int(m.group(1)) + 10] += 1
weights[int(m.group(1)) + 20] += 1
weights[int(m.group(1)) + 30] += 1
tail_str = f['尾数']
for m in re.finditer(r'(\d+)尾', tail_str):
base = int(m.group(1))
add(base, 2, f'挂牌 尾数 {base}尾 (本)')
add(base + 10, 1, f'挂牌 尾数 {base}尾 (+10)')
add(base + 20, 1, f'挂牌 尾数 {base}尾 (+20)')
add(base + 30, 1, f'挂牌 尾数 {base}尾 (+30)')
# 火烧 (特码生肖提示 — 数字解码: 加 1 个本年生肖号 +2)
# 2026-08-20 改: 解码本年生肖, 让挂牌稀疏时多一个号 (单条+2 不至于污染权重)
SX_TO_BENSHENG = { # 本年生肖 → 该生肖的"本数" (单数尾数对应)
'鼠': 23, '牛': 22, '虎': 21, '兔': 20, '龙': 19, '蛇': 18,
'马': 17, '羊': 16, '猴': 15, '鸡': 14, '狗': 13, '猪': 12,
}
if '火烧' in f:
for sx, num in SX_TO_BENSHENG.items():
if sx in f['火烧']:
add(num, 2, f'挂牌 火烧 {sx}={num} (本年生肖)')
break
# 出肖 / 六肖 (2026-08-20 改: 解码所有提到的生肖本数, 各 +1)
for kw in ['出肖', '六肖']:
if kw in f:
sxs = re.findall(r'[鼠牛虎兔龙蛇羊猴鸡狗猪]', f[kw])
for sx in sxs:
num = SX_TO_BENSHENG.get(sx)
if num:
add(num, 1, f'挂牌 {kw} {sx}={num}')
# Step 2: 玄机诗 (xuanjiziliao)
xuan = fetch_sol_list('/xuanjiziliao/', f'{period}期', limit=20)
@@ -213,21 +247,19 @@ def get_te_ma_candidates(period='082'):
for m in re.finditer(r'[((](\d+)[))]', line):
num = int(m.group(1))
if 1 <= num <= 49:
weights[num] += 3
add(num, 3, f'玄机诗 诗象 ({line[:30]}...)')
# 彩霸王 三一玄数
if '三一' in line or '一三' in line:
weights[3] += 2
weights[1] += 2
weights[13] += 2
weights[31] += 2
for n in [3, 1, 13, 31]:
add(n, 2, '玄机诗 彩霸王 三一玄数')
# 玄机字 (沐字型 8 划)
if '《沐》' in line:
weights[8] += 2
add(8, 2, '玄机字 (沐 8 划)')
# 红马蓝狗 (马 红色 = 偏红, 狗 蓝色 = 偏蓝)
if '红马' in line:
weights[12] += 1 # 马=12 偏红
add(12, 1, '玄机诗 红马 (马=12 偏红)')
if '蓝狗' in line:
weights[18] += 1 # 狗=18 偏蓝
add(18, 1, '玄机诗 蓝狗 (狗=18 偏蓝)')
# Step 3: 六信红字 (红字 大数偏多)
hong = fetch_sol_list('/lxhz/', f'{period}期', limit=5)
@@ -235,15 +267,15 @@ def get_te_ma_candidates(period='082'):
if '頤養' in line or '天年' in line:
# 大数偏多 (>25)
for n in range(25, 50):
weights[n] += 1
add(n, 1, '六信红字 大数偏多 (頤養/天年)')
return weights
return weights, src_tracker
def format_te_ma_result(weights, period=None, budget=15, qi_week=None, qi_day=None, qi_nq=None):
def format_te_ma_result(weights, src_tracker=None, period=None, budget=15, qi_week=None, qi_day=None, qi_nq=None):
"""输出特码候选 + 推荐分配
period: 要分析哪期 (None=自动取 v_xg.json Qi)
period: 要分析哪期 (None=自动取 v_xg.json Nq 未开)
qi_week / qi_day / qi_nq: v_xg.json 字段 (None=自动取)
"""
# 一次性查 v_xg.json 拿所有字段
@@ -261,9 +293,10 @@ def format_te_ma_result(weights, period=None, budget=15, qi_week=None, qi_day=No
qi_xg = nq_xg = '???'
week_xg = day_xg = '?'
# 如果用户没传 period, 默认用 Qi
# 如果用户没传 period, 默认取 Nq (未开下期, 跟 main() 一致)
# (2026-08-13 修: 之前注释写"默认用 Qi"是错的, Qi=已开期跟分析目的相反)
if period is None:
period = qi_xg
period = nq_xg
if qi_week is None:
qi_week = week_xg
if qi_day is None:
@@ -303,27 +336,38 @@ def format_te_ma_result(weights, period=None, budget=15, qi_week=None, qi_day=No
L.append("")
# 排序 Top 5+
# 2026-08-20 改: 保证至少 4-5 个候选。如果 top<4, 兜底补足 (标记来源为占位)
top = weights.most_common(8)
if len(top) < 4:
# most_common 不返回权重 0 的号, 这里显式补足到 5 个 (权重 0 = 占位,排最后)
need = 5 - len(top)
existing = {n for n, _ in top}
for n in range(1, 50):
if n not in existing:
top.append((n, 0))
existing.add(n)
if len(top) >= 5:
break
L.append("🏆 特码候选 (按挂牌共识权重):")
L.append("")
L.append("| 排序 | 特码 | 权重 | 来源 |")
L.append("|---|---|---|---|")
# 常见号映射 (通用)
src_map = {
9: '诗象 (09, 47 单出) + 彩图挂 09',
33: '彩图挂 33',
5: '彩图挂 05',
47: '诗象 (单, 单出)',
13: '彩霸王 三一玄数',
3: '彩霸王 三一',
1: '彩霸王 一三',
31: '彩霸王 一三',
8: '玄机字 (沐 8 划) + 中宫生气',
}
# 来源映射 — 优先用 src_tracker (实际抓取), 再 fallback 硬编码
def get_src(num, w):
if w == 0:
return '兜底占位 (挂牌稀疏)'
if src_tracker and num in src_tracker and src_tracker[num]:
# 显示前 2 个来源, 多了写 ...
srcs = src_tracker[num][:2]
txt = ' + '.join(srcs)
if len(src_tracker[num]) > 2:
txt += f' (+{len(src_tracker[num]) - 2})'
return txt
return '其他挂牌提示'
for i, (num, w) in enumerate(top, 1):
src = src_map.get(num, '其他挂牌提示')
src = get_src(num, w)
emoji = ['🥇', '🥈', '🥉', '4', '5', '6', '7', '8'][i-1]
L.append(f"| {emoji} | **{num}** | {w} | {src} |")
@@ -393,18 +437,19 @@ if __name__ == '__main__':
sys.exit(0)
# 默认: 跑分析 (period 第一个参数)
# 🚨 默认取 v_xg.json Nq (未开下期), 不是 Qi (已开) — 见 SKILL.md 硬规则 4
period = cmd
if period is None:
# 自动取 v_xg.json Qi
# 自动取 v_xg.json Nq (未开下期, 不是 Qi 已开)
try:
import urllib.request
req = urllib.request.Request('https://btc.tktk.app/data/v_xg.json',
headers={'User-Agent': 'Mozilla/5.0'})
with urllib.request.urlopen(req, timeout=10) as r:
period = json.loads(r.read().decode('utf-8')).get('Qi', '082')
period = json.loads(r.read().decode('utf-8')).get('Nq', '088')
except Exception:
period = '082'
weights = get_te_ma_candidates(period)
period = '088'
weights, src_tracker = get_te_ma_candidates(period)
# 自动取 v_xg.json Qi + Week + Day + Nq 一次, 传所有
# (period 保留用户 CLI 传的, 不要被 Qi 覆盖 — Qi 只用来推算开彩日)
try:
@@ -436,4 +481,4 @@ if __name__ == '__main__':
# 对所有未中奖的 analysis 更新 hit (开彩后)
check_hits()
print(format_te_ma_result(weights, period, 15, qi_week, qi_day, qi_nq))
print(format_te_ma_result(weights, src_tracker, period, 15, qi_week, qi_day, qi_nq))
+10 -6
View File
@@ -1,25 +1,29 @@
#!/bin/bash
# Lottery cron wrapper - 直接调 lottery_特码.py 输出
# cron no_agent 模式: 模型不参与,脚本输出直接推送
#
# 🚨 默认期号 = v_xg.json Nq (未开下期), 不是 Qi (已开)
# (2026-08-13 修过: Qi→Nq, fallback 082→088)
# 改这里时立刻 grep -n "Qi\|Nq" lottery_特码.py lottery_特码_cron.sh 对照
set -e
cd /home/openclaw/.hermes/skills/trading/lottery-hk
# 自动取 Qi 期
QI=$(python3 -c "
# 自动取 Nq 期 (未开下期, 不是 Qi 已开)
NQ=$(python3 -c "
import json, urllib.request
try:
req = urllib.request.Request('https://btc.tktk.app/data/v_xg.json',
headers={'User-Agent': 'Mozilla/5.0'})
with urllib.request.urlopen(req, timeout=10) as r:
d = json.loads(r.read().decode('utf-8'))
print(d['Qi'])
print(d['Nq'])
except Exception:
print('082') # fallback
print('088') # fallback
")
echo "🎯 分析期号: ${QI} (v_xg.json Qi)"
echo "🎯 分析期号: ${NQ} (v_xg.json Nq 未开下期)"
echo ""
# 跑真脚本
python3 /home/openclaw/.hermes/skills/trading/lottery-hk/scripts/lottery_特码.py "${QI}" 2>&1
python3 /home/openclaw/.hermes/skills/trading/lottery-hk/scripts/lottery_特码.py "${NQ}" 2>&1
+135 -42
View File
@@ -1,48 +1,122 @@
#!/bin/bash
# 核验当前期预测 vs 实际开奖,记录命中率
# 22:30 北京时间(开奖21:30后1小时)跑
#
# 流程 (2026-08-13 重写):
# 1. curl v_xg.json (带 UA + proxy fallback) → Qi + Data.1-7 (真开彩, 2026-08-04 验证)
# 2. 失败 fallback: 已有 draws 表数据 OR 提示用户手填
# 3. draws 表空 → 自动 add_draw (触发 check_hits 更新所有 analysis hit 状态)
# 4. 找 Qi 期分析 .md, 输出核验报告
#
# ⚠️ Qi→Nq 修复后: cron 11:30 北京 分析 Nq 期 (未开下期), 22:30 北京 verify 时 Qi 已经是新一期,
# 分析文件就是 Qi 期 (刚开的那期), 不是 Qi-1
#
# 🚨 marksix6.com 真开彩验证源: 必须用 browser (Vue SSR, curl 拿不到), 不在本脚本里跑
# (no_agent 模式没 browser 工具); cron 改 no_agent 时改这里
set -e
DB="$HOME/.hermes/trading/lottery.db"
OUT_DIR="$HOME/.hermes/cron/output/lottery-verify"
mkdir -p "$OUT_DIR"
SKILL_DIR="$(cd "$(dirname "$0")/.." && pwd)"
# 当前期号 - 优先代理,失败直连(VPS 出口有时被墙)
QI=$(curl -s --proxy http://127.0.0.1:7890 --max-time 8 "https://btc.tktk.app/data/v_xg.json" 2>/dev/null | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('Qi',''))" 2>/dev/null)
if [ -z "$QI" ]; then
QI=$(curl -s --noproxy '*' --max-time 8 "https://btc.tktk.app/data/v_xg.json" 2>/dev/null | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('Qi',''))" 2>/dev/null)
fi
if [ -z "$QI" ]; then
echo "❌ 无法获取当前期号(代理+直连都失败)"
exit 1
# === Step 1: 取 v_xg.json (Qi + Data.1-7) ===
fetch_v_xg() {
local out
# 优先代理,失败直连(VPS 出口有时被墙)
out=$(curl -s --proxy http://127.0.0.1:7890 --max-time 8 \
-A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" \
"https://btc.tktk.app/data/v_xg.json" 2>/dev/null || true)
if [ -z "$out" ] || echo "$out" | grep -q "请求出错\|Cann't connect"; then
out=$(curl -s --noproxy '*' --max-time 8 \
-A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" \
"https://btc.tktk.app/data/v_xg.json" 2>/dev/null || true)
fi
# 校验是不是 JSON 且有 Qi
if echo "$out" | python3 -c "import json,sys; d=json.loads(sys.stdin.read()); assert d.get('Qi')" 2>/dev/null; then
echo "$out"
fi
}
V_XG=$(fetch_v_xg || true)
NEED_FETCH=0
if [ -z "$V_XG" ]; then
NEED_FETCH=1
echo "⚠️ v_xg.json 暂不可用 (DB 故障或网络被墙), 尝试从 draws 表读已有数据"
fi
# 实际开奖结果
ACTUAL=$(sqlite3 "$DB" "SELECT n1||','||n2||','||n3||','||n4||','||n5||','||n6||','||special FROM draws WHERE period='$QI';")
# === Step 2: 解析 Qi + 真开彩 ===
QI=""
ACTUAL=""
if [ "$NEED_FETCH" = "0" ]; then
eval "$(echo "$V_XG" | python3 -c "
import json, sys
d = json.loads(sys.stdin.read())
qi = d.get('Qi','')
data = d.get('Data', {})
nums = [int(data[str(i)]['number']) for i in range(1, 8) if str(i) in data]
special = nums[6] if len(nums) >= 7 else 0
print(f'QI={qi!r}')
print(f'SPECIAL={special}')
print(f'N1={nums[0] if len(nums)>0 else 0}')
print(f'N2={nums[1] if len(nums)>1 else 0}')
print(f'N3={nums[2] if len(nums)>2 else 0}')
print(f'N4={nums[3] if len(nums)>3 else 0}')
print(f'N5={nums[4] if len(nums)>4 else 0}')
print(f'N6={nums[5] if len(nums)>5 else 0}')
")"
if [ -n "$QI" ]; then
ACTUAL="$N1,$N2,$N3,$N4,$N5,$N6,$SPECIAL"
echo "📡 v_xg.json: Qi=$QI 真开彩=$N1 $N2 $N3 $N4 $N5 $N6 特=$SPECIAL"
fi
fi
# === Step 3: 兜底从 draws 表读 (手填或之前入库) ===
if [ -z "$ACTUAL" ]; then
echo "❌ 期号 $QI 还没入库开奖结果"
exit 1
# v_xg 拿不到, 尝试从最近 Qi 期读
if [ -z "$QI" ]; then
QI=$(sqlite3 "$DB" "SELECT period FROM draws ORDER BY period DESC LIMIT 1;" 2>/dev/null || true)
fi
if [ -n "$QI" ]; then
ACTUAL=$(sqlite3 "$DB" "SELECT n1||','||n2||','||n3||','||n4||','||n5||','||n6||','||special FROM draws WHERE period='$QI';" 2>/dev/null || true)
fi
if [ -z "$ACTUAL" ]; then
echo "❌ 无法获取 $QI 期开奖结果 (v_xg.json 宕机 + draws 表空)"
echo " 手动填: python3 $SKILL_DIR/scripts/lottery_特码.py add $QI <special> <n1..n6>"
exit 1
fi
echo "📂 draws 表读 $QI 期: $ACTUAL"
fi
IFS=',' read -r A1 A2 A3 A4 A5 A6 AS <<< "$ACTUAL"
ACTUAL_FLAT="$A1 $A2 $A3 $A4 $A5 $A6"
ACTUAL_SPECIAL="$AS"
# 找对应的分析文件 - 看 Qi 是几(7-19/21的cron跑的就是 Qi-1 期预测)
QI_NUM=$((10#$QI))
PREV_PERIOD=$((QI_NUM - 1))
# 标题格式有几种:'077期热数据采集' / '热数据采集 · 077期' / '077期数据汇总'
# 简单找包含期号+期 的最近文件
ANALYSIS_FILE=$(grep -lE "${PREV_PERIOD}期数据汇总|${PREV_PERIOD}期热数据采集|热数据采集.*${PREV_PERIOD}期" "$HOME/.hermes/cron/output/5bec1f60f77f/"*.md 2>/dev/null | tail -1)
[ -z "$ANALYSIS_FILE" ] && ANALYSIS_FILE=$(grep -l "${PREV_PERIOD}期" "$HOME/.hermes/cron/output/5bec1f60f77f/"*.md 2>/dev/null | tail -1)
# === Step 4: 检查 draws 表, 没数据就入库 (v_xg 真开彩可用时) ===
EXISTING=$(sqlite3 "$DB" "SELECT special FROM draws WHERE period='$QI';" 2>/dev/null || true)
if [ -z "$EXISTING" ] && [ -n "$SPECIAL" ] && [ "$SPECIAL" != "0" ]; then
echo "💾 draws 表 $QI 期空, 自动入库..."
python3 "$SKILL_DIR/scripts/lottery_特码.py" add "$QI" "$SPECIAL" "$N1" "$N2" "$N3" "$N4" "$N5" "$N6" 2>&1 || echo "⚠️ add_draw 失败"
fi
# === Step 5: 跑 check_hits (确保所有 analysis 行 hit 状态更新) ===
python3 "$SKILL_DIR/scripts/lottery_特码.py" hits 2>&1 | tail -3
# === Step 6: 找 Qi 期分析 .md ===
ANALYSIS_FILE=$(grep -lE "${QI}期" "$HOME/.hermes/cron/output/5bec1f60f77f/"*.md 2>/dev/null | tail -1)
# === Step 7: 查 analysis 表最近一条 ===
ANALYSIS_HIT=$(sqlite3 "$DB" "SELECT actual_special || '|' || hit FROM analysis WHERE period='$QI' ORDER BY id DESC LIMIT 1;" 2>/dev/null || echo "|")
# === Step 8: 输出核验报告 ===
OUT_FILE="$OUT_DIR/$(date +%Y-%m-%d_%H-%M-%S)_${QI}.md"
{
echo "## 🎯 核验报告 | $QI期"
echo ""
echo "**开奖时间**: $(date +%Y-%m-%d) 21:30 北京"
echo "**核验时间**: $(date +%Y-%m-%d) 22:30 北京"
echo "**数据源**: v_xg.json Data.1-7 (2026-08-04 marksix6.com 验证)"
echo ""
echo "### 实际开奖"
echo "| 位置 | 号码 |"
@@ -53,44 +127,63 @@ echo ""
if [ -n "$ANALYSIS_FILE" ]; then
echo "### 分析文件"
echo "📄 $ANALYSIS_FILE"
echo "📄 \`$ANALYSIS_FILE\`"
echo ""
echo "### 预测 vs 实际"
PREDICTED_SPECIAL=$(grep -o "特码重点.*\*\*[0-9]\+\*\*\|特码.*\*\*[0-9]\+\*\*" "$ANALYSIS_FILE" | head -1)
PREDICTED_FLAT=$(grep "平码优先" "$ANALYSIS_FILE" | head -1)
echo "**预测**: $PREDICTED_SPECIAL · $PREDICTED_FLAT"
# 提取 Top 5 候选 (新格式: "| 🥇 | **42** | 3 | 挂牌 另版挂 (42) |")
TOP_CANDIDATES=$(grep -oE '\| \*\*[0-9]+\*\*' "$ANALYSIS_FILE" | head -5 | grep -oE '[0-9]+')
echo "### 预测 Top 5"
echo "| 排序 | 特码 |"
echo "|---|---|"
i=1
for c in $TOP_CANDIDATES; do
emoji=$([ $i -eq 1 ] && echo "🥇" || ([ $i -eq 2 ] && echo "🥈" || ([ $i -eq 3 ] && echo "🥉" || echo "$i")))
echo "| $emoji | $c |"
i=$((i+1))
done
echo ""
echo "### 命中分析"
HIT_SPECIAL="❌ 未中"
if echo "$PREDICTED_SPECIAL" | grep -q "\*\*$AS\*\*"; then
if echo " $TOP_CANDIDATES " | grep -q " $AS "; then
HIT_SPECIAL="✅ **特码命中**"
fi
echo "### 命中"
echo "- 特码 $AS: $HIT_SPECIAL"
HIT_FLAT=$(echo "$ACTUAL_FLAT" | tr ' ' '\n' | while read n; do
if echo "$PREDICTED_FLAT" | grep -q "\*\*$n\*\*\|\b$n\b"; then
echo "✅ $n"
HIT_FLAT=""
for n in $A1 $A2 $A3 $A4 $A5 $A6; do
if echo " $TOP_CANDIDATES " | grep -q " $n "; then
HIT_FLAT="$HIT_FLAT ✅$n"
fi
done | tr '\n' ' ')
echo "- 平码命中: ${HIT_FLAT:-无}"
TOTAL_HIT=$(echo "$ACTUAL_FLAT" | tr ' ' '\n' | while read n; do
if grep -qE "\*\*$n\*\*| $n[、,,]|\b$n( |$)" "$ANALYSIS_FILE"; then
echo "1"
fi
done | wc -l)
done
echo "- 平码命中:${HIT_FLAT:- 无}"
TOTAL=0
if echo " $TOP_CANDIDATES " | grep -q " $AS "; then TOTAL=$((TOTAL+1)); fi
for n in $A1 $A2 $A3 $A4 $A5 $A6; do
if echo " $TOP_CANDIDATES " | grep -q " $n "; then TOTAL=$((TOTAL+1)); fi
done
echo ""
echo "**总命中**: 特码 + 平码 共 $((TOTAL_HIT+0)) / 7 球"
echo "**总命中**: Top 5 候选命中 $TOTAL / 7 球 (特码+平码)"
else
echo "### ⚠️ 未找到分析文件"
echo " 查找路径: $HOME/.hermes/cron/output/5bec1f60f77f/"
echo " 期号: $QI"
fi
ACTUAL_FROM_DB=$(echo "$ANALYSIS_HIT" | cut -d'|' -f1)
HIT_FROM_DB=$(echo "$ANALYSIS_HIT" | cut -d'|' -f2)
if [ -n "$HIT_FROM_DB" ]; then
HIT_ICON=$([ "$HIT_FROM_DB" = "1" ] && echo "✅ 中奖" || echo "❌ 未中")
echo ""
echo "### SQLite analysis 标记"
echo "- actual_special: $ACTUAL_FROM_DB"
echo "- hit: $HIT_ICON"
fi
echo ""
echo "---"
echo "_生成时间: $(date '+%Y-%m-%d %H:%M:%S')_"
echo "_生成时间: $(date '+%Y-%m-%d %H:%M:%S') 北京_"
} > "$OUT_FILE"
cat "$OUT_FILE"
cat "$OUT_FILE"