""" batch_validate.py — 批量验证多只股票的收敛三角形形态(HTTP 版) 用法: python batch_validate.py [--no-show] [--save] --no-show 不弹窗,直接生成所有图(适合无显示器/批量场景) --save 保存图片到 output/ 目录 修改下方 BATCH_CASES 可自定义验证列表。 """ import sys import argparse from pathlib import Path from validate import run_formula, fetch_detail _THIS_DIR = Path(__file__).parent.resolve() # ── 批量验证列表(可自由修改)─────────────────────────────────────────────────── # 格式:(ticker, freq, mode=0, date=None) BATCH_CASES = [ # 日 K —— 知名个股 ('中远海控', '日', 0, None), ('贵州茅台', '日', 0, None), ('宁德时代', '日', 0, None), ('中芯国际', '日', 0, None), # 周 K —— 宽基指数 ('沪深300', '周', 0, None), ('中证500', '周', 0, None), # 月 K ('贵州茅台', '月', 0, None), ('中远海控', '月', 0, None), ] # ── 单条处理 ────────────────────────────────────────────────────────────────── def process_one(ticker: str, freq: str, mode: int, date, save: bool, show: bool) -> bool: print(f'[batch] → {ticker!r} {freq}K ...') try: index_id = run_formula(ticker, freq, mode, date) except Exception as e: print(f'[batch] ✗ 公式执行失败: {e}') return False try: detail = fetch_detail(index_id) except Exception as e: print(f'[batch] ✗ 读取详情失败: {e}') return False cd = detail.get('chart_data', {}) strength = detail.get('strength', 0) direction = detail.get('direction', 'none') print( f'[batch] ✓ 强度={strength:.4f} 方向={direction} ' f'窗口={cd.get("window_start_date", "?")}~{cd.get("window_end_date", "?")}' ) if not cd.get('klines'): print('[batch] ✗ 没有 klines,跳过绘图') return False from chart import draw_triangle_chart safe_ticker = ticker.replace('/', '_').replace('\\', '_') output_path = None if save: output_dir = _THIS_DIR / 'output' fname = f'{safe_ticker}_{freq}K_{cd.get("target_date", "")}.png' output_path = str(output_dir / fname) try: draw_triangle_chart(detail=detail, output_path=output_path, show=show) except Exception as e: print(f'[batch] ✗ 绘图失败: {e}') return False return True # ── 主函数 ──────────────────────────────────────────────────────────────────── def main(): parser = argparse.ArgumentParser(description='收敛三角形批量验证(HTTP 版)') parser.add_argument('--no-show', action='store_true', help='不弹出图形窗口') parser.add_argument('--save', action='store_true', help='保存图片到 output/') args = parser.parse_args() show = not args.no_show save = args.save if not show and not save: print('[batch] 提示:既未开启 --save 也未弹窗,将只打印摘要。') ok_count = 0 fail_count = 0 for case in BATCH_CASES: ticker, freq = case[0], case[1] mode = case[2] if len(case) > 2 else 0 date = case[3] if len(case) > 3 else None success = process_one(ticker, freq, mode, date, save, show) if success: ok_count += 1 else: fail_count += 1 print(f'\n[batch] 完成 成功={ok_count} 失败={fail_count} 总计={ok_count + fail_count}') if __name__ == '__main__': main()