A Flask-based webhook server that bridges Trading View alerts to Ninja Trader or similar platforms via CSV signal files, with multi-strategy support and layered validation.
Built for a specific use case - you'll likely need to modify it for your own setup.
Note: Note: This was built for a client with specific needs and isn't a plug-and-play solution for every setup. Expect to modify it for your own use case. That said, the core architecture - receiving Trading View webhooks and writing validated CSV signals - is reusable and should be a solid starting point.
It's possible to use this webhook with something like ngrok to expose it, but ideally it'd be used behind an SSL endpoint that can verify Trading View's client certificate before passing the request along.
Trading View Alert -> Webhook -> CSV Signal File -> Your Platform (Ninja Trader, etc)
- Multi-strategy support with easy configuration
- Support for custom per-strategy trade logic
- Configurable maximum trade limit
- Strong input validation and sanitization
- Password protection
- Rate limiting
- Atomic file writes for safety
- Rich console logging + optional file logging
- Debug and test mode for development
-
Install Dependencies
pip install -r requirements.txt
-
Set Environment Variable
export WEBHOOK_PASSWORD="your_strong_password_here" # Password must be 8–64 characters
-
Configure Strategies
Copy the existing entry in the STRATEGIES dict and modify:
"my_new_strat": { "description": "What this strategy does", **BASE_TEMPLATE, "required_fields": ["time", "ticker", "open", "high", "low", "close", "password"], "output_file": os.path.join(TARGET_DIR, "my_new_strat_current_signal.csv"), # "custom_logic": my_custom_function, # optional }, # Custom trade logic functions receive the webhook payload as a dict and must return: {"block": True, "reason": "..."} — trade is rejected {"block": False} — trade is allowed {"block": False, "warning": "..."} — trade allowed, warning logge
-
Run the Server
python webhook.py -d
Options
Flag Description --no-validation,-nvDisable all payload validation --no-password-check,-npDisable password authentication --debug,-dVerbose console logging (headers, body, etc.) --log-file,-lfPath to log file --max-trades,-mtCap on successful signal writes (default: unlimited)
Send a POST to /webhook with Content-Type: application/json:
{
"strategy": "your_strategy_name",
"ticker": "{{ticker}}",
"time": "{{time}}",
"open": "{{open}}",
"high": "{{high}}",
"low": "{{low}}",
"close": "{{close}}",
"password": "your_webhook_password"
}Optional fields: timenow, test (string "true" or "false")
See Trading View's variable documentation for available template placeholders.
Signals are written as a single-row CSV to the strategy's configured output file:
Timestamp,Ticker,Open,High,Low,Close,Limit_Price
2026-05-04T04:46:04,MES,6234.56,6238.00,6229.00,6238.0,6237.56Default output directory (Windows): C:/Users/<you>/Documents/NinjaTrader 8/bin/Custom/Signals/
Default output directory (Linux/macOS): User's home directory
This server listens on 127.0.0.1:5000 by default - it is not intended to be exposed directly to the internet. Optionally expose it using something like ngrok if you're comfortable with that.
For production use, place it behind an SSL-terminating reverse proxy that can verify Trading View's client certificate before forwarding the request.
This gives you TLS encryption and cryptographic assurance that the payload actually came from TradingView.
The --no-password-check and --no-validation flags exist for local development only. Do not use them in production.
This software is provided "as is" without warranty of any kind. The author assumes no liability for any trading losses, damages, or other issues arising from the use of this code. Trading involves substantial risk of loss and is not suitable for every investor. This tool is for educational and informational purposes only and does not constitute financial advice. Use at your own risk.
MIT - see LICENSE for full text.
https://github.com/cruxcoder | cruxcoder [at] proton [dot] me