Skip to main content

Installation

pip install requests pandas

Complete Signal Generator Class

import requests
import pandas as pd
from datetime import datetime
from typing import Optional, List, Dict, Any

class InnovaTradingClient:
    """Client for InnovaTrading External Indicators API"""

    def __init__(self, api_key: str, base_url: str = "https://api.innova-trading.com"):
        self.api_key = api_key
        self.base_url = base_url
        self.headers = {
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json"
        }

    def get_bars(
        self,
        symbol: str,
        timeframe: int,
        limit: int = 500
    ) -> pd.DataFrame:
        """
        Fetch OHLC bars for a symbol.

        Args:
            symbol: Trading pair (e.g., "EURUSD")
            timeframe: Timeframe in minutes (1, 5, 15, 60, 240, 1440)
            limit: Number of bars to fetch (max 500)

        Returns:
            DataFrame with columns: time, open, high, low, close, volume
        """
        url = f"{self.base_url}/api/external/bars/{symbol}/{timeframe}"
        response = requests.get(url, params={"limit": limit}, headers=self.headers)
        response.raise_for_status()

        data = response.json()
        df = pd.DataFrame(data["bars"])
        df["datetime"] = pd.to_datetime(df["time"], unit="s")
        return df

    def get_symbols(self) -> List[str]:
        """Get list of available symbols for your API key."""
        url = f"{self.base_url}/api/external/symbols"
        response = requests.get(url, headers=self.headers)
        response.raise_for_status()
        return response.json()["symbols"]

    def submit_indicator(
        self,
        indicator_id: str,
        symbol: str,
        timeframe: int,
        indicator_name: str,
        points: List[Dict[str, Any]],
        lines: Optional[List[Dict[str, Any]]] = None,
        metadata: Optional[Dict[str, Any]] = None,
        version: str = "1.0"
    ) -> Dict[str, Any]:
        """
        Submit indicator points and lines to be displayed on chart.

        Args:
            indicator_id: Unique identifier for your indicator
            symbol: Trading pair
            timeframe: Timeframe in minutes
            indicator_name: Display name in UI
            points: List of signal points (markers/arrows)
            lines: List of horizontal lines (SL/TP levels)
            metadata: Optional analytics data
            version: Indicator version

        Returns:
            API response with confirmation
        """
        url = f"{self.base_url}/api/external/indicators/{indicator_id}"

        payload = {
            "symbol": symbol,
            "timeframe": timeframe,
            "indicator_name": indicator_name,
            "version": version,
            "points": points,
            "lines": lines or []
        }

        if metadata:
            payload["metadata"] = metadata

        response = requests.post(url, json=payload, headers=self.headers)
        response.raise_for_status()
        return response.json()

    def get_indicator(
        self,
        indicator_id: str,
        symbol: str,
        timeframe: int
    ) -> Dict[str, Any]:
        """Retrieve indicator data."""
        url = f"{self.base_url}/api/external/indicators/{indicator_id}"
        response = requests.get(
            url,
            params={"symbol": symbol, "timeframe": timeframe},
            headers=self.headers
        )
        response.raise_for_status()
        return response.json()

    def delete_indicator(
        self,
        indicator_id: str,
        symbol: str,
        timeframe: int
    ) -> Dict[str, Any]:
        """Delete indicator data."""
        url = f"{self.base_url}/api/external/indicators/{indicator_id}"
        response = requests.delete(
            url,
            params={"symbol": symbol, "timeframe": timeframe},
            headers=self.headers
        )
        response.raise_for_status()
        return response.json()

    def list_indicators(self) -> Dict[str, Any]:
        """List all indicators for your API key."""
        url = f"{self.base_url}/api/external/indicators"
        response = requests.get(url, headers=self.headers)
        response.raise_for_status()
        return response.json()

Usage Examples

Basic Signal Submission

# Initialize client
client = InnovaTradingClient("YOUR_API_KEY")

# Fetch bars
df = client.get_bars("EURUSD", 60, limit=100)

# Create a simple BUY signal on the last bar
points = [
    {
        "time": int(df.iloc[-1]["time"]),
        "type": "low",
        "price": float(df.iloc[-1]["close"]),
        "label": "BUY",
        "color": "#3b82f6",
        "shape": "arrowUp",
        "size": 2
    }
]

