Using Azure Function to Trade on TradingView (2/3)
With your Azure Function deployed and your Binance API key stored safely, one piece is still missing: the signal. In this part we connect TradingView alerts directly to your function so the bot wakes up automatically — no manual clicking, no missed entries.
Writing a Pine Script Strategy with Alert Conditions
TradingView's Pine Script v5 lets you attach alert conditions to any strategy so a notification fires the moment a trade signal is generated. A simple EMA crossover is a good starting point — the script below fires a buy signal when the fast EMA crosses above the slow EMA, and a sell signal when it crosses below.
//@version=5
strategy("EMA Crossover Bot", overlay=true)
fastLen = input.int(9, "Fast EMA")
slowLen = input.int(21, "Slow EMA")
fastEMA = ta.ema(close, fastLen)
slowEMA = ta.ema(close, slowLen)
longCond = ta.crossover(fastEMA, slowEMA)
shortCond = ta.crossunder(fastEMA, slowEMA)
if longCond
strategy.entry("Long", strategy.long)
alert('{"symbol":"BNBUSDT","side":"BUY","price":"' + str.tostring(close) + '","total":"100"}', alert.freq_once_per_bar)
if shortCond
strategy.close("Long")
alert('{"symbol":"BNBUSDT","side":"SELL","price":"' + str.tostring(close) + '","total":"100"}', alert.freq_once_per_bar)
plot(fastEMA, color=color.blue, title="Fast EMA")
plot(slowEMA, color=color.orange, title="Slow EMA")
Notice the alert() call embeds a JSON string directly into the alert message. The fields — symbol, side, price, and total — match exactly the keys that function_app.py reads from the request body in the GitHub repo from Part 1. Keeping the shape consistent means no changes are needed on the Azure side.
Configuring the TradingView Webhook
Once the strategy is added to your chart, create a new alert: right-click the chart, select Add Alert, then choose your strategy as the condition. Scroll down to the Notifications tab and tick Webhook URL. Paste the Azure Function URL you copied in Part 1 (the one from Get function URL → default (Function key)) into the field.
TradingView sends a POST request to that URL within seconds of the alert firing. According to TradingView's webhook documentation, requests originate from a fixed set of IP addresses — 52.89.214.238, 34.212.75.30, 54.218.53.128, and 52.32.178.7 — which you can optionally allowlist on your Azure Function's networking settings for an extra layer of defence. TradingView also requires 2-factor authentication to be enabled on your account before webhooks are available.
One important constraint: TradingView cancels any webhook call that takes longer than three seconds to respond. Azure Functions on the Consumption plan typically cold-start in under two seconds, but if you notice missed alerts during low-traffic periods, consider switching to the Always On setting in your Function App's Configuration blade to keep the host warm.
Structuring the JSON Alert Payload
When the alert message is valid JSON, TradingView automatically sets the Content-Type header to application/json. This is exactly what req.get_json() in our Python function expects. The payload must supply the four keys the function reads: symbol (e.g., BNBUSDT), side (BUY or SELL), price, and total (the USDT notional value).
You can embed dynamic values from Pine Script using string concatenation with str.tostring(), as shown above. For the total field, a fixed notional like "100" means each alert places a $100 order — simple and predictable. More advanced setups can calculate position size as a percentage of portfolio equity using Pine's strategy.equity variable and pass it through the same field.
Securing Your Endpoint and Testing the Flow
The function URL already contains a function key query parameter (?code=...), which acts as a basic shared secret. For production, consider moving your Binance API key and secret — currently stored as Azure Function App Settings — into Azure Key Vault. Key Vault encrypts secrets at rest using FIPS 140-validated HSMs, and your Function App can retrieve them at runtime through a managed identity with no secrets ever stored in application settings or code.
To wire this up: create a Key Vault, add your api_key and api_secret as secrets, enable a system-assigned managed identity on the Function App, and grant it the Key Vault Secrets User role. Then replace the App Setting values with Key Vault references in the format @Microsoft.KeyVault(SecretUri=https://<vault-name>.vault.azure.net/secrets/api-key/) — Azure resolves these transparently at runtime.
Before going live, replay a test alert using Postman with the same JSON body your Pine Script produces. Verify the response is 200 OK and check the Azure Function's Monitor tab to confirm the order appears in the invocation logs. Run the same test against Binance's testnet endpoint (https://testnet.binance.vision) by temporarily swapping the client base URL, so you can validate order placement without risking real funds.
What's Next
At this point the pipeline is complete: TradingView fires → Azure Function receives → Binance executes. The bot is reliable, but it is still mechanical — it executes every signal without judgement. In Part 3 we introduce Microsoft Foundry, Microsoft's unified AI platform, to add an intelligence layer that can validate signals, check market conditions, and decide whether an order should actually be placed. The result is a trading bot with a reasoning brain sitting between the signal and the exchange.
Disclaimer: This series is for educational purposes only and does not constitute financial advice. Always test with small amounts and use Binance's testnet before deploying with real funds.