49260abaa2
- Trade setup TP now scales to SL distance ensuring min RR is met when no viable swing target exists; skip swing targets with poor RR - Add float tolerance to RR gate to prevent edge-case rejection - M5 auto-scan runs for level cache only, no Telegram broadcast - WebSocket limited to EUR/USD + XAU/USD (Grow plan constraint) - Register bot command menu via set_my_commands on startup
56 lines
1.5 KiB
Python
Executable File
56 lines
1.5 KiB
Python
Executable File
"""Live tick stream from Twelve Data WebSocket API."""
|
|
|
|
import json
|
|
import asyncio
|
|
import websockets
|
|
from datetime import datetime, timezone
|
|
|
|
|
|
API_KEY = "f563b22ffdfd4924955decbe1a8c8701"
|
|
WS_URL = f"wss://ws.twelvedata.com/v1/quotes/price?apikey={API_KEY}"
|
|
SYMBOLS = ["EUR/USD", "XAU/USD"]
|
|
|
|
|
|
async def stream_ticks():
|
|
async with websockets.connect(WS_URL) as ws:
|
|
subscribe = {
|
|
"action": "subscribe",
|
|
"params": {
|
|
"symbols": ",".join(SYMBOLS),
|
|
},
|
|
}
|
|
await ws.send(json.dumps(subscribe))
|
|
print(f"Subscribed to: {', '.join(SYMBOLS)}")
|
|
print("-" * 60)
|
|
|
|
async for raw in ws:
|
|
msg = json.loads(raw)
|
|
|
|
if msg.get("event") == "subscribe-status":
|
|
print(f"Status: {msg.get('status')} — {msg.get('message', '')}")
|
|
continue
|
|
|
|
if msg.get("event") == "heartbeat":
|
|
continue
|
|
|
|
if msg.get("event") == "price":
|
|
ts = datetime.fromtimestamp(msg["timestamp"], tz=timezone.utc)
|
|
symbol = msg["symbol"]
|
|
price = msg["price"]
|
|
print(f"{ts:%H:%M:%S} | {symbol:<8} | {price}")
|
|
|
|
|
|
async def main():
|
|
print(f"Connecting to Twelve Data WebSocket...")
|
|
print(f"API key: ...{API_KEY[-6:]}")
|
|
try:
|
|
await stream_ticks()
|
|
except KeyboardInterrupt:
|
|
print("\nStopped.")
|
|
except websockets.exceptions.ConnectionClosed as e:
|
|
print(f"\nConnection closed: {e}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
asyncio.run(main())
|