How to Get Started With Signal Trading on BitPerp
BitPerp can receive signals from TradingView — or any platform that can send a webhook — and execute perpetual-futures orders on your account automatically. You create a trading instruction on BitPerp, paste its private webhook into your alert, and from then on your strategy trades itself.
Updated September 2026 · 8 min read
How it works
An instruction is a saved trading rule: one pair, one direction, one size, one leverage. It has its own private webhook URL and its own passphrase. When your indicator fires an alert, TradingView posts that passphrase to that URL, BitPerp checks both, and places the order.
The important design decision, and the one that differs most from other platforms: the alert never decides how much you trade. Size, leverage and direction come from the instruction you saved, not from the message body. A tampered or replayed alert cannot resize your position, flip its direction, or trade a different pair. The only thing the message may influence is an optional take-profit price, and even that is validated before it is used.
Set the pair, direction, margin and leverage once. You receive a webhook URL and an alert message.
The URL goes in the Notifications tab, the message goes in the Message box.
Every time the alert fires, the order is placed. Results appear under each instruction on the Signals page.
Signal Trading lives at bitperp.com/signal-trading, reachable from the Automate link in the site navigation.
Step 1 — Create an instruction
Open the Signal Trading page and sign in. Fill in the form on the left:
| Field | What it does |
|---|---|
| Name | A label for you only, up to 15 characters. It is never sent to the exchange. |
| Trading pair | Any pair BitPerp lists for perpetual futures, written as BTC-USDT. Start typing to search. Crypto and TradFi pairs both work. |
| Direction | Long or Short. One instruction handles one direction, so a strategy that trades both ways needs two instructions and two alerts. |
| Margin (USDT) | The exact margin committed each time this instruction opens. This is the sizing input, and it is fixed at creation. |
| Leverage | 1× to 50×. Applied to the pair before the order is sent. |
| Take profit % / Stop loss % | Optional, measured from entry. Leave empty for none. See Take profit and stop loss. |
| Margin mode | Cross or Isolated. |
| Reverse mode | Off by default. When on, an opposite-direction signal closes the existing position first. See Reverse mode. |
| Publish as a public signal | Off by default. When on, every position this instruction opens becomes a shareable card on the Signals page. |
Press Create webhook. The new instruction appears on the right with three things to copy:
- Webhook URL — unique to this instruction, containing a long random token.
- Alert message — OPEN — the JSON that opens a position.
- Alert message — CLOSE — the JSON that closes it.
There is a fourth option, Alert message — OPEN + TP from indicator, for strategies that calculate their own take-profit level. Use it only if your Pine script plots one; the take-profit section explains how.
Step 2 — Configure your TradingView alert
In TradingView, open your indicator and press Create Alert.
- Under Condition, select your indicator and the alert condition that matches this instruction's direction — a long instruction pairs with your buy condition, a short instruction with your sell condition. Mixing them is the single most common setup mistake.
- Set Trigger to
Once per bar closeunless you deliberately want intrabar entries. - Open the Notifications tab, tick Webhook URL, and paste the instruction's webhook URL. Ticking the box matters: without it the alert fires but sends nothing.
- Back in Settings, clear the Message box and paste the instruction's alert message.
- Press Create.
{{plot("TP")}}. That is
expected — TradingView cannot validate JSON while the placeholder is still unfilled. The value is
substituted at fire time. Press Apply anyway.Repeat for the closing alert, using the same webhook URL and the CLOSE message. A close signal always flattens the whole position for that instruction's direction.
Alert message reference
Every message is a small JSON object. Only three keys are read; anything else is ignored.
| Key | Required | Meaning |
|---|---|---|
passphrase | Yes | The instruction's secret. Must match exactly. |
action | Yes | open or close. The aliases buy/long/enter and sell/exit/flat are also accepted. |
tp_price | No | An absolute take-profit price calculated by your indicator. |
Open a position
{"passphrase":"your-passphrase","action":"open"}
Open with a take-profit from your indicator
{"passphrase":"your-passphrase","action":"open","tp_price":{{plot("TP")}}}
Close the position
{"passphrase":"your-passphrase","action":"close"}
action is a verb, not a direction. A short instruction receiving
"action":"open" opens a short — the direction was already decided when you created
the instruction.
How your order size is decided
Size comes from two numbers you set on the instruction, and nothing else:
notional = margin × leverage
quantity = notional ÷ current market price
Worked example. An instruction with 50 USDT margin at 10× on BTC-USDT, with BTC trading at 76,000:
- Notional: 50 × 10 = 500 USDT
- Quantity: 500 ÷ 76,000 = 0.0065 BTC (rounded to the pair's quantity precision)
- Margin required: 50 × 1.02 = 51 USDT free, the extra 2% covering fees and slippage
Before every open, BitPerp checks that your free margin actually covers that requirement. If it does not, the order is skipped rather than sent and rejected, and the reason is recorded on the instruction. Orders are also checked against the pair's minimum quantity and minimum notional, and against a hard ceiling described under Safety limits.
All signal orders are placed at market, which means they pay the taker fee. See the fee breakdown for current rates.
Take profit and stop loss
Both are attached to the opening order itself, not sent afterwards. That matters: a follow-up call can arrive before the market fill registers and be lost, leaving the position briefly unprotected. There are two ways to set them.
As a percentage, on the instruction
Fill in Take profit % or Stop loss % when you create the instruction. They are measured from the entry price, in the profitable and losing direction respectively. This applies to every position the instruction opens.
As an absolute price, from your indicator
If your strategy calculates its own target — a Fibonacci extension, a measured move, a prior
swing — send it as tp_price and it takes precedence over the percentage.
For TradingView to substitute {{plot("TP")}}, your script must expose a
plot() whose title is exactly TP. A line.new() or a label
is invisible to alert placeholders, so drawing the level on the chart is not enough by itself.
Add a series alongside it:
// Alert placeholders read plot() titles only. display.none keeps the
// chart unchanged while still exposing the value to the alert.
tpAny = longSignal ? tpLong : shortSignal ? tpShort : na
plot(tpAny, title="TP", display=display.none)
The title is case-sensitive. If the placeholder is not substituted, BitPerp still honours the alert and opens the position without a take-profit rather than discarding the signal.
Why a level can be rejected
An absolute level is only accepted when it sits on the correct side of entry and between 0.05% and 50% away from it.
The lower bound is not caution for its own sake. A market round trip costs roughly 0.12% in taker fees, so a target sitting 0.03% from entry loses money every single time it is hit. Placing it would be worse than not placing it. When a level is rejected the position still opens, and the instruction's status line on the Signals page tells you why — for example "TP skipped: only 0.033% from entry, below the 0.05% minimum".
Levels are replaced, not stacked
When a new signal arrives for a side that is already open, the previous take-profit and stop are cancelled once the new order succeeds. Cancelling only after the new order is accepted means the position is never momentarily unprotected. Closing or reversing a position also clears any conditional orders left on that side.
Reverse mode
With Reverse mode on, opening one direction first closes the opposite one. A short signal cuts any open long on that pair before entering, and the other way round.
This suits strategies where an opposite signal means the trend has turned and the old position should not survive it — a reversal system, for instance. Leave it off for anything that needs to hold both sides at once, such as a hedge: with it on, each signal would close the other leg and the hedge would collapse.
Reverse mode only touches the opposite side of the same pair. Positions on other pairs are never affected.
Publishing your signals
Tick Publish as a public signal and every position this instruction opens is recorded as a card with its own link, listed on the Signals page. A card shows the entry, take-profit and leverage exactly as executed, so it always reflects a real trade with your own money at risk.
Anyone who opens the link can copy the trade onto their own BitPerp account, sized as a percentage of their own free margin that they choose before confirming. Your keys are never involved and you cannot manage or close anyone else's position.
When your position closes — whether you close it manually, a close signal arrives, or the take-profit fires at the exchange — the card is marked closed and its final result is frozen on the page.
Safety limits
These apply to every instruction and cannot be raised from the alert body.
| Limit | Value | Why |
|---|---|---|
| Instructions per account | 20 | Keeps a compromised session from creating an unbounded number of live webhooks. |
| Margin per instruction | 2,000 USDT | Caps the exposure any single automated rule can commit. |
| Leverage | 50× | Platform maximum for signal execution. |
| Order notional | 5,000 USDT | A hard ceiling on margin × leverage, checked on every open. |
| Duplicate window | 15 seconds | An identical signal repeated inside this window is ignored, so a retried or double-fired alert cannot open twice. |
| Requests per webhook | 30 per minute | Rate limit per instruction. |
| Copy size, published signals | 20% of free margin | Ceiling on what a follower can commit to one signal. |
Troubleshooting
TradingView shows "401 Unauthorized"
The webhook URL and the passphrase belong to different instructions, or to one that no longer exists. Each alert needs the URL and the message from the same card. The most frequent cause is a long instruction's URL paired with a short instruction's message. Recopy both from the same card using its Copy buttons.
TradingView shows "request took too long and timed out"
This should no longer occur. BitPerp answers the webhook as soon as your alert is authenticated and places the order immediately afterwards, so the reply lands well inside TradingView's three-second window. Because of that, a successful delivery in TradingView means your signal was received, not that the exchange accepted the order — check the instruction's status line on the Signals page for the actual outcome.
The alert fired but no position opened
Look at the instruction's Last line on the Signals page. It records the real result: insufficient margin, size below the exchange minimum, instruction paused, or an error returned by the exchange. If the line has not updated at all, the alert never reached us — check that the Webhook URL checkbox is actually ticked in the alert's Notifications tab, and that the alert condition matches the instruction's direction.
The position opened without a take-profit
Either your script does not expose a plot() titled TP, or the level
was rejected for being too close to entry. The status line distinguishes the two. See
Take profit and stop loss.
The take-profit price differs slightly from my chart
Prices are rounded to the pair's tick size before being sent, because the exchange rejects any price with more precision than the pair allows. On BTC-USDT that is one decimal place, so 75,976.77 is registered as 75,976.8. A difference larger than one tick is not rounding and worth reporting.
Notes and limitations
- Signal trading uses the funds in your BitPerp perpetual-futures account. Keep enough free margin available or opens will be skipped.
- TradingView's webhook feature requires a paid TradingView plan.
- Any platform that can send an HTTP POST with a JSON body works — TradingView is simply the most common.
- Signal delivery depends on an external platform. Signals can be delayed or lost, and BitPerp cannot act on one it never receives.
- An instruction can be paused at any time with the Pause button. A paused instruction accepts and acknowledges alerts but places no orders.
- Deleting an instruction stops its webhook immediately. Existing positions are not closed.
- If you are a copy-trading leader, positions opened by your signals are copied by your followers like any other trade.
Risk warning. Perpetual futures are leveraged products carrying a high risk of loss. Automation does not reduce that risk — it removes the pause between a signal and an order, so a flawed strategy loses money faster than a manual one. Test with small size before committing real capital, and never automate a strategy you have not watched trade. Nothing on this page is investment advice.