Skip to content

A session rail: veto ENTRIES when a session-bound venue is closed, exempt exits #809

Description

@eaitbrahim

keel already records a venue's session and spends it entirely on not crying wolf.

agent.py:1215 (FR-9, "a closed market is not a stale feed") writes, per venue and per cycle:

market_session:alpaca             = "open"
market_session_ts:alpaca          = 1789653606
market_session_interval_sec:alpaca= 86400
market_session_next_open:alpaca   = 1789738200
market_session_next_close:alpaca  = 1789675200

The design is careful -- venue-namespaced so two deployments cannot impersonate each other's
clock, each carrying its own trust window, and "a 24/7 venue writes NOTHING" so every crypto
deployment keeps byte-identical state.

Nothing consumes it but alerts. grep for market_session_key outside its own definitions
finds commands/fetch.py and commands/status.py. No rail, no guard, no engine branch. keel has
the data and the vocabulary for a session gate and uses it only to suppress staleness warnings.

What actually enforces the session today

A launchd schedule:

com.keel.paper-equities.plist -> StartCalendarInterval hours [10,11,12,13,14,15]
machine local: EDT            -> 10:00-15:00 ET, inside RTH 09:30-16:00

That is correct because the machine happens to sit in New York. It is a convention, not an
invariant: it is expressed in machine-local time, it is invisible from inside the engine, and a
bare keel agent run at 03:00 evaluates entries with nothing to stop it.

Proposed

A rail that vetoes ENTRIES when the recorded session for the order's venue is CLOSED, and
exempts exits -- the same asymmetry rails 17 and 22 already state verbatim ("Exits, stop
rolls, cancels and DCA exits are unaffected").

That asymmetry is the whole point, and it is already keel's idiom rather than a borrowed one:
entries are a decision that should respect the session; an exit is risk coming OFF and must never
be blocked by a clock.

Requirements:

  • Fails OPEN on an unknown or stale recording, not closed. A venue that reports nothing is a
    24/7 venue by the existing convention, and a stale stamp is not evidence the market is shut --
    _slot_market_closed already refuses to defuse alerts "off a value nobody vouches for" and this
    rail must not be stricter than the recording it reads.
  • Reads the recording, never a clock. Same shape as the rest: the component holding a broker
    records, everyone else reads. A rail making its own venue call would put a network round-trip
    inside the guard gate.
  • Silent on crypto. No recorded session means no veto, so every existing Coinbase deployment
    is unaffected.

Also worth a doctor check

Assert the profile's scheduled run times fall inside the recorded next_open/next_close. That
catches the timezone coupling above, and DST drift, without keel having to own a trading calendar.

Why not the shape Jesse just shipped

Jesse 3.2.0 adds trading hours as "three small building blocks that you place yourself, rather
than a switch that changes engine behavior behind your back". That is right for a product where
users author strategies and a hidden engine switch would be a betrayal.

It is wrong here. keel's rules are a closed registry and its idiom is the un-overridable rail --
and "a helper the author must remember to call" has a track record in this repo: rules seed
printed "Do not leave live-seeded rules in place afterwards", and they were left in place for two
months. A gate that can be forgotten is a gate that will be.

Scope

No trading calendar, no holiday list, no timezone handling -- all of that already arrives from
the venue through BrokerCapabilities and is already being recorded. This issue is only about
consuming what is there.

Related: the validated-conditions issue (same class -- evidence and execution must agree about
the shape of the feed).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    featureNew capability (groups under Features)railsUn-overridable safety rail / guard (Compliance & rails)

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions