Parameters: Param, ParamToggle, ParamList and ParamColor
An indicator you have to edit in order to change is a script. An indicator whose settings live
in a dialog is a tool. The difference is the Param* family, and getting it right takes about
twenty minutes of learning that will save you years of opening the Formula Editor to change a
number from 20 to 21.
Press Ctrl+R over any chart pane and the Parameters dialog opens, showing every Param*
call in that pane’s formula. Move a slider and the formula re-runs immediately.
The family, with exact signatures
Section titled “The family, with exact signatures”Every one of these is copied from the official function pages. The return types are the part people get wrong.
| Function | Signature | Returns |
|---|---|---|
Param |
Param( name, defaultval, min, max, step, sincr = 0 ) |
NUMBER |
ParamStr |
ParamStr( name, default ) |
STRING |
ParamColor |
ParamColor( name, defaultcolor ) |
NUMBER |
ParamStyle |
ParamStyle( name, defaultstyle = styleLine, mask = maskDefault ) |
NUMBER |
ParamField |
ParamField( name, field = 3 ) |
ARRAY |
ParamToggle |
ParamToggle( name, values, defaultval = 0 ) |
NUMBER |
ParamList |
ParamList( Name, Values, defaultval = 0 ) |
STRING |
ParamDate |
ParamDate( Name, "default date", format = 0 ) |
NUMBER or STRING |
ParamTime |
ParamTime( Name, "default time", format = 0 ) |
NUMBER or STRING |
ParamTrigger |
ParamTrigger( Name, "Button text" ) |
NUMBER |
Two rules apply to all of them. Parameter names and values must not contain non-printable
characters — codes below ASCII 32. And the default, min, max and step arguments must be
constant numbers: they are cached and are not re-read on later evaluations, so feeding them
a variable gives silently stale slider bounds.
Param() — the numeric slider
Section titled “Param() — the numeric slider”Fragment — not a complete formula
MaPeriod = Param( "Periods", 50, 2, 400, 1, 10 );Name, default, minimum, maximum, step, and then the sixth argument almost nobody uses:
sincr, the section increment. When the same drag-and-drop section is dropped into a pane
more than once, each new copy’s default is bumped by this amount. AmiBroker’s own moving
average ships with a default of 15 and an increment of 10, so dropping it twice gives you a
15-period average and a 25-period one rather than two identical lines.
The dialog cannot exceed the max you coded. If you want Bollinger periods above 100 you have
to raise the number in the formula; there is no user-facing override.
ParamToggle() — two states
Section titled “ParamToggle() — two states”Fragment — not a complete formula
ShowBands = ParamToggle( "Bands", "Hide|Show", 1 );if( ShowBands ) { /* draw them */ }The values argument is required and holds the two display labels separated by a pipe, with
the first label meaning false and the second meaning true. The function returns a
NUMBER — 0 or 1. The labels are decoration.
The single most common ParamToggle mistake is comparing the result against text:
if( ShowBands == "Show" ) is always false. Treat it as the Boolean it is.
ParamList() — a drop-down
Section titled “ParamList() — a drop-down”Fragment — not a complete formula
AverageName = ParamList( "Average", "Simple|Exponential|Weighted", 0 );Here the return really is a STRING — the label the user chose, not its index. Meanwhile
the third argument is an index: the zero-based position of the default item. Getting those
two backwards is the classic ParamList bug, and it fails quietly, because comparing a string
against a number simply never matches.
The delimiter is documented as “| or comma separated”, so both work. The corollary is that a
choice label cannot itself contain a comma or a pipe.
ParamColor() — a colour picker
Section titled “ParamColor() — a colour picker”Fragment — not a complete formula
LineTint = ParamColor( "Line colour", colorCycle );colorCycle is a special default accepted only by ParamColor. It makes each newly
dropped copy of a section pick the next colour in a fixed rotation — the colour equivalent of
Param’s sincr. Do not pass it to Plot(); that is not documented behaviour.
ParamStyle() — a style picker
Section titled “ParamStyle() — a style picker”Fragment — not a complete formula
LineStyle = ParamStyle( "Style", styleLine | styleThick, maskDefault );The mask argument decides which style flags appear in the drop-down.
maskDefault offers thick, dashed, hidden and own scale; maskPrice adds candle and bar;
maskHistogram offers histogram and area; maskAll offers everything. If a style you expect
is missing from the list, the mask is why.
ParamStr() — free text
Section titled “ParamStr() — free text”Two arguments only: name and default string. There is no validation, so a mistyped ticker
handed to Foreign() or PlotForeign() simply produces nothing rather than an error.
ParamField() — the odd one out
Section titled “ParamField() — the odd one out”Fragment — not a complete formula
Source = ParamField( "Price field", 3 );MyAverage = MA( Source, 20 );ParamField is the only member of the family that returns an ARRAY — the chosen data
series itself. The field argument selects the default: 0 Open, 1 High, 2 Low, 3 Close
(the default), 4 the average of high, low and close, 5 Volume, 6 Open Interest, and 7 upwards
the indicators already inserted into the pane, in insertion order.
The value −1 is the interesting one. It means “the first indicator inserted into this pane, or Close if there is none”, and it is what makes drag-and-drop chaining work — dropping a moving average onto an RSI pane gives you an average of the RSI. Hard-coding 3 breaks that behaviour for anyone who uses your formula the way AmiBroker intends.
ParamTrigger() — a button
Section titled “ParamTrigger() — a button”Fragment — not a complete formula
Rebuild = ParamTrigger( "Maintenance", "Rebuild cache" );if( Rebuild ){ // Runs exactly once, on the refresh caused by the button press.}ParamTrigger normally returns 0. When the button is pressed it refreshes the chart and
returns 1 for that single execution only; every later refresh returns 0 again. That makes
it a one-shot action, not a switch. Anything that has to persist beyond that one execution has
to be written somewhere persistent, which in AFL means a static variable — covered in Part 11.
Guard it carefully. A chart pane is re-evaluated for many reasons: a new tick, a zoom, a symbol change. The trigger returning 1 is tied to the press, but the side effect you perform is not automatically safe to repeat.
ParamDate() and ParamTime()
Section titled “ParamDate() and ParamTime()”Both take their default as a string and return a number by default, which is the first
trap. ParamDate format 0 returns a DateNum such as 990503; format 2, added in AmiBroker
6.20, returns a DateTime you can compare against the built-in DateTime() array.
ParamTime has no format 2 — assuming symmetry with ParamDate is a real mistake — and
its format 0 returns a TimeNum, so 09:30 becomes 93000.
Sections give parameters their identity
Section titled “Sections give parameters their identity”Fragment — not a complete formula
_SECTION_BEGIN( "Configurable MA" );// every Param* call in here belongs to this section_SECTION_END();AmiBroker identifies a parameter by section name plus parameter name. That is what lets you
drop two moving averages into one pane and have two independent “Periods” sliders: the second
section is auto-named MA1, so the two parameters have different full names.
The section name must be a literal string in double quotes. _SECTION_BEGIN( "MA" + i ) is
invalid, which rules out generating sections in a loop.
Two helpers exist for naming plots from within a section. _DEFAULT_NAME() returns the section
name followed by the values of its numeric parameters — for a section named MA1 containing a
price field and a 15-period setting, it evaluates to "MA1(Close,15)". _PARAM_VALUES()
returns just the bracketed list, so you can supply your own prefix. Both are evaluated when the
formula runs, so a title built from them tracks the sliders automatically.
Charts and Analysis keep separate values
Section titled “Charts and Analysis keep separate values”This is the behaviour that costs people the most time, and it has a simple mechanical cause.
Parameter values are stored per Chart ID — the read-only field you can see on the
Axes & Grid tab of the Parameters dialog — in a file called broker.params. And
GetChartID() is officially documented as returning 0 in Automatic Analysis.
Where a parameter value comes from
- Param() callname + section
- Chart IDthe pane, or 0 in Analysis
- broker.paramsstored value for that pair
- Value returnedor the coded default if none
Three consequences follow:
- The values you set on a chart pane have no effect on a Scan, Exploration, Backtest or Optimization. The Analysis window has its own Parameters control, and you must set them there as well. This is the second item on AmiBroker’s own checklist for “why do my Analysis results differ from my chart?”.
- Because every Analysis run shares Chart ID 0, two different formulas run from Analysis windows that happen to use the same parameter name share the same stored value. Distinctive names, or sections, prevent that.
- Two chart panes running the same formula are genuinely independent. That is a feature — it is how you compare a 20-period and a 200-period version side by side — but it also means “I changed it and nothing happened” usually means you changed it on the other pane.
Param() is not Optimize()
Section titled “Param() is not Optimize()”They look similar and do opposite things.
Fragment — not a complete formula
// Adjustable from a dialog. Constant during an optimisation run.MaPeriod = Param( "Periods", 50, 2, 400, 1 );
// Swept by the optimiser. No dialog control at all.MaPeriod = Optimize( "Periods", 50, 2, 400, 1 );During an Optimization, Param() keeps returning whatever the Analysis window’s parameter set
holds — it does not vary. Only Optimize() sweeps. A formula built entirely on Param() and
then “optimised” produces N identical rows, which is a memorable way to discover the
difference.
Designing a parameter set worth using
Section titled “Designing a parameter set worth using”Having every control available is not the same as using them well. A few principles that hold up in practice:
Expose what you would actually change; hide what you would not. Each slider is a decision the user now has to make. A tool with four meaningful settings is more usable than one with fourteen, and far more usable than one with fourteen where three of them interact.
Make the defaults the ones you would use. A formula that draws nothing useful until three parameters are adjusted will be deleted before anybody adjusts them.
Choose ranges that mean something. A period slider running 2–400 with a step of 1 offers 399 choices, most of which nobody wants. Setting the minimum to something the maths supports — 2 for an average, 1 for ATR — prevents the user producing a nonsense chart and blaming you.
Pick the right control type. A finite set of named alternatives is a ParamList, not a
Param running 1–6 that the user has to decode. An on/off is a ParamToggle, not a Param
running 0–1.
Do not let a parameter silently change what a number means. If one setting switches an output between points and percent, the title must say which is on screen. A parameter that changes the meaning of a displayed value without changing its label is how people misread their own tools.
Putting it together
Section titled “Putting it together”What we are building
Section titled “What we are building”A small study that exercises every control type in one section: a price field, a period, a band width, an averaging method chosen from a list, an on/off for the bands, a colour, a style, and a free-text symbol to overlay. The point is not the study — it is seeing all eight controls appear in one Parameters dialog and knowing which type each returns.
The formula
Section titled “The formula”Complete runnable AFL
/* * Every parameter control in one section - worked example for Part 10. * * Assumptions * - Chart pane formula. Press Ctrl+R over the pane to open the Parameters * dialog; every control below appears there, grouped under the section * name given to _SECTION_BEGIN. * - The bands are a dispersion measure, not a forecast. They say how far * price has recently wandered from its own average, nothing more. * - StDev's third argument exists from AmiBroker 6.20 onwards. */
_SECTION_BEGIN( "Parameter showcase" );
// ParamField returns an ARRAY - the only member of the family that does.// Field 3 is Close; field -1 chains onto whatever was plotted into the pane// first, which is how dropping an average onto an RSI pane averages the RSI.Source = ParamField( "Price field", 3 );
// Param( name, default, min, max, step, sincr )// The sixth argument bumps the default each time the section is dropped into// the same pane again, so two copies do not land on the same period.Periods = Param( "Periods", 20, 2, 300, 1, 10 );
// ParamList returns the chosen label as a STRING. The third argument is the// zero-based position of the default item, not the default text.AverageName = ParamList( "Average", "Simple|Exponential|Weighted", 0 );
// ParamToggle returns a NUMBER, 0 or 1. The two labels are display text only -// never compare the result against "Show".ShowBands = ParamToggle( "Bands", "Hide|Show", 1 );BandWidth = Param( "Band width (standard deviations)", 2, 0.5, 4, 0.1 );
// ParamColor and ParamStyle feed Plot()'s colour and style arguments directly.// colorCycle is accepted only as a ParamColor default.LineTint = ParamColor( "Line colour", colorCycle );LineStyle = ParamStyle( "Line style", styleLine | styleThick, maskDefault );
// ParamStr returns a STRING with no validation, so a mistyped ticker simply// draws nothing.Benchmark = ParamStr( "Overlay symbol (blank for none)", "" );
if( AverageName == "Exponential" ) Centre = EMA( Source, Periods );else if( AverageName == "Weighted" ) Centre = WMA( Source, Periods );else Centre = MA( Source, Periods );
Plot( Close, "Price", colorDefault, styleCandle | styleNoTitle );
// _DEFAULT_NAME() builds "section name (field, periods, ...)" from the numeric// parameters in this section, so a duplicated section labels itself correctly.Plot( Centre, _DEFAULT_NAME(), LineTint, LineStyle );
if( ShowBands ){ // False asks for the sample standard deviation; the documented default, // True, is the population form that matches Excel's STDEV.P. Spread = BandWidth * StDev( Source, Periods, False ); BandTint = ColorBlend( LineTint, GetChartBkColor(), 0.4 );
Plot( Centre + Spread, "Upper", BandTint, styleLine | styleDashed ); Plot( Centre - Spread, "Lower", BandTint, styleLine | styleDashed );}
if( Benchmark != "" ) PlotForeign( Benchmark, Benchmark, colorGrey40, styleLine | styleOwnScale | styleNoLabel );
_N( Title = StrFormat( "%s %s average, %g periods value %g", Name(), AverageName, Periods, SelectedValue( Centre ) ) );
_SECTION_END();How it works
Section titled “How it works”Every parameter is declared at the top, before any calculation, which is the convention worth adopting: a reader can see the whole configurable surface of a formula in one screen.
Source comes from ParamField, so it is an array and can be fed straight into EMA, WMA
or MA. AverageName comes from ParamList, so it is text and is compared with == against
the labels declared in the same call — a discipline worth keeping, since a typo in one of them
silently sends every case to the fallback branch.
ShowBands is a number and therefore usable in if(). The bands themselves are the average
plus and minus a multiple of the standard deviation, with False passed as StDev’s third
argument to request the sample form rather than the documented default, which is the
population form matching Excel’s STDEV.P.
The plot name is _DEFAULT_NAME(), so the title shows the section name and the current
numeric parameter values without any string building.
The overlay at the end shows why ParamStr needs care: an empty default means “no overlay”,
and a mistyped symbol produces nothing at all rather than an error message.
Key functions
Section titled “Key functions”ParamField( name, field )— returns the chosen price series as an array;-1chains onto the first indicator already in the pane._DEFAULT_NAME()— section name plus current numeric parameter values, as a string.StDev( array, periods, Population )—True, the default, is the population form.PlotForeign( ticker, name, color, style )— overlays another symbol without callingForeign()first. Note its default style includesstyleOwnScale.
What you should see
Section titled “What you should see”Press Ctrl+R and the dialog shows one section, “Parameter showcase”, containing a price-field chooser, two sliders, a drop-down, a two-state toggle, a colour swatch, a style drop-down and a text field. Changing any of them redraws the chart immediately.
Test it
Section titled “Test it”- Change the average from Simple to Exponential and watch the line move. Then set the period to 2 and confirm both methods converge on price, which they must.
- Drop the same formula into the same pane a second time. The two sections should be named differently and their sliders should be independent.
- Open an Analysis window, apply this formula, and open its own Parameters. Note that the values there start from the coded defaults, not from whatever you set on the chart.
- Set the overlay symbol to something that does not exist in your database. Nothing should be drawn, and no error should appear — which is exactly why a typo here is hard to spot.
Common errors
Section titled “Common errors”- A parameter change does nothing. You changed it on a different pane, or in the chart while the formula is running in Analysis.
ParamListcomparison never matches. The compared text does not exactly match a label in theValuesstring, including capitalisation and spaces.- The style drop-down is missing candles. The mask is
maskDefault; usemaskPriceormaskAll. - Sliders reset unexpectedly. A
_SECTION_BEGINmarker was deleted or renamed, so the stored values no longer match the parameter’s full name. - The optimiser reports identical results for every step. The formula uses
Param()where it needsOptimize().
Extension
Section titled “Extension”Add a ParamTrigger button labelled “Reset view” and, inside its if block, call
SetChartOptions to restore automatic scaling. Then observe the one-shot behaviour: the block
runs on the press and not on the next refresh. That is the whole of ParamTrigger’s contract.
What changed
Section titled “What changed”You now know all ten Param* functions, their exact argument orders and — more importantly —
their return types, which are what determine whether a value can go into an if, a Plot()
colour slot or a MA() call. You know that parameters are keyed by Chart ID, that Analysis
runs under Chart ID 0 and therefore keeps its own values, and that Param() and Optimize()
are not substitutes for each other.
That is the last piece of machinery. The next four pages build real tools with it.
Check your understanding
Sources for this lesson
11 verified · checked 2026-08-31
- 01AFL Function Reference — Paramamibroker.com/guide/afl/param.html2026-08-31
- 02AFL Function Reference — ParamToggleamibroker.com/guide/afl/paramtoggle.html2026-08-31
- 03AFL Function Reference — ParamListamibroker.com/guide/afl/paramlist.html2026-08-31
- 04AFL Function Reference — ParamColoramibroker.com/guide/afl/paramcolor.html2026-08-31
- 05AFL Function Reference — ParamFieldamibroker.com/guide/afl/paramfield.html2026-08-31
- 06AFL Function Reference — ParamStyleamibroker.com/guide/afl/paramstyle.html2026-08-31
- 07AFL Function Reference — ParamTriggeramibroker.com/guide/afl/paramtrigger.html2026-08-31
- 08AFL Function Reference — GetChartIDamibroker.com/guide/afl/getchartid.html2026-08-31
- 09AmiBroker User's Guide — Drag-and-drop indicator buildingamibroker.com/guide/h_dragdrop.html2026-08-31
- 10AmiBroker User's Guide — Parameters windowamibroker.com/guide/w_param.html2026-08-31
- 11AmiBroker Knowledge Base — Why Analysis results and chart output may differamibroker.com/kb/2015/01/28/why-analysis-results-and-chart-output-may-differ2026-08-31
Every technical claim on this page was checked against the official AmiBroker documentation on the date shown. Where the course disagrees with folklore, the source is how you can tell which one to trust.