fix: show TA-lib pattern spans on chart and add delete all annotations button
- Fix SpanAnnotationManager price range calculation: use direct candle filtering by time range instead of dummy Candle objects that fell back to 0/0 high/low, causing invisible rectangles - Add handleDeleteAllAnnotations in page.tsx (deletes all span annotations and regular annotations for current chart) - Add 'Delete All Annotations' button in sidebar below TA-Lib panel
This commit is contained in:
parent
7901a1a257
commit
d416aa409c
3 changed files with 50 additions and 5 deletions
|
|
@ -405,6 +405,21 @@ export default function Home() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleDeleteAllAnnotations = async () => {
|
||||||
|
if (!activeChartId) return;
|
||||||
|
await Promise.all([
|
||||||
|
fetch(`/api/span-annotations?chartId=${activeChartId}`, { method: 'DELETE' }),
|
||||||
|
fetch(`/api/annotations?all=true&chartId=${activeChartId}`, { method: 'DELETE' }),
|
||||||
|
]);
|
||||||
|
await Promise.all([
|
||||||
|
fetchSpanAnnotations(activeChartId),
|
||||||
|
fetchAnnotations(activeChartId),
|
||||||
|
chartRef.current?.refreshData(),
|
||||||
|
]);
|
||||||
|
setSelectedSpanId(null);
|
||||||
|
setSelectedLabelId(null);
|
||||||
|
};
|
||||||
|
|
||||||
const handleLabelDelete = async (id: number) => {
|
const handleLabelDelete = async (id: number) => {
|
||||||
setAnnotations(annotations.filter((a) => a.id !== id));
|
setAnnotations(annotations.filter((a) => a.id !== id));
|
||||||
if (selectedLabelId === id) {
|
if (selectedLabelId === id) {
|
||||||
|
|
@ -778,6 +793,17 @@ export default function Home() {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Delete all annotations */}
|
||||||
|
<div className="px-3 py-2 border-t border-sidebar-border">
|
||||||
|
<button
|
||||||
|
onClick={handleDeleteAllAnnotations}
|
||||||
|
disabled={!activeChartId}
|
||||||
|
className="w-full px-2 py-1 text-[10px] text-destructive border border-destructive/30 rounded hover:bg-destructive/10 transition-colors disabled:opacity-50"
|
||||||
|
>
|
||||||
|
Delete All Annotations
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Training Panel */}
|
{/* Training Panel */}
|
||||||
<div className="px-3 py-2 border-t border-sidebar-border">
|
<div className="px-3 py-2 border-t border-sidebar-border">
|
||||||
<TrainingPanel />
|
<TrainingPanel />
|
||||||
|
|
|
||||||
|
|
@ -112,12 +112,31 @@ export default function SpanAnnotationManager({
|
||||||
|
|
||||||
// Create primitives for each span annotation
|
// Create primitives for each span annotation
|
||||||
spanAnnotations.forEach((span) => {
|
spanAnnotations.forEach((span) => {
|
||||||
const { max_high, min_low } = calculatePriceRange(
|
// Find candles within span time range for price calculation
|
||||||
{ time: span.start_time, open: 0, high: 0, low: 0, close: 0 },
|
const spanCandles = candles.filter(
|
||||||
{ time: span.end_time, open: 0, high: 0, low: 0, close: 0 }
|
(c) => c.time >= span.start_time && c.time <= span.end_time
|
||||||
);
|
);
|
||||||
|
let max_high: number;
|
||||||
|
let min_low: number;
|
||||||
|
if (spanCandles.length > 0) {
|
||||||
|
max_high = Math.max(...spanCandles.map((c) => c.high));
|
||||||
|
min_low = Math.min(...spanCandles.map((c) => c.low));
|
||||||
|
} else {
|
||||||
|
// Fallback: find nearest candles to span boundaries
|
||||||
|
const nearest = candles.reduce(
|
||||||
|
(acc, c) => {
|
||||||
|
const distStart = Math.abs(c.time - span.start_time);
|
||||||
|
const distEnd = Math.abs(c.time - span.end_time);
|
||||||
|
if (distStart < acc.startDist) acc = { ...acc, startCandle: c, startDist: distStart };
|
||||||
|
if (distEnd < acc.endDist) acc = { ...acc, endCandle: c, endDist: distEnd };
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
{ startCandle: candles[0], startDist: Infinity, endCandle: candles[0], endDist: Infinity }
|
||||||
|
);
|
||||||
|
max_high = Math.max(nearest.startCandle?.high ?? 0, nearest.endCandle?.high ?? 0);
|
||||||
|
min_low = Math.min(nearest.startCandle?.low ?? 0, nearest.endCandle?.low ?? 0);
|
||||||
|
}
|
||||||
|
|
||||||
// If we can't calculate price range from candles, use sensible defaults
|
|
||||||
const spanData: SpanData = {
|
const spanData: SpanData = {
|
||||||
id: span.id,
|
id: span.id,
|
||||||
start_time: span.start_time,
|
start_time: span.start_time,
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue