Engineering · 2026.10.06 · 6 min · Updated 2026.10.26
TradingView Webhooks to Binance Auto Orders: A Relay and Exchange-Side Stops for a BTC Daily Strategy
A BTC daily strategy from backtest to automated Binance orders: only daily had enough samples, tuning the backtest wrapper beat tuning the indicator, the relay syncs to target position, and stops sit on the exchange.
Reading
Wiring TradingView webhooks to automated Binance orders means dealing with alerts that repeat or go missing, and with a relay that might be down while a position needs its stop.
I took a BTC daily trend strategy all the way from backtest to automated orders on Binance. On the execution side, two things are worth copying.
First, the relay aligns to the strategy's target position instead of placing orders from the alert's buy or sell instruction.
Second, the stop loss sits on the exchange, so it doesn't depend on the relay being online.
On the backtest side, only the daily timeframe had enough samples, and tuning the backtest wrapper helped more than tuning the indicator.
The strategy is an invite-only trend indicator on TradingView, with a backtest wrapper I wrote around it, trading the BTCUSDT perpetual contract.
Trust only the daily chart
I was on TradingView's Basic plan at the time, which can only backtest over the range the chart can load, so short timeframes have very little history.
On paper the highest profit factor (PF, gross profit over gross loss) was 6.90 on 15-minute candles, but that was only 2 round trips.
The daily chart had 23 round trips since 2020 with a PF of 3.20, the only timeframe with enough samples. The PF on the other timeframes jumped around mostly because there were too few trades.
I tried 32 single-parameter changes to the indicator itself, and every one made the daily results worse, so I left it alone. What worked were three parameters in the backtest wrapper. Before and after, on the BTCUSDT perpetual daily backtest:
| Original | Adjusted | |
|---|---|---|
| Entry tranches | 5 | 1 |
| Stop loss | 10% | 5% |
| Leverage | 3x | 2x |
| Profit factor | 3.20 | 3.56 |
| Total return | 1,966% | 10,618% |
| Max drawdown | 62.1% | 47.6% |
Worried about overfitting, I split the data into 2020 to 2023 and 2024 onward and looked at each separately. Both beat the original settings.
Shorting, a fixed take-profit, a trailing take-profit, and ATR stops all tested worse. This strategy's profit is concentrated in a few big trends, and any rule that gets you out early cuts into exactly those.
Max drawdown was recomputed from closing equity; with the original settings the report only said 28.7%. I can't see the indicator's source code, so I also used Bar Replay to confirm it doesn't repaint. Both are covered in the backtesting pitfalls post.
Webhook, tunnel, relay
TradingView's strategy alert fires a webhook when an order fills. It comes in through a Cloudflare Tunnel to a relay written with nothing but the Python standard library.
The relay listens only on localhost, calls Binance's USDⓈ-M futures API to place orders and stops, and sends me a Telegram message for every action plus a daily status.
TradingView's Basic plan has no webhooks, so you need Essential. Essential alerts expire after 2 months at most, and I chose to recreate them every two months.
The webhook also has a response deadline:
If a remote server takes longer than three seconds to process a request, the request will be cancelled.
That's from TradingView's webhook docs. Placing an order won't always finish within 3 seconds, so the relay returns 200 as soon as the request checks out, drops the work into a queue, and lets a background worker handle it.

Target position, exchange-side stop
The relay ignores whether the alert says buy or sell. It only looks at strategy.market_position, meaning whether the strategy should currently be long or flat, and brings the Binance position in line with it:
amt, entry = binance.position("BTCUSDT")
if target == "long":
if amt > 0:
ensure_stop(amt, entry) # already long, just make sure the stop is still there
else:
open_long() # only open when flat
elif amt != 0:
close_all(amt, entry) # strategy is flat but the exchange still holds a position, close it all
Duplicate alerts don't place duplicate orders, and if one gets missed, the next one pulls the state back in line.
The relay also drops webhooks with identical content within 10 minutes.
Once an entry fills, the relay places a STOP_MARKET with closePosition 5% below the actual average fill price. If the relay goes down or the network drops, the stop still works.
The relay also checks every 5 minutes. If there's a long position with no stop, it places one; if the position is gone, it clears the record and notifies me.

What Demo Trading caught
Before going live, I first ran it in a simulation mode that only sent notifications. Then I switched to Binance's Demo Trading and went through opening a position, duplicate signals, re-placing a stop, closing, and a stop getting hit. Pitfalls it caught:
- The response to a market order often doesn't include
avgPrice, which threw off the stop price. It now queries the order again after the fill to get the actual average price. - Restarting the relay while holding a position, setting cross margin got rejected by Binance (-4067), even when it was already on cross margin. It now reads the setting first and only changes it if it's different.
- Since December 2025, Binance conditional orders have to go through
/fapi/v1/algoOrder, and the old endpoint rejects them outright. See Binance's derivatives change log. - When I used a tool to list my TradingView alerts, the output printed the whole message, webhook secret included, and I ended up rotating the secret twice because of it.
If a tool prints configuration contents, treat its output as already leaked.
Security and risk
This service can move real money, so the entry point is locked down tight.
Alerts carry a webhook secret, and both the relay and Cloudflare WAF only allow TradingView's published webhook IPs. The Binance API key is bound to the server IP with withdrawals disabled.
Opening a position uses the futures wallet's entire available balance, so the wallet only holds the money meant for this strategy.
The backtest max drawdown is 47.6%, and you need to be able to stomach that number up front.
2x cross-margin perpetuals carry liquidation risk, though a 5% stop is far from the liquidation price. Funding fees are a fixed cost of holding longs for a long time, and in a sharp drop the stop can slip.
With a small account, order size gets rounded down to the 0.001 BTC minimum step, so actual leverage ends up a little below 2x.
At the time of writing, the strategy hadn't produced a real signal yet. It only counts as done once the first real entry and exit match TradingView.
This is my own small experiment, not investment advice.

Engineering
The Reconciliation Alert Fired Twice: Missed and Double-Counted Interest When Bitfinex Positions Switch Sides
I check user earnings with a ratio of interest actually paid to booked accrual; it fired twice, once undercounting and once double-counting, both because Bitfinex splits one position across credits and loans.
Letters
Loading comments…