#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 增强版彩票智能分析系统 v2.0 =============================== 核心升级: 1. 采集近200期数据(原100期) 2. AI逐期回滚推演:从第200期开始->模拟分析机选->比对实开->回滚优化 3. 方法论自优化:每轮回滚后总结方法论并迭代升级 4. 目标:胜出率(概率占比) >= 51% 用法: python enhanced_lottery.py --action full_report --lottery ssq --count 5 python enhanced_lottery.py --action rollback --lottery ssq python enhanced_lottery.py --action self_evolve --lottery ssq --iterations 10 """ import json, os, sys, math, random, copy, datetime from collections import Counter BASE_DIR = os.path.dirname(os.path.abspath(__file__)) DATA_DIR = os.path.join(BASE_DIR, "data") os.makedirs(DATA_DIR, exist_ok=True) LOTTERY_RULES = { "ssq": { "name": "双色球", "red_count": 6, "red_max": 33, "blue_count": 1, "blue_max": 16, "draw_days": [2, 4, 7], "draw_time": "21:15", }, "dlt": { "name": "大乐透", "red_count": 5, "red_max": 35, "blue_count": 2, "blue_max": 12, "draw_days": [1, 3, 6], "draw_time": "20:25", } } DEFAULT_WEIGHTS = { "frequency": 0.25, "hot_number": 0.20, "missing": 0.15, "tail": 0.10, "zone": 0.08, "odd_even": 0.06, "big_small": 0.05, "sum_value": 0.04, "probability": 0.04, "consecutive": 0.03, } # ============================================================ # 增强版分析引擎(200期 + 10维度深度分析) # ============================================================ def _normalize_rec(rec): """标准化记录,兼容新旧格式(blue vs blues)""" if "blues" not in rec or not rec["blues"]: if "blue" in rec: rec["blues"] = rec["blue"] if isinstance(rec["blue"], list) else [rec["blue"]] return rec def _get_blues(rec): """获取blue值,兼容新旧格式""" if "blues" in rec and rec["blues"]: raw = rec["blues"] elif "blue" in rec: raw = rec["blue"] else: raw = [] return raw if isinstance(raw, list) else [raw] class EnhancedAnalyzer: """使用近200期数据,10维度权重可调,输出结构化分析结果""" def __init__(self, data, lt, weights=None): self.lt = lt self.rule = LOTTERY_RULES[lt] # 标准化并取近200期 normed = [_normalize_rec(d) for d in data] self.data = sorted(normed, key=lambda x: int(x["issue"]), reverse=True)[:200] self.weights = weights if weights else copy.deepcopy(DEFAULT_WEIGHTS) self.rmax = self.rule["red_max"] self.bmax = self.rule["blue_max"] self.rcnt = self.rule["red_count"] self.bcnt = self.rule["blue_count"] self.mid = self.rmax / 2 def analyze(self): """完整分析,返回结构化分析结果""" if not self.data: return None # 1. 频率分析 all_r, all_b = [], [] for rec in self.data: all_r.extend(int(x) for x in rec["reds"]) bl = _get_blues(rec) all_b.extend(int(x) for x in bl) rf = Counter(all_r) bf = Counter(all_b) max_rf = max(rf.values()) or 1 max_bf = max(bf.values()) or 1 rf_score = {i: rf.get(i, 0) / max_rf for i in range(1, self.rmax + 1)} bf_score = {i: bf.get(i, 0) / max_bf for i in range(1, self.bmax + 1)} # 2. 热号分析(最近20期) hot = self.data[:20] hot_r = [int(x) for r in hot for x in r["reds"]] hot_rf = Counter(hot_r) max_hr = max(hot_rf.values()) or 1 hot_score = {i: hot_rf.get(i, 0) / max_hr for i in range(1, self.rmax + 1)} # 3. 遗漏值分析 r_miss = {} for n in range(1, self.rmax + 1): cnt = 0 for r in self.data: if n in [int(x) for x in r["reds"]]: break cnt += 1 r_miss[n] = cnt max_rm = max(r_miss.values()) or 1 rm_score = {n: math.sin(m / max_rm * math.pi) * 0.8 + 0.2 for n, m in r_miss.items()} b_miss = {} for n in range(1, self.bmax + 1): cnt = 0 for r in self.data: ns = [int(x) for x in _get_blues(r)] if n in ns: break cnt += 1 b_miss[n] = cnt max_bm = max(b_miss.values()) or 1 bm_score = {n: math.sin(m / max_bm * math.pi) * 0.8 + 0.2 for n, m in b_miss.items()} # 4. 奇偶模式 oe_counter = Counter() for rec in self.data: ns = [int(x) for x in rec["reds"]] odd_count = sum(1 for n in ns if n % 2 == 1) oe_counter[f"{odd_count}:{self.rcnt - odd_count}"] += 1 most_oe = oe_counter.most_common(1)[0][0] if oe_counter else "3:3" # 5. 大小模式 bs_counter = Counter() for rec in self.data: ns = [int(x) for x in rec["reds"]] big_count = sum(1 for n in ns if n > self.mid) bs_counter[f"{big_count}:{self.rcnt - big_count}"] += 1 most_bs = bs_counter.most_common(1)[0][0] if bs_counter else "3:3" # 6. 和值分析 sums = [sum(int(x) for x in r["reds"]) for r in self.data] avg_sum = sum(sums) / len(sums) if sums else 0 std_sum = math.sqrt(sum((s - avg_sum) ** 2 for s in sums) / len(sums)) if sums else 0 # 7. 尾数分布 tail_counter = Counter() for rec in self.data: for ns in rec["reds"]: tail_counter[int(ns) % 10] += 1 max_tf = max(tail_counter.values()) or 1 tail_score = {t: tail_counter.get(t, 0) / max_tf for t in range(10)} # 8. 区间分布 zones = [(1, 11), (12, 22), (23, self.rmax)] if self.lt == "ssq" else [(1, 12), (13, 24), (25, self.rmax)] zone_balance = [] for zs, ze in zones: count = sum(1 for r in self.data for n in [int(x) for x in r["reds"]] if zs <= n <= ze) expected = len(self.data) * self.rcnt / len(zones) zone_balance.append(count / expected if expected else 1.0) # 9. 连号分析 consec_counter = Counter() for rec in self.data: ns = sorted(int(x) for x in rec["reds"]) consec = sum(1 for i in range(len(ns) - 1) if ns[i + 1] - ns[i] == 1) consec_counter[consec] += 1 most_consec = consec_counter.most_common(1)[0][0] if consec_counter else 0 # 10. 综合评分 r_comp = {} for n in range(1, self.rmax + 1): s = rf_score.get(n, 0) * self.weights["frequency"] s += hot_score.get(n, 0) * self.weights["hot_number"] s += rm_score.get(n, 0.5) * self.weights["missing"] s += tail_score.get(n % 10, 0.5) * self.weights["tail"] for i, (zs, ze) in enumerate(zones): if zs <= n <= ze and zone_balance[i] < 0.85: s += 0.10 break r_comp[n] = round(s, 4) # 蓝球复合评分 recent_blue = [] for r in self.data[:20]: recent_blue.extend(int(x) for x in (r["blues"] if isinstance(r["blues"], list) else [r["blues"]])) rbf = Counter(recent_blue) max_rbf = max(rbf.values()) or 1 b_comp = {} for n in range(1, self.bmax + 1): s = bf_score.get(n, 0) * 0.35 + bm_score.get(n, 0.5) * 0.40 + (rbf.get(n, 0) / max_rbf) * 0.25 b_comp[n] = round(s, 4) result = { "data_range": { "total": len(self.data), "start": self.data[-1]["issue"], "end": self.data[0]["issue"] }, "red_composite": r_comp, "blue_composite": b_comp, "patterns": { "most_oe": most_oe, "most_bs": most_bs, "avg_sum": round(avg_sum, 1), "std_sum": round(std_sum, 1), "sum_range": [round(avg_sum - std_sum, 1), round(avg_sum + std_sum, 1)], "zone_balance": {f"Z{i+1}": round(zb, 3) for i, zb in enumerate(zone_balance)}, "most_consec": most_consec, }, "weights_used": copy.deepcopy(self.weights), } return result def recommend(self, analysis, count=5): """基于分析结果生成推荐号码""" if not analysis: return [] r_comp = analysis["red_composite"] b_comp = analysis["blue_composite"] pat = analysis["patterns"] sorted_r = sorted(r_comp.keys(), key=lambda n: r_comp[n], reverse=True) sorted_b = sorted(b_comp.keys(), key=lambda n: b_comp[n], reverse=True) target_oe = [int(x) for x in pat["most_oe"].split(":")] target_bs = [int(x) for x in pat["most_bs"].split(":")] sum_min, sum_max = pat["sum_range"] seed = int(datetime.datetime.now().timestamp() * 1000) % 1000000 rng = random.Random(seed) results = [] for _ in range(count * 3): top_r = sorted_r[:20] weights_r = [max(r_comp[n], 0) for n in top_r] total_w = sum(weights_r) if total_w <= 0: weights_r = [1] * len(top_r) total_w = len(top_r) probs_r = [w / total_w for w in weights_r] reds = set() attempts = 0 while len(reds) < self.rcnt and attempts < 100: n = rng.choices(top_r, weights=probs_r, k=1)[0] reds.add(n) attempts += 1 if len(reds) < self.rcnt: remaining = [n for n in range(1, self.rmax + 1) if n not in reds] rng.shuffle(remaining) reds.update(remaining[:self.rcnt - len(reds)]) reds = sorted(reds) top_b = sorted_b[:8] weights_b = [max(b_comp[n], 0) for n in top_b] total_bw = sum(weights_b) or 1 probs_b = [w / total_bw for w in weights_b] if self.bcnt > 1: blues = list(rng.choices(top_b, weights=probs_b, k=self.bcnt)) # 确保后区号码不重复 while len(set(blues)) < len(blues): for j in range(len(blues)): if blues.count(blues[j]) > 1: remaining = [n for n in range(1, self.bmax + 1) if n not in blues[:j] + blues[j+1:]] blues[j] = rng.choice(remaining) else: blues = list(rng.choices(top_b, weights=probs_b, k=self.bcnt)) score = sum(r_comp.get(n, 0) for n in reds) / self.rcnt score += sum(b_comp.get(n, 0) for n in blues) / self.bcnt score /= 2 oe = sum(1 for n in reds if n % 2 == 1) bs = sum(1 for n in reds if n > self.mid) total_sum = sum(reds) bonus = 0 if oe == target_oe[0]: bonus += 0.05 if bs == target_bs[0]: bonus += 0.05 if sum_min <= total_sum <= sum_max: bonus += 0.05 results.append({ "reds": reds, "blues": blues, "score": round(score + bonus, 4), "oe": f"{oe}:{self.rcnt - oe}", "bs": f"{bs}:{self.rcnt - bs}", "sum": total_sum, }) seen = set() unique = [] for r in sorted(results, key=lambda x: x["score"], reverse=True): key = tuple(r["reds"]) + tuple(r["blues"]) if key not in seen: seen.add(key) unique.append(r) return unique[:count] # ============================================================ # AI 逐期回滚推演引擎 # ============================================================ class AIRollbackEngine: """ AI逐期回滚推演: 从第200期开始 -> 使用当时可用的历史数据进行分析 -> 生成推荐 -> 与实开号码比对 -> 记录命中率 -> 自动调整权重 -> 进入下一期... 直至最新一期 """ def __init__(self, lt, data, initial_weights=None): self.lt = lt self.rule = LOTTERY_RULES[lt] # 标准化所有记录(兼容 blue/blues 混用) normed = [_normalize_rec(d) for d in data] self.all_data = sorted(normed, key=lambda x: int(x["issue"])) # 从旧到新 self.weights = initial_weights if initial_weights else copy.deepcopy(DEFAULT_WEIGHTS) self.rollback_history = [] self.methodology_log = [] def run(self): """执行完整回滚推演:从第200期开始逐期推演至最新一期""" total_periods = len(self.all_data) if total_periods < 200: return {"error": f"数据不足200期,当前仅{total_periods}期", "available": total_periods} start_idx = 199 # 第200期(0-based索引) total_simulations = 0 total_red_hits = 0 total_blue_hits = 0 possible_red = 0 possible_blue = 0 methodology_snapshots = [] print(f"{'='*60}") print(f" AI逐期回滚推演引擎 - {self.rule['name']}") print(f" 数据总量: {total_periods}期 | 推演范围: 第200期 ~ 第{total_periods}期") print(f" 推演总轮次: {total_periods - start_idx} 期") print(f"{'='*60}") for i in range(start_idx, total_periods): current_issue = self.all_data[i]["issue"] historical = self.all_data[:i] actual = self.all_data[i] actual_reds = [int(x) for x in actual["reds"]] actual_blues = [int(x) for x in _get_blues(actual)] analyzer = EnhancedAnalyzer(historical, self.lt, self.weights) analysis = analyzer.analyze() if not analysis: continue recommendations = analyzer.recommend(analysis, count=5) if not recommendations: continue best_pick = recommendations[0] pred_reds = best_pick["reds"] pred_blues = best_pick["blues"] red_hit = len(set(pred_reds) & set(actual_reds)) blue_hit = len(set(pred_blues) & set(actual_blues)) total_red_hits += red_hit total_blue_hits += blue_hit possible_red += self.rule["red_count"] possible_blue += self.rule["blue_count"] total_simulations += 1 self.rollback_history.append({ "issue": current_issue, "iteration": total_simulations, "pred_reds": pred_reds, "pred_blues": pred_blues, "actual_reds": actual_reds, "actual_blues": actual_blues, "red_hit": red_hit, "blue_hit": blue_hit, "score": best_pick["score"], "weights_at_time": copy.deepcopy(self.weights), }) self._optimize_weights(red_hit, blue_hit, pred_reds, actual_reds) if total_simulations % 5 == 0: red_acc = total_red_hits / possible_red * 100 if possible_red else 0 blue_acc = total_blue_hits / possible_blue * 100 if possible_blue else 0 methodology_snapshots.append({ "iteration": total_simulations, "issue": current_issue, "weights": copy.deepcopy(self.weights), "red_accuracy": round(red_acc, 2), "blue_accuracy": round(blue_acc, 2), }) if total_simulations % 10 == 0 or total_simulations == 1: red_acc = total_red_hits / possible_red * 100 if possible_red else 0 blue_acc = total_blue_hits / possible_blue * 100 if possible_blue else 0 overall_acc = (total_red_hits + total_blue_hits) / (possible_red + possible_blue) * 100 print(f" [推演 {total_simulations:3d}] 期{current_issue} " f"红{red_hit}/{self.rule['red_count']} 蓝{blue_hit}/{self.rule['blue_count']} " f"| 累计 红{red_acc:.1f}% 蓝{blue_acc:.1f}% 综合{overall_acc:.1f}%") # 最终统计 avg_red = total_red_hits / possible_red * 100 if possible_red else 0 avg_blue = total_blue_hits / possible_blue * 100 if possible_blue else 0 overall_hits = total_red_hits + total_blue_hits overall_possible = possible_red + possible_blue overall_acc = overall_hits / overall_possible * 100 if overall_possible else 0 win_probability = overall_acc hit_dist = {0: 0, 1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0} for entry in self.rollback_history: total_hit = entry["red_hit"] + entry["blue_hit"] if total_hit in hit_dist: hit_dist[total_hit] += 1 result = { "lottery": self.lt, "total_simulations": total_simulations, "start_issue": self.all_data[start_idx]["issue"], "end_issue": self.all_data[-1]["issue"], "final_weights": self.weights, "accuracy": { "red_accuracy": round(avg_red, 2), "blue_accuracy": round(avg_blue, 2), "overall_accuracy": round(overall_acc, 2), "win_probability": round(win_probability, 2), }, "hits": { "total_red_hits": total_red_hits, "total_blue_hits": total_blue_hits, "possible_red": possible_red, "possible_blue": possible_blue, }, "hit_distribution": hit_dist, "methodology_snapshots": methodology_snapshots, "weight_evolution": self._get_weight_evolution(), } return result def _optimize_weights(self, red_hit, blue_hit, pred_reds, actual_reds): """根据推演结果动态调整10维度权重""" iteration = len(self.rollback_history) + 1 lr = max(0.003, 0.01 - iteration * 0.0001) hit_ratio = (red_hit + blue_hit) / (self.rule["red_count"] + self.rule["blue_count"]) if hit_ratio >= 0.5: self.weights["frequency"] = min(0.35, self.weights["frequency"] * (1 + lr)) self.weights["hot_number"] = min(0.30, self.weights["hot_number"] * (1 + lr * 0.8)) else: self.weights["missing"] = min(0.30, self.weights["missing"] * (1 + lr)) self.weights["probability"] = min(0.15, self.weights["probability"] * (1 + lr * 1.2)) self.weights["frequency"] = max(0.15, self.weights["frequency"] * (1 - lr * 0.5)) pred_oe = sum(1 for n in pred_reds if n % 2 == 1) actual_oe = sum(1 for n in actual_reds if n % 2 == 1) if pred_oe == actual_oe: self.weights["odd_even"] = min(0.12, self.weights["odd_even"] * (1 + lr)) pred_sum = sum(pred_reds) actual_sum = sum(actual_reds) if abs(pred_sum - actual_sum) <= 15: self.weights["sum_value"] = min(0.10, self.weights["sum_value"] * (1 + lr)) pred_consec = sum(1 for i in range(len(pred_reds) - 1) if pred_reds[i + 1] - pred_reds[i] == 1) actual_consec = sum(1 for i in range(len(actual_reds) - 1) if actual_reds[i + 1] - actual_reds[i] == 1) if pred_consec == actual_consec: self.weights["consecutive"] = min(0.08, self.weights["consecutive"] * (1 + lr)) total = sum(self.weights.values()) if total > 0: for k in self.weights: self.weights[k] /= total def _get_weight_evolution(self): if not self.rollback_history: return [] interval = max(1, len(self.rollback_history) // 20) evolution = [] for i, entry in enumerate(self.rollback_history): if i % interval == 0 or i == len(self.rollback_history) - 1: evolution.append({ "iteration": entry["iteration"], "issue": entry["issue"], "weights": entry["weights_at_time"], }) return evolution # ============================================================ # 自进化系统(多轮迭代 + 方法论总结升级) # ============================================================ class SelfEvolvingSystem: """多轮迭代运行,每轮完成后总结方法论并升级,目标胜出率 >= 51%""" def __init__(self, lt, data): self.lt = lt self.data = data self.rule = LOTTERY_RULES[lt] self.best_weights = copy.deepcopy(DEFAULT_WEIGHTS) self.best_accuracy = 0 self.iteration_results = [] self.methodology_log = [] def run_iterations(self, max_iterations=20): print(f"\n{'='*60}") print(f" 🔬 自进化系统启动 - {self.rule['name']}") print(f" 目标:胜出率(概率占比) >= 51%") print(f" 最大迭代轮次: {max_iterations}") print(f"{'='*60}") for iteration in range(1, max_iterations + 1): print(f"\n{'─'*60}") print(f" 第 {iteration}/{max_iterations} 轮迭代") print(f"{'─'*60}") if iteration == 1: current_weights = copy.deepcopy(DEFAULT_WEIGHTS) else: current_weights = self._mutate_weights(self.best_weights, iteration) engine = AIRollbackEngine(self.lt, self.data, current_weights) result = engine.run() if "error" in result: print(f" ❌ 错误: {result['error']}") break accuracy = result["accuracy"]["win_probability"] self.iteration_results.append({ "iteration": iteration, "accuracy": accuracy, "weights": result["final_weights"], "simulations": result["total_simulations"], }) self._summarize_methodology(iteration, result) if accuracy > self.best_accuracy: self.best_accuracy = accuracy self.best_weights = result["final_weights"] print(f" 🏆 新最佳胜出率: {accuracy:.2f}%") else: print(f" 本轮胜出率: {accuracy:.2f}% (最佳: {self.best_accuracy:.2f}%)") if self.best_accuracy >= 51.0: print(f"\n{'='*60}") print(f" 🎯 目标达成!胜出率 {self.best_accuracy:.2f}% >= 51%") print(f"{'='*60}") break return self._final_report() def _mutate_weights(self, base_weights, iteration): mutated = copy.deepcopy(base_weights) mutation_rate = max(0.005, 0.03 - iteration * 0.001) for k in mutated: delta = random.uniform(-mutation_rate, mutation_rate) mutated[k] = max(0.01, mutated[k] + delta) total = sum(mutated.values()) for k in mutated: mutated[k] /= total return mutated def _summarize_methodology(self, iteration, result): acc = result["accuracy"] weights = result["final_weights"] dist = result.get("hit_distribution", {}) sorted_w = sorted(weights.items(), key=lambda x: x[1], reverse=True) top_dims = sorted_w[:3] weak_dims = sorted_w[-2:] summary_lines = [ f"\n === 方法论总结 - 第{iteration}轮 ===", f" 胜出率: {acc['win_probability']:.2f}% (红球{acc['red_accuracy']:.1f}% 蓝球{acc['blue_accuracy']:.1f}%)", f" 最优三维度:", ] for dim, w in top_dims: summary_lines.append(f" - {dim}: {w:.4f}") summary_lines.append(f" 最弱二维度:") for dim, w in weak_dims: summary_lines.append(f" - {dim}: {w:.4f}") summary_lines.append(f" 命中分布:") for level in sorted(dist.keys()): if dist.get(level, 0) > 0: pct = dist[level] / result["total_simulations"] * 100 summary_lines.append(f" - {level}个命中: {dist[level]}次 ({pct:.1f}%)") summary = "\n".join(summary_lines) print(summary) self.methodology_log.append(summary) mpath = os.path.join(DATA_DIR, f"methodology_{self.lt}_iter{iteration}.json") with open(mpath, "w", encoding="utf-8") as f: json.dump({ "iteration": iteration, "accuracy": acc, "weights": weights, "hit_distribution": dist, "snapshots": result.get("methodology_snapshots", []), }, f, ensure_ascii=False, indent=2) print(f" [方法论已保存] {mpath}") def _final_report(self): report = { "lottery": self.lt, "total_iterations": len(self.iteration_results), "best_accuracy": self.best_accuracy, "best_weights": self.best_weights, "iteration_summary": self.iteration_results, } rpath = os.path.join(DATA_DIR, f"self_evolve_{self.lt}_final.json") with open(rpath, "w", encoding="utf-8") as f: json.dump(report, f, ensure_ascii=False, indent=2) return report # ============================================================ # CLI 主入口 # ============================================================ def load_history(lt): path = os.path.join(DATA_DIR, f"{lt}_history.json") if os.path.exists(path): try: with open(path, "r", encoding="utf-8") as f: return json.load(f) except: pass return [] def print_header(): print("\n" + "*" * 60) print(" 双色球 & 大乐透 * 增强智能分析系统 v2.0") print(" AI回滚推演 | 方法论自优化 | 200期深度分析") print(" " + datetime.datetime.now().strftime("%Y-%m-%d %H:%M")) print("*" * 60) def show_full_report(lt, count=5): rule = LOTTERY_RULES[lt] data = load_history(lt) if not data: print(f"\n ⚠️ {rule['name']}暂无数据,请先采集") print(f" python3 lottery_tool.py --action fetch --lottery {lt}") return analyzer = EnhancedAnalyzer(data, lt) analysis = analyzer.analyze() if not analysis: print(f"\n ⚠️ {rule['name']}分析失败") return print(f"\n{'─'*60}") print(f" {rule['name']} - 增强分析报告 (200期)") print(f"{'─'*60}") dr = analysis["data_range"] print(f" 数据范围: {dr['total']}期 ({dr['start']} ~ {dr['end']})") w = analyzer.weights print(f" 权重体系: freq={w['frequency']:.3f} hot={w['hot_number']:.3f} miss={w['missing']:.3f}") pat = analysis["patterns"] print(f"\n 模式分析:") print(f" 奇偶比: {pat['most_oe']} | 大小比: {pat['most_bs']}") print(f" 和值范围: {pat['sum_range'][0]} ~ {pat['sum_range'][1]} (均{pat['avg_sum']})") print(f" 区间分布: {pat['zone_balance']}") recs = analyzer.recommend(analysis, count=count) print(f"\n 🎯 AI推荐号码 ({count}组):") for i, rec in enumerate(recs, 1): rs = " ".join(f"{n:02d}" for n in rec["reds"]) bs = " ".join(f"{n:02d}" for n in rec["blues"]) print(f" [{i}] 红球: {rs} 蓝球: {bs} (评分:{rec['score']:.3f} OE:{rec['oe']} BS:{rec['bs']})") def main(): import argparse parser = argparse.ArgumentParser(description="增强版彩票智能分析系统 v2.0") parser.add_argument("--action", choices=["report", "rollback", "self_evolve"], default="report", help="report: 200期分析推荐 | rollback: 逐期回滚推演 | self_evolve: 自进化") parser.add_argument("--lottery", choices=["ssq", "dlt", "all"], default="ssq") parser.add_argument("--count", type=int, default=5, help="推荐组数") parser.add_argument("--iterations", type=int, default=10, help="自进化迭代轮次") args = parser.parse_args() print_header() lotteries = ["ssq", "dlt"] if args.lottery == "all" else [args.lottery] if args.action == "report": for lt in lotteries: show_full_report(lt, args.count) return if args.action == "rollback": for lt in lotteries: data = load_history(lt) if len(data) < 200: print(f"\n ⚠️ {LOTTERY_RULES[lt]['name']}数据不足200期 (当前{len(data)}期)") print(f" 请先采集: python3 lottery_tool.py --action fetch --lottery {lt}") continue engine = AIRollbackEngine(lt, data) result = engine.run() if "error" not in result: acc = result["accuracy"] print(f"\n === 回滚推演完成 ===") print(f" 综合胜出率: {acc['win_probability']:.2f}%") print(f" 红球准确率: {acc['red_accuracy']:.1f}% | 蓝球: {acc['blue_accuracy']:.1f}%") if args.action == "self_evolve": for lt in lotteries: data = load_history(lt) if len(data) < 200: print(f"\n ⚠️ {LOTTERY_RULES[lt]['name']}数据不足200期 (当前{len(data)}期)") continue system = SelfEvolvingSystem(lt, data) final = system.run_iterations(max_iterations=args.iterations) print(f"\n === 自进化最终结果 ===") print(f" 最佳胜出率: {final['best_accuracy']:.2f}%") print(f" 迭代总轮次: {final['total_iterations']}") print(f" 最优权重:") for k, v in sorted(final['best_weights'].items(), key=lambda x: x[1], reverse=True): print(f" {k}: {v:.4f}") if __name__ == "__main__": main()