Trade Command Anatomy & Auto-Mapping
The JSON you send is not the JSON the exchange receives. TVH runs a fixed auto-mapping step that adjusts the payload before it reaches the exchange. This page documents exactly what it changes, so an unexpected entry or close never catches you off guard. For the map of every field, start at Advanced Trade Options.
- Normal webhook/manual payloads should set
isBuy,isSell, orisClosedirectly.orderTypeis for TradingView strategy-alert templates such as{{strategy.order.action}}. strategyCommentcontainingclose,exit, orflat(case-insensitive) auto-triggers a position close, even with an entry-shaped payload.stopLossExpressionandtakeProfitExpressionare evaluated server-side with sign-flipping based onorderType.- TradingView Pine placeholders (
{{ticker}},{{close}},{{strategy.order.price}}, etc.) are substituted by TradingView before the webhook fires — TVH never sees the curly braces.
Lifecycle from Pine to position
A couple of receiver-side details that occasionally surprise:
- The webhook body is URL-decoded and then has every
=stripped before JSON parsing. This compensates for TradingView'sapplication/x-www-form-urlencodedquirk. You don't need to encode anything specially — but JSON values that contain literal=characters will lose them. - Property matching is case-insensitive.
Exchangeandexchangeboth work. Stick with camelCase for clarity.
Auto-mapping: what the server changes
Right after it parses your JSON, the server runs the auto-mapping step on every payload. It performs four adjustments. Each one is documented below with the exact rule and an example of when it bites.
1. Strategy-alert orderType → boolean flags
For TradingView strategy alerts, TVH can derive isBuy, isSell, isClose (and sometimes isMarket, chaseLimitOrder) from the orderType string field. For normal webhook/manual commands, set the boolean direction fields directly.
orderType (case-insensitive) | Flags set |
|---|---|
"buy" | isBuy = true, isSell = false, isClose = false |
"sell" | isBuy = false, isSell = true, isClose = false |
"close" | isBuy = false, isSell = false, isClose = true, isMarket = true; also chaseLimitOrder = false unless useLimitClose is true |
Use orderType when your alert maps {{strategy.order.action}}. Otherwise set the booleans directly. The applied recipe is in Strategy Alerts → closed-source automation.
2. strategyComment → auto-close
If strategyComment contains any of the substrings close, exit, or flat (case-insensitive), TVH overrides the direction flags into a close:
isBuy = false
isSell = false
isClose = true
isMarket = true
chaseLimitOrder = false // unless useLimitClose=true
This wins even if you set orderType: "buy". So any comment containing close (e.g. "Closed above EMA") flips an entry into an exit.
- Custom keywords: set
strategyCloseValueto a token or pipe-separated list ("TP|SL|Ex Short") to register additional close triggers. It does not replace the built-inclose|exit|flatscan — that always runs first, so those three words still force a close regardless ofstrategyCloseValue. - Hedge mode: when the close triggers,
closeLong/closeShortare reconciled withorderTypeso only the matching side is closed.
Worked examples for both (closed-source automation, custom tokens, hedge reversals) are in Strategy Alerts → closed-source automation.
3. stopLossExpression → arithmetic evaluation
When stopLossType="absolute" and stopLossExpression contains any of + - * /, TVH evaluates the expression server-side and writes the result to stopLoss.
{
"stopLossType": "absolute",
"stopLossExpression": "3660-0.02*3660"
}
After parsing: stopLoss = 3592.8.
Smart sign-flip: TVH adjusts operators so the SL ends up on the correct side of entry, based on orderType:
orderType | Operator in expression | Auto-flipped to |
|---|---|---|
"sell" | - | + |
"buy" | + | - |
That way the same Pine template works for longs and shorts:
stopLossExpression = "{{strategy.order.price}}-0.02*{{strategy.order.price}}"
- On a long (
orderType="buy"): SL = entry − 2% = below entry. Correct. - On a short (
orderType="sell"): sign flips to+, SL = entry + 2% = above entry. Also correct.
Same machinery for take-profit: takeProfitExpression updates targets[0].price when targetType="absolute". The sign-flip is inverted (TPs sit on the opposite side of entry vs SL).
Errors are silently swallowed. If the expression can't be evaluated (e.g. you used ^ for power, which isn't supported), TVH does nothing. stopLoss stays at its prior value (often 0, which means no stop is placed). Test your expressions before you go live.
Full operator list and patterns in Math Expressions.
4. useLimitClose gate on close-chase
When the payload is forced into close mode (by orderType="close", a comment match, or a custom strategyCloseValue match), TVH also sets chaseLimitOrder = false — unless useLimitClose is true. This protects against accidental limit-chase loops on exit signals where the user expected a market close.
Default values to be aware of
These are the built-in defaults. Sending the field is optional; omitting it gives you the default behaviour shown below.
| Property | Default | Implication if you forget |
|---|---|---|
postOnly | true | Limit orders are maker-only. A marketable limit price is rejected silently. Flip to false for taker fills. |
unitsType | "absolute" | units is interpreted as base-asset quantity. Switch to "percent" for balance-relative sizing. |
targetType | "percent" | Use targets[].takeProfitPercent for percent-distance targets. Set "absolute" to use fixed targets[].price levels. |
limitPriceType | "fixedPrice" | TVH uses your price verbatim. Other values pin to top-of-book. |
retries | 1 | One re-send on a Binance overload (server-busy) response. Capped at 10; not a general cross-exchange retry. |
updateLimitOrderTimeInterval | 20 (seconds) | 20 s between chase attempts. With the fixed 180-attempt budget, that's a ~1 hour chase by default. |
positionSide | "net" | OKX one-way mode. Set "long" / "short" for OKX hedge mode. |
workingType | "mark" | Binance Futures: SL/TP triggers off mark price (safer). "contract" uses last trade price. |
stopLossSizeType | "currentPosition" | SL sized to whatever the entry actually fills. Preferred over "absolute". |
partialCloseType | "percent" | partialCloseValue is a percent of position. |
partialCloseAsset | "quote" | When partialCloseType="absolute", the value is in quote currency. |
These defaults match what the live webhook applies, so the table above always reflects current behaviour.
Dynamic values via TradingView placeholders
Placeholders like {{ticker}} or {{strategy.order.price}} are replaced by TradingView with live values before the webhook is posted. By the time the auto-mapping step runs, the curly braces are gone and the fields already hold real values, which is why TVH never sees a literal {{...}}. Booleans can't be placeholder-driven; strings, decimals, and integers can (the tv_placeholder_compatible column in the Parameter Reference marks which).
- Full token list: Pine Placeholders.
- Applied to strategy alerts: Strategy Alerts → useful placeholders.
Next
You now know what the server does on top of your JSON. Hop to the Parameter Reference for the full sortable table, or jump straight to a category like Core or Stop Loss.