- 📛 证券名称增强:修复 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,防止浮点精度丢失
465 lines
16 KiB
Markdown
465 lines
16 KiB
Markdown
# 个人投资持仓管理系统
|
||
|
||
> 现代化、全面化的个人投资组合管理平台,支持多市场(美股、A股、港股、加密货币)统一管理。
|
||
|
||

|
||

|
||

|
||

|
||
|
||
---
|
||
|
||
## 功能特性
|
||
|
||
### 核心功能
|
||
|
||
| 功能 | 描述 |
|
||
|------|------|
|
||
| **多市场支持** | 美股 (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 实时价格
|
||
- 响应式深色模式界面
|