初始化提交:AI价值投资盯盘系统
This commit is contained in:
parent
7ad16b0a1b
commit
5926fa5f46
7
.env.example
Normal file
7
.env.example
Normal file
@ -0,0 +1,7 @@
|
||||
# Tushare API配置
|
||||
TUSHARE_TOKEN=your_tushare_token_here
|
||||
|
||||
# Volces API配置
|
||||
VOLCES_MODEL_ID=your_model_id_here
|
||||
VOLCES_API_KEY=your_api_key_here
|
||||
VOLCES_BASE_URL=https://ark.cn-beijing.volces.com/api/v3
|
||||
22
.gitignore
vendored
22
.gitignore
vendored
@ -1,3 +1,7 @@
|
||||
# 环境配置
|
||||
.env
|
||||
config.py
|
||||
|
||||
# Python
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
@ -16,14 +20,16 @@ lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
# 虚拟环境
|
||||
venv/
|
||||
ENV/
|
||||
# 项目特定文件
|
||||
stock_cache.json
|
||||
watchlist.json
|
||||
ai_stock_analysis/
|
||||
dao_analysis/
|
||||
daka_analysis/
|
||||
|
||||
# IDE
|
||||
.idea/
|
||||
@ -31,10 +37,6 @@ ENV/
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# 项目特定
|
||||
config.json
|
||||
*.log
|
||||
.env
|
||||
# 系统文件
|
||||
.DS_Store
|
||||
stock_cache.json
|
||||
watchlist.json
|
||||
Thumbs.db
|
||||
310
README.md
310
README.md
@ -1,238 +1,158 @@
|
||||
# 价值投资盯盘系统
|
||||
# AI价值投资盯盘系统
|
||||
|
||||
一个专注于中国 A 股市场的智能股票分析与监控平台,基于 Python FastAPI 开发,集成实时行情监控、AI 智能分析和价值投资建议等功能,助力投资者进行理性的价值投资决策。
|
||||
一个基于Python的A股智能监控和AI分析系统,集成了多维度的投资分析功能,包括传统价值投资分析、道德经智慧分析以及知名投资大师的视角分析。
|
||||
|
||||
## 功能特点
|
||||
## 系统界面预览
|
||||

