fix: strict calendar time-lock validation, LaTeX syntax repair, and repository sync
This commit is contained in:
@@ -10,7 +10,7 @@ import CryptoBlueprintModal from './CryptoBlueprintModal';
|
||||
import {
|
||||
Cpu, Search, RefreshCw, BarChart2, TrendingUp, AlertCircle, Info,
|
||||
ChevronDown, ChevronUp, ArrowUpRight, ArrowDownRight, Compass, ShieldAlert, Sparkles,
|
||||
BookOpen, Check
|
||||
BookOpen, Check, EyeOff
|
||||
} from 'lucide-react';
|
||||
|
||||
interface TrackerState {
|
||||
@@ -98,6 +98,7 @@ interface Forecast {
|
||||
predictions: Record<string, Record<string, number>>;
|
||||
targetTimes: Record<string, number>;
|
||||
results?: Record<string, 'SUCCESS' | 'FAILURE'>;
|
||||
isHidden?: boolean;
|
||||
}
|
||||
|
||||
interface BasisArbitrageData {
|
||||
@@ -132,6 +133,18 @@ function formatRemainingTime(seconds: number): string {
|
||||
return `Verbleibend: ${parts.join(', ')}`;
|
||||
}
|
||||
|
||||
export const SYSTEM_DATE = 1781714824000; // 2026-06-17T18:47:04+02:00
|
||||
|
||||
export function isHorizonPending(fcTimestamp: number, hKey: 'T1' | 'T5' | 'T10'): boolean {
|
||||
const locks = {
|
||||
T1: 24 * 60 * 60 * 1000,
|
||||
T5: 5 * 24 * 60 * 60 * 1000,
|
||||
T10: 10 * 24 * 60 * 60 * 1000
|
||||
};
|
||||
const now = SYSTEM_DATE;
|
||||
return (now - fcTimestamp) < locks[hKey];
|
||||
}
|
||||
|
||||
export default function CryptoDemo() {
|
||||
const { addModelTrial } = useSandboxStore();
|
||||
|
||||
@@ -241,14 +254,13 @@ export default function CryptoDemo() {
|
||||
setForecasts(parsed);
|
||||
} catch (err) {
|
||||
console.log("Resetting legacy forecasts to multi-model format...");
|
||||
const now = Date.now();
|
||||
const mockForecasts: Forecast[] = [
|
||||
{
|
||||
id: 'mock-1',
|
||||
ticker: 'BTC',
|
||||
entryPrice: 65000,
|
||||
resolved: true,
|
||||
timestamp: now - 86400 * 1000 * 3,
|
||||
resolved: false,
|
||||
timestamp: SYSTEM_DATE - 86400 * 1000 * 3,
|
||||
predictions: {
|
||||
rf: { T1: 0.62, T5: 0.58, T10: 0.54 },
|
||||
gb: { T1: 0.65, T5: 0.61, T10: 0.51 },
|
||||
@@ -257,16 +269,12 @@ export default function CryptoDemo() {
|
||||
mlp: { T1: 0.64, T5: 0.60, T10: 0.53 }
|
||||
},
|
||||
targetTimes: {
|
||||
T1: now - 86400 * 1000 * 2,
|
||||
T5: now - 86400 * 1000 * 2,
|
||||
T10: now - 86400 * 1000 * 2
|
||||
T1: SYSTEM_DATE - 86400 * 1000 * 2,
|
||||
T5: SYSTEM_DATE + 86400 * 1000 * 2,
|
||||
T10: SYSTEM_DATE + 86400 * 1000 * 7
|
||||
},
|
||||
results: {
|
||||
rf_T1: 'SUCCESS', rf_T5: 'SUCCESS', rf_T10: 'SUCCESS',
|
||||
gb_T1: 'SUCCESS', gb_T5: 'SUCCESS', gb_T10: 'SUCCESS',
|
||||
lr_T1: 'SUCCESS', lr_T5: 'SUCCESS', lr_T10: 'SUCCESS',
|
||||
svm_T1: 'SUCCESS', svm_T5: 'SUCCESS', svm_T10: 'SUCCESS',
|
||||
mlp_T1: 'SUCCESS', mlp_T5: 'SUCCESS', mlp_T10: 'SUCCESS'
|
||||
rf_T1: 'SUCCESS', gb_T1: 'SUCCESS', lr_T1: 'SUCCESS', svm_T1: 'SUCCESS', mlp_T1: 'SUCCESS'
|
||||
}
|
||||
}
|
||||
];
|
||||
@@ -274,14 +282,13 @@ export default function CryptoDemo() {
|
||||
localStorage.setItem('crypto_bayes_forecasts', JSON.stringify(mockForecasts));
|
||||
}
|
||||
} else {
|
||||
const now = Date.now();
|
||||
const mockForecasts: Forecast[] = [
|
||||
{
|
||||
id: 'mock-1',
|
||||
ticker: 'BTC',
|
||||
entryPrice: 65000,
|
||||
resolved: true,
|
||||
timestamp: now - 86400 * 1000 * 3,
|
||||
resolved: false,
|
||||
timestamp: SYSTEM_DATE - 86400 * 1000 * 3,
|
||||
predictions: {
|
||||
rf: { T1: 0.62, T5: 0.58, T10: 0.54 },
|
||||
gb: { T1: 0.65, T5: 0.61, T10: 0.51 },
|
||||
@@ -290,16 +297,12 @@ export default function CryptoDemo() {
|
||||
mlp: { T1: 0.64, T5: 0.60, T10: 0.53 }
|
||||
},
|
||||
targetTimes: {
|
||||
T1: now - 86400 * 1000 * 2,
|
||||
T5: now - 86400 * 1000 * 2,
|
||||
T10: now - 86400 * 1000 * 2
|
||||
T1: SYSTEM_DATE - 86400 * 1000 * 2,
|
||||
T5: SYSTEM_DATE + 86400 * 1000 * 2,
|
||||
T10: SYSTEM_DATE + 86400 * 1000 * 7
|
||||
},
|
||||
results: {
|
||||
rf_T1: 'SUCCESS', rf_T5: 'SUCCESS', rf_T10: 'SUCCESS',
|
||||
gb_T1: 'SUCCESS', gb_T5: 'SUCCESS', gb_T10: 'SUCCESS',
|
||||
lr_T1: 'SUCCESS', lr_T5: 'SUCCESS', lr_T10: 'SUCCESS',
|
||||
svm_T1: 'SUCCESS', svm_T5: 'SUCCESS', svm_T10: 'SUCCESS',
|
||||
mlp_T1: 'SUCCESS', mlp_T5: 'SUCCESS', mlp_T10: 'SUCCESS'
|
||||
rf_T1: 'SUCCESS', gb_T1: 'SUCCESS', lr_T1: 'SUCCESS', svm_T1: 'SUCCESS', mlp_T1: 'SUCCESS'
|
||||
}
|
||||
}
|
||||
];
|
||||
@@ -325,9 +328,9 @@ export default function CryptoDemo() {
|
||||
forecasts.forEach((fc) => {
|
||||
if (fc.results) {
|
||||
ESTIMATORS.forEach((est) => {
|
||||
const rT1 = fc.results?.[`${est.id}_T1`];
|
||||
const rT5 = fc.results?.[`${est.id}_T5`];
|
||||
const rT10 = fc.results?.[`${est.id}_T10`];
|
||||
const rT1 = !isHorizonPending(fc.timestamp, 'T1') ? fc.results?.[`${est.id}_T1`] : undefined;
|
||||
const rT5 = !isHorizonPending(fc.timestamp, 'T5') ? fc.results?.[`${est.id}_T5`] : undefined;
|
||||
const rT10 = !isHorizonPending(fc.timestamp, 'T10') ? fc.results?.[`${est.id}_T10`] : undefined;
|
||||
|
||||
if (rT1 !== undefined) {
|
||||
t1Total++;
|
||||
@@ -477,12 +480,15 @@ export default function CryptoDemo() {
|
||||
const nextTrackers = { ...trackers };
|
||||
|
||||
const updatedForecasts = forecasts.map((f) => {
|
||||
if (f.resolved) return f;
|
||||
const isFullyResolved = ESTIMATORS.every(est =>
|
||||
HORIZONS.every(h => f.results && f.results[`${est.id}_${h.id}`] !== undefined && !isHorizonPending(f.timestamp, h.id))
|
||||
);
|
||||
if (isFullyResolved) return f;
|
||||
|
||||
const currentPrice = pricesMap[f.ticker] || pricesMap[`${f.ticker}-USD`];
|
||||
if (!currentPrice) return f;
|
||||
|
||||
const now = Date.now();
|
||||
const now = SYSTEM_DATE;
|
||||
const resultsMap = { ...(f.results || {}) };
|
||||
let modified = false;
|
||||
|
||||
@@ -492,7 +498,7 @@ export default function CryptoDemo() {
|
||||
|
||||
ESTIMATORS.forEach((est) => {
|
||||
const trackerKey = `${est.id}_${hKey}`;
|
||||
if (now >= targetTime && !resultsMap[trackerKey]) {
|
||||
if (now >= targetTime && !resultsMap[trackerKey] && !isHorizonPending(f.timestamp, hKey)) {
|
||||
const priceWentUp = currentPrice > f.entryPrice;
|
||||
const predProb = f.predictions[est.id]?.[hKey] ?? 0.5;
|
||||
const predDir = predProb > 0.5 ? 'UP' : 'DOWN';
|
||||
@@ -517,7 +523,7 @@ export default function CryptoDemo() {
|
||||
|
||||
if (modified) {
|
||||
const allResolved = ESTIMATORS.every(est =>
|
||||
HORIZONS.every(h => resultsMap[`${est.id}_${h.id}`] !== undefined)
|
||||
HORIZONS.every(h => resultsMap[`${est.id}_${h.id}`] !== undefined && !isHorizonPending(f.timestamp, h.id))
|
||||
);
|
||||
return {
|
||||
...f,
|
||||
@@ -1157,20 +1163,25 @@ export default function CryptoDemo() {
|
||||
<th className="p-2 text-center">T+1 Acc</th>
|
||||
<th className="p-2 text-center">T+5 Acc</th>
|
||||
<th className="p-2 text-center">T+10 Acc</th>
|
||||
<th className="p-2 text-center w-[50px]">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{filteredForecasts.length === 0 ? (
|
||||
<tr>
|
||||
<td colSpan={10} className="p-4 text-center text-slate-500 italic">No forecasts registered for {feedbackFilterAsset} yet.</td>
|
||||
</tr>
|
||||
) : (
|
||||
filteredForecasts.map((fc) => {
|
||||
const now = Date.now();
|
||||
{(() => {
|
||||
const visibleForecasts = filteredForecasts.filter(fc => !fc.isHidden);
|
||||
if (visibleForecasts.length === 0) {
|
||||
return (
|
||||
<tr>
|
||||
<td colSpan={11} className="p-4 text-center text-slate-500 italic">No forecasts registered for {feedbackFilterAsset} yet.</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
return visibleForecasts.map((fc) => {
|
||||
const now = SYSTEM_DATE;
|
||||
|
||||
const getHorizonStatus = (hKey: 'T1' | 'T5' | 'T10') => {
|
||||
const targetTime = fc.targetTimes[hKey];
|
||||
const isPast = now >= targetTime;
|
||||
const pending = isHorizonPending(fc.timestamp, hKey);
|
||||
|
||||
let successes = 0;
|
||||
let total = 0;
|
||||
@@ -1182,14 +1193,14 @@ export default function CryptoDemo() {
|
||||
}
|
||||
});
|
||||
|
||||
if (total === 5) {
|
||||
if (total === 5 && !pending) {
|
||||
return (
|
||||
<span className="text-emerald-400 font-bold">
|
||||
{successes}/5 OK
|
||||
</span>
|
||||
);
|
||||
}
|
||||
if (isPast) {
|
||||
if (now >= targetTime && !pending) {
|
||||
return <span className="text-cyan-400 animate-pulse">Resolving...</span>;
|
||||
}
|
||||
const secondsLeft = Math.max(0, Math.ceil((targetTime - now) / 1000));
|
||||
@@ -1227,6 +1238,9 @@ export default function CryptoDemo() {
|
||||
};
|
||||
|
||||
const getHorizonAccuracy = (hKey: 'T1' | 'T5' | 'T10') => {
|
||||
if (isHorizonPending(fc.timestamp, hKey)) {
|
||||
return <span className="text-slate-500">-</span>;
|
||||
}
|
||||
let resolvedCountH = 0;
|
||||
let successCountH = 0;
|
||||
ESTIMATORS.forEach((est) => {
|
||||
@@ -1252,8 +1266,11 @@ export default function CryptoDemo() {
|
||||
|
||||
let resolvedCount = 0;
|
||||
if (fc.results) {
|
||||
Object.values(fc.results).forEach(() => {
|
||||
resolvedCount++;
|
||||
Object.keys(fc.results).forEach((rKey) => {
|
||||
const hKey = rKey.endsWith('_T1') ? 'T1' : rKey.endsWith('_T5') ? 'T5' : 'T10';
|
||||
if (!isHorizonPending(fc.timestamp, hKey)) {
|
||||
resolvedCount++;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1285,10 +1302,24 @@ export default function CryptoDemo() {
|
||||
<td className="p-2 text-center text-xs">{getHorizonAccuracy('T1')}</td>
|
||||
<td className="p-2 text-center text-xs">{getHorizonAccuracy('T5')}</td>
|
||||
<td className="p-2 text-center text-xs">{getHorizonAccuracy('T10')}</td>
|
||||
<td className="p-2 text-center">
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
const updated = forecasts.map(item => item.id === fc.id ? { ...item, isHidden: true } : item);
|
||||
setForecasts(updated);
|
||||
localStorage.setItem('crypto_bayes_forecasts', JSON.stringify(updated));
|
||||
}}
|
||||
className="text-slate-500 hover:text-rose-400 transition-colors p-1 cursor-pointer"
|
||||
title="Hide Row"
|
||||
>
|
||||
<EyeOff className="w-3.5 h-3.5" />
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
{expandedRows[fc.id] && (
|
||||
<tr className="bg-slate-900/40 border-b border-slate-800">
|
||||
<td colSpan={10} className="p-4">
|
||||
<td colSpan={11} className="p-4">
|
||||
<div className="space-y-3">
|
||||
<div className="text-xs font-bold text-cyan-400 uppercase tracking-wider">
|
||||
Detailed Estimator Forecast Matrix
|
||||
@@ -1314,7 +1345,7 @@ export default function CryptoDemo() {
|
||||
<span className={direction === 'UP' ? 'text-emerald-400' : 'text-rose-400'}>
|
||||
{direction} ({(prob * 100).toFixed(0)}%)
|
||||
</span>
|
||||
{res && (
|
||||
{res && !isHorizonPending(fc.timestamp, hKey) && (
|
||||
res === 'SUCCESS' ? (
|
||||
<span className="text-emerald-400 font-bold" title="Correct Forecast">✓</span>
|
||||
) : (
|
||||
@@ -1337,7 +1368,7 @@ export default function CryptoDemo() {
|
||||
</React.Fragment>
|
||||
);
|
||||
})
|
||||
)}
|
||||
})()}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user