stock-portfolio/prisma/seed.ts
kennethcheng 4bad47f83d 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)
2026-04-12 08:22:52 +08:00

100 lines
3.8 KiB
TypeScript

import { PrismaClient, MarketType } from '@prisma/client'
const prisma = new PrismaClient()
async function main() {
// 创建默认用户
const user = await prisma.user.upsert({
where: { email: 'demo@portfolio.local' },
update: {},
create: {
email: 'demo@portfolio.local',
name: 'Demo User',
},
})
// 创建各市场的账户
const accounts = [
{ name: '港股账户', marketType: MarketType.HK, baseCurrency: 'HKD' },
{ name: '美股账户', marketType: MarketType.US, baseCurrency: 'USD' },
{ name: 'A股账户', marketType: MarketType.CN, baseCurrency: 'CNY' },
{ name: '加密货币账户', marketType: MarketType.CRYPTO, baseCurrency: 'USDT' },
]
for (const acc of accounts) {
await prisma.account.upsert({
where: { id: `${user.id}-${acc.marketType}` },
update: {},
create: {
id: `${user.id}-${acc.marketType}`,
userId: user.id,
name: acc.name,
marketType: acc.marketType,
baseCurrency: acc.baseCurrency,
balance: 0,
},
})
}
// 初始化汇率(以 USD 为基准)
const exchangeRates = [
{ fromCurrency: 'USD', toCurrency: 'USD', rate: 1, date: new Date('2026-01-01') },
{ fromCurrency: 'CNY', toCurrency: 'USD', rate: 0.137, date: new Date('2026-01-01') },
{ fromCurrency: 'HKD', toCurrency: 'USD', rate: 0.129, date: new Date('2026-01-01') },
{ fromCurrency: 'USDT', toCurrency: 'USD', rate: 1, date: new Date('2026-01-01') },
]
for (const rate of exchangeRates) {
await prisma.exchangeRate.upsert({
where: {
fromCurrency_toCurrency_effectiveDate: {
fromCurrency: rate.fromCurrency,
toCurrency: rate.toCurrency,
effectiveDate: rate.date,
},
},
update: {},
create: {
fromCurrency: rate.fromCurrency,
toCurrency: rate.toCurrency,
rate: rate.rate,
effectiveDate: rate.date,
},
})
}
// 初始化常见证券
const securities = [
{ symbol: '00700', name: '腾讯控股', market: MarketType.HK, currency: 'HKD', lotSize: 100, priceDecimals: 2, qtyDecimals: 0 },
{ symbol: '09868', name: '小鹏汽车', market: MarketType.HK, currency: 'HKD', lotSize: 100, priceDecimals: 2, qtyDecimals: 0 },
{ symbol: '09988', name: '阿里巴巴', market: MarketType.HK, currency: 'HKD', lotSize: 100, priceDecimals: 2, qtyDecimals: 0 },
{ symbol: 'AAPL', name: 'Apple Inc.', market: MarketType.US, currency: 'USD', lotSize: 1, priceDecimals: 2, qtyDecimals: 0 },
{ symbol: 'MSFT', name: 'Microsoft Corp.', market: MarketType.US, currency: 'USD', lotSize: 1, priceDecimals: 2, qtyDecimals: 0 },
{ symbol: 'NVDA', name: 'NVIDIA Corp.', market: MarketType.US, currency: 'USD', lotSize: 1, priceDecimals: 2, qtyDecimals: 0 },
{ symbol: 'GOOGL', name: 'Alphabet Inc.', market: MarketType.US, currency: 'USD', lotSize: 1, priceDecimals: 2, qtyDecimals: 0 },
{ symbol: '600690', name: '海尔智家', market: MarketType.CN, currency: 'CNY', lotSize: 100, priceDecimals: 2, qtyDecimals: 0 },
{ symbol: '159235', name: '中证现金流ETF', market: MarketType.CN, currency: 'CNY', lotSize: 100, priceDecimals: 3, qtyDecimals: 0 },
{ symbol: 'BTC', name: 'Bitcoin', market: MarketType.CRYPTO, currency: 'USDT', lotSize: 1, priceDecimals: 2, qtyDecimals: 8, isCrypto: true },
{ symbol: 'ETH', name: 'Ethereum', market: MarketType.CRYPTO, currency: 'USDT', lotSize: 1, priceDecimals: 2, qtyDecimals: 8, isCrypto: true },
]
for (const sec of securities) {
await prisma.security.upsert({
where: { symbol: sec.symbol },
update: {},
create: sec,
})
}
console.log('Seed completed:', { user, accountsCreated: accounts.length })
}
main()
.catch((e) => {
console.error(e)
process.exit(1)
})
.finally(async () => {
await prisma.$disconnect()
})