Your strategy's stop loss works great on Gold — but how does it hold up on Bitcoin? Will the same take-profit target that nails EURUSD also work for GBPJPY? Until now, you had to guess, or run separate workflows for every symbol and stitch the results together manually.
The Parameter Loop worker doesn't care what symbols your strategy trades. Connect a multi-symbol data fetcher and your strategy runs exactly the same way for every asset — but the Parameter Loop adds a second dimension: it also sweeps the parameters.
The result is a 3D optimization grid:
Symbol × Stop Loss × Take Profit = Total Iterations 3 × 5 × 5 = 75
Every combination runs automatically. The best parameter set for XAUUSD might be different from the best set for BTCUSD — and the results table shows you both.
The Swing Finder detects swing points across all three independently. The Backtest evaluates each symbol's signals separately and returns combined statistics.
Find parameters that balance risk across all assets
Cross-market validation
If parameters only work on one symbol, they're overfitted
Volatility regime testing
See which symbol needs tighter SL vs wider TP
Strategy generalization
Build strategies that adapt to any market, not just one
Live Production: Auto-Deploy Per-Symbol Parameters
Save the sweep results as a session, then set the Backtest's Production Mode to use_best. On every scheduled run, the optimized parameters load automatically — no re-sweep needed.
The takeaway: One workflow, one sweep, unlimited symbols. Stop guessing which parameters work where — let the Parameter Loop find out.
Strategies are easy to invent and hard to tune. The same trading idea can be profitable with one combination of (stop_loss, take_profit, size) and a money pit with another. Until now ApudFlow forced you to either hand-pick numbers or write one-off Python scripts (sweep_workflow.py, optimize_swing_strategy.py) outside the platform. The new Parameter Loop worker changes that — you describe the parameter grid once, click Run sweep, and watch every iteration stream into a results table inside the workflow editor.
Parameter Loop runs a single sub-worker multiple times with a different combination of input parameters on every iteration and stores the result of every iteration. The cartesian product of all values lists is executed, so a 3 × 5 grid produces exactly 15 iterations. The result of every iteration is rendered as a row in the right-hand panel of the dialog; the winning iteration (per rankingField / rankingMode) is highlighted in green, failures in red.
It is the worker you reach for when you are trying to answer "which combination of parameters is best?":
backtest → find the best (stop_loss, take_profit, size) triple
The node has its own custom rendering: a dashed border on the canvas (it is a sink — it has no input handle and no output handle) and a two-column layout inside the dialog. The left column holds the sweep configuration (sub-worker selector, parameter grid, ranking settings); the right column holds the per-iteration results table. There is no "central settings" column and no "output of the previous node" column — neither makes sense for a sweep.
The same rendering mode is now available to any worker that wants it. WorkerDefinition gained a new ui_layout field — set it to "two-column" and the dialog switches to the new layout.
subWorkerParameters is the base set of parameters passed to the sub-worker on every iteration. The sweep combination is deep-merged on top of it (the sweep value wins when the keys collide). For example, with:
…the sub-worker will see "symbol": "XAUUSD" on every iteration and "stop_loss" alternating between 2.0 and 3.0.
The sweep values are also reachable from the sub-worker's vars context as vars._sweep (a dict of all sweep values for the current iteration) and vars._sweepIndex / vars._sweepTotal, which is handy when the sub-worker wants to do early-exit logic or label its output.
collectField — dotted path of the field to extract from the sub-worker output (e.g. "result.sharpe"). Leave empty to keep the whole output.
rankingField — dotted path inside the collected result used to pick the best iteration (e.g. "sharpe_ratio").
rankingMode — "max" (default) or "min".
The best iteration is exposed as vars.<nodeName>.bestParameters and vars.<nodeName>.bestValue for downstream workers, so you can act on the winner in a follow-up step (run the best parameters through a live trade, log them to a webhook, send a Telegram notification, …).
continueOnError (default true) — keep going when an iteration throws. Set to false to stop at the first failure.
maxIterations (default 0 = no cap) — safety cap on the total number of iterations to run (useful to avoid accidentally running a 10 000-iteration sweep on a slow sub-worker).
Start with a coarse grid (3 × 3 = 9 iterations) to find the rough optimum, then refine around the winner with a finer grid.
When the sub-worker is slow, set maxIterations to a small number during development and lift it for the final run.
Use continueOnError: true while exploring so a single bad combination does not abort the whole sweep.
Always set a session label — saved sessions let you load results later and enable Production Mode's use_best functionality.
The Parameter Loop node does not route execution to a downstream graph — it is a sink. If you want to act on the result, read vars.<nodeName>.bestParameters in the next node.
Parameter Loop is in the flow category. Drop it onto a canvas, pick the sub-worker, fill in sweepParameters, and the new two-column dialog takes over from there. Happy hunting.