diff --git a/pages/api/sh300-index.js b/pages/api/sh300-index.js
index 60bf102..c7e79d5 100644
--- a/pages/api/sh300-index.js
+++ b/pages/api/sh300-index.js
@@ -22,30 +22,27 @@ async function handler(req, res) {
const params = [];
const conditions = [];
- if (startDate) {
- conditions.push('date >= ?');
- params.push(startDate);
- }
-
- if (endDate) {
- conditions.push('date <= ?');
- params.push(endDate);
+ if (startDate && endDate) {
+ conditions.push('date BETWEEN ? AND ?');
+ params.push(startDate, endDate);
}
if (conditions.length > 0) {
query += ' WHERE ' + conditions.join(' AND ');
}
- query += ' ORDER BY date ASC';
-
- if (limit) {
- query += ' LIMIT ?';
- params.push(parseInt(limit));
- }
+ query += ' ORDER BY date DESC';
const result = await pool.query(query, params);
- const data = result.map(row => {
+ // 限制返回数量,默认为30
+ const limitValue = limit ? parseInt(limit) : 30;
+ const limitedResult = result.slice(0, limitValue);
+
+ // 反转顺序,使日期从早到晚
+ const sortedResult = limitedResult.reverse();
+
+ const data = sortedResult.map(row => {
let dateStr;
if (row.date instanceof Date) {
dateStr = row.date.toISOString().split('T')[0];
diff --git a/pages/strategy.js b/pages/strategy.js
index 5143afc..b6a1a8a 100644
--- a/pages/strategy.js
+++ b/pages/strategy.js
@@ -50,12 +50,6 @@ export default function Strategy() {
}
]
- useEffect(() => {
- if (selectedStrategy === 'sh300-exchange-rate') {
- fetchSh300ExchangeData()
- }
- }, [selectedStrategy, timeRange, startDate, endDate])
-
const handleTimeRangeChange = (range, start, end) => {
setTimeRange(range)
setStartDate(start)
@@ -63,6 +57,7 @@ export default function Strategy() {
}
const fetchSh300ExchangeData = async () => {
+ console.log('fetchSh300ExchangeData called')
setSh300Loading(true)
try {
let sh300Url = '/api/sh300-index'
@@ -85,13 +80,19 @@ export default function Strategy() {
exchangeUrl += '?' + params.join('&')
}
+ console.log('Fetching from:', sh300Url, exchangeUrl)
+
const [sh300Res, exchangeRes] = await Promise.all([
fetch(sh300Url),
fetch(exchangeUrl)
])
+ console.log('Response status:', sh300Res.status, exchangeRes.status)
+
const sh300Json = await sh300Res.json()
const exchangeJson = await exchangeRes.json()
+ console.log('Response data:', sh300Json, exchangeJson)
+
if (sh300Json.success && exchangeJson.success) {
const sh300Map = new Map(sh300Json.data.map(item => [item.date, item.close]))
const exchangeMap = new Map(exchangeJson.data.map(item => [item.date, item.rate]))
@@ -104,6 +105,7 @@ export default function Strategy() {
exchangeRate: exchangeMap.get(date) || null
})).filter(item => item.sh300 !== null && item.exchangeRate !== null)
+ console.log('Merged data:', mergedData)
setSh300ExchangeData(mergedData)
}
} catch (error) {
@@ -113,6 +115,12 @@ export default function Strategy() {
}
}
+ useEffect(() => {
+ if (selectedStrategy === 'sh300-exchange-rate') {
+ fetchSh300ExchangeData()
+ }
+ }, [selectedStrategy, timeRange, startDate, endDate])
+
return (
@@ -371,8 +379,8 @@ export default function Strategy() {
-
- value.toFixed(4)} />
+
+ value.toFixed(4)} />
diff --git a/scripts/fetch-one-year.js b/scripts/fetch-one-year.js
new file mode 100644
index 0000000..a41d91e
--- /dev/null
+++ b/scripts/fetch-one-year.js
@@ -0,0 +1,79 @@
+
+import { spawn } from 'child_process';
+
+async function runScraper(scraperPath, startDate, endDate) {
+ return new Promise((resolve, reject) => {
+ const args = [scraperPath];
+ if (startDate) {
+ args.push('--start', startDate);
+ }
+ if (endDate) {
+ args.push('--end', endDate);
+ }
+
+ const proc = spawn('bun', args, { stdio: 'inherit' });
+ proc.on('close', (code) => {
+ if (code === 0) {
+ resolve();
+ } else {
+ reject(new Error(`Process exited with code ${code}`));
+ }
+ });
+ proc.on('error', (err) => {
+ reject(err);
+ });
+ });
+}
+
+async function fetchOneYearData() {
+ console.log('='.repeat(70));
+ console.log('📊 获取近一年数据');
+ console.log('='.repeat(70));
+
+ const currentDate = new Date();
+ const startDate = new Date(currentDate);
+ startDate.setFullYear(startDate.getFullYear() - 1);
+
+ const startDateStr = startDate.toISOString().split('T')[0];
+ const endDateStr = currentDate.toISOString().split('T')[0];
+
+ console.log(`时间范围: ${startDateStr} 至 ${endDateStr}`);
+ console.log('');
+
+ console.log('='.repeat(70));
+ console.log('💱 开始获取 USD-CNY 汇率数据...');
+ console.log('='.repeat(70));
+
+ let usdSuccess = false;
+ try {
+ await runScraper('./scraper/usd-cny-rate.scraper.js', startDateStr, endDateStr);
+ console.log(`✅ USD-CNY 汇率数据更新完成`);
+ usdSuccess = true;
+ } catch (error) {
+ console.error(`❌ USD-CNY 汇率数据更新失败:`, error.message);
+ }
+
+ console.log('');
+ console.log('='.repeat(70));
+ console.log('📈 开始获取沪深300指数数据...');
+ console.log('='.repeat(70));
+
+ let sh300Success = false;
+ try {
+ await runScraper('./scraper/sh300.scraper.js', startDateStr, endDateStr);
+ console.log(`✅ 沪深300指数数据更新完成`);
+ sh300Success = true;
+ } catch (error) {
+ console.error(`❌ 沪深300指数数据更新失败:`, error.message);
+ }
+
+ console.log('');
+ console.log('='.repeat(70));
+ console.log('📊 数据获取完成');
+ console.log('='.repeat(70));
+ console.log(`USD-CNY 汇率: ${usdSuccess ? '✅ 成功' : '❌ 失败'}`);
+ console.log(`沪深300指数: ${sh300Success ? '✅ 成功' : '❌ 失败'}`);
+ console.log('='.repeat(70));
+}
+
+fetchOneYearData();
diff --git a/scripts/scheduler/index.js b/scripts/scheduler/index.js
index fe969d4..52740fd 100644
--- a/scripts/scheduler/index.js
+++ b/scripts/scheduler/index.js
@@ -1,12 +1,13 @@
import cron from 'node-cron';
import { trigger as triggerUSDCNYRate } from '../scraper/usd-cny-rate.scraper.js';
+import { trigger as triggerSH300Data } from '../scraper/sh300.scraper.js';
console.log('='.repeat(70));
console.log('🚀 启动定时任务调度器');
console.log('='.repeat(70));
-// 注册定时任务
-const job = cron.schedule('0 0 * * *', async () => {
+// 注册定时任务 - USD-CNY 汇率数据
+const jobUSDCNY = cron.schedule('0 0 * * *', async () => {
console.log('\n' + '='.repeat(70));
console.log('⏰ 执行定时任务: USD-CNY 汇率数据更新');
console.log('📅 执行时间:', new Date().toISOString());
@@ -25,10 +26,34 @@ const job = cron.schedule('0 0 * * *', async () => {
timezone: 'Asia/Shanghai'
});
+// 注册定时任务 - 沪深300指数数据
+const jobSH300 = cron.schedule('0 0 * * *', async () => {
+ console.log('\n' + '='.repeat(70));
+ console.log('⏰ 执行定时任务: 沪深300指数数据更新');
+ console.log('📅 执行时间:', new Date().toISOString());
+ console.log('='.repeat(70));
+
+ try {
+ await triggerSH300Data();
+ console.log('\n✅ 任务执行成功!');
+ } catch (error) {
+ console.error('\n❌ 任务执行失败:', error.message);
+ } finally {
+ console.log('='.repeat(70));
+ }
+}, {
+ scheduled: true,
+ timezone: 'Asia/Shanghai'
+});
+
console.log('✅ 定时任务已启动: USD-CNY 汇率数据更新');
console.log('📅 执行表达式: 0 0 * * * (每天 0 点)');
console.log('📅 下次执行时间: 明天 00:00');
console.log('');
+console.log('✅ 定时任务已启动: 沪深300指数数据更新');
+console.log('📅 执行表达式: 0 0 * * * (每天 0 点)');
+console.log('📅 下次执行时间: 明天 00:00');
+console.log('');
console.log('按 Ctrl+C 停止...');
console.log('='.repeat(70));
@@ -38,7 +63,8 @@ process.on('SIGINT', () => {
console.log('🛑 停止定时任务调度器');
console.log('='.repeat(70));
- job.stop();
+ jobUSDCNY.stop();
+ jobSH300.stop();
console.log('✅ 定时任务已停止');
console.log('\n' + '='.repeat(70));
diff --git a/scripts/scraper/sh300.scraper.js b/scripts/scraper/sh300.scraper.js
index 959b54b..ccd3497 100644
--- a/scripts/scraper/sh300.scraper.js
+++ b/scripts/scraper/sh300.scraper.js
@@ -265,13 +265,50 @@ export async function trigger(startDate = null, endDate = null) {
return await checkAndFillSH300Data(startDate, endDate);
}
-// 直接运行测试
+function parseCommandLineArgs() {
+ const args = process.argv.slice(2);
+ let startDate = null;
+ let endDate = null;
+
+ for (let i = 0; i < args.length; i++) {
+ if (args[i] === '--start' && i + 1 < args.length) {
+ startDate = args[i + 1];
+ i++;
+ } else if (args[i] === '--end' && i + 1 < args.length) {
+ endDate = args[i + 1];
+ i++;
+ } else if (args[i] === '--help') {
+ console.log('使用方法:');
+ console.log(' bun sh300.scraper.js [选项]');
+ console.log('');
+ console.log('选项:');
+ console.log(' --start YYYY-MM-DD 指定开始日期');
+ console.log(' --end YYYY-MM-DD 指定结束日期');
+ console.log(' --help 显示帮助信息');
+ console.log('');
+ console.log('示例:');
+ console.log(' bun sh300.scraper.js');
+ console.log(' bun sh300.scraper.js --start 2024-01-01 --end 2024-01-31');
+ process.exit(0);
+ }
+ }
+
+ return { startDate, endDate };
+}
+
async function runTest() {
console.log('='.repeat(60));
console.log('测试 sh300.scraper.js');
console.log('='.repeat(60));
- // 测试配置读取
+ const { startDate, endDate } = parseCommandLineArgs();
+
+ if (startDate) {
+ console.log(`\n使用命令行参数:`);
+ console.log(` 开始日期: ${startDate}`);
+ console.log(` 结束日期: ${endDate || '默认'}`);
+ }
+
console.log('\n测试数据库配置读取...');
const config = loadDatabaseConfig();
console.log('配置读取结果:');
@@ -282,7 +319,7 @@ async function runTest() {
console.log('配置读取测试完成!');
try {
- const result = await trigger();
+ const result = await trigger(startDate, endDate);
console.log('\n' + '='.repeat(60));
console.log('测试结果:');
console.log(` 开始日期: ${result.startDate}`);
@@ -298,5 +335,4 @@ async function runTest() {
}
}
-// 运行测试
runTest();
diff --git a/scripts/scraper/usd-cny-rate.scraper.js b/scripts/scraper/usd-cny-rate.scraper.js
index 43ed9a0..e56e491 100644
--- a/scripts/scraper/usd-cny-rate.scraper.js
+++ b/scripts/scraper/usd-cny-rate.scraper.js
@@ -262,13 +262,50 @@ export async function trigger(startDate = null, endDate = null) {
return await checkAndFillUSDCNYRate(startDate, endDate);
}
-// 直接运行测试
+function parseCommandLineArgs() {
+ const args = process.argv.slice(2);
+ let startDate = null;
+ let endDate = null;
+
+ for (let i = 0; i < args.length; i++) {
+ if (args[i] === '--start' && i + 1 < args.length) {
+ startDate = args[i + 1];
+ i++;
+ } else if (args[i] === '--end' && i + 1 < args.length) {
+ endDate = args[i + 1];
+ i++;
+ } else if (args[i] === '--help') {
+ console.log('使用方法:');
+ console.log(' bun usd-cny-rate.scraper.js [选项]');
+ console.log('');
+ console.log('选项:');
+ console.log(' --start YYYY-MM-DD 指定开始日期');
+ console.log(' --end YYYY-MM-DD 指定结束日期');
+ console.log(' --help 显示帮助信息');
+ console.log('');
+ console.log('示例:');
+ console.log(' bun usd-cny-rate.scraper.js');
+ console.log(' bun usd-cny-rate.scraper.js --start 2024-01-01 --end 2024-01-31');
+ process.exit(0);
+ }
+ }
+
+ return { startDate, endDate };
+}
+
async function runTest() {
console.log('='.repeat(60));
console.log('测试 usd-cny-rate.scraper.js');
console.log('='.repeat(60));
- // 测试配置读取
+ const { startDate, endDate } = parseCommandLineArgs();
+
+ if (startDate) {
+ console.log(`\n使用命令行参数:`);
+ console.log(` 开始日期: ${startDate}`);
+ console.log(` 结束日期: ${endDate || '默认'}`);
+ }
+
console.log('\n测试数据库配置读取...');
const config = loadDatabaseConfig();
console.log('配置读取结果:');
@@ -279,7 +316,7 @@ async function runTest() {
console.log('配置读取测试完成!');
try {
- const result = await trigger();
+ const result = await trigger(startDate, endDate);
console.log('\n' + '='.repeat(60));
console.log('测试结果:');
console.log(` 开始日期: ${result.startDate}`);
@@ -295,5 +332,4 @@ async function runTest() {
}
}
-// 运行测试
runTest();