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%:
{
"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] }); }"
}fromis the input.wherefilters before the program runs.keynames the fields that make an event unique: the same key is published once a day (dedupeForchanges that).while (cond)publishes on every eventcondholds for;when (cond)only when it turns true.- A field the program leaves
nais 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#
| Input | Reads |
|---|---|
{ 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:
{
"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.