|
"text":"```python\nimport akshare as ak\nimport pandas as pd\n\n# --- 参数设置 ---\n# 股票代码,例如:'000001' (平安银行) 或 '600519' (贵州茅台)\nstock_code = '600519'\n# 数据起始日期,格式 'YYYYMMDD'\nstart_date = '20200101'\n# 数据结束日期,格式 'YYYYMMDD'\nend_date = '20231231'\n# 数据频率,'daily' (日线), 'weekly' (周线), 'monthly' (月线)\n# akshare 也支持分钟线等,但 backtrader 标准DataFeed通常使用日线\nfreq = 'daily'\n\n# --- 获取数据 ---\nprint(f\"正在获取股票 {stock_code} 从 {start_date} 到 {end_date} 的 {freq} 数据...\")\ntry:\n # 使用 akshare 获取股票历史数据\n # 这里以沪深A股为例,akshare 提供了多种数据接口,请根据需要选择\n if freq == 'daily':\n # 'frequence=\"daily\"', 'adjust=\"qfq\"' 表示日线数据,前复权\n stock_data = ak.stock_zh_a_hist(symbol=stock_code, period=freq, start_date=start_date, end_date=end_date, adjust=\"qfq\")\n # elif freq == 'weekly':\n # stock_data = ak.stock_zh_a_hist(symbol=stock_code, period=freq, start_date=start_date, end_date=end_date, adjust=\"qfq\")\n # elif freq == 'monthly':\n # stock_data = ak.stock_zh_a_hist(symbol=stock_code, period=freq, start_date=start_date, end_date=end_date, adjust=\"qfq\")\n else:\n raise ValueError(f\"不支持的数据频率: {freq}\")\n\n print(\"数据获取成功!\")\n print(f\"原始数据列名: {stock_data.columns.tolist()}\")\n\n # --- 数据处理与格式化 ---\n # backtrader 标准DataFeed期望的列名和顺序: Date, Open, High, Low, Close, Volume, OpenInterest\n # akshare 获取的数据列名通常是: 日期, 开盘, 收盘, 最高, 最低, 成交量, 成交额, 振幅, 涨跌幅, 涨跌额, 换手率\n # 我们需要重命名和选取必要的列\n\n # 检查必需的列是否存在\n required_cols_akshare = ['日期', '开盘', '最高', '最低', '收盘', '成交量']\n if not all(col in stock_data.columns for col in required_cols_akshare):\n raise ValueError(f\"获取的数据缺少 backtrader 所需的关键列。akshare原始列名: {stock_data.columns.tolist()}\")\n\n # 重命名列\n stock_data = stock_data.rename(columns={\n '日期': 'Date',\n '开盘': 'Open',\n '最高': 'High',\n '最低': 'Low',\n '收盘': 'Close',\n '成交量': 'Volume'\n # akshare 获取的 A 股数据通常不包含 OpenInterest,可以填充为 0\n })\n\n # 确保 Date 列是 datetime 对象,并设置为索引\n # backtrader 通常要求 Date 列为索引,且类型为 datetime\n stock_data['Date'] = pd.to_datetime(stock_data['Date'])\n stock_data = stock_data.set_index('Date')\n\n # 选取 backtrader 需要的列,并按顺序排列\n bt_data = stock_data[['Open', 'High', 'Low', 'Close', 'Volume']]\n\n # 添加 OpenInterest 列,通常填充为 0\n bt_data['OpenInterest'] = 0\n\n # 确认最终的数据格式和列名\n print(\"\\n处理后用于 backtrader 的数据格式:\")\n print(bt_data.head())\n print(f\"\\n处理后数据列名: {bt_data.columns.tolist()}\")\n print(f\"数据类型: {bt_data.index.dtype}\") # 确保索引是 datetime64[ns]\n print(f\"数据行数: {len(bt_data)}\")\n\n # --- 保存数据 (可选) ---\n # backtrader 可以直接从 pandas DataFrame 加载数据,也可以从 CSV 文件加载\n # 保存为 CSV 方便后续直接加载或检查\n output_filename = f\"{stock_code}_{start_date}_{end_date}_{freq}.csv\"\n bt_data.to_csv(output_filename)\n print(f\"\\n数据已保存至文件: {output_filename}\")\n\n # --- 如何在 backtrader 中使用这些数据 ---\n print(\"\\n--- 如何在 backtrader 中使用 ---\")\n print(\"1. 直接从 DataFrame 加载:\")\n print(\" import backtrader as bt\")\n print(\" data = bt.feeds.PandasData(dataname=bt_data)\")\n print(\" cerebro = bt.Cerebro()\")\n print(\" cerebro.adddata(data)\")\n print(\" # 添加策略等...\")\n print(\" # cerebro.run()\")\n print(\"\\n2. 从 CSV 文件加载:\")\n print(\" import backtrader as bt\")\n print(f\" data = bt.feeds.GenericCSVData(\")\n print(f\" dataname='{output_filename}',\")\n print( \" dtformat='%Y-%m-%d', # 日期格式\")\n print( \" datetime=0, # 日期在第0列 (索引列)\")\n print( \" open=1, # 开盘价在第1列\")\n print( \" high=2, # 最高价在第2列\")\n print( \" low=3, # 最低价在第3列\")\n print( \" close=4, # 收盘价在第4列\")\n print( \" volume=5, # 成交量在第5列\")\n print( \" openinterest=6, # 持仓量在第6列 (或使用 -1 如果CSV中没有此列)\")\n print( \" # headers=True, # 如果第一行是列名,则设置为 True\")\n print( \" )\")\n print(\" cerebro = bt.Cerebro()\")\n print(\" cerebro.adddata(data)\")\n print(\" # 添加策略等...\")\n print(\" # cerebro.run()\")\n\n\nexcept Exception as e:\n print(f\"处理过程中发生错误: {e}\")\n\n```" |