stock-portfolio/README.md
kennethcheng 0051f92b2b v1.0.5 (2026-04-13)
- 📛 证券名称增强:修复 INTC 等证券名称显示为空的问题 (BUG-101)
- 🔒 SELL超量校验:修复卖出数量超过持仓导致持仓变负的Bug (BUG-002)
- 🔄 撤销BUY成本还原:修复撤销买入时平均成本计算公式错误 (BUG-003)
- 💹 Decimal精度计算:持仓分析改用Prisma.Decimal进行金融计算,防止浮点精度丢失 (BUG-004)
- 📛 证券名称显示:在持仓分析卡片、资产分布、盈亏排行等位置同时显示股票代码和名称
- 📋 证券数据库扩展:新增 Intel Corp. (INTC) 证券记录
- 🔍 回退逻辑增强:确保证券名称为空时显示代码而非空白
- 📈 腾讯行情解析升级:精准解析股票名称(索引1),支持港/A/美股及 ETF 名称自动获取
- 🔀 多市场涨跌解析修复:重构腾讯行情多市场适配层,美股(索引4/5)与港A股(索引31/32)使用差异化索引解析涨跌数据
- 🇨🇳 GBK中文解码修复:改用 `arrayBuffer() + TextDecoder('gbk')` 替代 `text()`,彻底解决A股/港股中文股票名称乱码问题
- 💱 JisuAPI实时汇率:接入 JisuAPI 获取实时汇率,缓存1小时,支持 CNY/HKD/USD 转换
- 📊 资产配置动态图:环形图改由后端实时聚合持仓数据驱动,支持 Tooltip 和百分比显示
- 🎨 资产配置图表优化:精美毛玻璃 Tooltip、颜色图标、去除生硬描边、useMemo 性能优化
- 💱 全局货币联动:资产配置图表数值随 CNY/USD/HKD 切换实时转换
- 📝 交易流水增强:新增证券名称列,显示"名称+代码"双行格式
- 💹 全局汇率展示:在导航栏实时显示 USD/CNY/HKD 汇率信息
- 🔧 BUG-202 修复:修正 `convertCurrency` 汇率换算逻辑(原逻辑除法/乘法颠倒,导致 USD→CNY 换算失效)
- 🔧 BUG-201 修复:腾讯行情 API 获取失败时,`priceAvailable` 标记配合前端显示 "N/A" 替代虚假 0%
- 🔧 BUG-203 增强:持仓分析 `name` 字段确保回退到 `pos.symbol`,名称永不空
- 💹 Decimal 精度保障:所有盈亏/汇率计算均使用 Prisma.Decimal,防止浮点精度丢失
2026-04-13 18:41:37 +08:00

