Documentation Index
Fetch the complete documentation index at: https://uncoded.ch/docs/llms.txt
Use this file to discover all available pages before exploring further.
What the SignalsBot does for you
The SignalsBot is the single, validated entry point for external trade signals. If you’re publishing strategies from your SignalEditor, this is the receiver. If you’re sending TradingView alerts to your bot, this is the receiver. If you have a custom script or a third-party signal provider, this is also the receiver. Everything that wants to change your TradingBot’s behavior from the outside passes through here — and nothing reaches your local database without being authenticated and validated first. The SignalsBot is intentionally one of the smallest services in the stack. Its job is narrow, its surface is auditable, and its failure mode is contained.Receives webhooks securely
Validates every payload
sellPercentages.length === buySplits), and refuses unknown keys.Writes to local database only
Audits every accepted change
Rate-limited at the door
100 requests per 15-minute window per IP. Misbehaving sources get throttled before they can flood your dashboard.64 KB body cap
Standard security headers
Bounded surface area
GET /, GET /health, GET /tradepairs, POST /webhook). Every line of behaviour is auditable.Why this is its own service
You might wonder: why is the SignalsBot a separate container instead of an endpoint inside the TradingBot? Two reasons. Security boundary. The SignalsBot is the only internet-exposed component (besides the Dashboard). By making it a small, audit-clear, one-job service, the security-sensitive surface is minimized. The TradingBot — which holds your exchange API keys — is never internet-exposed. Independent failure mode. If the SignalsBot crashes (or is being attacked), your trading is unaffected. The TradingBot continues running with its existing configuration. You get a webhook outage, not a trading outage.What you can change via webhook
The SignalsBot accepts two kinds of operations — and only these two.Tradepair updates — which symbols to trade
Tradepair updates — which symbols to trade
- Add a symbol to the active set (e.g., start trading
ETHUSDT) - Remove a symbol from the active set (e.g., stop trading
XRPUSDT) - Replace the entire active set at once
tradePairs configuration entry that the TradingBot reads on every configuration poll. The change is picked up within seconds.Use case examples:- A “trend filter ON” strategy enables a symbol when conditions allow.
- A “trend filter OFF” strategy disables a symbol when conditions degrade.
- A daily script rotates the active set based on volatility ranks — high-vol symbols on, low-vol off.
- An emergency-stop script removes all symbols at once when news hits.
Mode-settings updates — how to trade
Mode-settings updates — how to trade
canBuy,canSell— enable or disable buying / selling for the modecanBuyUp,canBuyDown— directional gatingstart— the mode’s starting reference pricebuyPercentage,buySplits,buyVolumes,investmentPerBuy,investmentPercentMode— the buy-ladder shapesellPercentages,sellActivateDistancePercentage,sellCancelDistancePercentage— the sell-ladder shape and trailing-stop activationstopLoss,stopLossPercentage— the hard stop-lossonlyMakerBuy,onlyMakerSell— enforce maker-only orderssellTimeCurves,sellTimeCurveCheckIntervalMs— time-decay sell logicname,description— labelling
- A “regime change” strategy widens the sell ladder when volatility expands.
- A “news-mode” toggle enables
canBuy: falsefor risky modes when high-impact news hits. - A maker-rebate mode adjusts the buy-ladder spacing dynamically.
- A “weekend conservative” toggle reduces position sizing on Friday evening, restores Monday morning.
How a webhook flows through the SignalsBot
HTTPS POST arrives at /webhook
100 requests in the last 15 minutes, the request is rejected with 429 Too Many Requests.Authentication
- An
X-Signatureheader (HMAC-SHA256 of the raw body) - An
X-TRADINGVIEW-TOKENheader (shared secret) - A
secretfield inside the JSON body (shared secret)
401 Unauthorized and the bot logs the rejection.Payload classification
- If
tradePairs,pair, orsymbolis present → tradepair update. - If
mode(ormodes) is present along with allowed mode-settings keys → mode-settings update. - Both can be present — they’re processed in order.
- Neither match →
400 Bad Requestwith a precise reason.
Validation
Database write
config.tradePairs key, the modes table, or both. The configuration hash is updated, which is how the TradingBot detects “something changed, re-read.”Audit log
[AUDIT] <source IP> <action> <details>. The audit log is preserved in the bot’s logs and can be reviewed via the Dashboard’s Logs panel.The SignalsBot’s three small endpoints (besides /webhook)
Beyond the main/webhook POST, the SignalsBot exposes three read-only endpoints — each minimal and inspectable.
GET / — landing-page response
GET / — landing-page response
GET /health — health check
GET /health — health check
200 OK if the bot can reach the database, 503 Service Unavailable if it can’t.Useful for:- Reverse-proxy health checks (Caddy, nginx-proxy-manager).
- External monitoring (UptimeRobot, Better Uptime, similar).
- Operator manual checks:
curl https://signals.yourdomain.com/health.
GET /tradepairs — read-only inspection
GET /tradepairs — read-only inspection
What the SignalsBot does NOT do
Webhook source patterns
Operators send webhooks from a variety of sources. Here’s the standard pattern catalog.SignalEditor → SignalsBot (the canonical local pattern)
SignalEditor → SignalsBot (the canonical local pattern)
/webhook endpoint when triggers fire.Authentication: HMAC-SHA256 (the cryptographically stronger path). The shared secret is set in both the SignalEditor’s environment and the SignalsBot’s environment.Network: traffic stays on your VPS’s internal Docker network. The webhook does not traverse the public internet.This is the most common pattern — almost every operator using the SignalEditor uses this path.TradingView alert → SignalsBot (the external integration)
TradingView alert → SignalsBot (the external integration)
/webhook endpoint when a Pine Script alert fires.Authentication: shared-secret token (TradingView doesn’t support HMAC signing of webhook bodies). The secret is included in the alert message body as a secret field.Network: traffic traverses the public internet — TLS is mandatory.Setup: in TradingView’s alert dialog, set the webhook URL to https://signals.yourdomain.com/webhook. In the alert message body, include a JSON shape like:Custom script → SignalsBot (operator automation)
Custom script → SignalsBot (operator automation)
- Bash + curl: simplest. One-liner for ad-hoc operator actions.
- Python: most common for scheduled scripts (e.g., daily volatility-rank rotation).
- JavaScript: if you have other JS-based infrastructure.
Third-party signal provider → SignalsBot (with caution)
Third-party signal provider → SignalsBot (with caution)
- Trust assessment first. A signal provider with webhook access can affect your live trading. Vet them carefully.
- Rate-limit at your reverse proxy as an additional layer. The SignalsBot’s
100/15minis a default; you can be more restrictive. - Audit the provider’s signals weekly. If they start sending unexpected payloads, revoke immediately.
Setting up TradingView integration
A common operator setup. Step-by-step.Confirm your TradingView plan supports webhooks
Configure your reverse proxy
https://signals.yourdomain.com/health should return OK.Set the shared secret
TRADINGVIEW_WEBHOOK_SECRET environment variable in the SignalsBot container. Restart the container.Save this secret in your password manager. You’ll need it in TradingView’s alert configuration.Create a TradingView alert
- Webhook URL:
https://signals.yourdomain.com/webhook - Message body: paste the JSON template you want the alert to send, including the
secretfield with your shared secret value.
Test with a one-shot alert
Operational footprint
Resource cost
100–200 MB RAM at idle. Sub-percent CPU. The bot is a lightweight HTTP server with one mutating endpoint and a small connection pool.Network calls
Failure mode
Startup time
Audit log size
Internet exposure
/webhook endpoint. Behind a reverse proxy, configure your firewall to allow only the proxy’s port. The bot itself listens on internal Docker network.Common questions
Do I need the SignalsBot to use unCoded?
Do I need the SignalsBot to use unCoded?
- Running custom strategies in the SignalEditor (which posts webhooks here)
- Receiving TradingView alerts
- Driving configuration from external scripts or third-party signal providers
What's the right way to expose it to TradingView?
What's the right way to expose it to TradingView?
signals.yourdomain.com). Caddy and nginx-proxy-manager are operator favorites because they automate Let’s Encrypt certificates.In TradingView’s alert creation dialog, set the webhook URL to https://signals.yourdomain.com/webhook, and include the alert message body with your shared secret in the secret field. The SignalsBot will accept the alert if the secret matches.Never expose the raw HTTP port. TradingView’s webhooks travel over the public internet — without TLS, your shared secret is in the clear.What's the difference between HMAC and shared-secret authentication?
What's the difference between HMAC and shared-secret authentication?
Can I send webhooks from my own scripts?
Can I send webhooks from my own scripts?
secret plus the fields you want to change, POST to /webhook, and you’re done.Use this for ad-hoc operator actions (e.g., disabling buying for a specific mode in response to news), for integrations with your own analytics, or for bridging from a signal provider that doesn’t natively support webhooks.Operators with light dev backgrounds typically write a few small Bash + curl or Python scripts to wrap common actions (kill switch, mode reset, capital reallocation) — these become a reliable, version-controllable operator toolkit.What happens if I send the same webhook twice?
What happens if I send the same webhook twice?
enable buying for mode 4 twice in a row, the second one re-applies the same change (which is a no-op in this case) and emits two audit log lines.For ordinary configuration updates, this is fine — applying the same setting twice has no negative effect. For one-shot actions, your sender is responsible for de-duplication.For TradingView, this can occasionally happen during alert retries — TradingView retries failed webhook deliveries. The retries are usually idempotent (same content), so they’re handled gracefully.Why is there a 64 KB body cap?
Why is there a 64 KB body cap?
5 KB. The 64 KB cap is generous enough for any legitimate use, while protecting the bot from memory-flood attacks where a malicious source streams gigabytes of body.If you have a legitimate signal that exceeds 64 KB (very unusual), contact support — the cap is configurable but rarely needs to change.What does the audit log look like?
What does the audit log look like?
Can I rotate the webhook secret?
Can I rotate the webhook secret?
- Generate a new secret:
openssl rand -hex 32. - Update the SignalsBot’s environment variable. Restart the container.
- Update every upstream sender (SignalEditor, TradingView alerts, custom scripts) to use the new secret.
- Verify a test webhook works.
- The old secret is dead.
Can I have multiple SignalsBots?
Can I have multiple SignalsBots?
- Different webhook secrets per source (rotate independently).
- Different rate limits per source (high-rate strategy source vs low-rate operator script).
- Geographic distribution (a SignalsBot near each VPS).
What if a webhook is half-applied (network drops mid-write)?
What if a webhook is half-applied (network drops mid-write)?
What if my reverse proxy fails?
What if my reverse proxy fails?