股票数据收集 收集指定股票的完整数据:历史K线、实时行情、筹码分布(仅A股)。 执行命令 参数说明 : - :获取天数(默认60天) - :数据源(默认 ;仅用户选择时使用 ) - :保存文件的日期标识(必填,用于保证后续分析与决策可复现;不影响数据时间范围) 当 时: - 当前仅支持 A股 K线 - 需要设置环境变量 - 与 字段会返回 市场支持 自动识别市场类型: - A股 :6位数字(600519, 000001) - 港股 :5位数字(00700, 09988) - 美股 :字母代码(AAPL, MSFT) - ETF :51/52/56/58开头(512880) 详见 markets.md 输出结构 输出包含: - :历史K线(日期、开高低收、成交量额、涨跌幅) - :实时行情(价格、量比、换手率、市盈率等) - :筹码分布(仅A股,获利比例、筹码集中度等) 完整字段说明见 fields.md 失败处理 - 股票代码无效/市场不支持:检查 的识别规则 - K 线数据拉取失败:脚本会自动切换数据源;如果仍失败,可能是网络/源站限制,稍后重试 - 实时行情/筹码失败:会输出警告但不阻断(K 线仍会保存) 错误处理 A股数据源 :自动切换东方财富→新浪→腾讯,所有源失败才报错 可选数据 :实时行情和筹码数据获取失败不影响K线输出(会警告) 防封禁 :脚本自动在请求间随机休眠2…

