Flow & Live¶
Flow wires data, detectors, strategy, and engine into a single runnable
pipeline. A Run captures the result of executing a flow. Feeds drive the flow
over historical, replayed, or live data.
Flow¶
signalflow.Flow
dataclass
¶
Flow(name: str, forecasts: dict = dict(), detectors: list = list(), strategy: object = RulesStrategy(), risk: Risk = Risk(), validator: object | None = None, quote: str = 'USDT')
The framework's central noun: what you research, promote, and trade.
required_warmup
property
¶
Bars of history the flow needs before its outputs are valid.
Max over each detector's warmup, each forecast model's feature-pipe warmup, and the validator's feature warmup. Zero when the flow has none of these.
backtest ¶
Backtest the flow. oos=True scores leak-free out-of-fold predictions and
stamps the Run promotable; the default in-sample run of a model flow is not promotable.
Source code in src/signalflow/flow/flow.py
live ¶
live(feed, capital, target: str | None = None, broker=None, armed: bool = False, max_bars: int | None = None, state_path: str | None = None)
Trade a live (or replayed) feed via the real-time loop.
feed may be a LiveFeed or a Dataset (wrapped in a ReplayFeed). Armed
trading requires an explicit ExchangeBroker; SimBroker is paper-only.
Source code in src/signalflow/flow/flow.py
paper ¶
Replay a Dataset with simulated fills - the same loop as backtest, paper mode.
Source code in src/signalflow/flow/flow.py
save ¶
Serialize the flow to YAML at path and return it.
Each forecast/validator must already have a pinned URI, or pass model_dir to
save the trained artifacts there. load restores a byte-identical backtest.
Source code in src/signalflow/flow/flow.py
simulate ¶
simulate(data, capital, target: str | None = None, broker=None, warmup: int | None = None, maxlen: int = 5000, state_path: str | None = None)
Full-speed incremental live simulation (walk-forward).
Replays a Dataset through the live decision loop with no real-time wait:
the flow sees only data up to each bar, recomputed step by step, exactly
as in live. warmup reserves a leading lookback window that fills the
buffer without trading; None resolves to :attr:required_warmup while
an explicit 0 is honored. Use it to confirm the live path before arming.
Source code in src/signalflow/flow/flow.py
signalflow.Run
dataclass
¶
Run(name: str, mode: str, equity_curve: DataFrame, fills: list[Fill] = list(), target: str = 'USDT', promotable: bool = True, oos: bool = False)
Result of executing a Flow: equity curve, fills, and derived metrics.
promotable is false for an in-sample model backtest; oos flags a
leak-free out-of-sample run.
periods_per_year ¶
Annualization factor derived from the equity curve's median bar spacing.
Source code in src/signalflow/flow/run.py
scorecard ¶
Standard metric dict: name, mode, target, promotable, oos,
n_fills, initial_equity, final_equity, total_return,
max_drawdown, and sharpe.
Source code in src/signalflow/flow/run.py
sharpe ¶
Annualized Sharpe of per-bar equity returns (zero risk-free rate).
periods_per_year defaults to the factor implied by the equity curve's median
bar spacing (:meth:periods_per_year), so hourly bars annualize by ~8760.
Source code in src/signalflow/flow/run.py
Feeds¶
signalflow.LiveFeed ¶
Bases: Protocol
Warmup history (preloaded, no trades) + a stream of newly closed bars.
signalflow.ReplayFeed
dataclass
¶
Bases: LiveFeed
Replays a finished Dataset bar-by-bar - drives the live loop at full speed.
warmup_bars splits off a leading lookback window that fills the buffer
without trading; decisions then run incrementally over the remaining bars -
a faithful walk-forward of the live cycle.
signalflow.PollingFeed
dataclass
¶
PollingFeed(source: object, pairs: list[str], interval: str = '1m', quote: str = 'USDT', warmup_bars: int | None = None, max_bars: int | None = None, lag_seconds: float = 3.0, clock: Clock = (lambda: Clock(RunMode.LIVE))())
Bases: LiveFeed
Polls a Source for newly closed klines, one yield per new bar boundary.
warmup() fetches a closed-bar history prefix to fill the buffer. stream()
sleeps to each interval boundary, fetches the latest CLOSED bar(s), and never
yields the still-forming current candle.
Live loop¶
signalflow.run_live_loop ¶
run_live_loop(flow, feed: LiveFeed, capital, broker, target: str | None = None, maxlen: int = 5000, max_bars: int | None = None, mandate: dict | None = None, state_path: str | None = None, on_bar=None, max_latency_s: float = 10.0)
Drive a Flow over a live (or replayed) feed.
Warmup history fills the buffer without trading; decisions begin on the first
streamed bar. Per live bar, decision latency (execution wall-clock minus the
bar's close time) is measured and a breach of max_latency_s is logged.
Runs are not promotable.
Source code in src/signalflow/flow/live.py
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 | |