Merge branch 'vest-fix-timing' into vest-fixes
# Conflicts: # lib/reporter.ts # lib/vest-class.ts # scripts/check-vest.mjs
This commit is contained in:
+43
-7
@@ -433,6 +433,20 @@ export function awaitingLegs(p: VestPosition): VestLeg[] {
|
||||
return [...p.stopLosses, ...p.takeProfits].filter((l) => l.status === 'awaiting');
|
||||
}
|
||||
|
||||
/**
|
||||
* The position an open of unknown outcome (a timeout, a reset, a 5xx after
|
||||
* the send) made, once a read shows it: on its account, in its symbol and
|
||||
* side, opened between `from` and `until` — the send and the error, widened
|
||||
* for the gateway's clock. A market open is IOC, so a later one isn't it.
|
||||
*/
|
||||
export function unknownOpenFill(
|
||||
sent: { accountId: string; symbol: string; side: 'long' | 'short'; from: number; until: number },
|
||||
positions: VestPosition[],
|
||||
): VestPosition | null {
|
||||
return positions.find((p) => p.accountId === sent.accountId && p.symbol === sent.symbol && p.side === sent.side
|
||||
&& p.openedAt >= sent.from && p.openedAt <= sent.until) ?? null;
|
||||
}
|
||||
|
||||
export interface VestOpenOrder {
|
||||
orderId: string;
|
||||
accountId: string;
|
||||
@@ -706,7 +720,19 @@ export function hourlyVolatility(klines: unknown[]): number | null {
|
||||
*/
|
||||
export function marketOpen(periods: unknown, now: number): { open: boolean; closesAt: number | null } {
|
||||
if (!Array.isArray(periods) || periods.length === 0) return { open: true, closesAt: null };
|
||||
const list = periods.flatMap((p) => {
|
||||
const list = hoursPeriods(periods);
|
||||
const i = list.findIndex((p) => p.from <= now && now < p.to);
|
||||
if (i < 0 || !list[i].open) return { open: false, closesAt: null };
|
||||
// Consecutive open periods (overnight → pre-market → regular …) are one stretch.
|
||||
let end = list[i].to;
|
||||
for (let j = i + 1; j < list.length && list[j].open && list[j].from <= end + 1; j++) end = list[j].to;
|
||||
return { open: true, closesAt: end };
|
||||
}
|
||||
|
||||
/** The market-hours periods, read and in order; open = trading, with no
|
||||
* closure (see marketOpen). */
|
||||
function hoursPeriods(periods: unknown[]): { from: number; to: number; open: boolean }[] {
|
||||
return periods.flatMap((p) => {
|
||||
const r = p as {
|
||||
fromMs?: unknown; toMs?: unknown;
|
||||
state?: { tradingStatus?: unknown; closure?: unknown; price?: { allow?: unknown } };
|
||||
@@ -719,10 +745,20 @@ export function marketOpen(periods: unknown, now: number): { open: boolean; clos
|
||||
&& (closure === undefined || closure === 'unspecified');
|
||||
return [{ from, to, open }];
|
||||
}).sort((a, b) => a.from - b.from);
|
||||
const i = list.findIndex((p) => p.from <= now && now < p.to);
|
||||
if (i < 0 || !list[i].open) return { open: false, closesAt: null };
|
||||
// Consecutive open periods (overnight → pre-market → regular …) are one stretch.
|
||||
let end = list[i].to;
|
||||
for (let j = i + 1; j < list.length && list[j].open && list[j].from <= end + 1; j++) end = list[j].to;
|
||||
return { open: true, closesAt: end };
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the closure that starts at `closesAt` (marketOpen's) keeps the
|
||||
* market shut across one of Vest's 8 PM ET resets — a weekend, a holiday —
|
||||
* or for as far as the periods go. A position held into it can't be exited
|
||||
* or fitted to that reset until the market reopens, and meets the reopen's
|
||||
* gap with its stop; the daily maintenance hour reopens before the reset.
|
||||
* A close the periods don't show (they just end there) isn't one.
|
||||
*/
|
||||
export function longClosure(periods: unknown, closesAt: number): boolean {
|
||||
if (!Array.isArray(periods)) return false;
|
||||
const list = hoursPeriods(periods);
|
||||
if (!list.some((p) => p.to > closesAt)) return false;
|
||||
const reopensAt = list.find((p) => p.open && p.from >= closesAt)?.from;
|
||||
return reopensAt === undefined || nextVestResetMs(closesAt) < reopensAt;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user