diff --git a/mo_provider.py b/mo_provider.py index b9bd646..cbee72b 100644 --- a/mo_provider.py +++ b/mo_provider.py @@ -203,6 +203,58 @@ class MoDataProvider: return None + # ── 分钟级 K 线 ────────────────────────────────────────────── + + _last_minute_call = 0 # 限流时间戳 + + def get_minute_kline(self, code: str, count: int = 60) -> list | None: + """获取1分钟K线数据(东方财富 push2)。 + + 限流保护:每次调用间隔至少1秒,批量查询间隔2秒。 + + Args: + code: 股票代码(6位,如'600519') + count: 获取条数(最大240,约4小时) + + Returns: + [{"time":"09:31","open":xx,"close":xx,"high":xx,"low":xx,"volume":xx,"amount":xx}, ...] + 或 None + """ + import time, urllib.request + now = time.time() + elapsed = now - self._last_minute_call + if elapsed < 1.0: + time.sleep(1.0 - elapsed) + + # A股secid: 1.上海 0.深圳 + secid = f"1.{code}" if code.startswith(('6','5')) else f"0.{code}" + url = (f"https://push2.eastmoney.com/api/qt/stock/kline/get" + f"?secid={secid}&fields1=f1,f2,f3&fields2=f51,f52,f53,f54,f55,f56,f57" + f"&klt=1&fqt=1&end=20500101&lmt={min(count, 240)}") + + try: + req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"}) + resp = urllib.request.urlopen(req, timeout=8) + data = json.loads(resp.read())["data"]["klines"] + result = [] + for line in data: + parts = line.split(",") + if len(parts) >= 6: + result.append({ + "time": parts[0][-5:], # "2026-07-01 09:31" → "09:31" + "open": float(parts[1]), + "close": float(parts[2]), + "high": float(parts[3]), + "low": float(parts[4]), + "volume": int(parts[5]), + "amount": float(parts[6]) if len(parts) > 6 else 0, + }) + self._last_minute_call = time.time() + return result + except Exception as e: + logger.warning("get_minute_kline(%s) 失败: %s", code, e) + return None + # ── 新闻搜索 ────────────────────────────────────────────────── def search_news(self, query: str, max_results: int = 5) -> list: