feat: 添加 cloudflare_pages、mysql_d1_backup_scheduler,更新 start_system、ensemble_models 及配置文件
This commit is contained in:
1 parent
6184c34a3a
commit
62110554d1
20 files changed
+1438
-19
No files matched your search
@@ -0,0 +1,101 @@
|
||||
function json(data, status = 200) {
|
||||
return new Response(JSON.stringify(data), {
|
||||
status,
|
||||
headers: { "content-type": "application/json; charset=UTF-8" },
|
||||
});
|
||||
}
|
||||
|
||||
function toInt(v, d) {
|
||||
const n = Number(v);
|
||||
return Number.isFinite(n) && n > 0 ? Math.floor(n) : d;
|
||||
}
|
||||
|
||||
function ratio(correct, total) {
|
||||
if (!total) return 0;
|
||||
return Math.round((correct / total) * 10000) / 100;
|
||||
}
|
||||
|
||||
function item(total, correct) {
|
||||
const t = Number(total || 0);
|
||||
const c = Number(correct || 0);
|
||||
return {
|
||||
total: t,
|
||||
correct: c,
|
||||
incorrect: Math.max(0, t - c),
|
||||
accuracy: ratio(c, t),
|
||||
};
|
||||
}
|
||||
|
||||
export async function onRequestGet(context) {
|
||||
const db = context.env.DB;
|
||||
if (!db) {
|
||||
return json({ success: false, error: "缺少 D1 绑定 DB" }, 500);
|
||||
}
|
||||
|
||||
try {
|
||||
const url = new URL(context.request.url);
|
||||
const month = (url.searchParams.get("month") || new Date().toISOString().slice(0, 7)).trim();
|
||||
const page = toInt(url.searchParams.get("page"), 1);
|
||||
const limit = Math.min(100, toInt(url.searchParams.get("limit"), 10));
|
||||
const offset = (page - 1) * limit;
|
||||
|
||||
const baseWhere = "date LIKE ?";
|
||||
const monthArg = `${month}%`;
|
||||
|
||||
const dataSql = `
|
||||
SELECT
|
||||
date,
|
||||
SUM(CASE WHEN actual_result IS NOT NULL AND ensemble_prediction IS NOT NULL THEN 1 ELSE 0 END) AS ens_total,
|
||||
SUM(CASE WHEN ensemble_correct = 1 THEN 1 ELSE 0 END) AS ens_correct,
|
||||
|
||||
SUM(CASE WHEN actual_result IS NOT NULL AND dlinear_prediction IS NOT NULL THEN 1 ELSE 0 END) AS dl_total,
|
||||
SUM(CASE WHEN dlinear_correct = 1 THEN 1 ELSE 0 END) AS dl_correct,
|
||||
|
||||
SUM(CASE WHEN actual_result IS NOT NULL AND nbeats_prediction IS NOT NULL THEN 1 ELSE 0 END) AS nb_total,
|
||||
SUM(CASE WHEN nbeats_correct = 1 THEN 1 ELSE 0 END) AS nb_correct,
|
||||
|
||||
SUM(CASE WHEN actual_result IS NOT NULL AND ttm_prediction IS NOT NULL THEN 1 ELSE 0 END) AS ttm_total,
|
||||
SUM(CASE WHEN ttm_correct = 1 THEN 1 ELSE 0 END) AS ttm_correct
|
||||
FROM backup_hourly_model_predictions
|
||||
WHERE ${baseWhere}
|
||||
GROUP BY date
|
||||
ORDER BY date DESC
|
||||
LIMIT ? OFFSET ?
|
||||
`;
|
||||
|
||||
const countSql = `
|
||||
SELECT COUNT(*) AS cnt
|
||||
FROM (
|
||||
SELECT date
|
||||
FROM backup_hourly_model_predictions
|
||||
WHERE ${baseWhere}
|
||||
GROUP BY date
|
||||
) x
|
||||
`;
|
||||
|
||||
const dataResult = await db.prepare(dataSql).bind(monthArg, limit, offset).all();
|
||||
const countResult = await db.prepare(countSql).bind(monthArg).first();
|
||||
|
||||
const rows = (dataResult.results || []).map((r) => ({
|
||||
date: r.date,
|
||||
Ensemble: item(r.ens_total, r.ens_correct),
|
||||
DLinear: item(r.dl_total, r.dl_correct),
|
||||
"N-BEATS": item(r.nb_total, r.nb_correct),
|
||||
"TTM-R2": item(r.ttm_total, r.ttm_correct),
|
||||
}));
|
||||
|
||||
const total = Number(countResult?.cnt || 0);
|
||||
const totalPages = total > 0 ? Math.ceil(total / limit) : 1;
|
||||
|
||||
return json({
|
||||
success: true,
|
||||
data: rows,
|
||||
page,
|
||||
limit,
|
||||
total,
|
||||
total_pages: totalPages,
|
||||
});
|
||||
} catch (error) {
|
||||
return json({ success: false, error: String(error) }, 500);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
function json(data, status = 200) {
|
||||
return new Response(JSON.stringify(data), {
|
||||
status,
|
||||
headers: { "content-type": "application/json; charset=UTF-8" },
|
||||
});
|
||||
}
|
||||
|
||||
function modelItem(prediction, probability, isCorrect) {
|
||||
if (prediction === null || prediction === undefined) return null;
|
||||
return {
|
||||
prediction: Number(prediction),
|
||||
probability: probability === null || probability === undefined ? null : Number(probability),
|
||||
is_correct: isCorrect === null || isCorrect === undefined ? null : Number(isCorrect) === 1,
|
||||
};
|
||||
}
|
||||
|
||||
export async function onRequestGet(context) {
|
||||
const db = context.env.DB;
|
||||
if (!db) {
|
||||
return json({ success: false, error: "缺少 D1 绑定 DB" }, 500);
|
||||
}
|
||||
|
||||
try {
|
||||
const date = context.params.date;
|
||||
const sql = `
|
||||
SELECT
|
||||
timestamp,
|
||||
hour,
|
||||
open_price,
|
||||
close_price,
|
||||
actual_result,
|
||||
dlinear_prediction,
|
||||
dlinear_prob,
|
||||
dlinear_correct,
|
||||
nbeats_prediction,
|
||||
nbeats_prob,
|
||||
nbeats_correct,
|
||||
ttm_prediction,
|
||||
ttm_prob,
|
||||
ttm_correct,
|
||||
ensemble_prediction,
|
||||
ensemble_correct
|
||||
FROM backup_hourly_model_predictions
|
||||
WHERE date = ?
|
||||
ORDER BY hour ASC
|
||||
`;
|
||||
|
||||
const result = await db.prepare(sql).bind(date).all();
|
||||
const rows = (result.results || []).map((r) => ({
|
||||
timestamp_cst: r.timestamp,
|
||||
hour: r.hour,
|
||||
open_price: r.open_price === null || r.open_price === undefined ? null : Number(r.open_price),
|
||||
close_price: r.close_price === null || r.close_price === undefined ? null : Number(r.close_price),
|
||||
actual_result: r.actual_result === null || r.actual_result === undefined ? null : Number(r.actual_result),
|
||||
models: {
|
||||
Ensemble: modelItem(r.ensemble_prediction, null, r.ensemble_correct),
|
||||
DLinear: modelItem(r.dlinear_prediction, r.dlinear_prob, r.dlinear_correct),
|
||||
"N-BEATS": modelItem(r.nbeats_prediction, r.nbeats_prob, r.nbeats_correct),
|
||||
"TTM-R2": modelItem(r.ttm_prediction, r.ttm_prob, r.ttm_correct),
|
||||
},
|
||||
}));
|
||||
|
||||
return json({ success: true, date, data: rows });
|
||||
} catch (error) {
|
||||
return json({ success: false, error: String(error) }, 500);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
function json(data, status = 200) {
|
||||
return new Response(JSON.stringify(data), {
|
||||
status,
|
||||
headers: { "content-type": "application/json; charset=UTF-8" },
|
||||
});
|
||||
}
|
||||
|
||||
function ratio(correct, total) {
|
||||
if (!total) return 0;
|
||||
return Math.round((correct / total) * 10000) / 100;
|
||||
}
|
||||
|
||||
export async function onRequestGet(context) {
|
||||
const db = context.env.DB;
|
||||
if (!db) {
|
||||
return json({ success: false, error: "缺少 D1 绑定 DB" }, 500);
|
||||
}
|
||||
|
||||
try {
|
||||
const url = new URL(context.request.url);
|
||||
const month = (url.searchParams.get("month") || new Date().toISOString().slice(0, 7)).trim();
|
||||
|
||||
const sql = `
|
||||
SELECT
|
||||
SUM(CASE WHEN actual_result IS NOT NULL AND ensemble_prediction IS NOT NULL THEN 1 ELSE 0 END) AS ens_total,
|
||||
SUM(CASE WHEN ensemble_correct = 1 THEN 1 ELSE 0 END) AS ens_correct,
|
||||
|
||||
SUM(CASE WHEN actual_result IS NOT NULL AND dlinear_prediction IS NOT NULL THEN 1 ELSE 0 END) AS dl_total,
|
||||
SUM(CASE WHEN dlinear_correct = 1 THEN 1 ELSE 0 END) AS dl_correct,
|
||||
|
||||
SUM(CASE WHEN actual_result IS NOT NULL AND nbeats_prediction IS NOT NULL THEN 1 ELSE 0 END) AS nb_total,
|
||||
SUM(CASE WHEN nbeats_correct = 1 THEN 1 ELSE 0 END) AS nb_correct,
|
||||
|
||||
SUM(CASE WHEN actual_result IS NOT NULL AND ttm_prediction IS NOT NULL THEN 1 ELSE 0 END) AS ttm_total,
|
||||
SUM(CASE WHEN ttm_correct = 1 THEN 1 ELSE 0 END) AS ttm_correct
|
||||
FROM backup_hourly_model_predictions
|
||||
WHERE date LIKE ?
|
||||
`;
|
||||
|
||||
const row = await db.prepare(sql).bind(`${month}%`).first();
|
||||
|
||||
const ensTotal = Number(row?.ens_total || 0);
|
||||
const ensCorrect = Number(row?.ens_correct || 0);
|
||||
|
||||
const dlTotal = Number(row?.dl_total || 0);
|
||||
const dlCorrect = Number(row?.dl_correct || 0);
|
||||
|
||||
const nbTotal = Number(row?.nb_total || 0);
|
||||
const nbCorrect = Number(row?.nb_correct || 0);
|
||||
|
||||
const ttmTotal = Number(row?.ttm_total || 0);
|
||||
const ttmCorrect = Number(row?.ttm_correct || 0);
|
||||
|
||||
return json({
|
||||
success: true,
|
||||
month,
|
||||
data: {
|
||||
Ensemble: {
|
||||
total: ensTotal,
|
||||
correct: ensCorrect,
|
||||
incorrect: Math.max(0, ensTotal - ensCorrect),
|
||||
accuracy: ratio(ensCorrect, ensTotal),
|
||||
},
|
||||
DLinear: {
|
||||
total: dlTotal,
|
||||
correct: dlCorrect,
|
||||
incorrect: Math.max(0, dlTotal - dlCorrect),
|
||||
accuracy: ratio(dlCorrect, dlTotal),
|
||||
},
|
||||
"N-BEATS": {
|
||||
total: nbTotal,
|
||||
correct: nbCorrect,
|
||||
incorrect: Math.max(0, nbTotal - nbCorrect),
|
||||
accuracy: ratio(nbCorrect, nbTotal),
|
||||
},
|
||||
"TTM-R2": {
|
||||
total: ttmTotal,
|
||||
correct: ttmCorrect,
|
||||
incorrect: Math.max(0, ttmTotal - ttmCorrect),
|
||||
accuracy: ratio(ttmCorrect, ttmTotal),
|
||||
},
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
return json({ success: false, error: String(error) }, 500);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user