, code):\n return \"美股\"\n\n # 港股:5位数字 或 hk前缀\n if code.lower().startswith('hk'):\n return \"港股\"\n if code.isdigit() and len(code) == 5:\n return \"港股\"\n\n # ETF:特定前缀的6位数字\n etf_prefixes = ('51', '52', '56', '58', '15', '16', '18')\n if code.startswith(etf_prefixes) and len(code) == 6:\n return \"ETF\"\n\n # A股:6位数字\n if code.isdigit() and len(code) == 6:\n return \"A股\"\n\n return \"未知\"\n\n\n# === 列名标准化 ===\ndef _normalize_columns(df: pd.DataFrame) -> pd.DataFrame:\n \"\"\"统一列名\"\"\"\n column_map = {\n '日期': 'date', 'date': 'date',\n 'trade_date': 'date',\n '开盘': 'open', 'open': 'open',\n '收盘': 'close', 'close': 'close',\n '最高': 'high', 'high': 'high',\n '最低': 'low', 'low': 'low',\n '成交量': 'volume', 'volume': 'volume',\n 'vol': 'volume',\n '成交额': 'amount', 'amount': 'amount',\n '涨跌幅': 'pct_chg', 'pct_chg': 'pct_chg',\n }\n df = df.rename(columns=column_map)\n\n # 计算涨跌幅(如果缺失)\n if 'pct_chg' not in df.columns and 'close' in df.columns:\n df['pct_chg'] = df['close'].pct_change() * 100\n df['pct_chg'] = df['pct_chg'].fillna(0)\n\n return df\n\n\n# === A股数据(多数据源) ===\ndef _fetch_em(code: str, days: int) -> pd.DataFrame:\n \"\"\"东方财富接口\"\"\"\n end = datetime.now()\n start = end - timedelta(days=days)\n\n df = ak.stock_zh_a_hist(\n symbol=code,\n period=\"daily\",\n start_date=start.strftime('%Y%m%d'),\n end_date=end.strftime('%Y%m%d'),\n adjust=\"qfq\"\n )\n return _normalize_columns(df)\n\n\ndef _fetch_sina(code: str, days: int) -> pd.DataFrame:\n \"\"\"新浪财经接口\"\"\"\n end = datetime.now()\n start = end - timedelta(days=days)\n\n symbol = f\"sh{code}\" if code.startswith(('6', '5', '9')) else f\"sz{code}\"\n\n df = ak.stock_zh_a_daily(\n symbol=symbol,\n start_date=start.strftime('%Y%m%d'),\n end_date=end.strftime('%Y%m%d'),\n adjust=\"qfq\"\n )\n return _normalize_columns(df)\n\n\ndef _fetch_tencent(code: str, days: int) -> pd.DataFrame:\n \"\"\"腾讯财经接口\"\"\"\n end = datetime.now()\n start = end - timedelta(days=days)\n\n symbol = f\"sh{code}\" if code.startswith(('6', '5', '9')) else f\"sz{code}\"\n\n df = ak.stock_zh_a_hist_tx(\n symbol=symbol,\n start_date=start.strftime('%Y%m%d'),\n end_date=end.strftime('%Y%m%d'),\n adjust=\"qfq\"\n )\n return _normalize_columns(df)\n\n\ndef fetch_a_stock_kline_akshare(code: str, days: int = 60) -> pd.DataFrame:\n \"\"\"获取 A股 K线数据,多数据源自动切换\"\"\"\n methods = [\n (_fetch_em, \"东方财富\"),\n (_fetch_sina, \"新浪财经\"),\n (_fetch_tencent, \"腾讯财经\"),\n ]\n\n for fetch_func, source_name in methods:\n try:\n random_sleep()\n df = fetch_func(code, days)\n if df is not None and not df.empty:\n print(f\"[数据源] {source_name} 获取成功\", file=sys.stderr)\n return df\n except Exception as e:\n print(f\"[数据源] {source_name} 失败: {e}\", file=sys.stderr)\n\n raise Exception(\"所有数据源均获取失败\")\n\n\ndef _to_tushare_ts_code(code: str) -> str:\n \"\"\"A股代码转换为 tushare ts_code\"\"\"\n if not code.isdigit() or len(code) != 6:\n raise ValueError(\"tushare 目前仅支持 6 位 A 股代码\")\n suffix = \"SH\" if code.startswith(('5', '6', '9')) else \"SZ\"\n return f\"{code}.{suffix}\"\n\n\ndef fetch_a_stock_kline_tushare(code: str, days: int = 60) -> pd.DataFrame:\n \"\"\"通过 tushare 获取 A股 K线数据\"\"\"\n if ts is None:\n raise ImportError(\"未安装 tushare,请先执行: pip install tushare\")\n\n token = os.environ.get(\"TUSHARE_TOKEN\", \"\").strip()\n if not token:\n raise ValueError(\"缺少 TUSHARE_TOKEN 环境变量,无法使用 tushare 数据源\")\n\n ts.set_token(token)\n ts_code = _to_tushare_ts_code(code)\n\n end = datetime.now()\n start = end - timedelta(days=days)\n random_sleep()\n df = ts.pro_bar(\n ts_code=ts_code,\n start_date=start.strftime('%Y%m%d'),\n end_date=end.strftime('%Y%m%d'),\n freq='D',\n adj='qfq'\n )\n if df is None or df.empty:\n raise Exception(\"tushare 返回空数据\")\n\n df = _normalize_columns(df)\n df['date'] = pd.to_datetime(df['date'], format='%Y%m%d')\n df = df.sort_values('date').reset_index(drop=True)\n return df\n\n\n# === 港股数据 ===\ndef fetch_hk_stock_kline(code: str, days: int = 60) -> pd.DataFrame:\n \"\"\"获取港股 K线数据\"\"\"\n code = code.lower().replace('hk', '').zfill(5)\n\n end = datetime.now()\n start = end - timedelta(days=days)\n\n random_sleep()\n df = ak.stock_hk_hist(\n symbol=code,\n period=\"daily\",\n start_date=start.strftime('%Y%m%d'),\n end_date=end.strftime('%Y%m%d'),\n adjust=\"qfq\"\n )\n return _normalize_columns(df)\n\n\n# === 美股数据 ===\ndef fetch_us_stock_kline(code: str, days: int = 60) -> pd.DataFrame:\n \"\"\"获取美股 K线数据\"\"\"\n code = code.strip().upper()\n end = datetime.now()\n start = end - timedelta(days=days)\n\n random_sleep()\n df = ak.stock_us_daily(symbol=code, adjust=\"qfq\")\n\n df['date'] = pd.to_datetime(df['date'])\n df = df[(df['date'] >= start) & (df['date'] \u003c= end)]\n df = _normalize_columns(df)\n\n if 'amount' not in df.columns:\n df['amount'] = df['volume'] * df['close']\n\n return df\n\n\n# === ETF数据 ===\ndef fetch_etf_kline(code: str, days: int = 60) -> pd.DataFrame:\n \"\"\"获取 ETF K线数据\"\"\"\n end = datetime.now()\n start = end - timedelta(days=days)\n\n random_sleep()\n df = ak.fund_etf_hist_em(\n symbol=code,\n period=\"daily\",\n start_date=start.strftime('%Y%m%d'),\n end_date=end.strftime('%Y%m%d'),\n adjust=\"qfq\"\n )\n return _normalize_columns(df)\n\n\n# === 实时行情 ===\ndef fetch_realtime_quote(code: str, market: str) -> dict:\n \"\"\"获取实时行情\"\"\"\n if market == \"美股\":\n return None\n\n random_sleep()\n\n if market == \"港股\":\n df = ak.stock_hk_spot_em()\n code = code.lower().replace('hk', '').zfill(5)\n elif market == \"ETF\":\n df = ak.fund_etf_spot_em()\n else:\n df = ak.stock_zh_a_spot_em()\n\n row = df[df['代码'] == code]\n if row.empty:\n return None\n\n row = row.iloc[0]\n\n def safe_float(val):\n try:\n return float(val) if val and str(val) not in ['', '-', 'nan'] else None\n except:\n return None\n\n return {\n 'name': row.get('名称', ''),\n 'price': safe_float(row.get('最新价')),\n 'change_pct': safe_float(row.get('涨跌幅')),\n 'change': safe_float(row.get('涨跌额')),\n 'open': safe_float(row.get('今开')),\n 'high': safe_float(row.get('最高')),\n 'low': safe_float(row.get('最低')),\n 'volume': safe_float(row.get('成交量')),\n 'amount': safe_float(row.get('成交额')),\n 'volume_ratio': safe_float(row.get('量比')),\n 'turnover_rate': safe_float(row.get('换手率')),\n 'pe_ratio': safe_float(row.get('市盈率-动态')),\n 'pb_ratio': safe_float(row.get('市净率')),\n 'total_mv': safe_float(row.get('总市值')),\n 'circ_mv': safe_float(row.get('流通市值')),\n 'amplitude': safe_float(row.get('振幅')),\n 'high_52w': safe_float(row.get('52周最高')),\n 'low_52w': safe_float(row.get('52周最低')),\n 'change_60d': safe_float(row.get('60日涨跌幅')),\n }\n\n\n# === 筹码分布(A股专属) ===\ndef fetch_chip_distribution(code: str) -> dict:\n \"\"\"获取筹码分布数据\"\"\"\n random_sleep()\n\n try:\n df = ak.stock_cyq_em(symbol=code)\n if df.empty:\n return None\n\n latest = df.iloc[-1]\n\n def safe_float(val):\n try:\n return float(val) if val and str(val) not in ['', '-', 'nan'] else None\n except:\n return None\n\n return {\n 'date': str(latest.get('日期', '')),\n 'profit_ratio': safe_float(latest.get('获利比例')),\n 'avg_cost': safe_float(latest.get('平均成本')),\n 'concentration_90': safe_float(latest.get('90集中度')),\n 'concentration_70': safe_float(latest.get('70集中度')),\n 'cost_90_low': safe_float(latest.get('90成本-低')),\n 'cost_90_high': safe_float(latest.get('90成本-高')),\n 'cost_70_low': safe_float(latest.get('70成本-低')),\n 'cost_70_high': safe_float(latest.get('70成本-高')),\n }\n except Exception as e:\n print(f\"获取筹码数据失败: {e}\", file=sys.stderr)\n return None\n\n\n# === 统一入口 ===\ndef collect_stock_data(code: str, days: int = 60, provider: str = \"akshare\") -> dict:\n \"\"\"统一数据收集入口\"\"\"\n provider = provider.strip().lower()\n if provider not in (\"akshare\", \"tushare\"):\n raise ValueError(\"provider 仅支持: akshare, tushare\")\n\n market = identify_market(code)\n\n if market == \"未知\":\n raise ValueError(\n f\"不支持的股票代码/市场: {code}。\"\n \"请检查代码格式,或参考 skills/data-collect/references/markets.md 的识别规则。\"\n )\n\n # 获取 K线数据\n if provider == \"tushare\":\n if market != \"A股\":\n raise ValueError(\"tushare 目前仅支持 A 股 K 线,请改用 --provider akshare\")\n klines_df = fetch_a_stock_kline_tushare(code, days)\n else:\n if market == \"美股\":\n klines_df = fetch_us_stock_kline(code, days)\n elif market == \"港股\":\n klines_df = fetch_hk_stock_kline(code, days)\n elif market == \"ETF\":\n klines_df = fetch_etf_kline(code, days)\n else:\n klines_df = fetch_a_stock_kline_akshare(code, days)\n\n # 转换为列表格式\n klines = []\n for _, row in klines_df.iterrows():\n # 安全转换函数\n def safe_float(val, default=0.0):\n try:\n return float(val) if pd.notna(val) else default\n except (ValueError, TypeError):\n return default\n \n def safe_int(val, default=0):\n try:\n return int(val) if pd.notna(val) else default\n except (ValueError, TypeError):\n return default\n \n # 标准化日期格式为 YYYY-MM-DD\n date_val = row['date']\n if isinstance(date_val, pd.Timestamp):\n date_str = date_val.strftime('%Y-%m-%d')\n else:\n date_str = str(date_val).split()[0] # 去除可能的时间部分\n \n klines.append({\n 'date': date_str,\n 'open': round(safe_float(row['open']), 2),\n 'high': round(safe_float(row['high']), 2),\n 'low': round(safe_float(row['low']), 2),\n 'close': round(safe_float(row['close']), 2),\n 'volume': safe_int(row['volume']),\n 'amount': safe_float(row.get('amount', 0)),\n 'pct_chg': round(safe_float(row.get('pct_chg', 0)), 2),\n })\n\n # 获取实时行情(可选,失败不影响主流程)\n realtime = None\n if provider == \"akshare\":\n max_retries = 3\n for attempt in range(max_retries):\n try:\n realtime = fetch_realtime_quote(code, market)\n break\n except Exception as e:\n if attempt \u003c max_retries - 1:\n print(f\"[警告] 实时行情获取失败(尝试 {attempt + 1}/{max_retries}): {e}\", file=sys.stderr)\n time.sleep(2)\n else:\n print(f\"[警告] 实时行情获取失败,已重试 {max_retries} 次: {e}\", file=sys.stderr)\n\n # 获取筹码分布(仅 A股,可选)\n chip = None\n if provider == \"akshare\" and market == \"A股\":\n try:\n chip = fetch_chip_distribution(code)\n except Exception as e:\n print(f\"[警告] 筹码数据获取失败: {e}\", file=sys.stderr)\n\n return {\n 'code': code,\n 'name': realtime.get('name', code) if realtime else code,\n 'market': market,\n 'source': provider,\n 'update_time': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),\n 'klines': klines,\n 'realtime': realtime,\n 'chip': chip,\n }\n\n\ndef get_project_root() -> str:\n \"\"\"获取项目根目录(向上4级:scripts -> data-collect -> skills -> project)\"\"\"\n current = os.path.abspath(__file__)\n for _ in range(4):\n current = os.path.dirname(current)\n return current\n\n\ndef save_to_file(data: dict, code: str, date_str: str) -> str:\n \"\"\"保存数据到文件\"\"\"\n root = get_project_root()\n output_dir = os.path.join(root, 'output', code, date_str)\n os.makedirs(output_dir, exist_ok=True)\n\n output_path = os.path.join(output_dir, 'data.json')\n with open(output_path, 'w', encoding='utf-8') as f:\n json.dump(data, f, ensure_ascii=False, indent=2)\n\n return output_path\n\n\nif __name__ == \"__main__\":\n import argparse\n\n parser = argparse.ArgumentParser(description='股票数据收集')\n parser.add_argument('code', help='股票代码(如 600519, AAPL, 00700)')\n parser.add_argument('--days', type=int, default=60, help='获取K线天数(默认60)')\n parser.add_argument(\n '--provider',\n default='akshare',\n choices=['akshare', 'tushare'],\n help='数据源(默认 akshare;仅当用户选择时使用 tushare)'\n )\n parser.add_argument('--date', required=True, help='保存文件的日期标识,格式 YYYY-MM-DD(必填)')\n args = parser.parse_args()\n\n date_str = args.date\n\n try:\n result = collect_stock_data(args.code, args.days, args.provider)\n output_path = save_to_file(result, args.code, date_str)\n\n print(f\"[保存] {output_path}\", file=sys.stderr)\n print(json.dumps(result, ensure_ascii=False, indent=2))\n except Exception as e:\n print(f\"[错误] {e}\", file=sys.stderr)\n sys.exit(1)\n","content_type":"text/x-python; charset=utf-8","language":"python","size":15749,"content_sha256":"869b0051a61ef09a386ce507d56b306b3ac173b4db0c53c6fb535c8489aaf870"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"股票数据收集","type":"text"}]},{"type":"paragraph","content":[{"text":"收集指定股票的完整数据:历史K线、实时行情、筹码分布(仅A股)。","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"执行命令","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"python scripts/collect_stock_data.py \u003c股票代码> [--days N] [--provider akshare|tushare] --date YYYY-MM-DD\n\n# 示例\npython scripts/collect_stock_data.py 600519 --date 2025-01-01 # A股,60天\npython scripts/collect_stock_data.py 000001 --days 90 --date 2025-01-01 # 指定90天\npython scripts/collect_stock_data.py AAPL --days 30 --date 2025-01-01 # 美股30天\npython scripts/collect_stock_data.py 600519 --provider tushare --date 2025-01-01 # 用户选择 tushare","type":"text"}]},{"type":"paragraph","content":[{"text":"参数说明","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"--days","type":"text","marks":[{"type":"code_inline"}]},{"text":":获取天数(默认60天)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"--provider","type":"text","marks":[{"type":"code_inline"}]},{"text":":数据源(默认 ","type":"text"},{"text":"akshare","type":"text","marks":[{"type":"code_inline"}]},{"text":";仅用户选择时使用 ","type":"text"},{"text":"tushare","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"--date","type":"text","marks":[{"type":"code_inline"}]},{"text":":保存文件的日期标识(必填,用于保证后续分析与决策可复现;不影响数据时间范围)","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"当 ","type":"text"},{"text":"--provider tushare","type":"text","marks":[{"type":"code_inline"}]},{"text":" 时:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"当前仅支持 ","type":"text"},{"text":"A股 K线","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"需要设置环境变量 ","type":"text"},{"text":"TUSHARE_TOKEN","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"realtime","type":"text","marks":[{"type":"code_inline"}]},{"text":" 与 ","type":"text"},{"text":"chip","type":"text","marks":[{"type":"code_inline"}]},{"text":" 字段会返回 ","type":"text"},{"text":"null","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"市场支持","type":"text"}]},{"type":"paragraph","content":[{"text":"自动识别市场类型:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"A股","type":"text","marks":[{"type":"strong"}]},{"text":":6位数字(600519, 000001)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"港股","type":"text","marks":[{"type":"strong"}]},{"text":":5位数字(00700, 09988)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"美股","type":"text","marks":[{"type":"strong"}]},{"text":":字母代码(AAPL, MSFT)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"ETF","type":"text","marks":[{"type":"strong"}]},{"text":":51/52/56/58开头(512880)","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"详见 ","type":"text"},{"text":"markets.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/markets.md","title":null}}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"输出结构","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"output/\u003c股票代码>/\u003c日期>/data.json","type":"text"}]},{"type":"paragraph","content":[{"text":"输出包含:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"klines","type":"text","marks":[{"type":"code_inline"}]},{"text":":历史K线(日期、开高低收、成交量额、涨跌幅)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"realtime","type":"text","marks":[{"type":"code_inline"}]},{"text":":实时行情(价格、量比、换手率、市盈率等)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"chip","type":"text","marks":[{"type":"code_inline"}]},{"text":":筹码分布(仅A股,获利比例、筹码集中度等)","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"完整字段说明见 ","type":"text"},{"text":"fields.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/fields.md","title":null}}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"失败处理","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"股票代码无效/市场不支持:检查 ","type":"text"},{"text":"markets.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" 的识别规则","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"K 线数据拉取失败:脚本会自动切换数据源;如果仍失败,可能是网络/源站限制,稍后重试","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"实时行情/筹码失败:会输出警告但不阻断(K 线仍会保存)","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"错误处理","type":"text"}]},{"type":"paragraph","content":[{"text":"A股数据源","type":"text","marks":[{"type":"strong"}]},{"text":":自动切换东方财富→新浪→腾讯,所有源失败才报错","type":"text"}]},{"type":"paragraph","content":[{"text":"可选数据","type":"text","marks":[{"type":"strong"}]},{"text":":实时行情和筹码数据获取失败不影响K线输出(会警告)","type":"text"}]},{"type":"paragraph","content":[{"text":"防封禁","type":"text","marks":[{"type":"strong"}]},{"text":":脚本自动在请求间随机休眠2-5秒","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"依赖安装","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"pip install akshare tushare pandas","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}}]},"metadata":{"date":"2026-06-05","name":"data-collect","author":"@skillopedia","source":{"stars":0,"repo_name":"qing-skills","origin_url":"https://github.com/ismxy0934/qing-skills/blob/HEAD/skills/data-collect/SKILL.md","repo_owner":"ismxy0934","body_sha256":"caef91338555b6c3edd39d08e7b0cda733476c2348d6b4315c24964d9c9977fa","cluster_key":"bc03ce1663211162030633d4a116254ba935550d23d8b9b9e231d8d29f5de704","clean_bundle":{"format":"clean-skill-bundle-v1","source":"ismxy0934/qing-skills/skills/data-collect/SKILL.md","attachments":[{"id":"def3218a-3164-5bb1-8234-abc7d8d4cc99","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/def3218a-3164-5bb1-8234-abc7d8d4cc99/attachment.md","path":"references/fields.md","size":4111,"sha256":"168279443c038d2548b660c82a96e4faf0bc8051e0470c599d183832dc301fdb","contentType":"text/markdown; charset=utf-8"},{"id":"3f3f8853-93fd-5e1b-8eb9-bfd5c03e7a59","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/3f3f8853-93fd-5e1b-8eb9-bfd5c03e7a59/attachment.md","path":"references/markets.md","size":1231,"sha256":"aab50a6a20abc19481d5e7337488f731d95173f235758fc368c88bc329794f14","contentType":"text/markdown; charset=utf-8"},{"id":"bcdfd6a6-3a49-5cbd-bf69-3af0d28c4880","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/bcdfd6a6-3a49-5cbd-bf69-3af0d28c4880/attachment.py","path":"scripts/collect_stock_data.py","size":15749,"sha256":"869b0051a61ef09a386ce507d56b306b3ac173b4db0c53c6fb535c8489aaf870","contentType":"text/x-python; charset=utf-8"}],"bundle_sha256":"7aceb01cb570fc94dadac23c3a9ca0eae59c95e690179959d56590d74ab5522f","attachment_count":3,"text_attachments":3,"attachment_storage":"skillopedia-attachments-v1","binary_attachments":0,"excluded_attachments":[]},"cluster_size":1,"skill_md_path":"skills/data-collect/SKILL.md","import_metadata":{"date":"2026-06-05","author":"@skillopedia","version":"v1","category":"data-analytics","category_label":"Data"},"exact_dupes_collapsed_into_this":0},"version":"v1","category":"data-analytics","import_tag":"clean-skills-v1","description":"收集股票历史K线、实时行情、筹码分布数据,支持A股/港股/美股/ETF。当用户提及股票代码、获取行情数据、K线、实时报价、筹码分布、或询问茅台/AAPL等股票时使用"}},"renderedAt":1782987056409}

