Sources

Sources in Flowscript

Build a source with no code to host. A Flowscript program over ftw.trade's streams, a websocket, a polled API or a contract's events, keyed, barred, warmed up and backtested.

A Flowscript source is a declared input and a program over its events, one step each. It publishes events of its own with source.emit. State carries from event to event, and across restarts.

A first source#

Tokens whose bonding curve jumped past 90%:

JSON
{
  "name": "near-grad",
  "fields": { "token": "address", "progress": "number", "jump?": "number" },
  "from": { "stream": "curves", "where": { "progress": { "gte": 90 } } },
  "key": "token",
  "flow": "uses { input: \"^1\", source: \"^1\" }\nconst e = input.event();\nwhile (e.graduated == 0) { source.emit({ token: e.token, progress: e.progress, jump: e.progress - e.progress[1] }); }"
}
  • from is the input. where filters before the program runs.
  • key names the fields that make an event unique: the same key is published once a day (dedupeFor changes that).
  • while (cond) publishes on every event cond holds for; when (cond) only when it turns true.
  • A field the program leaves na is left out, so mark it optional ("jump?").

The same source can be one .source.flow file, with the definition in a // @source { … } header above the program.

Indicator sources, ready made#

Thirteen indicators are ready as sources: RSI zones, MACD cross, Bollinger Bands, EMA cross, SMA golden and death cross, stochastic, Supertrend, Donchian breakout, CCI, ADX/DMI cross, VWAP cross, volume spike and MFI. Pick one on the Sources page (or with get_source_guide), point it at a pool, a shared feed or a venue market, and it runs on closed bars.

Every indicator source publishes the same shape: the market, the bar's open, high, low and close, its own values (rsi, macd, upper…) and a signal: +1 buy, -1 sell, 0 nothing. So anything can trade it without knowing which indicator it is, and the recipe writes the strategy that does: buy on +1, sell on -1, with the values charted as metrics.

Inputs#

InputReads
{ stream: "…" }ftw.trade's own streams: launches, graduations, curves, swaps, prices, markets, books, trades, protocols
{ socket: "wss://…", read }A websocket, each message's fields picked by path and type
{ poll: "https://…", every, read }A URL polled every second or more (GET or POST)
{ event: "Swap(…)", chain, address }A contract's events, filtered at the RPC, backfilled from a date
{ source: "…" }Another source of yours, or one you subscribe to

Up to four inputs can be merged into one series.

Streaming like a chart#

  • by: "pool" keeps one run per value of a field: on the swaps stream, ema(e.price, 20) is each pool's own average.
  • bars: { every: "1m", price: "price" } gathers events into bars and steps once each closes, even when nothing more arrives.
  • warmup: "6h" steps stored history first, so indicators are warm on the first live event.
  • since: "2026-09-01" fills the source's history from a date when it's deployed, so a strategy can backtest over it the day it's written.

Pools whose 1-minute RSI runs hot:

JSON
{
  "name": "rsi-hot",
  "fields": { "pool": "text", "rsi": "number" },
  "from": { "stream": "swaps" },
  "by": "pool",
  "bars": { "every": "1m", "price": "price", "volume": "quote", "time": "ts" },
  "warmup": "6h",
  "flow": "uses { input: \"^1\", source: \"^1\" }\nconst e = input.event();\nconst r = rsi(e.close, 14);\nwhen (r > 70) { source.emit({ pool: e.pool, rsi: r }); }"
}

Backtest a source#

backtest_flow_source (or Preview on the Sources page) steps a definition over events you give, or over stored history, and shows what it would have published, before you save or deploy anything.

A source as a market#

A strategy can run on a source's own bars with series: "source:<name>", so a websocket feed aggregated with bars becomes a market to backtest and trade. Sources keep 30 days of events.

Polls on demand#

A poll with no every runs only when asked: a strategy asks with poll.source({ name }), a workflow with a poll step that waits for the fresh value.