Param()
תוכן זה אינו זמין עדיין בשפה שלך.
A Param() is a tunable strategy input. It has a default, an optional range, and optional optimizer hints. Every Param() is visible to the user in the UI and to the optimizer as a search dimension.
Its TYPE comes from its default value. Nothing else declares it, and you never have to write it down: 7 is an int, 2.0 a float, False a bool, and choices= makes a fixed set of options. 7 and 7.0 are two different declarations, so write the default the way you mean the parameter to behave.
Signature
Param(default, *, min=None, max=None, opt_min=None, opt_max=None, opt_step=None, choices=None, type=None, title=None)| Argument | Required | Notes |
|---|---|---|
default |
Yes | Sets the type: 7 = int, 2.0 = float, True = bool, "trail" needs choices=. |
min / max |
No | Hard bounds. Boundary violations reject at compile time (no silent clamping). |
opt_min / opt_max |
No | Optimizer grid range. Must be within min/max. Defaults to min/max. |
opt_step |
No | Grid step. Defaults to 1 (int) or 0.01 (float). A fractional step on an int is rejected. |
choices |
No | A fixed set of allowed values. Makes the parameter an enum. |
type |
No | int, float, bool or enum. A second opinion on the default, never a conversion. |
title |
No | The setting’s title on the run form: one text, or one per language, {"en": "…", "he": "…"}. See Titles. |
Examples
# Integer with hard boundsfast_period = Param(7, min=2, max=50)
# Floatsl_pct = Param(2.0, min=0.1, max=20.0)
# Booleanfractional = Param(False)
# Separate optimization bounds — sweep 15..100 step 5, but the user can still type 10..200slow = Param(21, min=10, max=200, opt_min=15, opt_max=100, opt_step=5)
# Enum — a fixed set of options. Three spellings: value-to-label, a bare list, strings.mode = Param(2, choices={1: "cross only", 2: "aroon", 3: "momentum"})exits = Param(0, choices=[0, 1, 2])style = Param("trail", choices=["none", "trail", "fixed"])
# Plain literal — not a Param. Appears as a constant in the editor; not optimizable.position_size = 100The four types
int, float, bool, enum. Each gets its own control and its own optimizer walk.
| Type | Declared by | Control | Optimizer |
|---|---|---|---|
int |
a whole-number default | integer slider, step 1, one stop per value | an integer grid; never hands the strategy 2.5 |
float |
a default with a decimal point | step-aware slider plus a decimal box | a decimal grid from opt_step |
bool |
True / False |
a switch | exactly {False, True} |
enum |
choices= |
the options as a checklist | the choice SET you tick, never a grid |
choices= (enum)
class ModeSwitch(Strategy): mode = Param(2, choices={1: "cross only", 2: "aroon", 3: "momentum"}) style = Param("trail", choices=["none", "trail", "fixed"]) trade = Symbol() sizing = FixedCapital()
def execute(self): fast = SMA(10, on=self.trade) slow = SMA(30, on=self.trade) if self.mode == 2 and fast.crossed_above(slow) and self.trade.is_flat: self.buy(self.trade, reason="Aroon mode")- Values stay raw.
self.modeis the integer2, not"2"and not the label, soif self.mode == 2:is how you branch. Saved parameter sets, walk-forward results, runner parameters and old backtests all keep meaning the same thing. - Labels are your strings, shown as written. The platform never translates them and never invents one; a bare list shows the values themselves.
- The default must be one of the choices, and
min/max/opt_min/opt_max/opt_stepare rejected on an enum — the choices ARE the range. - Every option is the same type, listed once, and there is at least one.
choices=[False, True]is rejected: a bool already is two values, so writeParam(False).
The explicit type=
Optional everywhere. Write it when the intent benefits from being spelled out, most often when a deliberate 0/1 integer switch sits next to a real bool:
enable_stop_loss = Param(0, min=0, max=1, type=int) # deliberate integer switchuse_trailing = Param(False) # a real booltype= never converts, so it has to agree with the default:
class TypeDisagrees(Strategy): bars = Param(2.5, type=int) trade = Symbol() sizing = FixedCapital()
def execute(self): if self.trade.is_flat: self.buy(self.trade)A 0/1 integer compiles green with a hint (RC2_PARAM_BOOL_HINT) suggesting Param(False); writing type=int silences it. Lists, dicts and tuples are still not parameters — a free-form string (a note, an arbitrary date) has no Param equivalent either; use a bool switch or split into multiple strategies.
Titles
The run form shows each setting under a title. Without title= the title is the Param’s own name, so fast_length reads as fast_length. With it, the member reads your words in their own language:
class TitledCross(Strategy): fast = Param(7, min=2, max=50, title={"en": "Fast average", "he": "ממוצע מהיר"}) slow = Param(21, min=10, max=200, title="Slow average") trade = Symbol() sizing = FixedCapital()
def execute(self): f = SMA(self.fast, on=self.trade) s = SMA(self.slow, on=self.trade) if f.value > s.value and self.trade.is_flat: self.buy(self.trade)- A dict gives one title per language. The platform speaks
enandhe. - A plain string is shown to everyone as written.
- A member whose language is missing from the dict sees the other one.
- A title is words only: changing it changes nothing a backtest, an optimizer or a live strategy does. Renaming the Param itself does, because saved values are kept by name.
title=is for strategy parameters. An indicator’s Param refuses it (RC2_PARAM_TITLE) until the indicator settings show titles.
How Params reach you
Inside execute() (or any helper method) every Param is exposed as self.<name>:
class MACross(Strategy): fast = Param(7, min=2, max=50) trade = Symbol() sizing = FixedCapital()
def execute(self): ma = SMA(self.fast, on=self.trade) # self.fast reads the Param's current valueOptimizer integration
Every Param with min/max (or opt_min/opt_max) automatically becomes a dimension in the optimizer grid. There is no separate “optimizer schema” to maintain.
fast = Param(7, min=2, max=50) # 49 values, step 1 = 49 dimsslow = Param(21, min=10, max=200, opt_step=5) # 39 values, step 5 = 39 dimssl_pct = Param(2.0, min=0.5, max=5.0, opt_step=0.5) # 10 float stepsTo freeze a Param (keep it in the UI but exclude from optimization), set opt_min == opt_max:
slippage = Param(0.5, min=0.0, max=5.0, opt_min=0.5, opt_max=0.5)Naming rules
A Param name cannot:
- Shadow a strategy-level property (
capital,initial_capital,bar_count,ready) →RC2_PARAM_RESERVED - Collide with a
Symbolname in the same class →RC2_STATE_PARAM_CLASH - Be assigned a value other than a
Param()call or a plain literal in the class body →RC2_CLASS_BODY
Common diagnostics
| Code | What it means |
|---|---|
RC2_PARAM_DEFAULT |
Param() called without a default value. |
RC2_PARAM_RESERVED |
Param name shadows a reserved property. |
RC2_PARAM_UNKNOWN_KWARG |
A keyword outside min, max, opt_min, opt_max, opt_step, choices, type, title. |
RC2_PARAM_TITLE |
title= is not text, or names a language the platform does not speak. |
RC2_STATE_PARAM_CLASH |
Param name collides with a Symbol or persistent state variable. |
RC2_PARAM_TYPE_MISMATCH |
type= disagrees with the default literal. |
RC2_PARAM_TYPE_UNKNOWN |
type= is not one of int, float, bool, enum. |
RC2_PARAM_DEFAULT_NOT_IN_CHOICES |
The default is not one of the declared choices. |
RC2_PARAM_ENUM_NO_RANGE |
A range keyword on an enum. The choices are the range. |
RC2_PARAM_ENUM_EMPTY |
choices= with nothing in it. |
RC2_PARAM_ENUM_DUPLICATE |
The same option listed twice. |
RC2_PARAM_ENUM_MIXED_TYPES |
The options are not all the same type. |
RC2_PARAM_ENUM_BOOL |
True/False as choices. Write Param(False). |
RC2_PARAM_ENUM_LABEL |
A choices dict’s values must be text labels. |
RC2_PARAM_ENUM_SHAPE |
choices= takes a list or a value-to-label dict. |
RC2_PARAM_RANGE_NOT_NUMERIC |
A range keyword on a bool or a text parameter. |
RC2_PARAM_INT_STEP |
A fractional opt_step on an integer parameter. |
RC2_PARAM_INT_BOUND |
A fractional min/max/opt_min/opt_max on an integer parameter. |