# Submit
result = client.submit_indicator(
    indicator_id="my_signals",
    symbol="EURUSD",
    timeframe=60,
    indicator_name="My Trading Signals",
    points=points
)

print(f"Submitted {result['points_received']} points")

Complete Trade Signal (Entry + SL + TPs)

def create_trade_signal(
    client: InnovaTradingClient,
    symbol: str,
    timeframe: int,
    signal_type: str,  # "BUY" or "SELL"
    entry_price: float,
    stop_loss: float,
    take_profits: List[float],
    bar_time: int
) -> Dict[str, Any]:
    """Create a complete trade signal with Entry, SL, and TPs."""

    points = []

    # Entry point
    points.append({
        "time": bar_time,
        "type": "low" if signal_type == "BUY" else "high",
        "price": entry_price,
        "label": signal_type,
        "color": "#3b82f6" if signal_type == "BUY" else "#f97316",
        "shape": "arrowUp" if signal_type == "BUY" else "arrowDown",
        "size": 2
    })

    # Stop Loss
    points.append({
        "time": bar_time,
        "type": "low" if signal_type == "BUY" else "high",
        "price": stop_loss,
        "label": "SL",
        "color": "#ef4444",
        "shape": "square",
        "size": 1
    })

    # Take Profits
    for i, tp_price in enumerate(take_profits, 1):
        points.append({
            "time": bar_time,
            "type": "high" if signal_type == "BUY" else "low",
            "price": tp_price,
            "label": f"TP{i}",
            "color": "#22c55e",
            "shape": "circle",
            "size": 1
        })

    # Calculate metadata
    risk_pips = abs(entry_price - stop_loss) * 10000  # For forex pairs
    reward_pips = abs(take_profits[-1] - entry_price) * 10000

    metadata = {
        "signal_type": signal_type,
        "entry_price": entry_price,
        "stop_loss": stop_loss,
        "take_profits": take_profits,
        "risk_pips": round(risk_pips, 1),
        "reward_pips": round(reward_pips, 1),
        "risk_reward": f"1:{round(reward_pips/risk_pips, 1)}"
    }

    return client.submit_indicator(
        indicator_id="trade_signals",
        symbol=symbol,
        timeframe=timeframe,
        indicator_name="Trade Signals",
        points=points,
        metadata=metadata
    )

# Usage
client = InnovaTradingClient("YOUR_API_KEY")
df = client.get_bars("EURUSD", 60, limit=1)

result = create_trade_signal(
    client=client,
    symbol="EURUSD",
    timeframe=60,
    signal_type="BUY",
    entry_price=1.1725,
    stop_loss=1.1695,
    take_profits=[1.1755, 1.1785, 1.1815],
    bar_time=int(df.iloc[-1]["time"])
)

Inside Bar Detector

def detect_inside_bars(df: pd.DataFrame) -> List[Dict[str, Any]]:
    """Detect inside bar patterns and return signal points."""
    points = []

    for i in range(1, len(df)):
        prev = df.iloc[i - 1]
        curr = df.iloc[i]

        # Inside bar: current high < previous high AND current low > previous low
        is_inside_bar = (curr["high"] < prev["high"]) and (curr["low"] > prev["low"])

        if is_inside_bar:
            points.append({
                "time": int(curr["time"]),
                "type": "high",
                "price": float(curr["high"]),
                "label": "IB",
                "color": "#eab308",
                "shape": "circle",
                "size": 1
            })

    return points

# Usage
client = InnovaTradingClient("YOUR_API_KEY")
df = client.get_bars("EURUSD", 60, limit=500)

inside_bar_points = detect_inside_bars(df)

if inside_bar_points:
    client.submit_indicator(
        indicator_id="inside_bars",
        symbol="EURUSD",
        timeframe=60,
        indicator_name="Inside Bar Detector",
        points=inside_bar_points
    )
    print(f"Found {len(inside_bar_points)} inside bars")

Continuous Update Loop

import time
import schedule

def update_signals():
    """Fetch data and update signals."""
    try:
        client = InnovaTradingClient("YOUR_API_KEY")
        df = client.get_bars("EURUSD", 60, limit=100)

        # Your analysis logic here
        points = analyze_and_generate_signals(df)

        if points:
            client.submit_indicator(
                indicator_id="my_strategy",
                symbol="EURUSD",
                timeframe=60,
                indicator_name="My Strategy",
                points=points
            )
            print(f"Updated with {len(points)} signals")
    except Exception as e:
        print(f"Error: {e}")

