Formulas in webhook payloads
You can now use formulas in your webhook JSON payloads to dynamically calculate field values. Any string value that starts with = is evaluated as a formula before the trade is processed.
Formulas can be used on most top-level fields and on takeProfit and stopLoss sub-fields. The ticker, action, test, and cancel fields must always be literal values and cannot use formulas.
Referencing payload fields
Reference other fields in the same payload using the signal. prefix:
{
"ticker": "AAPL",
"action": "buy",
"signalPrice": "195.50",
"limitPrice": "=signal.signalPrice + 0.05"
}
Numeric strings are automatically coerced to numbers, including values with commas (for example "1,234.50").
Supported operators
- Arithmetic:
+,-,*,/,% - Comparison:
==,!=,<,>,<=,>= - Logical:
and,or,not,|| - Ternary:
condition ? valueIfTrue : valueIfFalse - String concatenation:
~ - Containment:
in,not in - String tests:
contains,starts with,ends with
Exponentiation (**), ranges (..), and regex matching (matches) are not supported.
Math functions
| Function | Description | Example |
|---|---|---|
abs(x) |
Absolute value | =abs(signal.delta) |
ceil(x) |
Round up to nearest integer | =ceil(signal.value) |
floor(x) |
Round down to nearest integer | =floor(signal.value) |
min(a, b, ...) |
Minimum of two or more values, or of an array | =min(signal.a, signal.b) or =min(signal.values) |
max(a, b, ...) |
Maximum of two or more values, or of an array | =max(signal.a, signal.b) or =max(signal.values) |
round(x) |
Round to nearest integer | =round(signal.closePrice) |
round(x, precision) |
Round to a number of decimal places | =round(signal.closePrice, 2) |
round(x, precision, mode) |
Round with a specific rounding mode | =round(signal.value, 0, rounding.halfEven) |
For round(), the optional third argument accepts a rounding mode integer (1–8) or a named mode via rounding.*:
rounding.halfAwayFromZerorounding.halfTowardsZerorounding.halfEvenrounding.halfOddrounding.towardsZerorounding.awayFromZerorounding.negativeInfinityrounding.positiveInfinity
Examples
Limit price offset on buy and sell:
{
"ticker": "AAPL",
"action": "buy",
"orderType": "limit",
"signalPrice": "195.50",
"limitPrice": "=signal.signalPrice + 0.05"
}
{
"ticker": "AAPL",
"action": "sell",
"orderType": "limit",
"signalPrice": "195.50",
"limitPrice": "=signal.signalPrice - 0.05"
}
Stop price from a previous candle low:
{
"ticker": "AAPL",
"action": "buy",
"orderType": "stop",
"prevCandleLow": "194.20",
"stopPrice": "=signal.prevCandleLow - 0.10"
}
Conditional quantity based on sentiment:
{
"ticker": "AAPL",
"action": "buy",
"sentiment": "long",
"quantityType": "percent_of_equity",
"quantity": "=signal.sentiment == \"long\" ? 100 : 25"
}
Multiple formula fields in one signal:
{
"ticker": "TSLA",
"action": "buy",
"closePrice": "450.25",
"limitPrice": "=signal.closePrice + 0.50",
"quantity": "=signal.closePrice > 400 ? 1 : 5"
}
Conditional order type:
{
"ticker": "TSLA",
"action": "buy",
"closePrice": "150.25",
"orderType": "=signal.closePrice > 200 ? \"limit\" : \"market\""
}
Take profit and stop loss with formulas:
{
"ticker": "TSLA",
"action": "buy",
"limitPrice": "100.456",
"takeProfit": {
"limitPrice": "=round(signal.limitPrice + 10, 1)"
},
"stopLoss": {
"type": "stop",
"stopPrice": "=signal.limitPrice - 2.5"
}
}
Using min and max with an array:
{
"ticker": "TSLA",
"action": "buy",
"values": [5, 2, 8],
"quantity": "=min(signal.values)"
}
Rules and limitations
- Formulas are only supported on top-level fields and inside
takeProfitandstopLossobjects. - You cannot reference another formula field — chained formulas are not supported. Send literal values for intermediate calculations instead.
- Field references must use the
signal.prefix (for examplesignal.closePrice, notclosePrice). - Formulas must resolve to a string, number, boolean, or null. Array results are not allowed.
- Each formula expression is limited to 500 characters.