|
||||
|
||||
### 1. A股实时监控
|
||||
- 支持所有 A 股上市公司的实时监控
|
||||
- 沪深两市实时价格和涨跌幅更新
|
||||
- 自定义市值目标区间预警
|
||||
- 个股交易状态实时提示
|
||||
## 🚀 核心功能
|
||||
|
||||
### 2. AI 智能分析
|
||||
- 基于中国市场特点的智能投资建议
|
||||
- A股市场合理价格区间估算
|
||||
- 结合中国经济环境的目标市值评估
|
||||
- 多维度分析报告:
|
||||
- A股市场估值分析
|
||||
- 中国特色财务健康状况评估
|
||||
- 行业对标成长潜力评估
|
||||
- 系统性风险评估
|
||||
### 1. 股票监控
|
||||
- 实时股票数据监控
|
||||
- 自定义目标市值设置
|
||||
- 价格和市值预警
|
||||
- 多维度指标展示(PE、PB、ROE等)
|
||||
|
||||
### 3. A股财务指标分析
|
||||
- 估值指标:PE(市盈率)、PB(市净率)、PS(市销率)等
|
||||
- 盈利能力:ROE(净资产收益率)、毛利率、净利率
|
||||
- 成长能力:营收增长、利润增长、研发投入
|
||||
- 运营效率:资产周转率、存货周转率等
|
||||
- 偿债能力:资产负债率、流动比率等
|
||||
- 现金流指标:经营现金流、自由现金流等
|
||||
### 2. 指数行情
|
||||
- 主要指数实时行情展示
|
||||
- K线图技术分析
|
||||
- 大盘趋势分析
|
||||
|
||||
### 4. 中国市场行情
|
||||
- 上证指数、深证成指、创业板指等主要指数实时行情
|
||||
- 专业K线图技术分析
|
||||
- A股市场涨跌分布分析
|
||||
- 行业板块轮动分析
|
||||
### 3. AI智能分析
|
||||
- 基础价值投资分析
|
||||
- 财务指标分析
|
||||
- 估值分析
|
||||
- 风险评估
|
||||
- 投资建议
|
||||
- 道德经分析视角
|
||||
- 企业道德评估
|
||||
- 可持续发展分析
|
||||
- 长期投资价值判断
|
||||
- 价值投资大咖分析
|
||||
- 巴菲特视角
|
||||
- 格雷厄姆视角
|
||||
- 林园视角
|
||||
- 李大霄视角
|
||||
- 段永平视角
|
||||
|
||||
### 5. 上市公司详情
|
||||
- 工商登记信息
|
||||
- 十大股东持股变动
|
||||
- A股特色财务报表分析
|
||||
- 公司公告与重大事项
|
||||
- 行业地位分析
|
||||
### 4. 数据管理
|
||||
- 本地数据缓存
|
||||
- 历史数据查询
|
||||
- 分析报告导出
|
||||
- 自动数据更新
|
||||
|
||||
## 技术架构
|
||||
## 🛠️ 技术栈
|
||||
|
||||
### 后端技术栈
|
||||
- Web框架:FastAPI
|
||||
- 数据处理:Pandas
|
||||
- A股数据源:Tushare API(提供专业的 A 股数据)
|
||||
- 服务器:Uvicorn
|
||||
- 数据存储:JSON文件
|
||||
|
||||
### 前端技术栈
|
||||
- 框架:Bootstrap 5
|
||||
- 图表:ECharts
|
||||
- 交互:JavaScript
|
||||
- 样式:CSS3
|
||||
|
||||
### 主要模块
|
||||
```
|
||||
项目结构
|
||||
├── app/
|
||||
│ ├── __init__.py
|
||||
│ ├── api/
|
||||
│ │ └── stock_routes.py # API路由
|
||||
│ ├── models/
|
||||
│ │ └── stock.py # 数据模型
|
||||
│ ├── services/
|
||||
│ │ ├── stock_service.py # 股票服务
|
||||
│ │ └── ai_analysis_service.py # AI分析服务
|
||||
│ ├── templates/
|
||||
│ │ ├── index.html # 主页面
|
||||
│ │ └── market.html # 市场页面
|
||||
│ └── config.py # 配置文件
|
||||
├── run.py # 启动文件
|
||||
└── requirements.txt # 依赖包
|
||||
```
|
||||
|
||||
## 安装部署
|
||||
|
||||
### 环境要求
|
||||
### 后端
|
||||
- Python 3.8+
|
||||
- pip 包管理器
|
||||
- 网络连接(访问 Tushare API)
|
||||
- FastAPI:高性能Web框架
|
||||
- Tushare:金融数据API
|
||||
- 豆包大模型:AI分析引擎
|
||||
- SQLite:本地数据存储
|
||||
|
||||
### 安装步骤
|
||||
### 前端
|
||||
- Bootstrap 5:响应式UI框架
|
||||
- ECharts:数据可视化
|
||||
- jQuery:DOM操作
|
||||
- WebSocket:实时数据推送
|
||||
|
||||
1. 克隆项目
|
||||
## 📦 安装部署
|
||||
|
||||
### 1. 环境准备
|
||||
```bash
|
||||
git clone https://github.com/693696817/stock-monitor.git
|
||||
# 克隆项目
|
||||
git clone https://gitee.com/your-username/stock-monitor.git
|
||||
cd stock-monitor
|
||||
```
|
||||
|
||||
2. 创建虚拟环境(推荐)
|
||||
```bash
|
||||
# 创建虚拟环境
|
||||
python -m venv venv
|
||||
source venv/bin/activate # Linux/Mac
|
||||
venv\Scripts\activate # Windows
|
||||
```
|
||||
venv\\Scripts\\activate # Windows
|
||||
|
||||
3. 安装依赖
|
||||
```bash
|
||||
# 安装依赖
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
4. 配置
|
||||
- 复制 `config.json.example` 为 `config.json`
|
||||
- 在 `config.json` 中配置你的 Tushare Token
|
||||
```json
|
||||
{
|
||||
"watchlist": {},
|
||||
"tushare_token": "your_tushare_token_here"
|
||||
}
|
||||
### 2. API配置获取
|
||||
|
||||
#### Tushare API
|
||||
1. 访问 [Tushare官网](https://tushare.pro/)
|
||||
2. 注册并获取Token
|
||||
3. 可选:充值获取更高级别权限
|
||||
|
||||
#### 豆包大模型API
|
||||
1. 访问 [豆包大模型控制台](https://ark.cn-beijing.volces.com/)
|
||||
2. 注册企业账号
|
||||
3. 创建API Key和Model ID
|
||||
|
||||
### 3. 环境配置
|
||||
1. 复制配置文件
|
||||
```bash
|
||||
cp .env.example .env
|
||||
cp config.template.py config.py
|
||||
```
|
||||
|
||||
5. 运行
|
||||
2. 修改配置文件
|
||||
```bash
|
||||
# 编辑.env文件,填入API密钥
|
||||
TUSHARE_TOKEN=your_token_here
|
||||
VOLCES_MODEL_ID=your_model_id_here
|
||||
VOLCES_API_KEY=your_api_key_here
|
||||
```
|
||||
|
||||
### 4. 启动系统
|
||||
```bash
|
||||
python run.py
|
||||
```
|
||||
访问 http://localhost:8000 即可使用系统
|
||||
|
||||
6. 访问
|
||||
- 打开浏览器访问 `http://localhost:8000`
|
||||
- 默认端口为 8000,可在 `run.py` 中修改
|
||||
## 🤝 联系作者
|
||||
|
||||
## 使用指南
|
||||
如果您对系统有任何问题或建议,欢迎联系:
|
||||
|
||||
### 添加监控股票
|
||||
1. 在主页面顶部输入 A 股股票代码(6位数字,如:000001)
|
||||
2. 可选择设置目标市值区间
|
||||
3. 点击"添加"按钮开始监控
|
||||
- 微信:zyj118
|
||||
- QQ:693696817
|
||||
- Email:693696817@qq.com
|
||||
|
||||
### 查看股票详情
|
||||
1. 点击股票名称进入详情页
|
||||
2. 查看完整的 A 股特色财务指标
|
||||
3. 获取针对中国市场的 AI 投资建议
|
||||
## 📝 使用说明
|
||||
|
||||
### 指数行情
|
||||
- 实时展示沪深主要指数行情
|
||||
- 提供大盘趋势分析
|
||||
- 行业板块表现对比
|
||||
### 1. 添加监控股票
|
||||
1. 在主界面输入股票代码
|
||||
2. 设置目标市值范围
|
||||
3. 点击添加即可
|
||||
|
||||
### 数据更新频率
|
||||
- A股交易时段(9:30-11:30, 13:00-15:00)实时更新
|
||||
- 盘后自动更新财务数据
|
||||
- 可手动强制刷新最新数据
|
||||
### 2. 查看AI分析
|
||||
1. 点击股票行右侧的分析按钮
|
||||
2. 选择需要的分析维度(基础/道德经/大咖)
|
||||
3. 等待AI分析结果
|
||||
|
||||
## 开发指南
|
||||
### 3. 指数行情查看
|
||||
1. 点击顶部导航栏的"指数行情"
|
||||
2. 查看实时指数数据和K线图
|
||||
|
||||
### 代码规范
|
||||
- 遵循 PEP 8 编码规范
|
||||
- 使用类型注解
|
||||
- 保持代码简洁清晰
|
||||
## ⚠️ 注意事项
|
||||
|
||||
### 目录结构说明
|
||||
- `api/`: API路由和接口定义
|
||||
- `models/`: 数据模型和结构定义
|
||||
- `services/`: 业务逻辑和服务实现
|
||||
- `templates/`: 前端页面模板
|
||||
1. API使用限制
|
||||
- Tushare免费账号有调用频率限制
|
||||
- 豆包大模型API有Token限制
|
||||
|
||||
### 扩展开发
|
||||
1. 添加新的数据源
|
||||
- 在 `services` 中添加新的服务类
|
||||
- 实现数据获取和处理方法
|
||||
2. 数据时效性
|
||||
- 行情数据实时更新
|
||||
- AI分析结果默认缓存1小时
|
||||
|
||||
2. 扩展AI分析
|
||||
- 修改 `ai_analysis_service.py`
|
||||
- 添加新的分析维度和方法
|
||||
3. 系统性能
|
||||
- 建议监控股票数量不超过30只
|
||||
- 定时刷新间隔建议60秒以上
|
||||
|
||||
3. 自定义UI
|
||||
- 修改 `templates` 中的HTML文件
|
||||
- 更新样式和交互逻辑
|
||||
|
||||
## 维护说明
|
||||
|
||||
### 数据更新
|
||||
- A股交易时段实时行情更新
|
||||
- 每日收盘后自动更新财务数据
|
||||
- 定期同步公司公告信息
|
||||
- 可配置更新频率
|
||||
|
||||
### 错误处理
|
||||
- 完善的错误提示
|
||||
- 异常捕获和处理
|
||||
- 日志记录
|
||||
|
||||
## 贡献指南
|
||||
|
||||
欢迎提交 Issue 和 Pull Request:
|
||||
1. Fork 本仓库
|
||||
2. 创建特性分支
|
||||
3. 提交变更
|
||||
4. 发起 Pull Request
|
||||
|
||||
## 许可证
|
||||
## 📄 许可证
|
||||
|
||||
MIT License
|
||||
|
||||
## 联系方式
|
||||
## 🤝 贡献指南
|
||||
|
||||
- 作者:ZYJ
|
||||
- 邮箱:693696817@qq.com
|
||||
1. Fork 本仓库
|
||||
2. 新建 feature_xxx 分支
|
||||
3. 提交代码
|
||||
4. 新建 Pull Request
|
||||
|
||||
## 更新日志
|
||||
|
||||
### v1.0.0 (2024-03)
|
||||
- 支持全部 A 股上市公司监控
|
||||
- 实现核心功能:实时行情、AI 分析、财务分析
|
||||
- 完成基础框架搭建
|
||||
- 优化 A 股特色分析逻辑
|
||||
|
||||
## 配置说明
|
||||
|
||||
在运行系统之前,需要配置以下API密钥:
|
||||
|
||||
1. **Tushare API Token**
|
||||
- 访问 [Tushare官网](https://tushare.pro/)
|
||||
- 注册并登录账号
|
||||
- 在个人中心获取Token
|
||||
- 将Token填入 `config.json` 的 `tushare_token` 字段
|
||||
|
||||
2. **豆包大模型 API Key**
|
||||
- 访问 [豆包大模型](https://www.doubao.com/)
|
||||
- 注册并登录账号
|
||||
- 在控制台获取API Key和模型ID
|
||||
- 将API Key填入 `config.json` 的 `ai_api_key` 字段
|
||||
- 将模型ID填入 `config.json` 的 `ai_model_id` 字段
|
||||
|
||||
配置文件示例 (`config.json`):
|
||||
```json
|
||||
{
|
||||
"watchlist": {},
|
||||
"tushare_token": "your_tushare_token_here",
|
||||
"ai_api_key": "your_ai_api_key_here",
|
||||
"ai_model_id": "your_ai_model_id_here"
|
||||
}
|
||||
```
|
||||
|
||||
注意:请妥善保管你的API密钥,不要将其提交到代码仓库中。
|
||||
欢迎提交Issue和Pull Request!
|
||||
@ -11,7 +11,7 @@ Config.ensure_directories()
|
||||
app = FastAPI()
|
||||
|
||||
# 设置tushare token
|
||||
ts.set_token(Config.get_tushare_token())
|
||||
ts.set_token(Config.TUSHARE_TOKEN)
|
||||
pro = ts.pro_api()
|
||||
|
||||
# Mount static files
|
||||
|
||||
@ -68,7 +68,7 @@ async def get_value_analysis(stock_code: str):
|
||||
return stock_service.get_value_analysis_data(stock_code)
|
||||
|
||||
@router.get("/api/ai_analysis/{stock_code}")
|
||||
async def get_ai_analysis(stock_code: str):
|
||||
async def get_ai_analysis(stock_code: str, force_refresh: bool = False):
|
||||
"""获取AI价值投资分析结果"""
|
||||
try:
|
||||
# 首先获取价值分析数据
|
||||
@ -77,6 +77,47 @@ async def get_ai_analysis(stock_code: str):
|
||||
return analysis_data
|
||||
|
||||
# 使用AI服务进行分析
|
||||
return ai_service.analyze_value_investment(analysis_data)
|
||||
return ai_service.analyze_value_investment(analysis_data, force_refresh)
|
||||
except Exception as e:
|
||||
return {"error": f"AI分析失败: {str(e)}"}
|
||||
return {"error": f"AI分析失败: {str(e)}"}
|
||||
|
||||
@router.post("/api/update_target")
|
||||
async def update_target(
|
||||
stock_code: str = Form(...),
|
||||
target_market_value_min: Optional[float] = Form(None),
|
||||
target_market_value_max: Optional[float] = Form(None)
|
||||
):
|
||||
"""更新股票的目标市值"""
|
||||
return stock_service.update_target(stock_code, target_market_value_min, target_market_value_max)
|
||||
|
||||
@router.get("/api/tao_analysis/{stock_code}")
|
||||
async def get_tao_analysis(stock_code: str):
|
||||
"""获取基于道德经的公司分析"""
|
||||
try:
|
||||
# 首先获取公司详细信息
|
||||
company_info = stock_service.get_company_detail(stock_code)
|
||||
if "error" in company_info:
|
||||
return company_info
|
||||
|
||||
# 使用AI服务进行道德经分析
|
||||
return ai_service.analyze_tao_philosophy(company_info)
|
||||
except Exception as e:
|
||||
return {"error": f"道德经分析失败: {str(e)}"}
|
||||
|
||||
@router.get("/api/master_analysis/{stock_code}")
|
||||
async def get_master_analysis(stock_code: str):
|
||||
"""获取价值投资大咖的分析结果"""
|
||||
try:
|
||||
# 首先获取公司详细信息和财务数据
|
||||
company_info = stock_service.get_company_detail(stock_code)
|
||||
if "error" in company_info:
|
||||
return company_info
|
||||
|
||||
value_analysis = stock_service.get_value_analysis_data(stock_code)
|
||||
if "error" in value_analysis:
|
||||
return value_analysis
|
||||
|
||||
# 使用AI服务进行大咖分析
|
||||
return ai_service.analyze_by_masters(company_info, value_analysis)
|
||||
except Exception as e:
|
||||
return {"error": f"价值投资大咖分析失败: {str(e)}"}
|
||||
@ -1,11 +1,13 @@
|
||||
import os
|
||||
import json
|
||||
|
||||
# 基础配置
|
||||
class Config:
|
||||
# 项目根目录
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
# Tushare API配置
|
||||
TUSHARE_TOKEN = '90f8a141125e1decb952cd49032b7b8409a2d7fa370745f6c9f45c96'
|
||||
|
||||
# 配置文件路径
|
||||
CONFIG_FILE = os.path.join(BASE_DIR, "config.json")
|
||||
|
||||
@ -15,29 +17,6 @@ class Config:
|
||||
# 静态文件目录
|
||||
STATIC_DIR = os.path.join(BASE_DIR, "app", "static")
|
||||
|
||||
# API配置
|
||||
@classmethod
|
||||
def load_config(cls):
|
||||
if os.path.exists(cls.CONFIG_FILE):
|
||||
with open(cls.CONFIG_FILE, 'r', encoding='utf-8') as f:
|
||||
return json.load(f)
|
||||
return {"watchlist": {}}
|
||||
|
||||
@classmethod
|
||||
def get_tushare_token(cls):
|
||||
config = cls.load_config()
|
||||
return config.get('tushare_token')
|
||||
|
||||
@classmethod
|
||||
def get_ai_api_key(cls):
|
||||
config = cls.load_config()
|
||||
return config.get('ai_api_key')
|
||||
|
||||
@classmethod
|
||||
def get_ai_model_id(cls):
|
||||
config = cls.load_config()
|
||||
return config.get('ai_model_id')
|
||||
|
||||
# 确保目录存在
|
||||
@classmethod
|
||||
def ensure_directories(cls):
|
||||
|
||||
@ -1,24 +1,115 @@
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
from openai import OpenAI
|
||||
from app.config import Config
|
||||
|
||||
class AIAnalysisService:
|
||||
def __init__(self):
|
||||
self.model = Config.get_ai_model_id() # 从配置获取 model ID
|
||||
# 配置OpenAI客户端连接到Volces API
|
||||
self.model = os.getenv('VOLCES_MODEL_ID', 'your_model_id_here') # 从环境变量获取
|
||||
self.client = OpenAI(
|
||||
api_key = Config.get_ai_api_key(), # 从配置获取 API Key
|
||||
base_url = "https://ark.cn-beijing.volces.com/api/v3"
|
||||
api_key = os.getenv('VOLCES_API_KEY', 'your_api_key_here'), # 从环境变量获取
|
||||
base_url = os.getenv('VOLCES_BASE_URL', 'https://ark.cn-beijing.volces.com/api/v3')
|
||||
)
|
||||
# 创建AI分析结果缓存目录
|
||||
self.cache_dir = os.path.join(Config.BASE_DIR, "ai_stock_analysis")
|
||||
self.dao_cache_dir = os.path.join(Config.BASE_DIR, "dao_analysis")
|
||||
self.daka_cache_dir = os.path.join(Config.BASE_DIR, "daka_analysis")
|
||||
|
||||
def analyze_value_investment(self, analysis_data):
|
||||
# 确保所有缓存目录存在
|
||||
for directory in [self.cache_dir, self.dao_cache_dir, self.daka_cache_dir]:
|
||||
if not os.path.exists(directory):
|
||||
os.makedirs(directory)
|
||||
|
||||
def get_cache_path(self, stock_code: str) -> str:
|
||||
"""获取缓存文件路径"""
|
||||
return os.path.join(self.cache_dir, f"{stock_code}.json")
|
||||
|
||||
def get_dao_cache_path(self, stock_code: str) -> str:
|
||||
"""获取道德经分析缓存文件路径"""
|
||||
return os.path.join(self.dao_cache_dir, f"{stock_code}.json")
|
||||
|
||||
def get_daka_cache_path(self, stock_code: str) -> str:
|
||||
"""获取大咖分析缓存文件路径"""
|
||||
return os.path.join(self.daka_cache_dir, f"{stock_code}.json")
|
||||
|
||||
def load_cache(self, stock_code: str):
|
||||
"""加载缓存的AI分析结果"""
|
||||
cache_path = self.get_cache_path(stock_code)
|
||||
if os.path.exists(cache_path):
|
||||
try:
|
||||
with open(cache_path, 'r', encoding='utf-8') as f:
|
||||
return json.load(f)
|
||||
except Exception as e:
|
||||
print(f"读取AI分析缓存失败: {str(e)}")
|
||||
return None
|
||||
|
||||
def save_cache(self, stock_code: str, analysis_result: dict):
|
||||
"""保存AI分析结果到缓存"""
|
||||
cache_path = self.get_cache_path(stock_code)
|
||||
try:
|
||||
with open(cache_path, 'w', encoding='utf-8') as f:
|
||||
json.dump(analysis_result, f, ensure_ascii=False, indent=4)
|
||||
except Exception as e:
|
||||
print(f"保存AI分析缓存失败: {str(e)}")
|
||||
|
||||
def load_dao_cache(self, stock_code: str):
|
||||
"""加载缓存的道德经分析结果"""
|
||||
cache_path = self.get_dao_cache_path(stock_code)
|
||||
if os.path.exists(cache_path):
|
||||
try:
|
||||
with open(cache_path, 'r', encoding='utf-8') as f:
|
||||
return json.load(f)
|
||||
except Exception as e:
|
||||
print(f"读取道德经分析缓存失败: {str(e)}")
|
||||
return None
|
||||
|
||||
def save_dao_cache(self, stock_code: str, analysis_result: dict):
|
||||
"""保存道德经分析结果到缓存"""
|
||||
cache_path = self.get_dao_cache_path(stock_code)
|
||||
try:
|
||||
with open(cache_path, 'w', encoding='utf-8') as f:
|
||||
json.dump(analysis_result, f, ensure_ascii=False, indent=4)
|
||||
except Exception as e:
|
||||
print(f"保存道德经分析缓存失败: {str(e)}")
|
||||
|
||||
def load_daka_cache(self, stock_code: str):
|
||||
"""加载缓存的大咖分析结果"""
|
||||
cache_path = self.get_daka_cache_path(stock_code)
|
||||
if os.path.exists(cache_path):
|
||||
try:
|
||||
with open(cache_path, 'r', encoding='utf-8') as f:
|
||||
return json.load(f)
|
||||
except Exception as e:
|
||||
print(f"读取大咖分析缓存失败: {str(e)}")
|
||||
return None
|
||||
|
||||
def save_daka_cache(self, stock_code: str, analysis_result: dict):
|
||||
"""保存大咖分析结果到缓存"""
|
||||
cache_path = self.get_daka_cache_path(stock_code)
|
||||
try:
|
||||
with open(cache_path, 'w', encoding='utf-8') as f:
|
||||
json.dump(analysis_result, f, ensure_ascii=False, indent=4)
|
||||
except Exception as e:
|
||||
print(f"保存大咖分析缓存失败: {str(e)}")
|
||||
|
||||
def analyze_value_investment(self, analysis_data: dict, force_refresh: bool = False):
|
||||
"""
|
||||
对股票进行价值投资分析
|
||||
:param analysis_data: 包含各项财务指标的字典
|
||||
:param force_refresh: 是否强制刷新分析结果
|
||||
:return: AI分析结果
|
||||
"""
|
||||
try:
|
||||
stock_code = analysis_data["stock_info"]["code"]
|
||||
|
||||
# 如果不是强制刷新,尝试从缓存加载
|
||||
if not force_refresh:
|
||||
cached_result = self.load_cache(stock_code)
|
||||
if cached_result:
|
||||
print(f"从缓存加载AI分析结果: {stock_code}")
|
||||
return cached_result
|
||||
|
||||
# 打印输入数据用于调试
|
||||
print(f"输入的分析数据: {json.dumps(analysis_data, ensure_ascii=False, indent=2)}")
|
||||
|
||||
@ -53,16 +144,15 @@ class AIAnalysisService:
|
||||
analysis_result = json.loads(analysis_text)
|
||||
print(f"解析后的JSON结果: {json.dumps(analysis_result, ensure_ascii=False, indent=2)}")
|
||||
|
||||
# 构建完整的返回结果
|
||||
result = analysis_result
|
||||
# 保存到缓存
|
||||
self.save_cache(stock_code, analysis_result)
|
||||
|
||||
print(f"最终返回结果: {json.dumps(result, ensure_ascii=False, indent=2)}")
|
||||
return result
|
||||
return analysis_result
|
||||
|
||||
except json.JSONDecodeError as e:
|
||||
print(f"JSON解析失败: {str(e)}")
|
||||
# 如果JSON解析失败,返回错误信息
|
||||
return {
|
||||
error_result = {
|
||||
'stock_info': analysis_data.get('stock_info', {}),
|
||||
'valuation': analysis_data.get('valuation', {}),
|
||||
'profitability': analysis_data.get('profitability', {}),
|
||||
@ -76,12 +166,10 @@ class AIAnalysisService:
|
||||
"raw_text": analysis_text
|
||||
}
|
||||
}
|
||||
|
||||
return error_result
|
||||
|
||||
except Exception as e:
|
||||
print(f"AI分析失败: {str(e)}")
|
||||
print(f"错误详情: {e.__class__.__name__}")
|
||||
import traceback
|
||||
print(f"错误堆栈: {traceback.format_exc()}")
|
||||
return {"error": f"AI分析失败: {str(e)}"}
|
||||
|
||||
def _parse_analysis_result(self, analysis_text, current_price):
|
||||
@ -285,7 +373,7 @@ class AIAnalysisService:
|
||||
analysis_requirements = """
|
||||
请基于以上数据,从价值投资的角度进行分析。请特别注意:
|
||||
1. 结合行业特点、公司竞争力、成长性等因素,给出合理的估值区间
|
||||
2. 存货周转率为0可能表示数据缺失,分析时需要谨慎对待
|
||||
2. 某些数据可能缺失或异常,分析时需要谨慎对待,或者从东财choice获取
|
||||
3. 考虑当前市场环境和行业整体估值水平
|
||||
|
||||
在给出估值区间时,请充分考虑:
|
||||
@ -300,10 +388,332 @@ class AIAnalysisService:
|
||||
1. investment_suggestion: 投资建议,包含summary(总体建议)、action(具体操作建议)和key_points(关注重点)
|
||||
2. analysis: 详细分析,包含估值分析、财务健康状况、成长潜力和风险评估
|
||||
3. price_analysis: 价格分析,包含合理价格区间和目标市值区间
|
||||
实例:
|
||||
"price_analysis": {
|
||||
"合理价格区间": [
|
||||
xxx,
|
||||
xxx
|
||||
],
|
||||
"目标市值区间": [
|
||||
xxx,
|
||||
xxx
|
||||
]
|
||||
|
||||
请确保返回的是一个有效的JSON格式,数值使用数字而不是字符串(价格、市值等),文本分析使用字符串。分析要客观、专业、详细。"""
|
||||
|
||||
# 组合完整的提示词
|
||||
prompt = data_section + analysis_requirements
|
||||
|
||||
return prompt
|
||||
|
||||
def analyze_tao_philosophy(self, company_info: dict, force_refresh: bool = False):
|
||||
"""
|
||||
基于道德经理念分析公司
|
||||
:param company_info: 公司信息
|
||||
:param force_refresh: 是否强制刷新分析结果
|
||||
:return: AI分析结果
|
||||
"""
|
||||
try:
|
||||
stock_code = company_info.get('basic_info', {}).get('code')
|
||||
|
||||
# 如果不是强制刷新,尝试从缓存加载
|
||||
if not force_refresh and stock_code:
|
||||
cached_result = self.load_dao_cache(stock_code)
|
||||
if cached_result:
|
||||
print(f"从缓存加载道德经分析结果: {stock_code}")
|
||||
return cached_result
|
||||
|
||||
# 构建提示词
|
||||
prompt = self._build_tao_analysis_prompt(company_info)
|
||||
|
||||
# 调用API
|
||||
response = self.client.chat.completions.create(
|
||||
model=self.model,
|
||||
messages=[
|
||||
{
|
||||
"role": "user",
|
||||
"content": prompt
|
||||
}
|
||||
]
|
||||
)
|
||||
|
||||
# 获取分析结果
|
||||
analysis_text = response.choices[0].message.content
|
||||
|
||||
try:
|
||||
# 解析JSON结果
|
||||
analysis_result = json.loads(analysis_text)
|
||||
|
||||
# 保存到缓存
|
||||
if stock_code:
|
||||
self.save_dao_cache(stock_code, analysis_result)
|
||||
|
||||
return analysis_result
|
||||
except json.JSONDecodeError as e:
|
||||
print(f"道德经分析结果JSON解析失败: {str(e)}")
|
||||
return {"error": "分析结果格式错误"}
|
||||
|
||||
except Exception as e:
|
||||
print(f"道德经分析失败: {str(e)}")
|
||||
return {"error": f"道德经分析失败: {str(e)}"}
|
||||
|
||||
def _build_tao_analysis_prompt(self, company_info: dict):
|
||||
"""
|
||||
构建道德经分析提示词
|
||||
"""
|
||||
basic_info = company_info.get('basic_info', {})
|
||||
|
||||
prompt = f"""请作为一位精通道德经的智者,运用道德经的智慧来分析{basic_info.get('name', '')}({basic_info.get('code', '')})这家公司。
|
||||
|
||||
公司基本信息:
|
||||
- 公司名称:{basic_info.get('name', '')}
|
||||
- 所属行业:{basic_info.get('industry', '')}
|
||||
- 主营业务:{basic_info.get('main_business', '')}
|
||||
- 经营范围:{basic_info.get('business_scope', '')}
|
||||
- 公司简介:{basic_info.get('introduction', '')}
|
||||
|
||||
请从道德经的智慧角度,分析以下几个方面:
|
||||
|
||||
1. 道德经视角:
|
||||
- 公司的经营理念是否符合"道法自然"的原则
|
||||
- 企业的发展是否遵循"无为而治"的智慧
|
||||
- 公司是否体现"上善若水"的品质
|
||||
- 管理方式是否符合"柔弱胜刚强"的道理
|
||||
|
||||
2. 企业道德评估:
|
||||
- 公司对待员工、客户、供应商的态度
|
||||
- 企业的社会责任感和可持续发展理念
|
||||
- 公司的价值观和企业文化
|
||||
- 经营中的道德风险评估
|
||||
|
||||
3. 投资建议:
|
||||
- 基于道德经智慧的投资建议
|
||||
- 长期发展潜力分析
|
||||
- 需要关注的风险点
|
||||
- 持有建议
|
||||
|
||||
请以JSON格式返回分析结果,包含以下字段:
|
||||
1. tao_philosophy: 道德经视角的分析
|
||||
2. business_ethics: 企业道德评估
|
||||
3. investment_advice: 投资建议
|
||||
|
||||
分析要客观、专业、深入,同时体现道德经的智慧。"""
|
||||
|
||||
return prompt
|
||||
|
||||
def analyze_by_masters(self, company_info: dict, value_analysis: dict, force_refresh: bool = False):
|
||||
"""
|
||||
基于各位价值投资大咖的理念分析公司
|
||||
:param company_info: 公司信息
|
||||
:param value_analysis: 价值分析数据
|
||||
:param force_refresh: 是否强制刷新分析结果
|
||||
:return: AI分析结果
|
||||
"""
|
||||
try:
|
||||
stock_code = company_info.get('basic_info', {}).get('code')
|
||||
|
||||
# 如果不是强制刷新,尝试从缓存加载
|
||||
if not force_refresh and stock_code:
|
||||
cached_result = self.load_daka_cache(stock_code)
|
||||
if cached_result:
|
||||
print(f"从缓存加载大咖分析结果: {stock_code}")
|
||||
return cached_result
|
||||
|
||||
# 打印输入数据用于调试
|
||||
print(f"公司信息: {json.dumps(company_info, ensure_ascii=False, indent=2)}")
|
||||
print(f"价值分析数据: {json.dumps(value_analysis, ensure_ascii=False, indent=2)}")
|
||||
|
||||
# 构建提示词
|
||||
prompt = self._build_masters_analysis_prompt(company_info, value_analysis)
|
||||
|
||||
# 打印提示词用于调试
|
||||
print(f"大咖分析提示词: {prompt}")
|
||||
|
||||
# 调用API
|
||||
response = self.client.chat.completions.create(
|
||||
model=self.model,
|
||||
messages=[
|
||||
{
|
||||
"role": "user",
|
||||
"content": prompt
|
||||
}
|
||||
]
|
||||
)
|
||||
|
||||
# 获取分析结果
|
||||
analysis_text = response.choices[0].message.content
|
||||
print(f"AI原始返回结果: {analysis_text}")
|
||||
|
||||
try:
|
||||
# 解析JSON结果
|
||||
analysis_result = json.loads(analysis_text)
|
||||
print(f"解析后的JSON结果: {json.dumps(analysis_result, ensure_ascii=False, indent=2)}")
|
||||
|
||||
# 保存到缓存
|
||||
if stock_code:
|
||||
self.save_daka_cache(stock_code, analysis_result)
|
||||
|
||||
return analysis_result
|
||||
except json.JSONDecodeError as e:
|
||||
print(f"大咖分析结果JSON解析失败: {str(e)}")
|
||||
return {"error": "分析结果格式错误"}
|
||||
|
||||
except Exception as e:
|
||||
print(f"价值投资大咖分析失败: {str(e)}")
|
||||
return {"error": f"价值投资大咖分析失败: {str(e)}"}
|
||||
|
||||
def _build_masters_analysis_prompt(self, company_info: dict, value_analysis: dict):
|
||||
"""
|
||||
构建价值投资大咖分析提示词
|
||||
"""
|
||||
basic_info = company_info.get('basic_info', {})
|
||||
|
||||
# 从value_analysis中获取财务数据
|
||||
valuation = value_analysis.get('valuation', {})
|
||||
profitability = value_analysis.get('profitability', {})
|
||||
growth = value_analysis.get('growth', {})
|
||||
operation = value_analysis.get('operation', {})
|
||||
solvency = value_analysis.get('solvency', {})
|
||||
cash_flow = value_analysis.get('cash_flow', {})
|
||||
per_share = value_analysis.get('per_share', {})
|
||||
stock_info = value_analysis.get('stock_info', {})
|
||||
|
||||
# 格式化百分比
|
||||
def format_percent(value):
|
||||
if value is None:
|
||||
return '-'
|
||||
try:
|
||||
if isinstance(value, str):
|
||||
value = float(value)
|
||||
if abs(value) <= 1:
|
||||
value = value * 100
|
||||
return f"{value:.2f}%"
|
||||
except:
|
||||
return '-'
|
||||
|
||||
# 格式化数字
|
||||
def format_number(value):
|
||||
if value is None:
|
||||
return '-'
|
||||
try:
|
||||
if isinstance(value, str):
|
||||
value = float(value)
|
||||
return f"{value:.4f}"
|
||||
except:
|
||||
return '-'
|
||||
|
||||
prompt = f"""请分别以五位价值投资大咖的视角,分析{basic_info.get('name', '')}({basic_info.get('code', '')})这家公司。
|
||||
|
||||
公司基本信息:
|
||||
- 公司名称:{basic_info.get('name', '')}
|
||||
- 所属行业:{basic_info.get('industry', '')}
|
||||
- 主营业务:{basic_info.get('main_business', '')}
|
||||
- 经营范围:{basic_info.get('business_scope', '')}
|
||||
- 公司简介:{basic_info.get('introduction', '')}
|
||||
- 法人代表:{basic_info.get('chairman', '')}
|
||||
- 总经理:{basic_info.get('manager', '')}
|
||||
- 注册资本:{basic_info.get('reg_capital', '')}万元
|
||||
- 员工人数:{basic_info.get('employees', '')}人
|
||||
- 成立日期:{basic_info.get('setup_date', '')}
|
||||
- 上市日期:{basic_info.get('list_date', '')}
|
||||
|
||||
当前市场信息:
|
||||
- 当前股价:{format_number(stock_info.get('current_price'))}元
|
||||
- 总市值:{format_number(valuation.get('total_market_value'))}亿元
|
||||
- 流通市值:{format_number(valuation.get('circulating_market_value'))}亿元
|
||||
- 流通比例:{format_percent(valuation.get('circulating_ratio'))}
|
||||
- 换手率:{format_percent(stock_info.get('turnover_ratio'))}
|
||||
|
||||
估值指标:
|
||||
- 市盈率(PE):{format_number(valuation.get('pe_ratio'))}
|
||||
- 市净率(PB):{format_number(valuation.get('pb_ratio'))}
|
||||
- 市销率(PS):{format_number(valuation.get('ps_ratio'))}
|
||||
- 股息率:{format_percent(valuation.get('dividend_yield'))}
|
||||
|
||||
盈利能力指标:
|
||||
- ROE:{format_percent(profitability.get('roe'))}
|
||||
- ROE(扣非):{format_percent(profitability.get('deducted_roe'))}
|
||||
- ROA:{format_percent(profitability.get('roa'))}
|
||||
- 毛利率:{format_percent(profitability.get('gross_margin'))}
|
||||
- 净利率:{format_percent(profitability.get('net_margin'))}
|
||||
|
||||
成长能力指标:
|
||||
- 净利润增长率:{format_percent(growth.get('net_profit_growth'))}
|
||||
- 扣非净利润增长率:{format_percent(growth.get('deducted_net_profit_growth'))}
|
||||
- 营业总收入增长率:{format_percent(growth.get('revenue_growth'))}
|
||||
- 营业收入增长率:{format_percent(growth.get('operating_revenue_growth'))}
|
||||
|
||||
运营能力指标:
|
||||
- 总资产周转率:{format_number(operation.get('asset_turnover'))}
|
||||
- 存货周转率:{format_number(operation.get('inventory_turnover'))}
|
||||
- 应收账款周转率:{format_number(operation.get('receivables_turnover'))}
|
||||
- 流动资产周转率:{format_number(operation.get('current_asset_turnover'))}
|
||||
|
||||
偿债能力指标:
|
||||
- 流动比率:{format_number(solvency.get('current_ratio'))}
|
||||
- 速动比率:{format_number(solvency.get('quick_ratio'))}
|
||||
- 资产负债率:{format_percent(solvency.get('debt_to_assets'))}
|
||||
- 产权比率:{format_number(solvency.get('equity_ratio'))}
|
||||
|
||||
现金流指标:
|
||||
- 经营现金流/营收:{format_percent(cash_flow.get('ocf_to_revenue'))}
|
||||
- 经营现金流/经营利润:{format_percent(cash_flow.get('ocf_to_operating_profit'))}
|
||||
- 经营现金流同比增长:{format_percent(cash_flow.get('ocf_growth'))}
|
||||
|
||||
每股指标:
|
||||
- 每股收益(EPS):{format_number(per_share.get('eps'))}元
|
||||
- 每股收益(扣非):{format_number(per_share.get('deducted_eps'))}元
|
||||
- 每股净资产:{format_number(per_share.get('bps'))}元
|
||||
- 每股经营现金流:{format_number(per_share.get('ocfps'))}元
|
||||
- 每股留存收益:{format_number(per_share.get('retained_eps'))}元
|
||||
- 每股现金流量:{format_number(per_share.get('cfps'))}元
|
||||
- 每股息税前利润:{format_number(per_share.get('ebit_ps'))}元
|
||||
|
||||
请分别从以下五位投资大师的视角进行分析:
|
||||
|
||||
1. 巴菲特视角:
|
||||
- 是否具有护城河(品牌优势、规模效应、专利技术等)
|
||||
- 管理层能力和诚信(从财务指标、现金流等反映的经营能力)
|
||||
- 业务是否容易理解(商业模式的清晰度)
|
||||
- 长期竞争优势(市场地位、核心竞争力)
|
||||
- 是否是好生意(盈利能力、现金流状况)
|
||||
- 以合理价格购买优秀企业的原则(估值分析)
|
||||
|
||||
2. 格雷厄姆视角:
|
||||
- 安全边际分析(基于净资产、市盈率等)
|
||||
- 内在价值计算(基于盈利能力和资产价值)
|
||||
- 财务安全性(偿债能力、资产质量)
|
||||
- 是否具有投资价值(基于定量分析)
|
||||
- 基于定量分析的结论(综合财务指标评估)
|
||||
|
||||
3. 林园视角:
|
||||
- 行业成长性(收入增长、利润增长)
|
||||
- 公司治理结构(股权结构、管理层背景)
|
||||
- 研发创新能力(技术优势、产品创新)
|
||||
- 市场竞争格局(市场份额、竞争态势)
|
||||
- 估值是否合理(相对估值和绝对估值)
|
||||
|
||||
4. 李大霄视角:
|
||||
- 市场地位和品牌价值(行业地位、品牌影响力)
|
||||
- 行业发展趋势(产业政策、市场空间)
|
||||
- 政策影响分析(行业政策、监管环境)
|
||||
- 投资时机把握(技术面和基本面)
|
||||
- 投资建议(综合分析结论)
|
||||
|
||||
5. 段永平视角:
|
||||
- 商业模式分析(盈利模式、竞争优势)
|
||||
- 用户价值(产品力、客户粘性)
|
||||
- 企业文化(管理理念、团队建设)
|
||||
- 长期发展潜力(成长空间、持续经营能力)
|
||||
- 是否值得长期持有(投资价值判断)
|
||||
|
||||
请以JSON格式返回分析结果,包含以下字段:
|
||||
1. buffett_analysis: 巴菲特的分析观点
|
||||
2. graham_analysis: 格雷厄姆的分析观点
|
||||
3. lin_yuan_analysis: 林园的分析观点
|
||||
4. li_daxiao_analysis: 李大霄的分析观点
|
||||
5. duan_yongping_analysis: 段永平的分析观点
|
||||
|
||||
分析要客观、专业、深入,并体现每位投资大师的独特投资理念。请基于上述详细的财务数据进行分析(如果指标缺失或异常,请联网获取),尤其是定量指标的解读。"""
|
||||
|
||||
return prompt
|
||||
@ -226,6 +226,20 @@ class StockService:
|
||||
self._save_watchlist()
|
||||
return {"status": "success"}
|
||||
|
||||
def update_target(self, stock_code: str, target_market_value_min: float = None, target_market_value_max: float = None):
|
||||
"""更新股票的目标市值"""
|
||||
if stock_code not in self.watchlist:
|
||||
return {"error": "股票不在监控列表中"}
|
||||
|
||||
self.watchlist[stock_code] = {
|
||||
"target_market_value": {
|
||||
"min": target_market_value_min,
|
||||
"max": target_market_value_max
|
||||
}
|
||||
}
|
||||
self._save_watchlist()
|
||||
return {"status": "success"}
|
||||
|
||||
def get_index_info(self):
|
||||
"""获取主要指数数据"""
|
||||
try:
|
||||
|
||||
@ -642,8 +642,13 @@
|
||||
<!-- AI价值投资分析模块 -->
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header bg-light">
|
||||
<i class="bi bi-robot"></i> AI价值投资分析
|
||||
<div class="card-header bg-light d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<i class="bi bi-robot"></i> AI价值投资分析
|
||||
</div>
|
||||
<button class="btn btn-outline-primary btn-sm" onclick="refreshAIAnalysis()" id="refreshAIBtn">
|
||||
<i class="bi bi-arrow-repeat"></i> 更新分析
|
||||
</button>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="aiAnalysisError" class="alert alert-danger d-none">
|
||||
@ -785,6 +790,203 @@
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<!-- 编辑目标市值弹窗 -->
|
||||
<div class="modal fade" id="editTargetModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">编辑监控目标</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="editTargetForm">
|
||||
<input type="hidden" id="editStockCode" name="stock_code">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">目标市值区间 (亿元)</label>
|
||||
<div class="input-group">
|
||||
<input type="number" step="0.01" class="form-control" id="editTargetMin"
|
||||
name="target_market_value_min" placeholder="最小值">
|
||||
<span class="input-group-text">-</span>
|
||||
<input type="number" step="0.01" class="form-control" id="editTargetMax"
|
||||
name="target_market_value_max" placeholder="最大值">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
|
||||
<button type="button" class="btn btn-primary" onclick="updateTarget()">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 道德经分析弹窗 -->
|
||||
<div class="modal fade" id="taoAnalysisModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">道德经分析</h5>
|
||||
<div class="ms-auto me-2">
|
||||
<button type="button" class="btn btn-outline-primary btn-sm" onclick="refreshTaoAnalysis()">
|
||||
<i class="bi bi-arrow-clockwise"></i> 更新分析
|
||||
</button>
|
||||
</div>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div id="taoAnalysisError" class="alert alert-danger d-none">
|
||||
<!-- 错误信息将在这里显示 -->
|
||||
</div>
|
||||
<div id="taoAnalysisLoading" class="text-center py-4 d-none">
|
||||
<div class="spinner-border text-success" role="status">
|
||||
<span class="visually-hidden">分析中...</span>
|
||||
</div>
|
||||
<div class="mt-2 text-muted">以道德经智慧分析中,请稍候...</div>
|
||||
</div>
|
||||
<div id="taoAnalysisContent">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header bg-light">
|
||||
<i class="bi bi-book"></i> 道德经视角
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="taoPhilosophy" class="mb-4">
|
||||
<!-- 道德经哲学分析将在这里显示 -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mb-4">
|
||||
<div class="card-header bg-light">
|
||||
<i class="bi bi-building"></i> 企业道德评估
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="businessEthics" class="mb-4">
|
||||
<!-- 企业道德评估将在这里显示 -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header bg-light">
|
||||
<i class="bi bi-lightbulb"></i> 投资建议
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="taoAdvice">
|
||||
<!-- 基于道德经的投资建议将在这里显示 -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 价值投资大咖分析弹窗 -->
|
||||
<div class="modal fade" id="masterAnalysisModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">价值投资大咖分析</h5>
|
||||
<div class="ms-auto me-2">
|
||||
<button type="button" class="btn btn-outline-primary btn-sm" onclick="refreshMasterAnalysis()">
|
||||
<i class="bi bi-arrow-clockwise"></i> 更新分析
|
||||
</button>
|
||||
</div>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div id="masterAnalysisError" class="alert alert-danger d-none">
|
||||
<!-- 错误信息将在这里显示 -->
|
||||
</div>
|
||||
<div id="masterAnalysisLoading" class="text-center py-4 d-none">
|
||||
<div class="spinner-border text-warning" role="status">
|
||||
<span class="visually-hidden">分析中...</span>
|
||||
</div>
|
||||
<div class="mt-2 text-muted">大咖们正在分析,请稍候...</div>
|
||||
</div>
|
||||
<div id="masterAnalysisContent">
|
||||
<!-- 巴菲特分析 -->
|
||||
<div class="card mb-4">
|
||||
<div class="card-header bg-light d-flex align-items-center">
|
||||
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/5/51/Warren_Buffett_KU_Visit.jpg/120px-Warren_Buffett_KU_Visit.jpg"
|
||||
class="rounded-circle me-2" style="width: 30px; height: 30px; object-fit: cover;"
|
||||
alt="Warren Buffett">
|
||||
<span>巴菲特视角</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="buffettAnalysis" class="mb-4">
|
||||
<!-- 巴菲特分析将在这里显示 -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 格雷厄姆分析 -->
|
||||
<div class="card mb-4">
|
||||
<div class="card-header bg-light d-flex align-items-center">
|
||||
<img src="https://upload.wikimedia.org/wikipedia/en/thumb/5/5e/Benjamin_Graham.jpg/120px-Benjamin_Graham.jpg"
|
||||
class="rounded-circle me-2" style="width: 30px; height: 30px; object-fit: cover;"
|
||||
alt="Benjamin Graham">
|
||||
<span>格雷厄姆视角</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="grahamAnalysis" class="mb-4">
|
||||
<!-- 格雷厄姆分析将在这里显示 -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 林园分析 -->
|
||||
<div class="card mb-4">
|
||||
<div class="card-header bg-light d-flex align-items-center">
|
||||
<img src="https://pic3.zhimg.com/v2-f6a12dbc2d5f6e7f9c4f2e4e5c9c9c9c_720w.jpg"
|
||||
class="rounded-circle me-2" style="width: 30px; height: 30px; object-fit: cover;"
|
||||
alt="林园">
|
||||
<span>林园视角</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="linYuanAnalysis" class="mb-4">
|
||||
<!-- 林园分析将在这里显示 -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 李大霄分析 -->
|
||||
<div class="card mb-4">
|
||||
<div class="card-header bg-light d-flex align-items-center">
|
||||
<img src="https://img.gelonghui.com/apply/column/20200410/column_20200410112754895_31795.jpg"
|
||||
class="rounded-circle me-2" style="width: 30px; height: 30px; object-fit: cover;"
|
||||
alt="李大霄">
|
||||
<span>李大霄视角</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="liDaxiaoAnalysis" class="mb-4">
|
||||
<!-- 李大霄分析将在这里显示 -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 段永平分析 -->
|
||||
<div class="card">
|
||||
<div class="card-header bg-light d-flex align-items-center">
|
||||
<img src="https://img.caixin.com/2011-05-17/1305626275743167_840_560.jpg"
|
||||
class="rounded-circle me-2" style="width: 30px; height: 30px; object-fit: cover;"
|
||||
alt="段永平">
|
||||
<span>段永平视角</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="duanYongpingAnalysis">
|
||||
<!-- 段永平分析将在这里显示 -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
|
||||
<script>
|
||||
@ -793,6 +995,42 @@
|
||||
let stockData = [];
|
||||
let loadingStocks = new Set();
|
||||
|
||||
// 显示编辑目标市值弹窗
|
||||
function showEditTargetModal(btn) {
|
||||
const stockCode = btn.dataset.stockCode;
|
||||
const targetMin = btn.dataset.targetMin;
|
||||
const targetMax = btn.dataset.targetMax;
|
||||
|
||||
document.getElementById('editStockCode').value = stockCode;
|
||||
document.getElementById('editTargetMin').value = targetMin;
|
||||
document.getElementById('editTargetMax').value = targetMax;
|
||||
|
||||
new bootstrap.Modal(document.getElementById('editTargetModal')).show();
|
||||
}
|
||||
|
||||
// 更新监控目标
|
||||
async function updateTarget() {
|
||||
const form = document.getElementById('editTargetForm');
|
||||
const formData = new FormData(form);
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/update_target', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(await response.text() || '更新失败');
|
||||
}
|
||||
|
||||
bootstrap.Modal.getInstance(document.getElementById('editTargetModal')).hide();
|
||||
await refreshWatchlist(true);
|
||||
} catch (error) {
|
||||
console.error('更新目标失败:', error);
|
||||
alert('更新目标失败:' + error.message);
|
||||
}
|
||||
}
|
||||
|
||||
// 添加排序功能
|
||||
document.querySelectorAll('.sortable').forEach(header => {
|
||||
header.addEventListener('click', () => {
|
||||
@ -910,9 +1148,12 @@
|
||||
function renderStockList(data) {
|
||||
const stockTableBody = document.getElementById('stockTableBody');
|
||||
if (!stockTableBody) return;
|
||||
|
||||
// 清空现有内容
|
||||
stockTableBody.innerHTML = '';
|
||||
|
||||
if (!data || data.length === 0) {
|
||||
// 检查数据是否为空
|
||||
if (!data || !Array.isArray(data) || data.length === 0) {
|
||||
const emptyRow = document.createElement('tr');
|
||||
emptyRow.innerHTML = '<td colspan="18" class="text-center text-muted py-4">暂无监控的股票</td>';
|
||||
stockTableBody.appendChild(emptyRow);
|
||||
@ -921,14 +1162,15 @@
|
||||
}
|
||||
|
||||
// 排序数据
|
||||
let sortedData = [...data];
|
||||
if (currentSortField) {
|
||||
data.sort((a, b) => {
|
||||
sortedData.sort((a, b) => {
|
||||
let aValue = parseFloat(a.stock_info[currentSortField]);
|
||||
let bValue = parseFloat(b.stock_info[currentSortField]);
|
||||
|
||||
// 处理无效值
|
||||
if (aValue === null || aValue === undefined || isNaN(aValue)) aValue = -Infinity;
|
||||
if (bValue === null || bValue === undefined || isNaN(bValue)) bValue = -Infinity;
|
||||
if (isNaN(aValue)) aValue = -Infinity;
|
||||
if (isNaN(bValue)) bValue = -Infinity;
|
||||
|
||||
// 数值比较
|
||||
const comparison = aValue - bValue;
|
||||
@ -936,8 +1178,11 @@
|
||||
});
|
||||
}
|
||||
|
||||
data.forEach(item => {
|
||||
// 渲染每一行
|
||||
sortedData.forEach(item => {
|
||||
const { stock_info, targets } = item;
|
||||
if (!stock_info) return; // 跳过无效数据
|
||||
|
||||
const row = document.createElement('tr');
|
||||
row.setAttribute('data-stock-code', stock_info.code);
|
||||
|
||||
@ -951,10 +1196,29 @@
|
||||
<a href="javascript:void(0)" onclick="showCompanyDetail('${stock_info.code}')" class="text-primary">
|
||||
${stock_info.name || '-'}
|
||||
</a>
|
||||
<button class="btn btn-link btn-sm p-0 ms-2 text-danger"
|
||||
onclick="showTaoAnalysis('${stock_info.code}')"
|
||||
title="道德经分析">
|
||||
<i class="bi bi-yin-yang"></i>
|
||||
</button>
|
||||
<button class="btn btn-link btn-sm p-0 ms-2 text-dark"
|
||||
onclick="showMasterAnalysis('${stock_info.code}')"
|
||||
title="价值投资大咖分析">
|
||||
<i class="bi bi-person-fill"></i>
|
||||
</button>
|
||||
</td>
|
||||
<td>${formatNumber(stock_info.price)}</td>
|
||||
<td>${formatPercent(stock_info.change_percent)}</td>
|
||||
<td>${formatTargetRange(targets.target_market_value)}</td>
|
||||
<td>${formatTargetRange(targets.target_market_value)}
|
||||
<button class="btn btn-link btn-sm p-0 ms-2 text-primary edit-target-btn"
|
||||
data-stock-code="${stock_info.code}"
|
||||
data-target-min="${targets.target_market_value?.min || ''}"
|
||||
data-target-max="${targets.target_market_value?.max || ''}"
|
||||
onclick="showEditTargetModal(this)"
|
||||
title="编辑目标市值">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</button>
|
||||
</td>
|
||||
<td>${formatNumber(stock_info.market_value, true)}</td>
|
||||
<td>${formatNumber(stock_info.pe_ratio, true)}</td>
|
||||
<td>${formatNumber(stock_info.pb_ratio, true)}</td>
|
||||
@ -981,47 +1245,6 @@
|
||||
document.getElementById('stockCount').textContent = data.length;
|
||||
}
|
||||
|
||||
// 更新单个股票数据
|
||||
function updateStockData(stockData) {
|
||||
const row = document.querySelector(`tr[data-stock-code="${stockData.stock_info.code}"]`);
|
||||
if (!row) return;
|
||||
|
||||
const { stock_info, targets } = stockData;
|
||||
|
||||
// 检查市值状态
|
||||
const marketValueStatus = checkMarketValueStatus(stock_info.market_value, targets.target_market_value);
|
||||
const marketValueIcon = getMarketValueIcon(marketValueStatus);
|
||||
|
||||
row.innerHTML = `
|
||||
<td>${stock_info.code}${marketValueIcon}</td>
|
||||
<td>
|
||||
<a href="javascript:void(0)" onclick="showCompanyDetail('${stock_info.code}')" class="text-primary">
|
||||
${stock_info.name || '-'}
|
||||
</a>
|
||||
</td>
|
||||
<td>${formatNumber(stock_info.price)}</td>
|
||||
<td>${formatPercent(stock_info.change_percent)}</td>
|
||||
<td>${formatTargetRange(stockData.targets.target_market_value)}</td>
|
||||
<td>${formatNumber(stock_info.market_value, true)}</td>
|
||||
<td>${formatNumber(stock_info.pe_ratio, true)}</td>
|
||||
<td>${formatNumber(stock_info.pb_ratio, true)}</td>
|
||||
<td>${formatNumber(stock_info.ps_ratio, true)}</td>
|
||||
<td>${formatPercent(stock_info.dividend_yield)}</td>
|
||||
<td>${formatPercent(stock_info.roe)}</td>
|
||||
<td>${formatPercent(stock_info.gross_profit_margin)}</td>
|
||||
<td>${formatPercent(stock_info.net_profit_margin)}</td>
|
||||
<td>${formatPercent(stock_info.debt_to_assets, false, true)}</td>
|
||||
<td>${formatPercent(stock_info.net_profit_yoy)}</td>
|
||||
<td>${formatNumber(stock_info.bps, true)}</td>
|
||||
<td>${formatNumber(stock_info.ocfps)}</td>
|
||||
<td>
|
||||
<button class="btn btn-sm btn-danger remove-btn" data-stock-code="${stock_info.code}">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
</td>
|
||||
`;
|
||||
}
|
||||
|
||||
// 刷新监控列表
|
||||
async function refreshWatchlist(forceRefresh = false) {
|
||||
try {
|
||||
@ -1029,32 +1252,72 @@
|
||||
if (!response.ok) throw new Error('获取监控列表失败');
|
||||
|
||||
const data = await response.json();
|
||||
if (!Array.isArray(data)) {
|
||||
throw new Error('返回数据格式错误');
|
||||
}
|
||||
|
||||
stockData = data; // 更新全局数据
|
||||
renderStockList(data);
|
||||
|
||||
// 异步加载每个股票的详细数据
|
||||
data.forEach(item => {
|
||||
loadStockData(item.stock_info.code, forceRefresh);
|
||||
if (item && item.stock_info && item.stock_info.code) {
|
||||
loadStockData(item.stock_info.code, forceRefresh);
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('刷新数据失败:', error);
|
||||
alert('刷新数据失败:' + error.message);
|
||||
// 显示错误信息
|
||||
const stockTableBody = document.getElementById('stockTableBody');
|
||||
if (stockTableBody) {
|
||||
stockTableBody.innerHTML = `
|
||||
<tr>
|
||||
<td colspan="18" class="text-center text-danger">
|
||||
<i class="bi bi-exclamation-triangle"></i>
|
||||
加载数据失败:${error.message}
|
||||
</td>
|
||||
</tr>
|
||||
`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 异步加载股票数据
|
||||
// 更新单个股票数据
|
||||
async function loadStockData(stockCode, forceRefresh = false) {
|
||||
if (!stockCode || loadingStocks.has(stockCode)) return;
|
||||
|
||||
try {
|
||||
loadingStocks.add(stockCode);
|
||||
const url = `/api/stock_info/${stockCode}${forceRefresh ? '?force_refresh=true' : ''}`;
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) throw new Error('获取股票数据失败');
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('获取股票数据失败');
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
if (data.error) throw new Error(data.error);
|
||||
if (data.error) {
|
||||
throw new Error(data.error);
|
||||
}
|
||||
|
||||
updateStockData(data);
|
||||
// 更新全局数据中的股票信息
|
||||
const index = stockData.findIndex(item => item.stock_info.code === stockCode);
|
||||
if (index !== -1) {
|
||||
stockData[index] = data;
|
||||
renderStockList(stockData);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`加载股票 ${stockCode} 数据失败:`, error);
|
||||
// 在界面上显示错误状态
|
||||
const row = document.querySelector(`tr[data-stock-code="${stockCode}"]`);
|
||||
if (row) {
|
||||
const cells = row.getElementsByTagName('td');
|
||||
for (let i = 2; i < cells.length - 1; i++) {
|
||||
cells[i].innerHTML = '<span class="text-danger">加载失败</span>';
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
loadingStocks.delete(stockCode);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1116,6 +1379,12 @@
|
||||
removeStock(stockCode);
|
||||
}
|
||||
});
|
||||
|
||||
// 移除DataTable初始化代码,因为我们使用原生表格排序
|
||||
|
||||
// 初始化指数数据
|
||||
refreshIndexData();
|
||||
setInterval(refreshIndexData, 60000); // 每分钟更新一次
|
||||
});
|
||||
|
||||
// 获取指数数据
|
||||
@ -1217,6 +1486,7 @@
|
||||
// 显示公司详情弹窗
|
||||
async function showCompanyDetail(stockCode) {
|
||||
const modal = new bootstrap.Modal(document.getElementById('companyModal'));
|
||||
document.getElementById('companyModal').setAttribute('data-stock-code', stockCode);
|
||||
modal.show();
|
||||
|
||||
// 显示加载状态
|
||||
@ -1509,6 +1779,235 @@
|
||||
zeroRecords: "暂无数据"
|
||||
}
|
||||
});
|
||||
|
||||
// 刷新AI分析
|
||||
async function refreshAIAnalysis() {
|
||||
const stockCode = document.querySelector('#companyModal').getAttribute('data-stock-code');
|
||||
if (!stockCode) return;
|
||||
|
||||
const refreshBtn = document.getElementById('refreshAIBtn');
|
||||
const originalText = refreshBtn.innerHTML;
|
||||
refreshBtn.innerHTML = '<i class="bi bi-arrow-repeat"></i> 分析中...';
|
||||
refreshBtn.disabled = true;
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/ai_analysis/${stockCode}?force_refresh=true`);
|
||||
if (!response.ok) {
|
||||
throw new Error(await response.text() || '更新失败');
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
if (result.error) {
|
||||
throw new Error(result.error);
|
||||
}
|
||||
|
||||
// 更新AI分析显示
|
||||
document.getElementById('investmentSuggestion').innerHTML = `
|
||||
<div class="mb-2"><strong>总体建议:</strong>${result.investment_suggestion.summary || '-'}</div>
|
||||
<div class="mb-2"><strong>建议操作:</strong>${result.investment_suggestion.action || '-'}</div>
|
||||
<div><strong>关注重点:</strong>
|
||||
<p class="mb-0">${result.investment_suggestion.key_points || '-'}</p>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const priceRange = result.price_analysis?.合理价格区间 || [];
|
||||
document.getElementById('reasonablePriceRange').innerHTML = `
|
||||
<div class="mb-2">${priceRange[0] || '-'} - ${priceRange[1] || '-'} 元</div>
|
||||
`;
|
||||
|
||||
const marketValue = result.price_analysis?.目标市值区间 || [];
|
||||
document.getElementById('targetMarketValue').innerHTML = `
|
||||
<div class="mb-2">${marketValue[0] || '-'} - ${marketValue[1] || '-'} 亿元</div>
|
||||
`;
|
||||
|
||||
document.getElementById('valuationAnalysis').innerHTML = `
|
||||
<div class="mb-2">${result.analysis?.估值分析 || '-'}</div>
|
||||
`;
|
||||
|
||||
document.getElementById('financialHealth').innerHTML = `
|
||||
<div>${result.analysis?.财务健康状况 || '-'}</div>
|
||||
`;
|
||||
|
||||
document.getElementById('growthPotential').innerHTML = `
|
||||
<div>${result.analysis?.成长潜力 || '-'}</div>
|
||||
`;
|
||||
|
||||
document.getElementById('riskAssessment').innerHTML = `
|
||||
<div>${result.analysis?.风险评估 || '-'}</div>
|
||||
`;
|
||||
|
||||
} catch (error) {
|
||||
console.error('更新AI分析失败:', error);
|
||||
alert('更新AI分析失败:' + error.message);
|
||||
} finally {
|
||||
refreshBtn.innerHTML = originalText;
|
||||
refreshBtn.disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 显示道德经分析弹窗
|
||||
async function showTaoAnalysis(stockCode) {
|
||||
const modal = new bootstrap.Modal(document.getElementById('taoAnalysisModal'));
|
||||
document.getElementById('taoAnalysisModal').setAttribute('data-stock-code', stockCode);
|
||||
modal.show();
|
||||
|
||||
// 显示加载状态
|
||||
document.getElementById('taoAnalysisError').classList.add('d-none');
|
||||
document.getElementById('taoAnalysisLoading').classList.remove('d-none');
|
||||
document.getElementById('taoAnalysisContent').classList.add('d-none');
|
||||
|
||||
try {
|
||||
// 获取道德经分析数据
|
||||
const response = await fetch(`/api/tao_analysis/${stockCode}`);
|
||||
const data = await response.json();
|
||||
|
||||
if (data.error) {
|
||||
document.getElementById('taoAnalysisError').textContent = data.error;
|
||||
document.getElementById('taoAnalysisError').classList.remove('d-none');
|
||||
document.getElementById('taoAnalysisLoading').classList.add('d-none');
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新道德经分析显示
|
||||
const formatContent = (content) => {
|
||||
if (typeof content === 'string') {
|
||||
return content.replace(/\n/g, '<br>');
|
||||
} else if (content && typeof content === 'object') {
|
||||
return JSON.stringify(content, null, 2).replace(/\n/g, '<br>');
|
||||
}
|
||||
return String(content || '-');
|
||||
};
|
||||
|
||||
document.getElementById('taoPhilosophy').innerHTML = formatContent(data.tao_philosophy);
|
||||
document.getElementById('businessEthics').innerHTML = formatContent(data.business_ethics);
|
||||
document.getElementById('taoAdvice').innerHTML = formatContent(data.investment_advice);
|
||||
|
||||
document.getElementById('taoAnalysisLoading').classList.add('d-none');
|
||||
document.getElementById('taoAnalysisContent').classList.remove('d-none');
|
||||
} catch (error) {
|
||||
console.error('获取道德经分析失败:', error);
|
||||
document.getElementById('taoAnalysisError').textContent = error.message || '获取道德经分析失败,请稍后重试';
|
||||
document.getElementById('taoAnalysisError').classList.remove('d-none');
|
||||
document.getElementById('taoAnalysisLoading').classList.add('d-none');
|
||||
document.getElementById('taoAnalysisContent').classList.add('d-none');
|
||||
}
|
||||
}
|
||||
|
||||
// 显示价值投资大咖分析弹窗
|
||||
async function showMasterAnalysis(stockCode) {
|
||||
const modal = new bootstrap.Modal(document.getElementById('masterAnalysisModal'));
|
||||
document.getElementById('masterAnalysisModal').setAttribute('data-stock-code', stockCode);
|
||||
modal.show();
|
||||
|
||||
// 显示加载状态
|
||||
document.getElementById('masterAnalysisError').classList.add('d-none');
|
||||
document.getElementById('masterAnalysisLoading').classList.remove('d-none');
|
||||
document.getElementById('masterAnalysisContent').classList.add('d-none');
|
||||
|
||||
try {
|
||||
// 获取价值投资大咖分析数据
|
||||
const response = await fetch(`/api/master_analysis/${stockCode}`);
|
||||
const data = await response.json();
|
||||
|
||||
if (data.error) {
|
||||
document.getElementById('masterAnalysisError').textContent = data.error;
|
||||
document.getElementById('masterAnalysisError').classList.remove('d-none');
|
||||
document.getElementById('masterAnalysisLoading').classList.add('d-none');
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新各个大咖的分析显示
|
||||
const formatContent = (content) => {
|
||||
if (typeof content === 'string') {
|
||||
return content.replace(/\n/g, '<br>');
|
||||
} else if (content && typeof content === 'object') {
|
||||
return JSON.stringify(content, null, 2).replace(/\n/g, '<br>');
|
||||
}
|
||||
return String(content || '-');
|
||||
};
|
||||
|
||||
document.getElementById('buffettAnalysis').innerHTML = formatContent(data.buffett_analysis);
|
||||
document.getElementById('grahamAnalysis').innerHTML = formatContent(data.graham_analysis);
|
||||
document.getElementById('linYuanAnalysis').innerHTML = formatContent(data.lin_yuan_analysis);
|
||||
document.getElementById('liDaxiaoAnalysis').innerHTML = formatContent(data.li_daxiao_analysis);
|
||||
document.getElementById('duanYongpingAnalysis').innerHTML = formatContent(data.duan_yongping_analysis);
|
||||
|
||||
document.getElementById('masterAnalysisLoading').classList.add('d-none');
|
||||
document.getElementById('masterAnalysisContent').classList.remove('d-none');
|
||||
} catch (error) {
|
||||
console.error('获取价值投资大咖分析失败:', error);
|
||||
document.getElementById('masterAnalysisError').textContent = error.message || '获取价值投资大咖分析失败,请稍后重试';
|
||||
document.getElementById('masterAnalysisError').classList.remove('d-none');
|
||||
document.getElementById('masterAnalysisLoading').classList.add('d-none');
|
||||
document.getElementById('masterAnalysisContent').classList.add('d-none');
|
||||
}
|
||||
}
|
||||
|
||||
async function refreshTaoAnalysis() {
|
||||
const stockCode = document.querySelector('#taoAnalysisModal').getAttribute('data-stock-code');
|
||||
if (!stockCode) return;
|
||||
|
||||
// 显示加载状态
|
||||
document.querySelector('#taoAnalysisLoading').classList.remove('d-none');
|
||||
document.querySelector('#taoAnalysisContent').classList.add('d-none');
|
||||
document.querySelector('#taoAnalysisError').classList.add('d-none');
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/tao_analysis/${stockCode}?force_refresh=true`);
|
||||
const data = await response.json();
|
||||
|
||||
if (data.error) {
|
||||
throw new Error(data.error);
|
||||
}
|
||||
|
||||
// 更新内容
|
||||
document.querySelector('#taoPhilosophy').innerHTML = formatContent(data.tao_philosophy);
|
||||
document.querySelector('#businessEthics').innerHTML = formatContent(data.business_ethics);
|
||||
document.querySelector('#investmentAdvice').innerHTML = formatContent(data.investment_advice);
|
||||
|
||||
// 显示内容
|
||||
document.querySelector('#taoAnalysisContent').classList.remove('d-none');
|
||||
} catch (error) {
|
||||
document.querySelector('#taoAnalysisError').textContent = `分析失败: ${error.message}`;
|
||||
document.querySelector('#taoAnalysisError').classList.remove('d-none');
|
||||
} finally {
|
||||
document.querySelector('#taoAnalysisLoading').classList.add('d-none');
|
||||
}
|
||||
}
|
||||
|
||||
async function refreshMasterAnalysis() {
|
||||
const stockCode = document.querySelector('#masterAnalysisModal').getAttribute('data-stock-code');
|
||||
if (!stockCode) return;
|
||||
|
||||
// 显示加载状态
|
||||
document.querySelector('#masterAnalysisLoading').classList.remove('d-none');
|
||||
document.querySelector('#masterAnalysisContent').classList.add('d-none');
|
||||
document.querySelector('#masterAnalysisError').classList.add('d-none');
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/master_analysis/${stockCode}?force_refresh=true`);
|
||||
const data = await response.json();
|
||||
|
||||
if (data.error) {
|
||||
throw new Error(data.error);
|
||||
}
|
||||
|
||||
// 更新内容
|
||||
document.querySelector('#buffettAnalysis').innerHTML = formatContent(data.buffett_analysis);
|
||||
document.querySelector('#grahamAnalysis').innerHTML = formatContent(data.graham_analysis);
|
||||
document.querySelector('#linYuanAnalysis').innerHTML = formatContent(data.lin_yuan_analysis);
|
||||
document.querySelector('#liDaxiaoAnalysis').innerHTML = formatContent(data.li_daxiao_analysis);
|
||||
document.querySelector('#duanYongpingAnalysis').innerHTML = formatContent(data.duan_yongping_analysis);
|
||||
|
||||
// 显示内容
|
||||
document.querySelector('#masterAnalysisContent').classList.remove('d-none');
|
||||
} catch (error) {
|
||||
document.querySelector('#masterAnalysisError').textContent = `分析失败: ${error.message}`;
|
||||
document.querySelector('#masterAnalysisError').classList.remove('d-none');
|
||||
} finally {
|
||||
document.querySelector('#masterAnalysisLoading').classList.add('d-none');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
178
config.json
Normal file
178
config.json
Normal file
@ -0,0 +1,178 @@
|
||||
{
|
||||
"watchlist": {
|
||||
"300059": {
|
||||
"target_market_value": {
|
||||
"min": 2500.0,
|
||||
"max": 2800.0
|
||||
}
|
||||
},
|
||||
"601318": {
|
||||
"target_market_value": {
|
||||
"min": 8000.0,
|
||||
"max": 9500.0
|
||||
}
|
||||
},
|
||||
"000963": {
|
||||
"target_market_value": {
|
||||
"min": 500.0,
|
||||
"max": 650.0
|
||||
}
|
||||
},
|
||||
"002415": {
|
||||
"target_market_value": {
|
||||
"min": 2000.0,
|
||||
"max": 2200.0
|
||||
}
|
||||
},
|
||||
"000423": {
|
||||
"target_market_value": {
|
||||
"min": 270.0,
|
||||
"max": 330.0
|
||||
}
|
||||
},
|
||||
"000538": {
|
||||
"target_market_value": {
|
||||
"min": 807.0,
|
||||
"max": 1210.0
|
||||
}
|
||||
},
|
||||
"600085": {
|
||||
"target_market_value": {
|
||||
"min": 336.0,
|
||||
"max": 429.0
|
||||
}
|
||||
},
|
||||
"002714": {
|
||||
"target_market_value": {
|
||||
"min": 1650.0,
|
||||
"max": 2200.0
|
||||
}
|
||||
},
|
||||
"002007": {
|
||||
"target_market_value": {
|
||||
"min": 240.0,
|
||||
"max": 288.0
|
||||
}
|
||||
},
|
||||
"600132": {
|
||||
"target_market_value": {
|
||||
"min": 220.0,
|
||||
"max": 290.0
|
||||
}
|
||||
},
|
||||
"002049": {
|
||||
"target_market_value": {
|
||||
"min": 360.0,
|
||||
"max": 480.0
|
||||
}
|
||||
},
|
||||
"600436": {
|
||||
"target_market_value": {
|
||||
"min": 960.0,
|
||||
"max": 1080.0
|
||||
}
|
||||
},
|
||||
"002216": {
|
||||
"target_market_value": {
|
||||
"min": 72.0,
|
||||
"max": 97.0
|
||||
}
|
||||
},
|
||||
"601966": {
|
||||
"target_market_value": {
|
||||
"min": 220.0,
|
||||
"max": 280.0
|
||||
}
|
||||
},
|
||||
"603195": {
|
||||
"target_market_value": {
|
||||
"min": 730.0,
|
||||
"max": 950.0
|
||||
}
|
||||
},
|
||||
"000001": {
|
||||
"target_market_value": {
|
||||
"min": 1800.0,
|
||||
"max": 2500.0
|
||||
}
|
||||
},
|
||||
"600867": {
|
||||
"target_market_value": {
|
||||
"min": 120.0,
|
||||
"max": 160.0
|
||||
}
|
||||
},
|
||||
"603087": {
|
||||
"target_market_value": {
|
||||
"min": 170.0,
|
||||
"max": 283.0
|
||||
}
|
||||
},
|
||||
"603290": {
|
||||
"target_market_value": {
|
||||
"min": 150.0,
|
||||
"max": 200.0
|
||||
}
|
||||
},
|
||||
"600332": {
|
||||
"target_market_value": {
|
||||
"min": 380.0,
|
||||
"max": 460.0
|
||||
}
|
||||
},
|
||||
"300124": {
|
||||
"target_market_value": {
|
||||
"min": 1200.0,
|
||||
"max": 1400.0
|
||||
}
|
||||
},
|
||||
"300146": {
|
||||
"target_market_value": {
|
||||
"min": 150.0,
|
||||
"max": 200.0
|
||||
}
|
||||
},
|
||||
"000999": {
|
||||
"target_market_value": {
|
||||
"min": 450.0,
|
||||
"max": 580.0
|
||||
}
|
||||
},
|
||||
"002466": {
|
||||
"target_market_value": {
|
||||
"min": 330.0,
|
||||
"max": 415.0
|
||||
}
|
||||
},
|
||||
"300009": {
|
||||
"target_market_value": {
|
||||
"min": 120.0,
|
||||
"max": 160.0
|
||||
}
|
||||
},
|
||||
"300743": {
|
||||
"target_market_value": {
|
||||
"min": null,
|
||||
"max": null
|
||||
}
|
||||
},
|
||||
"603511": {
|
||||
"target_market_value": {
|
||||
"min": null,
|
||||
"max": null
|
||||
}
|
||||
},
|
||||
"688553": {
|
||||
"target_market_value": {
|
||||
"min": null,
|
||||
"max": null
|
||||
}
|
||||
},
|
||||
"600030": {
|
||||
"target_market_value": {
|
||||
"min": 3200.0,
|
||||
"max": 3600.0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,6 +0,0 @@
|
||||
{
|
||||
"watchlist": {},
|
||||
"tushare_token": "your_tushare_token_here",
|
||||
"ai_api_key": "your_ai_api_key_here",
|
||||
"ai_model_id": "your_ai_model_id_here"
|
||||
}
|
||||
12
config.template.py
Normal file
12
config.template.py
Normal file
@ -0,0 +1,12 @@
|
||||
import os
|
||||
|
||||
# 基础配置
|
||||
class Config:
|
||||
# 项目根目录
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
# Tushare API配置
|
||||
TUSHARE_TOKEN = 'your_tushare_token_here'
|
||||
|
||||
# 配置文件路径
|
||||
CONFIG_FILE = os.path.join(BASE_DIR, "config.json")
|
||||
BIN
docs/images/main.png
Normal file
BIN
docs/images/main.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 501 KiB |
@ -1,11 +1,51 @@
|
||||
aiofiles==23.2.1
|
||||
annotated-types==0.7.0
|
||||
anyio==3.7.1
|
||||
beautifulsoup4==4.12.3
|
||||
bs4==0.0.2
|
||||
certifi==2024.12.14
|
||||
charset-normalizer==3.4.1
|
||||
click==8.1.8
|
||||
decorator==5.1.1
|
||||
et_xmlfile==1.0.0
|
||||
fastapi==0.104.1
|
||||
uvicorn==0.24.0
|
||||
python-multipart==0.0.6
|
||||
pydantic==2.10.4
|
||||
requests==2.32.3
|
||||
pandas==2.2.3
|
||||
numpy==2.2.1
|
||||
tushare==1.4.16
|
||||
h11==0.14.0
|
||||
html5lib==1.1
|
||||
idna==3.10
|
||||
Jinja2==3.1.2
|
||||
jsonpath==0.82.2
|
||||
lxml==5.3.0
|
||||
markdown-it-py==3.0.0
|
||||
MarkupSafe==3.0.2
|
||||
mdurl==0.1.2
|
||||
multitasking==0.0.11
|
||||
numpy==2.2.1
|
||||
openpyxl==3.1.5
|
||||
pandas==2.2.3
|
||||
py==1.11.0
|
||||
py_mini_racer==0.6.0
|
||||
pydantic==2.10.4
|
||||
pydantic_core==2.27.2
|
||||
Pygments==2.19.1
|
||||
pypinyin==0.53.0
|
||||
python-dateutil==2.9.0.post0
|
||||
python-multipart==0.0.6
|
||||
pytz==2024.2
|
||||
requests==2.32.3
|
||||
retry==0.9.2
|
||||
rich==13.9.4
|
||||
simplejson==3.19.3
|
||||
six==1.17.0
|
||||
sniffio==1.3.1
|
||||
soupsieve==2.6
|
||||
starlette==0.27.0
|
||||
tabulate==0.9.0
|
||||
tqdm==4.67.1
|
||||
tushare==1.4.16
|
||||
typing_extensions==4.12.2
|
||||
tzdata==2024.2
|
||||
urllib3==2.3.0
|
||||
uvicorn==0.24.0
|
||||
webencodings==0.5.1
|
||||
websocket-client==1.8.0
|
||||
xlrd==2.0.1
|
||||
|
||||
478
stock_cache.json
478
stock_cache.json
@ -4,13 +4,13 @@
|
||||
"stock_info": {
|
||||
"code": "300059",
|
||||
"name": "东方财富",
|
||||
"market_value": 3491.76,
|
||||
"pe_ratio": 42.62,
|
||||
"pb_ratio": 4.54,
|
||||
"ps_ratio": 89.81,
|
||||
"dividend_yield": 0.0018,
|
||||
"price": 22.12,
|
||||
"change_percent": 0.011,
|
||||
"market_value": 3766.43,
|
||||
"pe_ratio": 45.97,
|
||||
"pb_ratio": 4.9,
|
||||
"ps_ratio": 96.88,
|
||||
"dividend_yield": 0.0017,
|
||||
"price": 23.86,
|
||||
"change_percent": 0.0787,
|
||||
"roe": 0.0811,
|
||||
"gross_profit_margin": 0.8372,
|
||||
"net_profit_margin": 2.694,
|
||||
@ -28,20 +28,20 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp": "2025-01-13"
|
||||
"timestamp": "2025-01-15"
|
||||
},
|
||||
"601318": {
|
||||
"data": {
|
||||
"stock_info": {
|
||||
"code": "601318",
|
||||
"name": "中国平安",
|
||||
"market_value": 8848.35,
|
||||
"pe_ratio": 10.33,
|
||||
"pb_ratio": 0.99,
|
||||
"ps_ratio": 0.97,
|
||||
"dividend_yield": 0.0498,
|
||||
"price": 48.59,
|
||||
"change_percent": -0.0074,
|
||||
"market_value": 8988.57,
|
||||
"pe_ratio": 10.49,
|
||||
"pb_ratio": 1.01,
|
||||
"ps_ratio": 0.98,
|
||||
"dividend_yield": 0.0491,
|
||||
"price": 49.36,
|
||||
"change_percent": 0.0158,
|
||||
"roe": 0.1319,
|
||||
"gross_profit_margin": 0,
|
||||
"net_profit_margin": 0.1806,
|
||||
@ -59,20 +59,20 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp": "2025-01-13"
|
||||
"timestamp": "2025-01-15"
|
||||
},
|
||||
"600085": {
|
||||
"data": {
|
||||
"stock_info": {
|
||||
"code": "600085",
|
||||
"name": "同仁堂",
|
||||
"market_value": 507.86,
|
||||
"pe_ratio": 30.43,
|
||||
"pb_ratio": 4.13,
|
||||
"ps_ratio": 2.84,
|
||||
"dividend_yield": 0.027,
|
||||
"price": 37.03,
|
||||
"change_percent": 0.0082,
|
||||
"market_value": 519.24,
|
||||
"pe_ratio": 31.11,
|
||||
"pb_ratio": 4.22,
|
||||
"ps_ratio": 2.91,
|
||||
"dividend_yield": 0.0264,
|
||||
"price": 37.86,
|
||||
"change_percent": 0.0224,
|
||||
"roe": 0.1037,
|
||||
"gross_profit_margin": 0.437,
|
||||
"net_profit_margin": 0.1435,
|
||||
@ -90,20 +90,20 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp": "2025-01-13"
|
||||
"timestamp": "2025-01-15"
|
||||
},
|
||||
"002714": {
|
||||
"data": {
|
||||
"stock_info": {
|
||||
"code": "002714",
|
||||
"name": "牧原股份",
|
||||
"market_value": 1980.25,
|
||||
"market_value": 2023.41,
|
||||
"pe_ratio": 0,
|
||||
"pb_ratio": 2.97,
|
||||
"ps_ratio": 1.79,
|
||||
"dividend_yield": 0.0227,
|
||||
"price": 36.25,
|
||||
"change_percent": 0.0014,
|
||||
"pb_ratio": 3.04,
|
||||
"ps_ratio": 1.83,
|
||||
"dividend_yield": 0.0223,
|
||||
"price": 37.04,
|
||||
"change_percent": 0.0218,
|
||||
"roe": 0.1552,
|
||||
"gross_profit_margin": 0.1727,
|
||||
"net_profit_margin": 0.1162,
|
||||
@ -121,20 +121,20 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp": "2025-01-13"
|
||||
"timestamp": "2025-01-15"
|
||||
},
|
||||
"000538": {
|
||||
"data": {
|
||||
"stock_info": {
|
||||
"code": "000538",
|
||||
"name": "云南白药",
|
||||
"market_value": 1001.86,
|
||||
"pe_ratio": 24.47,
|
||||
"pb_ratio": 2.61,
|
||||
"ps_ratio": 2.56,
|
||||
"dividend_yield": 0.0586,
|
||||
"price": 56.15,
|
||||
"change_percent": -0.0083,
|
||||
"market_value": 1024.17,
|
||||
"pe_ratio": 25.02,
|
||||
"pb_ratio": 2.67,
|
||||
"ps_ratio": 2.62,
|
||||
"dividend_yield": 0.0573,
|
||||
"price": 57.4,
|
||||
"change_percent": 0.0223,
|
||||
"roe": 0.1076,
|
||||
"gross_profit_margin": 0.284,
|
||||
"net_profit_margin": 0.1447,
|
||||
@ -152,20 +152,20 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp": "2025-01-13"
|
||||
"timestamp": "2025-01-15"
|
||||
},
|
||||
"000423": {
|
||||
"data": {
|
||||
"stock_info": {
|
||||
"code": "000423",
|
||||
"name": "东阿阿胶",
|
||||
"market_value": 391.86,
|
||||
"pe_ratio": 34.05,
|
||||
"pb_ratio": 3.95,
|
||||
"ps_ratio": 8.31,
|
||||
"dividend_yield": 0.0481,
|
||||
"price": 60.85,
|
||||
"change_percent": -0.0178,
|
||||
"market_value": 398.75,
|
||||
"pe_ratio": 34.65,
|
||||
"pb_ratio": 4.02,
|
||||
"ps_ratio": 8.46,
|
||||
"dividend_yield": 0.0472,
|
||||
"price": 61.92,
|
||||
"change_percent": 0.0176,
|
||||
"roe": 0.1117,
|
||||
"gross_profit_margin": 0.7413,
|
||||
"net_profit_margin": 0.2661,
|
||||
@ -183,20 +183,20 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp": "2025-01-13"
|
||||
"timestamp": "2025-01-15"
|
||||
},
|
||||
"000963": {
|
||||
"data": {
|
||||
"stock_info": {
|
||||
"code": "000963",
|
||||
"name": "华东医药",
|
||||
"market_value": 567.33,
|
||||
"pe_ratio": 19.98,
|
||||
"pb_ratio": 2.57,
|
||||
"ps_ratio": 1.4,
|
||||
"dividend_yield": 0.0288,
|
||||
"price": 32.34,
|
||||
"change_percent": -0.0089,
|
||||
"market_value": 582.24,
|
||||
"pe_ratio": 20.51,
|
||||
"pb_ratio": 2.64,
|
||||
"ps_ratio": 1.43,
|
||||
"dividend_yield": 0.028,
|
||||
"price": 33.19,
|
||||
"change_percent": 0.0263,
|
||||
"roe": 0.1189,
|
||||
"gross_profit_margin": 0.3255,
|
||||
"net_profit_margin": 0.0814,
|
||||
@ -214,20 +214,20 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp": "2025-01-13"
|
||||
"timestamp": "2025-01-15"
|
||||
},
|
||||
"002415": {
|
||||
"data": {
|
||||
"stock_info": {
|
||||
"code": "002415",
|
||||
"name": "海康威视",
|
||||
"market_value": 2554.83,
|
||||
"pe_ratio": 18.11,
|
||||
"pb_ratio": 3.33,
|
||||
"ps_ratio": 2.86,
|
||||
"dividend_yield": 0.0329,
|
||||
"price": 27.67,
|
||||
"change_percent": -0.0047,
|
||||
"market_value": 2618.54,
|
||||
"pe_ratio": 18.56,
|
||||
"pb_ratio": 3.41,
|
||||
"ps_ratio": 2.93,
|
||||
"dividend_yield": 0.0321,
|
||||
"price": 28.36,
|
||||
"change_percent": 0.0249,
|
||||
"roe": 0.1059,
|
||||
"gross_profit_margin": 0.4476,
|
||||
"net_profit_margin": 0.1371,
|
||||
@ -245,20 +245,20 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp": "2025-01-13"
|
||||
"timestamp": "2025-01-15"
|
||||
},
|
||||
"002007": {
|
||||
"data": {
|
||||
"stock_info": {
|
||||
"code": "002007",
|
||||
"name": "华兰生物",
|
||||
"market_value": 284.92,
|
||||
"pe_ratio": 19.23,
|
||||
"pb_ratio": 2.44,
|
||||
"ps_ratio": 5.33,
|
||||
"dividend_yield": 0.0193,
|
||||
"price": 15.58,
|
||||
"change_percent": -0.0133,
|
||||
"market_value": 291.32,
|
||||
"pe_ratio": 19.66,
|
||||
"pb_ratio": 2.49,
|
||||
"ps_ratio": 5.45,
|
||||
"dividend_yield": 0.0188,
|
||||
"price": 15.93,
|
||||
"change_percent": 0.0225,
|
||||
"roe": 0.0801,
|
||||
"gross_profit_margin": 0.6177,
|
||||
"net_profit_margin": 0.2897,
|
||||
@ -276,20 +276,20 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp": "2025-01-13"
|
||||
"timestamp": "2025-01-15"
|
||||
},
|
||||
"600132": {
|
||||
"data": {
|
||||
"stock_info": {
|
||||
"code": "600132",
|
||||
"name": "重庆啤酒",
|
||||
"market_value": 277.32,
|
||||
"pe_ratio": 20.75,
|
||||
"pb_ratio": 19.67,
|
||||
"ps_ratio": 1.87,
|
||||
"dividend_yield": 0.075,
|
||||
"price": 57.3,
|
||||
"change_percent": 0.0145,
|
||||
"market_value": 281.28,
|
||||
"pe_ratio": 21.04,
|
||||
"pb_ratio": 19.95,
|
||||
"ps_ratio": 1.9,
|
||||
"dividend_yield": 0.074,
|
||||
"price": 58.12,
|
||||
"change_percent": 0.0143,
|
||||
"roe": 0.623,
|
||||
"gross_profit_margin": 0.492,
|
||||
"net_profit_margin": 0.2041,
|
||||
@ -302,25 +302,25 @@
|
||||
},
|
||||
"targets": {
|
||||
"target_market_value": {
|
||||
"min": 225.0,
|
||||
"max": 260.0
|
||||
"min": 220.0,
|
||||
"max": 290.0
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp": "2025-01-13"
|
||||
"timestamp": "2025-01-15"
|
||||
},
|
||||
"002049": {
|
||||
"data": {
|
||||
"stock_info": {
|
||||
"code": "002049",
|
||||
"name": "紫光国微",
|
||||
"market_value": 492.36,
|
||||
"pe_ratio": 19.46,
|
||||
"pb_ratio": 4.1,
|
||||
"ps_ratio": 6.51,
|
||||
"dividend_yield": 0.0116,
|
||||
"price": 57.95,
|
||||
"change_percent": -0.0113,
|
||||
"market_value": 508.67,
|
||||
"pe_ratio": 20.1,
|
||||
"pb_ratio": 4.24,
|
||||
"ps_ratio": 6.72,
|
||||
"dividend_yield": 0.0113,
|
||||
"price": 59.87,
|
||||
"change_percent": 0.0331,
|
||||
"roe": 0.0847,
|
||||
"gross_profit_margin": 0.5681,
|
||||
"net_profit_margin": 0.2383,
|
||||
@ -338,20 +338,20 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp": "2025-01-13"
|
||||
"timestamp": "2025-01-15"
|
||||
},
|
||||
"600436": {
|
||||
"data": {
|
||||
"stock_info": {
|
||||
"code": "600436",
|
||||
"name": "片仔癀",
|
||||
"market_value": 1236.8,
|
||||
"pe_ratio": 44.21,
|
||||
"pb_ratio": 9.28,
|
||||
"ps_ratio": 12.3,
|
||||
"dividend_yield": 0.0169,
|
||||
"price": 205.0,
|
||||
"change_percent": 0.0029,
|
||||
"market_value": 1261.9,
|
||||
"pe_ratio": 45.11,
|
||||
"pb_ratio": 9.47,
|
||||
"ps_ratio": 12.55,
|
||||
"dividend_yield": 0.0166,
|
||||
"price": 209.16,
|
||||
"change_percent": 0.0203,
|
||||
"roe": 0.1961,
|
||||
"gross_profit_margin": 0.4544,
|
||||
"net_profit_margin": 0.3216,
|
||||
@ -369,20 +369,20 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp": "2025-01-13"
|
||||
"timestamp": "2025-01-15"
|
||||
},
|
||||
"002216": {
|
||||
"data": {
|
||||
"stock_info": {
|
||||
"code": "002216",
|
||||
"name": "三全食品",
|
||||
"market_value": 97.77,
|
||||
"pe_ratio": 13.05,
|
||||
"pb_ratio": 2.28,
|
||||
"ps_ratio": 1.39,
|
||||
"dividend_yield": 0.045,
|
||||
"price": 11.12,
|
||||
"change_percent": 0.0091,
|
||||
"market_value": 100.14,
|
||||
"pe_ratio": 13.36,
|
||||
"pb_ratio": 2.34,
|
||||
"ps_ratio": 1.42,
|
||||
"dividend_yield": 0.0439,
|
||||
"price": 11.39,
|
||||
"change_percent": 0.0243,
|
||||
"roe": 0.0914,
|
||||
"gross_profit_margin": 0.2503,
|
||||
"net_profit_margin": 0.0769,
|
||||
@ -396,24 +396,24 @@
|
||||
"targets": {
|
||||
"target_market_value": {
|
||||
"min": 72.0,
|
||||
"max": 96.0
|
||||
"max": 97.0
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp": "2025-01-13"
|
||||
"timestamp": "2025-01-15"
|
||||
},
|
||||
"601966": {
|
||||
"data": {
|
||||
"stock_info": {
|
||||
"code": "601966",
|
||||
"name": "玲珑轮胎",
|
||||
"market_value": 251.87,
|
||||
"pe_ratio": 18.11,
|
||||
"pb_ratio": 1.18,
|
||||
"ps_ratio": 1.25,
|
||||
"dividend_yield": 0.0371,
|
||||
"price": 17.21,
|
||||
"change_percent": -0.0023,
|
||||
"market_value": 257.87,
|
||||
"pe_ratio": 18.54,
|
||||
"pb_ratio": 1.2,
|
||||
"ps_ratio": 1.28,
|
||||
"dividend_yield": 0.0363,
|
||||
"price": 17.62,
|
||||
"change_percent": 0.0238,
|
||||
"roe": 0.0801,
|
||||
"gross_profit_margin": 0.2435,
|
||||
"net_profit_margin": 0.1073,
|
||||
@ -431,20 +431,20 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp": "2025-01-13"
|
||||
"timestamp": "2025-01-15"
|
||||
},
|
||||
"603195": {
|
||||
"data": {
|
||||
"stock_info": {
|
||||
"code": "603195",
|
||||
"name": "公牛集团",
|
||||
"market_value": 861.35,
|
||||
"pe_ratio": 22.26,
|
||||
"pb_ratio": 5.8,
|
||||
"ps_ratio": 5.49,
|
||||
"dividend_yield": 0.0321,
|
||||
"price": 66.66,
|
||||
"change_percent": -0.0141,
|
||||
"market_value": 875.57,
|
||||
"pe_ratio": 22.62,
|
||||
"pb_ratio": 5.9,
|
||||
"ps_ratio": 5.58,
|
||||
"dividend_yield": 0.0316,
|
||||
"price": 67.76,
|
||||
"change_percent": 0.0165,
|
||||
"roe": 0.2228,
|
||||
"gross_profit_margin": 0.4312,
|
||||
"net_profit_margin": 0.2589,
|
||||
@ -462,20 +462,20 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp": "2025-01-13"
|
||||
"timestamp": "2025-01-15"
|
||||
},
|
||||
"000001": {
|
||||
"data": {
|
||||
"stock_info": {
|
||||
"code": "000001",
|
||||
"name": "平安银行",
|
||||
"market_value": 2173.46,
|
||||
"pe_ratio": 4.68,
|
||||
"pb_ratio": 0.52,
|
||||
"ps_ratio": 1.32,
|
||||
"dividend_yield": 0.0862,
|
||||
"price": 11.2,
|
||||
"change_percent": -0.0089,
|
||||
"market_value": 2208.39,
|
||||
"pe_ratio": 4.75,
|
||||
"pb_ratio": 0.53,
|
||||
"ps_ratio": 1.34,
|
||||
"dividend_yield": 0.0848,
|
||||
"price": 11.38,
|
||||
"change_percent": 0.0161,
|
||||
"roe": 0.0825,
|
||||
"gross_profit_margin": 0,
|
||||
"net_profit_margin": 0.3561,
|
||||
@ -488,25 +488,25 @@
|
||||
},
|
||||
"targets": {
|
||||
"target_market_value": {
|
||||
"min": 2300.0,
|
||||
"max": 2800.0
|
||||
"min": 1800.0,
|
||||
"max": 2500.0
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp": "2025-01-13"
|
||||
"timestamp": "2025-01-15"
|
||||
},
|
||||
"600867": {
|
||||
"data": {
|
||||
"stock_info": {
|
||||
"code": "600867",
|
||||
"name": "通化东宝",
|
||||
"market_value": 145.52,
|
||||
"pe_ratio": 12.46,
|
||||
"pb_ratio": 2.33,
|
||||
"ps_ratio": 4.73,
|
||||
"dividend_yield": 0.034,
|
||||
"price": 7.43,
|
||||
"change_percent": 0.0095,
|
||||
"market_value": 150.22,
|
||||
"pe_ratio": 12.86,
|
||||
"pb_ratio": 2.41,
|
||||
"ps_ratio": 4.88,
|
||||
"dividend_yield": 0.033,
|
||||
"price": 7.67,
|
||||
"change_percent": 0.0323,
|
||||
"roe": -0.0097,
|
||||
"gross_profit_margin": 0.7447,
|
||||
"net_profit_margin": -0.0459,
|
||||
@ -524,20 +524,20 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp": "2025-01-13"
|
||||
"timestamp": "2025-01-15"
|
||||
},
|
||||
"603087": {
|
||||
"data": {
|
||||
"stock_info": {
|
||||
"code": "603087",
|
||||
"name": "甘李药业",
|
||||
"market_value": 250.34,
|
||||
"pe_ratio": 73.62,
|
||||
"pb_ratio": 2.3,
|
||||
"ps_ratio": 9.6,
|
||||
"dividend_yield": 0.0168,
|
||||
"price": 41.65,
|
||||
"change_percent": 0.0161,
|
||||
"market_value": 258.16,
|
||||
"pe_ratio": 75.91,
|
||||
"pb_ratio": 2.37,
|
||||
"ps_ratio": 9.9,
|
||||
"dividend_yield": 0.0163,
|
||||
"price": 42.95,
|
||||
"change_percent": 0.0312,
|
||||
"roe": 0.0462,
|
||||
"gross_profit_margin": 0.7536,
|
||||
"net_profit_margin": 0.226,
|
||||
@ -555,20 +555,20 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp": "2025-01-13"
|
||||
"timestamp": "2025-01-15"
|
||||
},
|
||||
"603290": {
|
||||
"data": {
|
||||
"stock_info": {
|
||||
"code": "603290",
|
||||
"name": "斯达半导",
|
||||
"market_value": 193.85,
|
||||
"pe_ratio": 21.29,
|
||||
"pb_ratio": 2.94,
|
||||
"ps_ratio": 5.29,
|
||||
"dividend_yield": 0.0141,
|
||||
"price": 80.95,
|
||||
"change_percent": 0.0021,
|
||||
"market_value": 202.52,
|
||||
"pe_ratio": 22.24,
|
||||
"pb_ratio": 3.07,
|
||||
"ps_ratio": 5.53,
|
||||
"dividend_yield": 0.0135,
|
||||
"price": 84.57,
|
||||
"change_percent": 0.0447,
|
||||
"roe": 0.065,
|
||||
"gross_profit_margin": 0.3169,
|
||||
"net_profit_margin": 0.1773,
|
||||
@ -586,20 +586,20 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp": "2025-01-13"
|
||||
"timestamp": "2025-01-15"
|
||||
},
|
||||
"600332": {
|
||||
"data": {
|
||||
"stock_info": {
|
||||
"code": "600332",
|
||||
"name": "白云山",
|
||||
"market_value": 433.11,
|
||||
"pe_ratio": 10.68,
|
||||
"pb_ratio": 1.22,
|
||||
"ps_ratio": 0.57,
|
||||
"dividend_yield": 0.0431,
|
||||
"price": 26.64,
|
||||
"change_percent": 0.0019,
|
||||
"market_value": 442.54,
|
||||
"pe_ratio": 10.91,
|
||||
"pb_ratio": 1.24,
|
||||
"ps_ratio": 0.59,
|
||||
"dividend_yield": 0.0422,
|
||||
"price": 27.22,
|
||||
"change_percent": 0.0218,
|
||||
"roe": 0.0888,
|
||||
"gross_profit_margin": 0.177,
|
||||
"net_profit_margin": 0.0557,
|
||||
@ -617,20 +617,20 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp": "2025-01-13"
|
||||
"timestamp": "2025-01-15"
|
||||
},
|
||||
"300124": {
|
||||
"data": {
|
||||
"stock_info": {
|
||||
"code": "300124",
|
||||
"name": "汇川技术",
|
||||
"market_value": 1570.93,
|
||||
"pe_ratio": 33.13,
|
||||
"pb_ratio": 5.86,
|
||||
"ps_ratio": 5.16,
|
||||
"dividend_yield": 0.0077,
|
||||
"price": 58.35,
|
||||
"change_percent": -0.0273,
|
||||
"market_value": 1663.81,
|
||||
"pe_ratio": 35.09,
|
||||
"pb_ratio": 6.21,
|
||||
"ps_ratio": 5.47,
|
||||
"dividend_yield": 0.0072,
|
||||
"price": 61.8,
|
||||
"change_percent": 0.0591,
|
||||
"roe": 0.1316,
|
||||
"gross_profit_margin": 0.3102,
|
||||
"net_profit_margin": 0.1345,
|
||||
@ -648,20 +648,20 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp": "2025-01-13"
|
||||
"timestamp": "2025-01-15"
|
||||
},
|
||||
"300146": {
|
||||
"data": {
|
||||
"stock_info": {
|
||||
"code": "300146",
|
||||
"name": "汤臣倍健",
|
||||
"market_value": 192.2,
|
||||
"pe_ratio": 11.01,
|
||||
"pb_ratio": 1.7,
|
||||
"ps_ratio": 2.04,
|
||||
"dividend_yield": 0.0789,
|
||||
"price": 11.3,
|
||||
"change_percent": 0.0116,
|
||||
"market_value": 198.49,
|
||||
"pe_ratio": 11.37,
|
||||
"pb_ratio": 1.75,
|
||||
"ps_ratio": 2.11,
|
||||
"dividend_yield": 0.0764,
|
||||
"price": 11.67,
|
||||
"change_percent": 0.0327,
|
||||
"roe": 0.074,
|
||||
"gross_profit_margin": 0.6793,
|
||||
"net_profit_margin": 0.1504,
|
||||
@ -679,20 +679,20 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp": "2025-01-13"
|
||||
"timestamp": "2025-01-15"
|
||||
},
|
||||
"000999": {
|
||||
"data": {
|
||||
"stock_info": {
|
||||
"code": "000999",
|
||||
"name": "华润三九",
|
||||
"market_value": 546.6,
|
||||
"pe_ratio": 19.16,
|
||||
"pb_ratio": 2.84,
|
||||
"ps_ratio": 2.21,
|
||||
"dividend_yield": 0.0506,
|
||||
"price": 42.56,
|
||||
"change_percent": -0.0014,
|
||||
"market_value": 557.39,
|
||||
"pe_ratio": 19.54,
|
||||
"pb_ratio": 2.9,
|
||||
"ps_ratio": 2.25,
|
||||
"dividend_yield": 0.0496,
|
||||
"price": 43.4,
|
||||
"change_percent": 0.0197,
|
||||
"roe": 0.1499,
|
||||
"gross_profit_margin": 0.5268,
|
||||
"net_profit_margin": 0.1644,
|
||||
@ -710,7 +710,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp": "2025-01-13"
|
||||
"timestamp": "2025-01-15"
|
||||
},
|
||||
"000516": {
|
||||
"data": {
|
||||
@ -748,13 +748,13 @@
|
||||
"stock_info": {
|
||||
"code": "002466",
|
||||
"name": "天齐锂业",
|
||||
"market_value": 529.95,
|
||||
"pe_ratio": 7.26,
|
||||
"pb_ratio": 1.22,
|
||||
"ps_ratio": 1.31,
|
||||
"dividend_yield": 0.0418,
|
||||
"price": 32.29,
|
||||
"change_percent": 0.0416,
|
||||
"market_value": 541.44,
|
||||
"pe_ratio": 7.42,
|
||||
"pb_ratio": 1.24,
|
||||
"ps_ratio": 1.34,
|
||||
"dividend_yield": 0.0409,
|
||||
"price": 32.99,
|
||||
"change_percent": 0.0217,
|
||||
"roe": -0.12,
|
||||
"gross_profit_margin": 0.4903,
|
||||
"net_profit_margin": 0.1723,
|
||||
@ -772,7 +772,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp": "2025-01-13"
|
||||
"timestamp": "2025-01-15"
|
||||
},
|
||||
"index_data": {
|
||||
"data": {
|
||||
@ -2130,13 +2130,13 @@
|
||||
"stock_info": {
|
||||
"code": "300009",
|
||||
"name": "安科生物",
|
||||
"market_value": 135.81,
|
||||
"pe_ratio": 16.03,
|
||||
"pb_ratio": 3.47,
|
||||
"ps_ratio": 4.74,
|
||||
"dividend_yield": 0.0308,
|
||||
"price": 8.12,
|
||||
"change_percent": 0.01,
|
||||
"market_value": 139.66,
|
||||
"pe_ratio": 16.48,
|
||||
"pb_ratio": 3.56,
|
||||
"ps_ratio": 4.87,
|
||||
"dividend_yield": 0.0299,
|
||||
"price": 8.35,
|
||||
"change_percent": 0.0283,
|
||||
"roe": 0.1537,
|
||||
"gross_profit_margin": 0.7775,
|
||||
"net_profit_margin": 0.3122,
|
||||
@ -2149,25 +2149,25 @@
|
||||
},
|
||||
"targets": {
|
||||
"target_market_value": {
|
||||
"min": null,
|
||||
"max": null
|
||||
"min": 120.0,
|
||||
"max": 160.0
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp": "2025-01-13"
|
||||
"timestamp": "2025-01-15"
|
||||
},
|
||||
"300743": {
|
||||
"data": {
|
||||
"stock_info": {
|
||||
"code": "300743",
|
||||
"name": "天地数码",
|
||||
"market_value": 21.74,
|
||||
"pe_ratio": 39.08,
|
||||
"pb_ratio": 3.57,
|
||||
"ps_ratio": 3.38,
|
||||
"dividend_yield": 0.0241,
|
||||
"price": 14.17,
|
||||
"change_percent": 0.0093,
|
||||
"market_value": 22.94,
|
||||
"pe_ratio": 41.23,
|
||||
"pb_ratio": 3.76,
|
||||
"ps_ratio": 3.56,
|
||||
"dividend_yield": 0.0229,
|
||||
"price": 14.95,
|
||||
"change_percent": 0.055,
|
||||
"roe": 0.1209,
|
||||
"gross_profit_margin": 0.3493,
|
||||
"net_profit_margin": 0.1335,
|
||||
@ -2185,20 +2185,20 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp": "2025-01-13"
|
||||
"timestamp": "2025-01-15"
|
||||
},
|
||||
"603511": {
|
||||
"data": {
|
||||
"stock_info": {
|
||||
"code": "603511",
|
||||
"name": "爱慕股份",
|
||||
"market_value": 46.23,
|
||||
"pe_ratio": 15.12,
|
||||
"pb_ratio": 1.05,
|
||||
"ps_ratio": 1.35,
|
||||
"dividend_yield": 0.0662,
|
||||
"price": 11.37,
|
||||
"change_percent": -0.0026,
|
||||
"market_value": 50.86,
|
||||
"pe_ratio": 16.64,
|
||||
"pb_ratio": 1.16,
|
||||
"ps_ratio": 1.48,
|
||||
"dividend_yield": 0.0602,
|
||||
"price": 12.51,
|
||||
"change_percent": 0.1003,
|
||||
"roe": 0.0317,
|
||||
"gross_profit_margin": 0.6597,
|
||||
"net_profit_margin": 0.0615,
|
||||
@ -2216,20 +2216,20 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp": "2025-01-13"
|
||||
"timestamp": "2025-01-15"
|
||||
},
|
||||
"688553": {
|
||||
"data": {
|
||||
"stock_info": {
|
||||
"code": "688553",
|
||||
"name": "汇宇制药-W",
|
||||
"market_value": 58.37,
|
||||
"pe_ratio": 41.76,
|
||||
"pb_ratio": 1.5,
|
||||
"ps_ratio": 6.3,
|
||||
"market_value": 60.79,
|
||||
"pe_ratio": 43.49,
|
||||
"pb_ratio": 1.57,
|
||||
"ps_ratio": 6.56,
|
||||
"dividend_yield": 0.0,
|
||||
"price": 13.78,
|
||||
"change_percent": 0.0117,
|
||||
"price": 14.35,
|
||||
"change_percent": 0.0414,
|
||||
"roe": 0.0594,
|
||||
"gross_profit_margin": 0.8315,
|
||||
"net_profit_margin": 0.2592,
|
||||
@ -2247,20 +2247,20 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp": "2025-01-13"
|
||||
"timestamp": "2025-01-15"
|
||||
},
|
||||
"600030": {
|
||||
"data": {
|
||||
"stock_info": {
|
||||
"code": "600030",
|
||||
"name": "中信证券",
|
||||
"market_value": 3928.93,
|
||||
"pe_ratio": 19.92,
|
||||
"pb_ratio": 1.53,
|
||||
"ps_ratio": 6.54,
|
||||
"dividend_yield": 0.027,
|
||||
"price": 26.51,
|
||||
"change_percent": 0.0019,
|
||||
"market_value": 4105.29,
|
||||
"pe_ratio": 20.82,
|
||||
"pb_ratio": 1.6,
|
||||
"ps_ratio": 6.83,
|
||||
"dividend_yield": 0.0258,
|
||||
"price": 27.7,
|
||||
"change_percent": 0.0449,
|
||||
"roe": 0.0605,
|
||||
"gross_profit_margin": 0,
|
||||
"net_profit_margin": 0.3782,
|
||||
@ -2273,11 +2273,11 @@
|
||||
},
|
||||
"targets": {
|
||||
"target_market_value": {
|
||||
"min": null,
|
||||
"max": null
|
||||
"min": 3200.0,
|
||||
"max": 3600.0
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp": "2025-01-13"
|
||||
"timestamp": "2025-01-15"
|
||||
}
|
||||
}
|
||||
193
项目文档.txt
Normal file
193
项目文档.txt
Normal file
@ -0,0 +1,193 @@
|
||||
# 价值投资盯盘系统项目文档
|
||||
|
||||
## 项目概述
|
||||
|
||||
**项目名称**:价值投资盯盘系统
|
||||
**开发者**:张艺杰
|
||||
**项目类型**:A股智能股票分析与监控平台
|
||||
**技术栈**:Python + FastAPI + Bootstrap + ECharts
|
||||
|
||||
## 系统功能
|
||||
|
||||
### 1. 核心功能
|
||||
|
||||
1. **股票监控**
|
||||
- 实时股票行情监控
|
||||
- 自定义市值目标区间
|
||||
- 多维度指标展示
|
||||
- 涨跌幅实时更新
|
||||
|
||||
2. **指数行情**
|
||||
- 主要指数实时展示
|
||||
- K线图可视化
|
||||
- 涨跌幅实时更新
|
||||
|
||||
3. **公司详情分析**
|
||||
- 公司基本信息
|
||||
- 财务指标分析
|
||||
- 股东结构分析
|
||||
- AI智能分析
|
||||
|
||||
### 2. 具体指标监控
|
||||
|
||||
#### 2.1 基础指标
|
||||
- 股票代码和名称
|
||||
- 现价和涨跌幅
|
||||
- 市值监控
|
||||
- 目标区间对比
|
||||
|
||||
#### 2.2 估值指标
|
||||
- 市盈率(PE)
|
||||
- 市净率(PB)
|
||||
- 市销率(PS)
|
||||
- 股息率
|
||||
|
||||
#### 2.3 财务指标
|
||||
- ROE(净资产收益率)
|
||||
- 毛利率
|
||||
- 净利率
|
||||
- 资产负债率
|
||||
- 净利润增长率
|
||||
- 每股净资产
|
||||
- 每股经营现金流
|
||||
|
||||
### 3. AI分析功能
|
||||
|
||||
1. **投资建议**
|
||||
- 总体建议
|
||||
- 建议操作
|
||||
- 关注重点
|
||||
|
||||
2. **价格分析**
|
||||
- 合理价格区间
|
||||
- 目标市值区间
|
||||
|
||||
3. **多维度分析**
|
||||
- 估值分析
|
||||
- 财务健康状况
|
||||
- 成长潜力
|
||||
- 风险评估
|
||||
|
||||
## 技术实现
|
||||
|
||||
### 1. 后端架构
|
||||
|
||||
1. **Web框架**
|
||||
- FastAPI作为主要Web框架
|
||||
- Uvicorn作为ASGI服务器
|
||||
|
||||
2. **数据源集成**
|
||||
- Tushare API接口
|
||||
|
||||
3. **数据处理**
|
||||
- Pandas进行数据分析
|
||||
- NumPy进行数值计算
|
||||
|
||||
### 2. 前端实现
|
||||
|
||||
1. **UI框架**
|
||||
- Bootstrap 5.1.3
|
||||
- 响应式设计
|
||||
|
||||
2. **数据可视化**
|
||||
- ECharts 5.4.3
|
||||
- 动态K线图表
|
||||
|
||||
3. **交互设计**
|
||||
- AJAX异步数据更新
|
||||
- 实时数据刷新
|
||||
- 模态框展示详情
|
||||
|
||||
### 3. 数据存储
|
||||
|
||||
1. **配置存储**
|
||||
- JSON文件存储监控列表
|
||||
- 配置文件自动管理
|
||||
|
||||
2. **缓存机制**
|
||||
- 行情数据缓存
|
||||
- 智能更新策略
|
||||
|
||||
## 部署要求
|
||||
|
||||
### 1. 系统要求
|
||||
- Python 3.8+
|
||||
- 8GB+ RAM
|
||||
- 现代浏览器支持
|
||||
|
||||
### 2. 依赖安装
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
### 3. 配置说明
|
||||
- 需配置Tushare API Token
|
||||
- 配置端口默认为8000
|
||||
- 支持热重载
|
||||
|
||||
## 使用说明
|
||||
|
||||
### 1. 启动系统
|
||||
```bash
|
||||
python run.py
|
||||
```
|
||||
|
||||
### 2. 访问系统
|
||||
- 浏览器访问:`http://localhost:8000`
|
||||
|
||||
### 3. 基本操作
|
||||
1. 添加监控股票
|
||||
- 输入6位股票代码
|
||||
- 设置目标市值区间
|
||||
|
||||
2. 查看股票详情
|
||||
- 点击股票名称查看详细信息
|
||||
- 查看AI分析报告
|
||||
|
||||
3. 管理监控列表
|
||||
- 删除不需要的股票
|
||||
- 强制刷新数据
|
||||
|
||||
## 安全性考虑
|
||||
|
||||
1. **数据安全**
|
||||
- API Token安全存储
|
||||
- 敏感信息加密
|
||||
|
||||
2. **访问控制**
|
||||
- 请求频率限制
|
||||
- 错误处理机制
|
||||
|
||||
## 后续优化方向
|
||||
|
||||
1. **功能扩展**
|
||||
- 增加更多技术指标
|
||||
- 添加自定义告警功能
|
||||
- 支持多维度筛选
|
||||
|
||||
2. **性能优化**
|
||||
- 优化数据缓存机制
|
||||
- 提升响应速度
|
||||
- 减少资源占用
|
||||
|
||||
3. **用户体验**
|
||||
- 增加自定义主题
|
||||
- 优化移动端显示
|
||||
- 添加更多图表类型
|
||||
|
||||
## 维护说明
|
||||
|
||||
1. **日常维护**
|
||||
- 定期更新依赖
|
||||
- 检查API可用性
|
||||
- 优化数据缓存
|
||||
|
||||
2. **问题处理**
|
||||
- 日志监控
|
||||
- 异常处理
|
||||
- 性能监控
|
||||
|
||||
## 版权信息
|
||||
|
||||
版权所有 © 2024 张艺杰
|
||||
保留所有权利
|
||||
Loading…
Reference in New Issue
Block a user