# Run every 5 minutes
schedule.every(5).minutes.do(update_signals)

# Initial run
update_signals()

# Keep running
while True:
    schedule.run_pending()
    time.sleep(1)

Error Handling

import requests
from requests.exceptions import HTTPError, ConnectionError, Timeout

def safe_request(func, *args, max_retries=3, **kwargs):
    """Execute request with retry logic."""
    for attempt in range(max_retries):
        try:
            return func(*args, **kwargs)
        except HTTPError as e:
            if e.response.status_code == 429:
                wait_time = 60 * (attempt + 1)
                print(f"Rate limited. Waiting {wait_time}s...")
                time.sleep(wait_time)
            elif e.response.status_code >= 500:
                time.sleep(5 * (attempt + 1))
            else:
                raise
        except (ConnectionError, Timeout):
            time.sleep(5 * (attempt + 1))

    raise Exception("Max retries exceeded")

# Usage
result = safe_request(client.get_bars, "EURUSD", 60)

Type Hints (TypedDict)

from typing import TypedDict, Literal, Optional, List

class SignalPoint(TypedDict):
    time: int
    type: Literal["high", "low"]
    price: float
    label: Optional[str]
    color: Optional[str]
    shape: Optional[Literal["circle", "arrowUp", "arrowDown", "square"]]
    size: Optional[Literal[1, 2, 3]]

class IndicatorPayload(TypedDict):
    symbol: str
    timeframe: int
    indicator_name: str
    version: str
    points: List[SignalPoint]
    metadata: Optional[dict]

Using Lines for SL/TP Levels

Lines are horizontal levels that extend across multiple bars - perfect for Stop Loss and Take Profit zones:
def create_signal_with_lines(
    client: InnovaTradingClient,
    symbol: str,
    timeframe: int,
    signal_type: str,
    entry_price: float,
    stop_loss: float,
    take_profits: List[float],
    bar_time: int
) -> Dict[str, Any]:
    """Create a signal with Entry arrow + SL/TP horizontal lines."""

    signal_id = f"signal_{bar_time}"

    # Entry point (arrow marker)
    points = [{
        "time": bar_time,
        "type": "low" if signal_type == "BUY" else "high",
        "price": entry_price,
        "label": signal_type,
        "color": "#3b82f6" if signal_type == "BUY" else "#f97316",
        "shape": "arrowUp" if signal_type == "BUY" else "arrowDown",
        "size": 2
    }]

    # Horizontal lines (extend 15 bars)
    lines = [
        {
            "id": f"{signal_id}_entry",
            "price": entry_price,
            "start_time": bar_time,
            "bars": 15,
            "label": f"Entry: {entry_price:.5f}",
            "color": "#3b82f6",
            "style": "dashed",
            "width": 1
        },
        {
            "id": f"{signal_id}_sl",
            "price": stop_loss,
            "start_time": bar_time,
            "bars": 15,
            "label": f"SL: {stop_loss:.5f}",
            "color": "#ef4444",
            "style": "solid",
            "width": 2
        }
    ]

    # Add TP lines
    tp_colors = ["#22c55e", "#10b981", "#059669"]
    for i, tp_price in enumerate(take_profits):
        lines.append({
            "id": f"{signal_id}_tp{i+1}",
            "price": tp_price,
            "start_time": bar_time,
            "bars": 15,
            "label": f"TP{i+1}: {tp_price:.5f}",
            "color": tp_colors[i % len(tp_colors)],
            "style": "dotted",
            "width": 1
        })

    return client.submit_indicator(
        indicator_id="trading_signals",
        symbol=symbol,
        timeframe=timeframe,
        indicator_name="Trading Signals with Lines",
        points=points,
        lines=lines
    )

# Usage
client = InnovaTradingClient("YOUR_API_KEY")
df = client.get_bars("EURUSD", 60, limit=1)

result = create_signal_with_lines(
    client=client,
    symbol="EURUSD",
    timeframe=60,
    signal_type="BUY",
    entry_price=1.1725,
    stop_loss=1.1695,
    take_profits=[1.1755, 1.1785, 1.1815],
    bar_time=int(df.iloc[-1]["time"])
)

print(f"Points: {result['points_received']}, Lines: {result['lines_received']}")

Download Complete Examples

Next Steps