股票数据收集 收集指定股票的完整数据:历史K线、实时行情、筹码分布(仅A股)。 执行命令 参数说明 : - :获取天数(默认60天) - :数据源(默认 ;仅用户选择时使用 ) - :保存文件的日期标识(必填,用于保证后续分析与决策可复现;不影响数据时间范围) 当 时: - 当前仅支持 A股 K线 - 需要设置环境变量 - 与 字段会返回 市场支持 自动识别市场类型: - A股 :6位数字(600519, 000001) - 港股 :5位数字(00700, 09988) - 美股 :字母代码(AAPL, MSFT) - ETF :51/52/56/58开头(512880) 详见 markets.md 输出结构 输出包含: - :历史K线(日期、开高低收、成交量额、涨跌幅) - :实时行情(价格、量比、换手率、市盈率等) - :筹码分布(仅A股,获利比例、筹码集中度等) 完整字段说明见 fields.md 失败处理 - 股票代码无效/市场不支持:检查 的识别规则 - K 线数据拉取失败:脚本会自动切换数据源;如果仍失败,可能是网络/源站限制,稍后重试 - 实时行情/筹码失败:会输出警告但不阻断(K 线仍会保存) 错误处理 A股数据源 :自动切换东方财富→新浪→腾讯,所有源失败才报错 可选数据 :实时行情和筹码数据获取失败不影响K线输出(会警告) 防封禁 :脚本自动在请求间随机休眠2…