465 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 个人投资持仓管理系统
> 现代化、全面化的个人投资组合管理平台支持多市场美股、A股、港股、加密货币统一管理。
![License](https://img.shields.io/badge/license-MIT-blue.svg)
![Next.js](https://img.shields.io/badge/Next.js-16-black.svg)
![TypeScript](https://img.shields.io/badge/TypeScript-5-blue.svg)
![PostgreSQL](https://img.shields.io/badge/PostgreSQL-16-blue.svg)
---
## 功能特性
### 核心功能
| 功能 | 描述 |
|------|------|
| **多市场支持** | 美股 (US)、A股 (CN)、港股 (HK)、加密货币 (CRYPTO) |
| **资金流水管理** | 入金、出金记录 |
| **交易流水管理** | 买入、卖出、分红、利息、费用 |
| **持仓统计** | 实时市值、平均成本、浮动盈亏 |
| **多币种转换** | 自动将各币种资产折算为 USD |
| **资产配置图** | 饼图展示各市场占比 |
| **数据导入导出** | CSV 格式导入导出 |
### 交易类型
| 类型 | 说明 |
|------|------|
| `BUY` | 买入 |
| `SELL` | 卖出 |
| `DEPOSIT` | 入金 |
| `WITHDRAW` | 出金 |
| `DIVIDEND` | 分红 |
| `INTEREST` | 利息 |
| `FEE` | 费用/手续费 |
---
## 技术架构
### 技术栈
```
前端:
├── Next.js 16 (App Router)
├── React 19
├── TypeScript 5
├── Tailwind CSS 4
├── shadcn/ui (组件库)
├── Recharts (图表)
└── Sonner (Toast 通知)
后端:
├── Next.js API Routes
├── Prisma ORM
└── PostgreSQL 16
实时数据:
└── Alpha Vantage API
```
### 数据库模型
```
┌─────────────┐ ┌─────────────┐
│ User │───1:N─│ Account │
└─────────────┘ └─────────────┘
│ 1:N
┌─────────────┼─────────────┐
│ │ │
▼ ▼ ▼
┌───────────┐ ┌───────────┐ ┌───────────┐
│Position │ │Transaction│ │ExchangeRate│
└───────────┘ └───────────┘ └───────────┘
┌───────────┐
│ Security │
└───────────┘
```
### 表结构说明
| 表名 | 说明 |
|------|------|
| `User` | 用户表(预留多用户扩展) |
| `Account` | 账户表(按市场类型分组) |
| `Security` | 证券参考表(代码、名称、精度) |
| `Transaction` | 交易流水表 |
| `Position` | 持仓表(查询优化) |
| `ExchangeRate` | 汇率参考表 |
### 字段精度设计
| 字段类型 | 精度 | 说明 |
|----------|------|------|
| 价格/金额 | `Decimal(20,4)` | 避免浮点精度丢失 |
| 数量 | `Decimal(20,8)` | 加密货币支持8位小数 |
| 汇率 | `Decimal(20,8)` | 高精度汇率转换 |
---
## API 接口
### 账户管理
| 接口 | 方法 | 描述 |
|------|------|------|
| `/api/accounts` | GET | 获取账户列表 |
| `/api/accounts` | POST | 创建账户 |
### 交易管理
| 接口 | 方法 | 描述 |
|------|------|------|
| `/api/transactions` | GET | 获取交易流水(支持分页) |
| `/api/transactions` | POST | 记录交易(自动更新持仓/余额) |
### 持仓管理
| 接口 | 方法 | 描述 |
|------|------|------|
| `/api/positions` | GET | 获取持仓列表 |
### 仪表盘
| 接口 | 方法 | 描述 |
|------|------|------|
| `/api/dashboard/stats` | GET | 资产统计概览 |
| `/api/dashboard/analytics` | GET | 持仓分析(含实时价格) |
### 数据导入
| 接口 | 方法 | 描述 |
|------|------|------|
| `/api/import/transactions` | POST | 批量导入交易记录 |
### 证券管理
| 接口 | 方法 | 描述 |
|------|------|------|
| `/api/securities` | GET | 搜索证券 |
| `/api/securities` | POST | 添加证券 |
### 汇率管理
| 接口 | 方法 | 描述 |
|------|------|------|
| `/api/exchange-rates` | GET | 获取汇率列表 |
| `/api/exchange-rates` | POST | 更新汇率 |
---
## 快速开始
### 环境要求
- Node.js 20+
- PostgreSQL 16+
- npm 或 yarn
### 安装步骤
```bash
# 1. 克隆项目
git clone <repository-url>
cd stock-portfolio
# 2. 安装依赖
npm install
# 3. 配置环境变量
cp .env.example .env
# 编辑 .env 填入数据库连接信息
# 4. 生成 Prisma 客户端
npx prisma generate
# 5. 初始化数据库
npx prisma migrate dev --name init
npx prisma db seed
# 6. 启动开发服务器
npm run dev
# 7. 重置数据库
npx prisma migrate reset --force
```
### 环境变量
```env
# 数据库连接
DATABASE_URL="postgresql://postgres:password@localhost:5432/stock_portfolio"
# Alpha Vantage API Key用于获取实时股价
ALPHA_VANTAGE_API_KEY="your-api-key"
# HTTP 代理(可选,用于解决 API 访问问题)
HTTP_PROXY="http://192.168.48.171:7893"
HTTPS_PROXY="http://192.168.48.171:7893"
# 极速数据 API Key用于获取实时汇率必须配置
JISU_API_KEY="your-jisuapi-key"
```
> **注意**:运行本项目前,必须在根目录配置 `.env` 文件,并添加 `JISU_API_KEY=您的极速数据Key`。汇率服务通过后端代理调用 JisuAPI避免前端跨域问题。
---
## 使用指南
### 添加交易记录
1. 点击右上角「**记录交易**」按钮
2. 选择账户和交易类型
3. 输入证券代码(支持搜索)
4. 填写数量、价格(成交总额自动计算)
5. 点击「**确认记录**」
6. 在确认对话框中核实信息,点击「**确认**」
### 导入批量交易
1. 点击右上角「**导入**」按钮
2. 点击「**下载模板**」获取 CSV 模板
3. 按照模板格式填写交易数据
4. 选择填写好的 CSV 文件
5. 预览导入数据(有效/错误标记)
6. 点击「**导入**」执行批量导入
### 导出数据
1. 点击右上角「**导出**」按钮
2. 自动下载持仓 CSV 文件
3. 在「交易流水」标签页也可导出交易记录
### 字段说明
#### 交易模板 CSV 格式
```csv
时间,类型,证券代码,数量,价格,金额,手续费,币种,备注
2024-01-15 10:30:00,BUY,AAPL,10,185.50,1855.00,1.00,USD,买入苹果
```
| 字段 | 必填 | 说明 |
|------|------|------|
| 时间 | 是 | 格式:`YYYY-MM-DD HH:mm:ss` |
| 类型 | 是 | `BUY`/`SELL`/`DEPOSIT`/`WITHDRAW`/`DIVIDEND` |
| 证券代码 | 否 | 买入/卖出/分红时填写 |
| 数量 | 否 | 股票数量 |
| 价格 | 否 | 单价 |
| 金额 | 是 | 总金额 |
| 手续费 | 否 | 交易手续费 |
| 币种 | 是 | `USD`/`CNY`/`HKD`/`USDT` |
| 备注 | 否 | 任意备注信息 |
---
## 成本计算
### 平均成本法 (Average Cost)
系统采用**平均成本法**计算持仓成本:
```
新平均成本 = (现有成本 × 现有数量 + 新买入成本) / (现有数量 + 新买入数量)
```
### 示例
```
初始:买入 10 股 AAPL价格 $150
→ 平均成本 = $150
再次:买入 10 股 AAPL价格 $160
→ 新平均成本 = ($150×10 + $160×10) / 20 = $155
```
---
## 多币种处理
### 汇率转换
系统以 **USD** 为基准货币,将所有资产折算为 USD 进行汇总:
| 币种 | 汇率 (示例) |
|------|-------------|
| USD | 1.0 |
| CNY | 0.137 |
| HKD | 0.129 |
| USDT | 1.0 |
### 更新汇率
通过 `/api/exchange-rates` 接口或数据库直接更新汇率参考表。
---
## 界面预览
### 资产概览
```
┌─────────────────────────────────────────────────────────┐
│ [Logo] 投资持仓管理 [账户▼] [导入] [导出] [记录交易] │
├─────────────────────────────────────────────────────────┤
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 总资产 │ │ 浮动盈亏 │ │ 持仓市值 │ │ 账户数量 │ │
│ │ $125,430 │ │ +$3,250 │ │ $98,200 │ │ 4 │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────┘
```
### 持仓明细
| 证券 | 市场 | 数量 | 成本价 | 当前价 | 市值 | 盈亏 |
|------|------|------|--------|--------|------|------|
| AAPL | 美股 | 50 | $150.00 | $178.50 | $8,925 | +$1,425 (+19.0%) |
| MSFT | 美股 | 20 | $380.00 | $415.20 | $8,304 | +$704 (+9.3%) |
| BTC | 加密 | 0.5 | $60,000 | $67,500 | $33,750 | +$3,750 (+12.5%) |
---
## 项目结构
```
stock-portfolio/
├── prisma/
│ ├── schema.prisma # 数据库模型
│ ├── seed.ts # 初始化数据
│ └── migrations/ # 数据库迁移
├── src/
│ ├── app/
│ │ ├── api/ # API 路由
│ │ │ ├── accounts/
│ │ │ ├── transactions/
│ │ │ ├── positions/
│ │ │ ├── securities/
│ │ │ ├── exchange-rates/
│ │ │ ├── dashboard/
│ │ │ └── import/
│ │ ├── page.tsx # 主页面
│ │ ├── layout.tsx # 布局
│ │ └── globals.css # 全局样式
│ ├── components/
│ │ └── ui/ # shadcn/ui 组件
│ ├── lib/
│ │ ├── api.ts # API 调用封装
│ │ ├── prisma.ts # Prisma 客户端
│ │ ├── import-export.ts # 导入导出工具
│ │ └── price-service.ts # 价格服务
│ └── types/
│ └── index.ts # 类型定义
├── .env # 环境变量
├── .env.example # 环境变量示例
├── package.json
├── tsconfig.json
├── next.config.ts
└── README.md
```
---
## 常见问题
### Q: 实时价格如何获取?
A: 系统使用 Alpha Vantage API 获取美股实时价格。需要配置 `ALPHA_VANTAGE_API_KEY` 环境变量。
### Q: 支持哪些市场?
A: 目前支持美股 (US)、A股 (CN)、港股 (HK)、加密货币 (CRYPTO) 四个市场。
### Q: 成本计算使用什么算法?
A: 系统使用**平均成本法 (Average Cost)** 计算持仓成本。
### Q: 基准货币是什么?
A: 系统以 **USD** 为基准货币,所有资产会折算为 USD 进行汇总展示。
---
## 许可证
MIT License - 详见 [LICENSE](LICENSE) 文件
---
## 更新日志
### v1.0.5 (2026-04-13)
- 📛 证券名称增强:修复 INTC 等证券名称显示为空的问题 (BUG-101)
- 🔒 SELL超量校验修复卖出数量超过持仓导致持仓变负的Bug (BUG-002)
- 🔄 撤销BUY成本还原修复撤销买入时平均成本计算公式错误 (BUG-003)
- 💹 Decimal精度计算持仓分析改用Prisma.Decimal进行金融计算防止浮点精度丢失 (BUG-004)
- 📛 证券名称显示:在持仓分析卡片、资产分布、盈亏排行等位置同时显示股票代码和名称
- 📋 证券数据库扩展:新增 Intel Corp. (INTC) 证券记录
- 🔍 回退逻辑增强:确保证券名称为空时显示代码而非空白
- 📈 腾讯行情解析升级精准解析股票名称索引1支持港/A/美股及 ETF 名称自动获取
- 🔀 多市场涨跌解析修复:重构腾讯行情多市场适配层,美股(索引4/5)与港A股(索引31/32)使用差异化索引解析涨跌数据
- 🇨🇳 GBK中文解码修复改用 `arrayBuffer() + TextDecoder('gbk')` 替代 `text()`彻底解决A股/港股中文股票名称乱码问题
- 💱 JisuAPI实时汇率接入 JisuAPI 获取实时汇率缓存1小时支持 CNY/HKD/USD 转换
- 📊 资产配置动态图:环形图改由后端实时聚合持仓数据驱动,支持 Tooltip 和百分比显示
- 🎨 资产配置图表优化:精美毛玻璃 Tooltip、颜色图标、去除生硬描边、useMemo 性能优化
- 💱 全局货币联动:资产配置图表数值随 CNY/USD/HKD 切换实时转换
- 📝 交易流水增强:新增证券名称列,显示"名称+代码"双行格式
- 💹 全局汇率展示:在导航栏实时显示 USD/CNY/HKD 汇率信息
- 🔧 BUG-202 修复:修正 `convertCurrency` 汇率换算逻辑(原逻辑除法/乘法颠倒,导致 USD→CNY 换算失效)
- 🔧 BUG-201 修复:腾讯行情 API 获取失败时,`priceAvailable` 标记配合前端显示 "N/A" 替代虚假 0%
- 🔧 BUG-203 增强:持仓分析 `name` 字段确保回退到 `pos.symbol`,名称永不空
- 💹 Decimal 精度保障:所有盈亏/汇率计算均使用 Prisma.Decimal防止浮点精度丢失
### v1.0.4 (2026-04-12)
- 🐛 总资产计算修复:修复了多市场持仓汇总时货币转换错误的问题
- 🐛 浮动盈亏修复:修复了成本基数和市值货币单位不一致导致的错误
- 💹 持仓分析修复:确保所有持仓数据统一转换为 USD 后再汇总
- 📈 港股价格获取:改用腾讯行情接口(r_hk前缀)获取港股实时价格(小鹏汽车等)
- 📈 A股价格获取改用腾讯行情接口(sz/sh前缀)获取A股实时价格海尔智家、中证现金流ETF等
- 📈 美股价格获取:改用腾讯行情接口(s_us前缀)获取美股实时价格
- 🔍 证券名称显示:搜索和选择证券时同时显示代码和中文名称
- 📋 证券数据库扩展:新增小鹏汽车(09868)、海尔智家(600690)、中证现金流ETF(159235)、Alphabet(GOOGL)
- ✏️ 交易流水编辑:支持编辑已创建的交易记录
- 💰 持仓货币随市场持仓明细和分析中各市场使用对应货币显示港股用HKD、A股用CNY、美股用USD
### v1.0.3 (2026-04-12)
- 🗑️ 删除交易记录功能:支持删除误添加的交易记录,自动回滚账户余额和持仓变化
- 💰 显示货币选择器:支持 CNY/USD/HKD 三种货币显示,默认 CNY
- 🔄 实时货币转换:根据汇率自动转换总资产显示
- 💱 账户货币联动选择账户时自动设置对应结算货币美股→USD、A股→CNY、加密→USDT、港股→HKD
- 🔧 加密货币格式化USDT 映射为 USD 进行显示
### v1.0.2 (2026-04-12)
- 🔧 账户名称优化改为港股账户、美股账户、A股账户、加密货币账户
- ✨ 成交总额自动计算:根据数量 × 价格自动计算
- 🗑️ 删除持仓功能:支持通过卖出全部来删除持仓
- 🎨 Select 组件显示优化:修复了下拉框显示问题
- 📝 代码注释中文化
### v1.0.1 (2026-04-12)
- 🔧 账户名称优化改为港股账户、美股账户、A股账户、加密货币账户
- ✨ 成交总额自动计算:根据数量 × 价格自动计算
- 🗑️ 删除持仓功能:支持通过卖出全部来删除持仓
- 🎨 Select 组件显示优化:修复了下拉框显示问题
- 📝 代码注释中文化
### v1.0.0 (2026-04-12)
- ✨ 初始版本发布
- 支持多市场账户管理
- 支持交易记录(买入/卖出/入金/出金/分红)
- 支持持仓统计和盈亏计算
- 支持数据导入导出CSV
- 支持 Alpha Vantage 实时价格
- 响应式深色模式界面