功能: - 支持中文名称搜索股票(如"中控技术"、"英伟达") - 支持 A 股和美股 - 趋势线从窗口起点延伸到终点(与前端一致) - Y 轴自动调整以包含趋势线 - 支持 --window 参数(1Y/3Y/5Y/ALL) 用法: python validate.py 中控技术 日 --window 3Y --save python validate.py 英伟达 日 --window 3Y --save Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
117 lines
3.9 KiB
Python
117 lines
3.9 KiB
Python
"""
|
||
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()
|