Declaring a feed
A feed is declared withsources.DataFeed in place of sources.Csv:
- The URL scheme selects the transport:
wss://is WebSocket,https://is SSE. Insecurews://andhttp://are rejected. stale_afteris optional: how long the feed may stay silent before the platform treats the stream as quiet. Whole seconds only. When omitted, the platform default applies (currently 90 seconds).
@dataclass and process records with a @data_context callback, or read them directly
with request_series. The schema rules from that page apply; the fields of a record’s JSON payload are matched to
dataclass fields by name.
Live model signal
- There is no
time_frame. A feed has no cadence: records are point-in-time events. In loaded history a record is visible from the first chart bar that opens at or after its timestamp; a live record that lands inside the current bar is applied immediately and revises that bar. Passingtime_frame=next to a DataFeed source is an error, and so islookahead=, which requires a time frame. - There is no candle mode: a
@sec_contextcallback does not accept a DataFeed source. - The server must be publicly reachable. There is no authentication in this version; if you need access control, put a signed token into the URL query string — it is passed through unchanged.
How much history a live run starts with
A live run does not have to start empty. What fills it depends on how the chart was launched. There is no separate setting for feeds and nothing to declare in code. Launched by history depth. The past comes from the platform’s own rolling buffer, which holds the recent records of every feed it is connected to — currently the last 1,000 records or 4 MiB per feed, whichever fills first. Your server is not asked for anything. Launched from a date. The platform loads the range before the run starts. It opens a short connection to your feed, asks for the records from that date up to the present, and subscribes for live records only after the answer is in. A feed that answers replay requests can start a run with far more past than the buffer holds.A run launched from a date
Sma.new(self._price, 50) over feed records. Without warm-up it stays empty until
50 live records arrive; at one record per minute that is most of an hour. With warm-up the past arrives first, and
if it covers 50 records the average has a value right away. The code is the same in both cases.
Warm-up is best effort. When it comes up short the series starts shallower and grows on live records, which is a
normal outcome rather than an error:
- A depth launch never reaches further back than the buffer.
- A date launch on a feed that ignores replay requests gets only what the buffer holds.
- A date launch whose collection is cut short — the feed goes quiet part-way through, or the range is larger than the platform loads at once — drops that collection whole and starts from the live stream.
Reconnects and gaps
Connections drop: your server restarts, the network blips, the platform redeploys. The platform reconnects on its own; you do not write any of this logic. What a reconnect recovers depends on where the break happened. A break inside the platform is healed from the buffer: if the buffered past reaches back to the last delivered record, the stream continues without a hole. A break between the platform and your server is different: the platform reconnects and resumes with live records, but it does not ask your server to resend, so records published during the outage are lost. Either way the stream continues, and a hole is not repaired later.Runs over a date window
A strategy launch with both dates set does not open a live stream at all. The platform collects the records of the window, the script computes over them and finishes. Window records come from a single source, never merged: the feed’s replay answer when the feed gives one, the platform’s buffer otherwise. A feed that answers and finishes with areplay_done frame, even for an empty window, has said that this is all
the history it has, and the script computes on it. A feed that starts answering and stops part-way is a different
case: the platform cannot tell a whole window from a truncated one, so the run ends with
external_feed_replay_interrupted rather than computing on a range it cannot vouch for. A window larger than the
platform loads in one batch ends with external_feed_window_limit, and narrower dates fix it.
Errors and quiet streams
When a feed fails for good, the indicator stops and shows the error code followed by a short explanation, the same form CSV errors take — for exampleexternal_feed_gone: the data feed is no longer available. The codes are:
The URL is validated when the indicator instance is created, before any connection:
invalid_url,
scheme_not_secure, userinfo_not_allowed, ipv6_literal_not_supported, non_ascii_host mirror the
CSV declaration errors, and
stale_invalid rejects a stale_after that is not a whole positive number of seconds. Passing time_frame=
next to a DataFeed source fails with datafeed_time_frame_not_supported.
Not everything stops the script:
- Silence is not an error. A feed quiet for longer than
stale_afteris treated as stale; the script keeps its last values and the stream continues when records resume. - Reconnects and gaps are not errors: see above.
- Rate limiting is not an error. When the server answers 429 or refuses connections because of load, the platform waits and retries with increasing delays.
What is not promised
The feed contract is best effort end to end:- Completeness is not guaranteed. The platform does not verify that the feed sent everything; a record the feed did not deliver does not exist.
- Holes are not backfilled. A series already delivered to the script is not rewritten; the one exception is a record with the same timestamp as the latest one, which replaces it as a newer revision.
- A record can arrive twice around reconnects. Duplicates at the seam are collapsed by timestamp, so the script sees each logical record once.
- Feed data lives in platform memory. A platform restart can reset the loaded series; warm-up then refills what the buffer and the feed still hold.