Metadata-Version: 2.4
Name: eastmoney-concept-picker
Version: 0.2.0
Summary: Fetch Eastmoney stock data and use OpenAI to pick core concept labels.
Author: eastmoney-concept-picker
License-Expression: LicenseRef-Proprietary
Keywords: a-share,eastmoney,openai,stocks,concept
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Operating System :: OS Independent
Requires-Python: >=3.10
Description-Content-Type: text/markdown

# eastmoney-concept-picker

一个基于东方财富数据和 OpenAI 的 A 股概念筛选工具。

当前功能：

- 根据股票代码从东方财富抓取个股主题数据
- 将原始数据保存到本地 JSON 文件
- 支持原始数据缓存，默认 7 天有效
- 将原始 JSON 内容发送给 OpenAI 分析
- 从 `boards` 中筛选 3 个更核心的概念标签
- 自动压掉明显的上位概念，优先保留更具体的下位概念
- 将 AI 分析结果单独保存为 `*.analysis.json`
- 支持分析结果缓存，默认 7 天有效

## 工作流程

执行：

```bash
python main.py <股票代码>
```

程序会按这个顺序运行：

1. 读取 `config.yaml`
2. 检查原始数据缓存 `<股票代码>.json`
3. 如果原始缓存失效或不存在，则从东方财富重新抓取
4. 检查分析缓存 `<股票代码>.analysis.json`
5. 如果分析缓存失效或不存在，则将原始 JSON 发送给 OpenAI
6. 要求模型只能从 `boards[].BOARD_NAME` 中挑选 3 个核心概念
7. 在控制台打印结果

## 项目结构

```text
.
├── main.py
├── pyproject.toml
├── config.yaml.example
├── eastmoney_spider/
│   ├── __init__.py
│   ├── api.py
│   ├── fetcher.py
│   └── llm.py
├── tests/
└── docs/
```

## 配置

项目默认读取根目录下的 `config.yaml`。

建议先从示例文件复制：

```bash
copy config.yaml.example config.yaml
```

配置示例：

```yaml
cache_days: 7
analysis_cache_days: 7

openai:
  api_key: your-openai-api-key
  base_url: https://api.openai.com/v1
  model: gpt-4o-mini
  proxy: http://127.0.0.1:7890
```

说明：

- `cache_days`
  控制原始抓取结果 `<股票代码>.json` 的缓存有效期
- `analysis_cache_days`
  控制分析结果 `<股票代码>.analysis.json` 的缓存有效期
- `openai.api_key`
  OpenAI API Key
- `openai.base_url`
  OpenAI 兼容接口地址
- `openai.model`
  使用的模型名称
- `openai.proxy`
  可选配置，只对 OpenAI 请求生效，不影响东方财富抓取

## 命令行使用

示例：

```bash
python main.py 600032
```

首次分析时，终端类似输出：

```text
使用缓存: 600032.json
已分析并保存: 600032.analysis.json

股票: 600032 浙江新能

核心概念标签:
1. 光伏发电
   原因: 公司主营业务包括光伏发电，符合该板块的定义。
2. 风能
   原因: 公司主营业务还包括风力发电，属于风能板块。
3. 新能源
   原因: 公司专注于可再生能源的投资与开发，符合新能源的概念。
```

命中分析缓存时，终端类似输出：

```text
使用缓存: 600032.json
使用分析缓存: 600032.analysis.json

股票: 600032 浙江新能

核心概念标签:
1. 光伏发电
   原因: 公司主营业务包括光伏发电，符合该板块的定义。
2. 风能
   原因: 公司主营业务还包括风力发电，属于风能板块。
3. 新能源
   原因: 公司专注于可再生能源的投资与开发，符合新能源的概念。
```

## 作为 Python 库使用

这个项目现在既可以作为命令行工具使用，也可以直接在别的 Python 项目中导入。

### 推荐用法：高层函数

```python
from eastmoney_spider import analyze_stock

result = analyze_stock("600032")

print(result["raw"]["stock"])
print(result["analysis"]["top_concepts"])
print(result["raw_cache_hit"], result["analysis_cache_hit"])
```

返回结构示例：

```python
{
    "raw": {...},
    "analysis": {
        "stock": {...},
        "top_concepts": [
            {"name": "光伏发电", "reason": "原因1"},
            {"name": "风能", "reason": "原因2"},
            {"name": "新能源", "reason": "原因3"},
        ],
        "metadata": {...},
    },
    "raw_cache_hit": True,
    "analysis_cache_hit": False,
}
```

### 分步用法：低层函数

```python
from eastmoney_spider import get_or_fetch_stock_data, get_or_analyze_stock_data, load_config

config = load_config("config.yaml")

raw_payload, raw_cache_hit = get_or_fetch_stock_data(
    "600032",
    output_dir=".",
    cache_days=config["cache_days"],
)

analysis_payload, analysis_cache_hit = get_or_analyze_stock_data(
    raw_payload,
    config["openai"],
    output_dir=".",
    analysis_cache_days=config["analysis_cache_days"],
)

print(analysis_payload["top_concepts"])
```

## 输出文件

程序会在当前目录生成两类文件：

```text
<股票代码>.json
<股票代码>.analysis.json
```

例如：

```text
600032.json
600032.analysis.json
```

其中：

- `600032.json` 保存东方财富原始数据
- `600032.analysis.json` 保存 AI 分析结果

## 当前规则

为了减少概念冗余，程序会优先保留更具体的标签。

例如同一层级链中如果同时出现：

- `公用事业`
- `电力`
- `光伏发电`

则会优先保留更具体的 `光伏发电`，避免把明显存在包含关系的上位概念和下位概念同时交给模型。

## 安装与构建

当前项目基于 Python 3.10+。

本地安装：

```bash
pip install .
```

构建 PyPI 包：

```bash
python -m build --no-isolation
```

构建后产物位于：

```text
dist/
```

## 测试

运行测试：

```bash
python -m unittest discover -s tests -v
```

## 注意事项

- `config.yaml` 不应提交到仓库
- 请只提交 `config.yaml.example`
- 本地生成的 JSON 文件属于缓存结果，不建议提交
- OpenAI 返回结果仍然是模型判断，不构成投资建议

## 后续可扩展方向

- 进一步压制像 `新能源` 这类更宽泛的大概念
- 输出更稳定的中文理由
- 支持批量股票分析
- 增加更完整的 OpenAI 配置校验和异常处理
- 上传并发布到正式 PyPI
