feat: near-close scan schedule and distinct-day gate reset

Move the only qualifying R:R scan to 15:30 ET with chained Telegram alerts,
put outcome eval after a final-bar OHLCV fetch, enforce NY trading-day
requalify semantics, stamp paper trades fill_mode=near_close, and migrate
stored schedule_* keys to America/New_York.
This commit is contained in:
2026-07-18 17:55:39 +02:00
parent 5a61b164f6
commit 736451e26f
14 changed files with 428 additions and 83 deletions
@@ -4,34 +4,48 @@ import { useScheduleSettings, useUpdateScheduleSettings } from '../../hooks/useA
import { SkeletonTable } from '../ui/Skeleton';
const DEFAULTS: ScheduleConfig = {
schedule_timezone: 'Europe/Berlin',
schedule_daily_pipeline_cron: '0 7 * * *',
schedule_intraday_pipeline_cron: '0 14-22 * * 1-5',
schedule_fundamentals_cron: '0 4 * * 1',
schedule_timezone: 'America/New_York',
schedule_daily_pipeline_cron: '0 2 * * *',
schedule_near_close_pipeline_cron: '30 15 * * 1-5',
schedule_after_close_pipeline_cron: '45 16 * * 1-5',
schedule_intraday_pipeline_cron: '0 10-15 * * 1-5',
schedule_fundamentals_cron: '0 1 * * 1',
};
const FIELDS: { key: keyof ScheduleConfig; label: string; hint: string; mono?: boolean }[] = [
{
key: 'schedule_timezone',
label: 'Timezone',
hint: 'IANA name, e.g. Europe/Berlin. All times below are in this zone.',
hint: 'IANA name. Prefer America/New_York so the near-close scan tracks the US cash close through DST.',
},
{
key: 'schedule_daily_pipeline_cron',
label: 'Daily pipeline (full)',
hint: 'OHLCV → sentiment → R:R scan → outcomes → regime. Default 07:00 so data is ready by 8.',
label: 'Morning pipeline',
hint: 'OHLCV → benchmark → sentiment → regime (no R:R scan). Default 02:00 ET.',
mono: true,
},
{
key: 'schedule_near_close_pipeline_cron',
label: 'Near-close pipeline (scan + alert)',
hint: 'OHLCV fetch → R:R scan → Telegram. Default 15:30 ET MonFri so manual MOC fills can still hit ~15:50/15:55.',
mono: true,
},
{
key: 'schedule_after_close_pipeline_cron',
label: 'After-close pipeline (outcome)',
hint: 'OHLCV fetch (final bar) → outcome eval. Default 16:45 ET MonFri — not chained to the partial near-close bar.',
mono: true,
},
{
key: 'schedule_intraday_pipeline_cron',
label: 'Intraday pipeline (light)',
hint: 'Refresh prices + resolve outcomes. Default hourly across the US session, weekdays.',
hint: 'Refresh prices + resolve outcomes mid-session. Default hourly 10:0015:00 ET weekdays.',
mono: true,
},
{
key: 'schedule_fundamentals_cron',
label: 'Fundamentals (weekly)',
hint: 'Slow, rate-limited. Default early Monday so it finishes well before the day starts.',
hint: 'Slow, rate-limited. Default early Monday ET.',
mono: true,
},
];
@@ -43,7 +57,7 @@ export function ScheduleSettings() {
const [form, setForm] = useState<ScheduleConfig>(DEFAULTS);
useEffect(() => {
if (data) setForm(data);
if (data) setForm({ ...DEFAULTS, ...data });
}, [data]);
if (isLoading) return <SkeletonTable rows={2} cols={2} />;
@@ -55,8 +69,8 @@ export function ScheduleSettings() {
<h3 className="text-sm font-semibold text-gray-200">Pipeline Schedule</h3>
<p className="mt-1 text-xs text-gray-500">
When the jobs run, as 5-field cron (<span className="num">min hour day month weekday</span>).
Saved changes apply to the running scheduler immediately no redeploy. The big nightly run
does the full refresh; the light intraday run just keeps prices current.
Saved changes apply to the running scheduler immediately no redeploy.
One qualifying R:R scan per day is the near-close job; alerts fire immediately after that scan.
</p>
</div>
@@ -66,7 +80,7 @@ export function ScheduleSettings() {
<span className="text-xs text-gray-400">{f.label}</span>
<input
type="text"
value={form[f.key]}
value={form[f.key] ?? ''}
spellCheck={false}
onChange={(e) => setForm((prev) => ({ ...prev, [f.key]: e.target.value }))}
className={`w-full input-glass px-3 py-2 text-sm ${f.mono ? 'num' : ''}`}
+3 -1
View File
@@ -187,10 +187,12 @@ export interface ActivationConfig {
exclude_neutral: boolean;
}
// Cron schedule for the daily/intraday pipelines + fundamentals
// Cron schedule for morning / near-close / after-close / intraday + fundamentals
export interface ScheduleConfig {
schedule_timezone: string;
schedule_daily_pipeline_cron: string;
schedule_near_close_pipeline_cron: string;
schedule_after_close_pipeline_cron: string;
schedule_intraday_pipeline_cron: string;
schedule_fundamentals_cron: string;
}