# pulse-tradingview

[![PyPI version](https://badge.fury.io/py/pulse-tradingview.svg)](https://pypi.org/project/pulse-tradingview/)
[![PyPI downloads](https://img.shields.io/pypi/dm/pulse-tradingview.svg)](https://pypi.org/project/pulse-tradingview/)
[![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE)

**Connect TradingView alerts to any crypto exchange — free alternative to 3Commas and Alertatron.**

TradingView fires a webhook when your alert triggers. `pulse-tradingview` catches it and places the trade on Binance, Bybit, OKX, or Kraken. No cloud subscription. Runs on your own machine.

---

## Installation

```bash
pip install pulse-tradingview

# Add the exchange you trade on:
pip install pulse-tradingview pulse-bybit
pip install pulse-tradingview pulse-binance
pip install pulse-tradingview pulse-okx
pip install pulse-tradingview pulse-kraken

# Or all at once:
pip install "pulse-tradingview[all]"
```

---

## Quick Start

### 1. Create config

```bash
pulse-tv init
```

Edit the generated `pulse_tv_config.json`:

```json
{
  "bybit": {
    "api_key": "YOUR_BYBIT_API_KEY",
    "api_secret": "YOUR_BYBIT_API_SECRET"
  },
  "min_confidence": 0.7,
  "pairs": ["BTC/USDT", "ETH/USDT", "SOL/USDT"]
}
```

### 2. Start the server

```bash
pulse-tv start
```

```
pulse-tradingview v0.1.0
Webhook server: http://0.0.0.0:8888/
Exchanges:      Bybit

In TradingView → Alert → Webhook URL:
  http://YOUR_PUBLIC_IP:8888/

Waiting for signals...
```

### 3. Set up TradingView alert

In TradingView, create an alert and set the webhook URL to `http://YOUR_SERVER_IP:8888/`.

Use this JSON template as the alert message:

```json
{
  "action": "{{strategy.order.action}}",
  "symbol": "{{ticker}}",
  "price": "{{close}}",
  "interval": "{{interval}}",
  "confidence": "0.85"
}
```

That's it. When the alert fires, the trade goes to Bybit.

---

## Alert message format

TradingView sends the alert message as the POST body. `pulse-tradingview` understands three formats:

**JSON (recommended):**
```json
{"action": "buy", "symbol": "BTCUSDT", "price": "83000", "confidence": "0.9"}
```

**Pine Script placeholders** (TradingView fills these in automatically):
```json
{"action": "{{strategy.order.action}}", "symbol": "{{ticker}}", "price": "{{close}}"}
```

**Plain text (legacy):**
```
BUY BTCUSDT
```

**Supported fields:**

| Field | Required | Values | Example |
|---|---|---|---|
| `action` | Yes | buy, sell, long, short, close | `"buy"` |
| `symbol` | Yes | Exchange symbol | `"BTCUSDT"` |
| `price` | No | Current price | `"83000"` |
| `interval` | No | Chart timeframe | `"60"` (= 1h) |
| `confidence` | No | 0.0 – 1.0 | `"0.85"` |

Any extra fields (`rsi`, `strategy`, `reason`) are passed through and available in your handler.

---

## Python API

For more control, use the library directly:

```python
from pulse_tradingview import WebhookReceiver, SignalRouter
from pulse_bybit import BybitAdapter

# Set up router
router = SignalRouter()
router.add_adapter(BybitAdapter(api_key="...", api_secret="..."), "Bybit")

# Only act on confident signals for major pairs
router.add_filter(lambda p: p["confidence"] >= 0.8)
router.add_filter(lambda p: p["pair"] in ["BTC/USDT", "ETH/USDT"])

# Start server
with WebhookReceiver(port=8888, on_signal=router.route):
    print("Listening...")
    input("Press Enter to stop")
```

---

## Multi-exchange routing

One TradingView alert → multiple exchanges simultaneously:

```python
router = SignalRouter()
router.add_adapter(BybitAdapter(api_key="...", api_secret="..."), "Bybit")
router.add_adapter(BinanceAdapter(api_key="...", api_secret="..."), "Binance")

# Signal goes to both exchanges
router.route({"pair": "BTC/USDT", "direction": "long", "confidence": 0.9})
```

---

## Pine Script strategies

Ready-to-use Pine Script files are in [`pine_scripts/`](pine_scripts/):

- `rsi_pulse_strategy.pine` — RSI oversold/overbought with configurable levels
- `macd_pulse_strategy.pine` — MACD crossover strategy

Both send properly formatted JSON alerts that `pulse-tradingview` parses automatically.

Example from `rsi_pulse_strategy.pine`:
```javascript
long_msg = '{"action":"buy","symbol":"' + syminfo.ticker +
           '","price":"' + str.tostring(close) +
           '","confidence":"0.85","rsi":"' + str.tostring(rsi) + '"}'

alertcondition(long_signal, title="PULSE Buy Signal", message=long_msg)
```

---

## CLI reference

```bash
# Start webhook server
pulse-tv start
pulse-tv start --port 9000 --config my_config.json --verbose

# Create sample config
pulse-tv init
pulse-tv init --output /path/to/config.json

# Send test signal to running server
pulse-tv test
pulse-tv test --action buy --symbol BTC/USDT --price 83000 --confidence 0.9
```

---

## Security

Add a shared secret so only TradingView can trigger your server:

**Config:**
```json
{"secret": "my-random-secret-string", "bybit": {...}}
```

**TradingView webhook URL:**
```
http://YOUR_IP:8888/
```

**Add header in TradingView alert** (Advanced → Headers):
```
X-PULSE-Secret: my-random-secret-string
```

Requests without the correct secret get a 401 response.

---

## PULSE Ecosystem

`pulse-tradingview` is part of the [PULSE Protocol](https://github.com/pulseprotocolorg-cyber/pulse-python) ecosystem.

| Package | Description |
|---|---|
| [pulse-protocol](https://pypi.org/project/pulse-protocol/) | Core protocol |
| [pulse-bybit](https://pypi.org/project/pulse-bybit/) | Bybit exchange |
| [pulse-binance](https://pypi.org/project/pulse-binance/) | Binance exchange |
| [pulse-okx](https://pypi.org/project/pulse-okx/) | OKX exchange |
| [pulse-kraken](https://pypi.org/project/pulse-kraken/) | Kraken exchange |
| [pulse-freqtrade](https://pypi.org/project/pulse-freqtrade/) | Freqtrade bot |
| [pulse-anthropic](https://pypi.org/project/pulse-anthropic/) | Claude AI adapter |

---

## License

Apache 2.0 — free forever, open source.
