remove min_target_probability gate + add chart time-range presets
min_target_probability is gone: it filtered on the probability model the calibration has repeatedly shown to be weak and overconfident, it was redundant with the momentum gate, and as an off-by-default knob it just invited bad tuning. Removed from the backend gate, activation config/schema, the frontend mirror (qualifiesSetup / activationSummary), and ActivationSettings. The probability model stays where it does real work (primary-target selection + display). Charts: with multi-year history the all-bars default was unreadable. Added time-range presets (1M / 3M / 6M / YTD / 1Y / 3Y / 5Y / All), defaulting to 1Y; clicking a preset always re-applies (snaps back after a manual zoom). Y-axis autoscale and wheel-zoom / drag-pan were already there. 339 backend tests pass; frontend build clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -51,6 +51,26 @@ interface TooltipState {
|
||||
|
||||
const MIN_VISIBLE_BARS = 10;
|
||||
|
||||
type RangePreset = '1M' | '3M' | '6M' | 'YTD' | '1Y' | '3Y' | '5Y' | 'All';
|
||||
const RANGE_PRESETS: RangePreset[] = ['1M', '3M', '6M', 'YTD', '1Y', '3Y', '5Y', 'All'];
|
||||
const PRESET_MONTHS: Record<string, number> = { '1M': 1, '3M': 3, '6M': 6, '1Y': 12, '3Y': 36, '5Y': 60 };
|
||||
const DEFAULT_PRESET: RangePreset = '1Y';
|
||||
|
||||
/** First bar index to show for a time-range preset (data is ascending by date). */
|
||||
function startIndexForPreset(data: OHLCVBar[], preset: RangePreset): number {
|
||||
if (preset === 'All' || data.length === 0) return 0;
|
||||
const last = new Date(data[data.length - 1].date);
|
||||
let cutoff: Date;
|
||||
if (preset === 'YTD') {
|
||||
cutoff = new Date(last.getFullYear(), 0, 1);
|
||||
} else {
|
||||
cutoff = new Date(last);
|
||||
cutoff.setMonth(cutoff.getMonth() - PRESET_MONTHS[preset]);
|
||||
}
|
||||
const idx = data.findIndex((b) => new Date(b.date) >= cutoff);
|
||||
return idx < 0 ? 0 : idx;
|
||||
}
|
||||
|
||||
export function CandlestickChart({ data, srLevels = [], zones = [], tradeSetup, currentPrice }: CandlestickChartProps) {
|
||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||
const overlayCanvasRef = useRef<HTMLCanvasElement>(null);
|
||||
@@ -67,11 +87,13 @@ export function CandlestickChart({ data, srLevels = [], zones = [], tradeSetup,
|
||||
start: 0,
|
||||
end: data.length,
|
||||
});
|
||||
const [preset, setPreset] = useState<RangePreset>(DEFAULT_PRESET);
|
||||
|
||||
// Reset visible range when data changes
|
||||
// Apply the active time-range preset when the data or preset changes (so the
|
||||
// default view is a readable window, not the whole multi-year history).
|
||||
useEffect(() => {
|
||||
setVisibleRange({ start: 0, end: data.length });
|
||||
}, [data]);
|
||||
setVisibleRange({ start: startIndexForPreset(data, preset), end: data.length });
|
||||
}, [data, preset]);
|
||||
|
||||
const draw = useCallback(() => {
|
||||
const canvas = canvasRef.current;
|
||||
@@ -627,12 +649,33 @@ export function CandlestickChart({ data, srLevels = [], zones = [], tradeSetup,
|
||||
}
|
||||
|
||||
return (
|
||||
<div ref={containerRef} className="relative w-full" style={{ height: 400 }}>
|
||||
<canvas
|
||||
ref={canvasRef}
|
||||
className="w-full"
|
||||
style={{ height: 400 }}
|
||||
/>
|
||||
<div className="w-full">
|
||||
<div className="mb-2 flex flex-wrap items-center gap-1">
|
||||
{RANGE_PRESETS.map((p) => (
|
||||
<button
|
||||
key={p}
|
||||
type="button"
|
||||
onClick={() => {
|
||||
// Re-apply the range directly so clicking the active preset still
|
||||
// snaps back after a manual wheel-zoom / pan.
|
||||
setPreset(p);
|
||||
setVisibleRange({ start: startIndexForPreset(data, p), end: data.length });
|
||||
}}
|
||||
className={`rounded px-2 py-1 text-[11px] font-medium tabular-nums transition-colors ${
|
||||
preset === p ? 'bg-white/10 text-blue-300' : 'text-gray-500 hover:text-gray-300'
|
||||
}`}
|
||||
>
|
||||
{p}
|
||||
</button>
|
||||
))}
|
||||
<span className="ml-1 text-[10px] text-gray-600">scroll to zoom · drag to pan</span>
|
||||
</div>
|
||||
<div ref={containerRef} className="relative w-full" style={{ height: 400 }}>
|
||||
<canvas
|
||||
ref={canvasRef}
|
||||
className="w-full"
|
||||
style={{ height: 400 }}
|
||||
/>
|
||||
<canvas
|
||||
ref={overlayCanvasRef}
|
||||
className="absolute top-0 left-0 w-full cursor-crosshair"
|
||||
@@ -643,11 +686,12 @@ export function CandlestickChart({ data, srLevels = [], zones = [], tradeSetup,
|
||||
onMouseLeave={handleMouseLeave}
|
||||
onWheel={handleWheel}
|
||||
/>
|
||||
<div
|
||||
ref={tooltipRef}
|
||||
className="glass absolute pointer-events-none px-3 py-2 text-xs shadow-2xl z-50"
|
||||
style={{ display: 'none' }}
|
||||
/>
|
||||
<div
|
||||
ref={tooltipRef}
|
||||
className="glass absolute pointer-events-none px-3 py-2 text-xs shadow-2xl z-50"
|
||||
style={{ display: 'none' }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user