← All posts

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
Theme
Size
Width

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.

Flow chart: a TradingView strategy alert fires a webhook when an order fills; the relay checks it, returns 200 within 3 seconds, queues the work, and a background worker places orders and stops on the Binance futures API to match the target position. The stop sits on the exchange and still works if the relay goes offline. Every action and a daily status go out as Telegram messages.

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:

Python
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.

Decision grid: the relay ignores buy or sell in the alert and reads only strategy.market_position. If the strategy should be long and Binance is already long, it places no order and only makes sure the stop exists; if Binance has no position, it opens a long with a STOP_MARKET 5% below the average fill. If the strategy should be flat and Binance still holds a position, it closes it all; if both are flat, it does nothing.

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.

#Automated Trading#TradingView#Webhook#Binance

Letters

Loading comments…

Next

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.