Files
vf_react/src/mocks/data/market.js
zdl 88b836e75a fix(mock): 完善大宗交易和龙虎榜数据结构
- 融券余额增加 balance_amount 字段
- 大宗交易:新增 deals 明细、买卖营业部、成交均价
- 龙虎榜:新增 buyers/sellers 营业部列表、净买入金额

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-22 13:04:55 +08:00

247 lines
12 KiB
JavaScript

// src/mocks/data/market.js
// 市场行情相关的 Mock 数据
// 股票名称映射
const STOCK_NAME_MAP = {
'000001': { name: '平安银行', basePrice: 13.50 },
'600000': { name: '浦发银行', basePrice: 8.20 },
'600519': { name: '贵州茅台', basePrice: 1650.00 },
'000858': { name: '五粮液', basePrice: 165.00 },
'601318': { name: '中国平安', basePrice: 45.00 },
'600036': { name: '招商银行', basePrice: 32.00 },
'300750': { name: '宁德时代', basePrice: 180.00 },
'002594': { name: '比亚迪', basePrice: 260.00 },
};
// 生成市场数据
export const generateMarketData = (stockCode) => {
const stockInfo = STOCK_NAME_MAP[stockCode] || { name: `股票${stockCode}`, basePrice: 20.00 };
const basePrice = stockInfo.basePrice;
return {
stockCode,
// 成交数据 - 必须包含K线所需的字段
tradeData: {
success: true,
data: Array(30).fill(null).map((_, i) => {
const open = basePrice + (Math.random() - 0.5) * 0.5;
const close = basePrice + (Math.random() - 0.5) * 0.5;
const high = Math.max(open, close) + Math.random() * 0.3;
const low = Math.min(open, close) - Math.random() * 0.3;
return {
date: new Date(Date.now() - (29 - i) * 24 * 60 * 60 * 1000).toISOString().split('T')[0],
open: parseFloat(open.toFixed(2)),
close: parseFloat(close.toFixed(2)),
high: parseFloat(high.toFixed(2)),
low: parseFloat(low.toFixed(2)),
volume: Math.floor(Math.random() * 500000000) + 100000000, // 1-6亿股
amount: Math.floor(Math.random() * 7000000000) + 1300000000, // 13-80亿元
turnover_rate: parseFloat((Math.random() * 2 + 0.5).toFixed(2)), // 0.5-2.5%
change_percent: parseFloat((Math.random() * 6 - 3).toFixed(2)), // -3% to +3%
pe_ratio: parseFloat((Math.random() * 3 + 4).toFixed(2)) // 4-7
};
})
},
// 资金流向 - 融资融券数据数组
fundingData: {
success: true,
data: Array(30).fill(null).map((_, i) => ({
date: new Date(Date.now() - (29 - i) * 24 * 60 * 60 * 1000).toISOString().split('T')[0],
financing: {
balance: Math.floor(Math.random() * 5000000000) + 10000000000, // 融资余额
buy: Math.floor(Math.random() * 500000000) + 100000000, // 融资买入
repay: Math.floor(Math.random() * 500000000) + 80000000 // 融资偿还
},
securities: {
balance: Math.floor(Math.random() * 100000000) + 50000000, // 融券余额(股数)
balance_amount: Math.floor(Math.random() * 2000000000) + 1000000000, // 融券余额(金额)
sell: Math.floor(Math.random() * 10000000) + 5000000, // 融券卖出
repay: Math.floor(Math.random() * 10000000) + 3000000 // 融券偿还
}
}))
},
// 大宗交易 - 包含 daily_stats 数组,符合 BigDealDayStats 类型
bigDealData: {
success: true,
data: [],
daily_stats: Array(10).fill(null).map((_, i) => {
const count = Math.floor(Math.random() * 5) + 1; // 1-5 笔交易
const avgPrice = parseFloat((basePrice * (0.95 + Math.random() * 0.1)).toFixed(2)); // 折价/溢价 -5%~+5%
const deals = Array(count).fill(null).map(() => {
const volume = parseFloat((Math.random() * 500 + 100).toFixed(2)); // 100-600 万股
const price = parseFloat((avgPrice * (0.98 + Math.random() * 0.04)).toFixed(2));
return {
buyer_dept: ['中信证券北京总部', '国泰君安上海分公司', '华泰证券深圳营业部', '招商证券广州分公司'][Math.floor(Math.random() * 4)],
seller_dept: ['中金公司北京营业部', '海通证券上海分公司', '广发证券深圳营业部', '平安证券广州分公司'][Math.floor(Math.random() * 4)],
price,
volume,
amount: parseFloat((price * volume).toFixed(2))
};
});
const totalVolume = deals.reduce((sum, d) => sum + d.volume, 0);
const totalAmount = deals.reduce((sum, d) => sum + d.amount, 0);
return {
date: new Date(Date.now() - (9 - i) * 24 * 60 * 60 * 1000).toISOString().split('T')[0],
count,
total_volume: parseFloat(totalVolume.toFixed(2)),
total_amount: parseFloat(totalAmount.toFixed(2)),
avg_price: avgPrice,
deals
};
})
},
// 龙虎榜数据 - 包含 grouped_data 数组,符合 UnusualDayData 类型
unusualData: {
success: true,
data: [],
grouped_data: Array(5).fill(null).map((_, i) => {
const buyerDepts = ['中信证券北京总部', '国泰君安上海分公司', '华泰证券深圳营业部', '招商证券广州分公司', '中金公司北京营业部'];
const sellerDepts = ['海通证券上海分公司', '广发证券深圳营业部', '平安证券广州分公司', '东方证券上海营业部', '兴业证券福州营业部'];
const infoTypes = ['日涨幅偏离值达7%', '日振幅达15%', '连续三日涨幅偏离20%', '换手率达20%'];
const buyers = buyerDepts.map(dept => ({
dept_name: dept,
buy_amount: Math.floor(Math.random() * 50000000) + 10000000 // 1000万-6000万
})).sort((a, b) => b.buy_amount - a.buy_amount);
const sellers = sellerDepts.map(dept => ({
dept_name: dept,
sell_amount: Math.floor(Math.random() * 40000000) + 8000000 // 800万-4800万
})).sort((a, b) => b.sell_amount - a.sell_amount);
const totalBuy = buyers.reduce((sum, b) => sum + b.buy_amount, 0);
const totalSell = sellers.reduce((sum, s) => sum + s.sell_amount, 0);
return {
date: new Date(Date.now() - (4 - i) * 24 * 60 * 60 * 1000).toISOString().split('T')[0],
total_buy: totalBuy,
total_sell: totalSell,
net_amount: totalBuy - totalSell,
buyers,
sellers,
info_types: infoTypes.slice(0, Math.floor(Math.random() * 3) + 1) // 随机选1-3个类型
};
})
},
// 股权质押 - 匹配 PledgeData[] 类型
pledgeData: {
success: true,
data: Array(12).fill(null).map((_, i) => {
const date = new Date();
date.setMonth(date.getMonth() - (11 - i));
return {
end_date: date.toISOString().split('T')[0].slice(0, 7) + '-01',
unrestricted_pledge: Math.floor(Math.random() * 1000000000) + 500000000,
restricted_pledge: Math.floor(Math.random() * 200000000) + 50000000,
total_pledge: Math.floor(Math.random() * 1200000000) + 550000000,
total_shares: 19405918198,
pledge_ratio: parseFloat((Math.random() * 3 + 6).toFixed(2)), // 6-9%
pledge_count: Math.floor(Math.random() * 50) + 100 // 100-150
};
})
},
// 市场摘要 - 匹配 MarketSummary 类型
summaryData: {
success: true,
data: {
stock_code: stockCode,
stock_name: stockInfo.name,
latest_trade: {
close: basePrice,
change_percent: 1.89,
volume: 345678900,
amount: 4678900000,
turnover_rate: 1.78,
pe_ratio: 4.96
},
latest_funding: {
financing_balance: 5823000000,
securities_balance: 125600000
},
latest_pledge: {
pledge_ratio: 8.25
}
}
},
// 涨停分析 - 返回数组格式,每个元素对应一个交易日
riseAnalysisData: {
success: true,
data: Array(30).fill(null).map((_, i) => {
const tradeDate = new Date(Date.now() - (29 - i) * 24 * 60 * 60 * 1000).toISOString().split('T')[0];
const isLimitUp = Math.random() < 0.05; // 5%概率涨停
return {
trade_date: tradeDate,
is_limit_up: isLimitUp,
limit_up_price: (basePrice * 1.10).toFixed(2),
current_price: (basePrice + (Math.random() - 0.5) * 0.5).toFixed(2),
distance_to_limit: (Math.random() * 10).toFixed(2), // %
consecutive_days: isLimitUp ? Math.floor(Math.random() * 3) + 1 : 0,
reason: isLimitUp ? '业绩超预期' : '',
concept_tags: ['银行', '深圳国资', 'MSCI', '沪深300'],
analysis: isLimitUp ? '股价触及涨停板,资金流入明显' : '股价正常波动,交投活跃'
};
})
},
// 最新分时数据 - 匹配 MinuteData 类型
latestMinuteData: {
success: true,
data: (() => {
const minuteData = [];
// 上午 9:30-11:30 (120分钟)
for (let i = 0; i < 120; i++) {
const hour = 9 + Math.floor((30 + i) / 60);
const min = (30 + i) % 60;
const time = `${hour.toString().padStart(2, '0')}:${min.toString().padStart(2, '0')}`;
const randomChange = (Math.random() - 0.5) * 0.1;
const open = parseFloat((basePrice + randomChange).toFixed(2));
const close = parseFloat((basePrice + randomChange + (Math.random() - 0.5) * 0.05).toFixed(2));
const high = parseFloat(Math.max(open, close, open + Math.random() * 0.05).toFixed(2));
const low = parseFloat(Math.min(open, close, close - Math.random() * 0.05).toFixed(2));
minuteData.push({
time,
open,
close,
high,
low,
volume: Math.floor(Math.random() * 2000000) + 500000,
amount: Math.floor(Math.random() * 30000000) + 5000000
});
}
// 下午 13:00-15:00 (120分钟)
for (let i = 0; i < 120; i++) {
const hour = 13 + Math.floor(i / 60);
const min = i % 60;
const time = `${hour.toString().padStart(2, '0')}:${min.toString().padStart(2, '0')}`;
const randomChange = (Math.random() - 0.5) * 0.1;
const open = parseFloat((basePrice + randomChange).toFixed(2));
const close = parseFloat((basePrice + randomChange + (Math.random() - 0.5) * 0.05).toFixed(2));
const high = parseFloat(Math.max(open, close, open + Math.random() * 0.05).toFixed(2));
const low = parseFloat(Math.min(open, close, close - Math.random() * 0.05).toFixed(2));
minuteData.push({
time,
open,
close,
high,
low,
volume: Math.floor(Math.random() * 1500000) + 400000,
amount: Math.floor(Math.random() * 25000000) + 4000000
});
}
return minuteData;
})(),
code: stockCode,
name: stockInfo.name,
trade_date: new Date().toISOString().split('T')[0],
type: '1min'
}
};
};