Example 1: Swing Points Detector (HH/HL/LH/LL)
Detects Higher Highs, Higher Lows, Lower Highs, and Lower Lows - the foundation of market structure analysis.- Python
- JavaScript
#!/usr/bin/env python3
"""
Swing Points Detector - InnovaTrading External Indicator
Detects HH, HL, LH, LL on chart
"""
import requests
import pandas as pd
from typing import List, Dict, Any
# === CONFIGURATION ===
API_KEY = "YOUR_API_KEY"
BASE_URL = "https://api.innova-trading.com"
SYMBOL = "EURUSD"
TIMEFRAME = 60 # H1
SWING_LOOKBACK = 5 # Bars on each side to confirm swing
# === API CLIENT ===
def get_bars(symbol: str, timeframe: int, limit: int = 500) -> pd.DataFrame:
url = f"{BASE_URL}/api/external/bars/{symbol}/{timeframe}"
headers = {"Authorization": f"Bearer {API_KEY}"}
response = requests.get(url, params={"limit": limit}, headers=headers)
response.raise_for_status()
return pd.DataFrame(response.json()["bars"])
def submit_indicator(indicator_id: str, points: List[Dict], symbol: str, timeframe: int):
url = f"{BASE_URL}/api/external/indicators/{indicator_id}"
headers = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}
payload = {
"symbol": symbol,
"timeframe": timeframe,
"indicator_name": "Swing Points (HH/HL/LH/LL)",
"version": "1.0",
"points": points,
"metadata": {"lookback": SWING_LOOKBACK, "total_swings": len(points)}
}
response = requests.post(url, json=payload, headers=headers)
response.raise_for_status()
return response.json()
# === INDICATOR LOGIC ===
def is_swing_high(df: pd.DataFrame, index: int, lookback: int) -> bool:
"""Check if index is a swing high."""
if index < lookback or index >= len(df) - lookback:
return False
current_high = df.iloc[index]["high"]
for i in range(index - lookback, index + lookback + 1):
if i != index and df.iloc[i]["high"] >= current_high:
return False
return True
def is_swing_low(df: pd.DataFrame, index: int, lookback: int) -> bool:
"""Check if index is a swing low."""
if index < lookback or index >= len(df) - lookback:
return False
current_low = df.iloc[index]["low"]
for i in range(index - lookback, index + lookback + 1):
if i != index and df.iloc[i]["low"] <= current_low:
return False
return True
def detect_swing_points(df: pd.DataFrame) -> List[Dict[str, Any]]:
"""Detect swing points and classify as HH/HL/LH/LL."""
points = []
# Find all swings
swing_highs = []
swing_lows = []
for i in range(len(df)):
if is_swing_high(df, i, SWING_LOOKBACK):
swing_highs.append({"index": i, "price": df.iloc[i]["high"], "time": df.iloc[i]["time"]})
if is_swing_low(df, i, SWING_LOOKBACK):
swing_lows.append({"index": i, "price": df.iloc[i]["low"], "time": df.iloc[i]["time"]})
# Classify Swing Highs as HH or LH
for i, sh in enumerate(swing_highs):
if i == 0:
label = "SH" # First swing, no comparison
color = "#94a3b8"
else:
prev_high = swing_highs[i-1]["price"]
if sh["price"] > prev_high:
label = "HH" # Higher High
color = "#22c55e" # Green
else:
label = "LH" # Lower High
color = "#ef4444" # Red
points.append({
"time": int(sh["time"]),
"type": "high",
"price": float(sh["price"]),
"label": label,
"color": color,
"shape": "circle",
"size": 1 if label == "SH" else 2
})
# Classify Swing Lows as HL or LL
for i, sl in enumerate(swing_lows):
if i == 0:
label = "SL" # First swing, no comparison
color = "#94a3b8"
else:
prev_low = swing_lows[i-1]["price"]
if sl["price"] > prev_low:
label = "HL" # Higher Low
color = "#22c55e" # Green
else:
label = "LL" # Lower Low
color = "#ef4444" # Red
points.append({
"time": int(sl["time"]),
"type": "low",
"price": float(sl["price"]),
"label": label,
"color": color,
"shape": "circle",
"size": 1 if label == "SL" else 2
})
return points
# === MAIN ===
def main():
print("=" * 50)
print("Swing Points Detector")
print("=" * 50)
print(f"\n1. Fetching {SYMBOL} {TIMEFRAME}m bars...")
df = get_bars(SYMBOL, TIMEFRAME, 500)
print(f" Got {len(df)} bars")
print("\n2. Detecting swing points...")
points = detect_swing_points(df)
# Count types
hh = sum(1 for p in points if p["label"] == "HH")
hl = sum(1 for p in points if p["label"] == "HL")
lh = sum(1 for p in points if p["label"] == "LH")
ll = sum(1 for p in points if p["label"] == "LL")
print(f" HH: {hh}, HL: {hl}, LH: {lh}, LL: {ll}")
print("\n3. Submitting to InnovaTrading...")
result = submit_indicator("swing_points", points, SYMBOL, TIMEFRAME)
print(f" Submitted {result['points_received']} points")
print(f" Expires: {result['expires_at']}")
print("\n" + "=" * 50)
print("Done! Check the chart.")
print("=" * 50)
if __name__ == "__main__":
main()
/**
* Swing Points Detector - InnovaTrading External Indicator
* Detects HH, HL, LH, LL on chart
*/
const axios = require("axios");
// === CONFIGURATION ===
const API_KEY = "YOUR_API_KEY";
const BASE_URL = "https://api.innova-trading.com";
const SYMBOL = "EURUSD";
const TIMEFRAME = 60; // H1
const SWING_LOOKBACK = 5;
// === API CLIENT ===
async function getBars(symbol, timeframe, limit = 500) {
const response = await axios.get(
`${BASE_URL}/api/external/bars/${symbol}/${timeframe}`,
{
params: { limit },
headers: { Authorization: `Bearer ${API_KEY}` },
}
);
return response.data.bars;
}
async function submitIndicator(indicatorId, points, symbol, timeframe) {
const response = await axios.post(
`${BASE_URL}/api/external/indicators/${indicatorId}`,
{
symbol,
timeframe,
indicator_name: "Swing Points (HH/HL/LH/LL)",
version: "1.0",
points,
metadata: { lookback: SWING_LOOKBACK, total_swings: points.length },
},
{
headers: {
Authorization: `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
}
);
return response.data;
}
// === INDICATOR LOGIC ===
function isSwingHigh(bars, index, lookback) {
if (index < lookback || index >= bars.length - lookback) return false;
const currentHigh = bars[index].high;
for (let i = index - lookback; i <= index + lookback; i++) {
if (i !== index && bars[i].high >= currentHigh) return false;
}
return true;
}
function isSwingLow(bars, index, lookback) {
if (index < lookback || index >= bars.length - lookback) return false;
const currentLow = bars[index].low;
for (let i = index - lookback; i <= index + lookback; i++) {
if (i !== index && bars[i].low <= currentLow) return false;
}
return true;
}
function detectSwingPoints(bars) {
const points = [];
const swingHighs = [];
const swingLows = [];
// Find all swings
for (let i = 0; i < bars.length; i++) {
if (isSwingHigh(bars, i, SWING_LOOKBACK)) {
swingHighs.push({
index: i,
price: bars[i].high,
time: bars[i].time,
});
}
if (isSwingLow(bars, i, SWING_LOOKBACK)) {
swingLows.push({
index: i,
price: bars[i].low,
time: bars[i].time,
});
}
}
// Classify Swing Highs
swingHighs.forEach((sh, i) => {
let label, color;
if (i === 0) {
label = "SH";
color = "#94a3b8";
} else {
const prevHigh = swingHighs[i - 1].price;
if (sh.price > prevHigh) {
label = "HH";
color = "#22c55e";
} else {
label = "LH";
color = "#ef4444";
}
}
points.push({
time: sh.time,
type: "high",
price: sh.price,
label,
color,
shape: "circle",
size: label === "SH" ? 1 : 2,
});
});
// Classify Swing Lows
swingLows.forEach((sl, i) => {
let label, color;
if (i === 0) {
label = "SL";
color = "#94a3b8";
} else {
const prevLow = swingLows[i - 1].price;
if (sl.price > prevLow) {
label = "HL";
color = "#22c55e";
} else {
label = "LL";
color = "#ef4444";
}
}
points.push({
time: sl.time,
type: "low",
price: sl.price,
label,
color,
shape: "circle",
size: label === "SL" ? 1 : 2,
});
});
return points;
}
// === MAIN ===
async function main() {
console.log("=".repeat(50));
console.log("Swing Points Detector");
console.log("=".repeat(50));
console.log(`\n1. Fetching ${SYMBOL} ${TIMEFRAME}m bars...`);
const bars = await getBars(SYMBOL, TIMEFRAME, 500);
console.log(` Got ${bars.length} bars`);
console.log("\n2. Detecting swing points...");
const points = detectSwingPoints(bars);
const hh = points.filter((p) => p.label === "HH").length;
const hl = points.filter((p) => p.label === "HL").length;
const lh = points.filter((p) => p.label === "LH").length;
const ll = points.filter((p) => p.label === "LL").length;
console.log(` HH: ${hh}, HL: ${hl}, LH: ${lh}, LL: ${ll}`);
console.log("\n3. Submitting to InnovaTrading...");
const result = await submitIndicator("swing_points", points, SYMBOL, TIMEFRAME);
console.log(` Submitted ${result.points_received} points`);
console.log(` Expires: ${result.expires_at}`);
console.log("\n" + "=".repeat(50));
console.log("Done! Check the chart.");
console.log("=".repeat(50));
}
main().catch(console.error);
Example 2: RSI with Overbought/Oversold Zones
Calculates RSI and marks overbought (>70) and oversold (<30) zones.- Python
- JavaScript
#!/usr/bin/env python3
"""
RSI Indicator - InnovaTrading External Indicator
Marks overbought and oversold zones
"""
import requests
import pandas as pd
from typing import List, Dict, Any
# === CONFIGURATION ===
API_KEY = "YOUR_API_KEY"
BASE_URL = "https://api.innova-trading.com"
SYMBOL = "EURUSD"
TIMEFRAME = 60
RSI_PERIOD = 14
RSI_OVERBOUGHT = 70
RSI_OVERSOLD = 30
def get_bars(symbol: str, timeframe: int, limit: int = 500) -> pd.DataFrame:
url = f"{BASE_URL}/api/external/bars/{symbol}/{timeframe}"
headers = {"Authorization": f"Bearer {API_KEY}"}
response = requests.get(url, params={"limit": limit}, headers=headers)
response.raise_for_status()
return pd.DataFrame(response.json()["bars"])
def submit_indicator(indicator_id: str, points: List[Dict], symbol: str, timeframe: int, metadata: Dict = None):
url = f"{BASE_URL}/api/external/indicators/{indicator_id}"
headers = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}
payload = {
"symbol": symbol,
"timeframe": timeframe,
"indicator_name": f"RSI({RSI_PERIOD}) Signals",
"version": "1.0",
"points": points,
"metadata": metadata or {}
}
response = requests.post(url, json=payload, headers=headers)
response.raise_for_status()
return response.json()
def calculate_rsi(df: pd.DataFrame, period: int = 14) -> pd.Series:
"""Calculate RSI using Wilder's method."""
delta = df["close"].diff()
gain = delta.where(delta > 0, 0)
loss = (-delta).where(delta < 0, 0)
avg_gain = gain.ewm(alpha=1/period, min_periods=period).mean()
avg_loss = loss.ewm(alpha=1/period, min_periods=period).mean()
rs = avg_gain / avg_loss
rsi = 100 - (100 / (1 + rs))
return rsi
def detect_rsi_signals(df: pd.DataFrame) -> List[Dict[str, Any]]:
"""Detect RSI crosses at extreme zones."""
df["rsi"] = calculate_rsi(df, RSI_PERIOD)
points = []
for i in range(1, len(df)):
prev_rsi = df.iloc[i-1]["rsi"]
curr_rsi = df.iloc[i]["rsi"]
curr = df.iloc[i]
if pd.isna(prev_rsi) or pd.isna(curr_rsi):
continue
# RSI crosses down from overbought (sell signal)
if prev_rsi >= RSI_OVERBOUGHT and curr_rsi < RSI_OVERBOUGHT:
points.append({
"time": int(curr["time"]),
"type": "high",
"price": float(curr["high"]) + 0.0003,
"label": f"OB",
"color": "#ef4444",
"shape": "arrowDown",
"size": 2
})
# RSI crosses up from oversold (buy signal)
if prev_rsi <= RSI_OVERSOLD and curr_rsi > RSI_OVERSOLD:
points.append({
"time": int(curr["time"]),
"type": "low",
"price": float(curr["low"]) - 0.0003,
"label": f"OS",
"color": "#22c55e",
"shape": "arrowUp",
"size": 2
})
return points
def main():
print("=" * 50)
print(f"RSI({RSI_PERIOD}) Indicator")
print("=" * 50)
print(f"\n1. Fetching {SYMBOL} {TIMEFRAME}m bars...")
df = get_bars(SYMBOL, TIMEFRAME, 500)
print(f" Got {len(df)} bars")
print("\n2. Calculating RSI and detecting signals...")
points = detect_rsi_signals(df)
ob_count = sum(1 for p in points if p["label"] == "OB")
os_count = sum(1 for p in points if p["label"] == "OS")
print(f" Overbought (OB): {ob_count}")
print(f" Oversold (OS): {os_count}")
if points:
print("\n3. Submitting to InnovaTrading...")
result = submit_indicator(
"rsi_signals",
points,
SYMBOL,
TIMEFRAME,
{
"rsi_period": RSI_PERIOD,
"overbought": RSI_OVERBOUGHT,
"oversold": RSI_OVERSOLD,
"ob_signals": ob_count,
"os_signals": os_count
}
)
print(f" Submitted {result['points_received']} points")
else:
print("\n No RSI signals found")
print("\n" + "=" * 50)
if __name__ == "__main__":
main()
/**
* RSI Indicator - InnovaTrading External Indicator
* Marks overbought and oversold zones
*/
const axios = require("axios");
// === CONFIGURATION ===
const API_KEY = "YOUR_API_KEY";
const BASE_URL = "https://api.innova-trading.com";
const SYMBOL = "EURUSD";
const TIMEFRAME = 60;
const RSI_PERIOD = 14;
const RSI_OVERBOUGHT = 70;
const RSI_OVERSOLD = 30;
async function getBars(symbol, timeframe, limit = 500) {
const response = await axios.get(
`${BASE_URL}/api/external/bars/${symbol}/${timeframe}`,
{
params: { limit },
headers: { Authorization: `Bearer ${API_KEY}` },
}
);
return response.data.bars;
}
async function submitIndicator(indicatorId, points, symbol, timeframe, metadata = {}) {
const response = await axios.post(
`${BASE_URL}/api/external/indicators/${indicatorId}`,
{
symbol,
timeframe,
indicator_name: `RSI(${RSI_PERIOD}) Signals`,
version: "1.0",
points,
metadata,
},
{
headers: {
Authorization: `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
}
);
return response.data;
}
function calculateRSI(bars, period = 14) {
const closes = bars.map((b) => b.close);
const rsi = new Array(closes.length).fill(null);
const changes = [];
for (let i = 1; i < closes.length; i++) {
changes.push(closes[i] - closes[i - 1]);
}
let avgGain = 0;
let avgLoss = 0;
for (let i = 0; i < period; i++) {
if (changes[i] > 0) avgGain += changes[i];
else avgLoss += Math.abs(changes[i]);
}
avgGain /= period;
avgLoss /= period;
if (avgLoss === 0) {
rsi[period] = 100;
} else {
const rs = avgGain / avgLoss;
rsi[period] = 100 - 100 / (1 + rs);
}
for (let i = period; i < changes.length; i++) {
const change = changes[i];
const gain = change > 0 ? change : 0;
const loss = change < 0 ? Math.abs(change) : 0;
avgGain = (avgGain * (period - 1) + gain) / period;
avgLoss = (avgLoss * (period - 1) + loss) / period;
if (avgLoss === 0) {
rsi[i + 1] = 100;
} else {
const rs = avgGain / avgLoss;
rsi[i + 1] = 100 - 100 / (1 + rs);
}
}
return rsi;
}
function detectRSISignals(bars) {
const rsi = calculateRSI(bars, RSI_PERIOD);
const points = [];
for (let i = 1; i < bars.length; i++) {
const prevRsi = rsi[i - 1];
const currRsi = rsi[i];
if (prevRsi === null || currRsi === null) continue;
if (prevRsi >= RSI_OVERBOUGHT && currRsi < RSI_OVERBOUGHT) {
points.push({
time: bars[i].time,
type: "high",
price: bars[i].high + 0.0003,
label: "OB",
color: "#ef4444",
shape: "arrowDown",
size: 2,
});
}
if (prevRsi <= RSI_OVERSOLD && currRsi > RSI_OVERSOLD) {
points.push({
time: bars[i].time,
type: "low",
price: bars[i].low - 0.0003,
label: "OS",
color: "#22c55e",
shape: "arrowUp",
size: 2,
});
}
}
return points;
}
async function main() {
console.log("=".repeat(50));
console.log(`RSI(${RSI_PERIOD}) Indicator`);
console.log("=".repeat(50));
console.log(`\n1. Fetching ${SYMBOL} ${TIMEFRAME}m bars...`);
const bars = await getBars(SYMBOL, TIMEFRAME, 500);
console.log(` Got ${bars.length} bars`);
console.log("\n2. Calculating RSI and detecting signals...");
const points = detectRSISignals(bars);
const obCount = points.filter((p) => p.label === "OB").length;
const osCount = points.filter((p) => p.label === "OS").length;
console.log(` Overbought (OB): ${obCount}`);
console.log(` Oversold (OS): ${osCount}`);
if (points.length > 0) {
console.log("\n3. Submitting to InnovaTrading...");
const result = await submitIndicator("rsi_signals", points, SYMBOL, TIMEFRAME, {
rsi_period: RSI_PERIOD,
overbought: RSI_OVERBOUGHT,
oversold: RSI_OVERSOLD,
ob_signals: obCount,
os_signals: osCount,
});
console.log(` Submitted ${result.points_received} points`);
} else {
console.log("\n No RSI signals found");
}
console.log("\n" + "=".repeat(50));
}
main().catch(console.error);
Example 3: Complete Trade Signal Generator
Generates BUY/SELL signals with Entry, Stop Loss, and multiple Take Profits.- Python
- JavaScript
#!/usr/bin/env python3
"""
Complete Trade Signal Generator
Entry + SL + TP1 + TP2 + TP3
"""
import requests
import pandas as pd
from typing import List, Dict, Any
# === CONFIGURATION ===
API_KEY = "YOUR_API_KEY"
BASE_URL = "https://api.innova-trading.com"
SYMBOL = "EURUSD"
TIMEFRAME = 60
# Trading parameters
ATR_PERIOD = 14
SL_ATR_MULTIPLIER = 1.5
TP1_ATR_MULTIPLIER = 1.5 # 1:1
TP2_ATR_MULTIPLIER = 3.0 # 1:2
TP3_ATR_MULTIPLIER = 4.5 # 1:3
def get_bars(symbol: str, timeframe: int, limit: int = 500) -> pd.DataFrame:
url = f"{BASE_URL}/api/external/bars/{symbol}/{timeframe}"
headers = {"Authorization": f"Bearer {API_KEY}"}
response = requests.get(url, params={"limit": limit}, headers=headers)
response.raise_for_status()
return pd.DataFrame(response.json()["bars"])
def submit_indicator(indicator_id: str, points: List[Dict], symbol: str, timeframe: int, metadata: Dict = None):
url = f"{BASE_URL}/api/external/indicators/{indicator_id}"
headers = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}
payload = {
"symbol": symbol,
"timeframe": timeframe,
"indicator_name": "Trade Signals (Entry + SL + TPs)",
"version": "1.0",
"points": points,
"metadata": metadata or {}
}
response = requests.post(url, json=payload, headers=headers)
response.raise_for_status()
return response.json()
def calculate_atr(df: pd.DataFrame, period: int = 14) -> pd.Series:
"""Calculate Average True Range."""
high = df["high"]
low = df["low"]
close = df["close"].shift(1)
tr1 = high - low
tr2 = abs(high - close)
tr3 = abs(low - close)
tr = pd.concat([tr1, tr2, tr3], axis=1).max(axis=1)
atr = tr.rolling(window=period).mean()
return atr
def detect_bullish_setup(df: pd.DataFrame, index: int) -> bool:
"""Detect simple bullish setup (3 consecutive bullish candles)."""
if index < 3:
return False
for i in range(index - 2, index + 1):
if df.iloc[i]["close"] <= df.iloc[i]["open"]:
return False
return True
def detect_bearish_setup(df: pd.DataFrame, index: int) -> bool:
"""Detect simple bearish setup (3 consecutive bearish candles)."""
if index < 3:
return False
for i in range(index - 2, index + 1):
if df.iloc[i]["close"] >= df.iloc[i]["open"]:
return False
return True
def generate_trade_signals(df: pd.DataFrame) -> List[Dict[str, Any]]:
"""Generate complete trade signals."""
df["atr"] = calculate_atr(df, ATR_PERIOD)
points = []
for i in range(max(ATR_PERIOD, 3), len(df)):
curr = df.iloc[i]
atr = curr["atr"]
if pd.isna(atr):
continue
bar_time = int(curr["time"])
# Bullish setup
if detect_bullish_setup(df, i):
entry = float(curr["close"])
sl = entry - (atr * SL_ATR_MULTIPLIER)
tp1 = entry + (atr * TP1_ATR_MULTIPLIER)
tp2 = entry + (atr * TP2_ATR_MULTIPLIER)
tp3 = entry + (atr * TP3_ATR_MULTIPLIER)
# Entry point
points.append({
"time": bar_time,
"type": "low",
"price": entry,
"label": "BUY",
"color": "#3b82f6",
"shape": "arrowUp",
"size": 2
})
# Stop Loss
points.append({
"time": bar_time,
"type": "low",
"price": sl,
"label": "SL",
"color": "#ef4444",
"shape": "square",
"size": 1
})
# Take Profits
for tp_num, tp_price in enumerate([tp1, tp2, tp3], 1):
points.append({
"time": bar_time,
"type": "high",
"price": tp_price,
"label": f"TP{tp_num}",
"color": "#22c55e",
"shape": "circle",
"size": 1
})
# Bearish setup
elif detect_bearish_setup(df, i):
entry = float(curr["close"])
sl = entry + (atr * SL_ATR_MULTIPLIER)
tp1 = entry - (atr * TP1_ATR_MULTIPLIER)
tp2 = entry - (atr * TP2_ATR_MULTIPLIER)
tp3 = entry - (atr * TP3_ATR_MULTIPLIER)
# Entry point
points.append({
"time": bar_time,
"type": "high",
"price": entry,
"label": "SELL",
"color": "#f97316",
"shape": "arrowDown",
"size": 2
})
# Stop Loss
points.append({
"time": bar_time,
"type": "high",
"price": sl,
"label": "SL",
"color": "#ef4444",
"shape": "square",
"size": 1
})
# Take Profits
for tp_num, tp_price in enumerate([tp1, tp2, tp3], 1):
points.append({
"time": bar_time,
"type": "low",
"price": tp_price,
"label": f"TP{tp_num}",
"color": "#22c55e",
"shape": "circle",
"size": 1
})
return points
def main():
print("=" * 50)
print("Complete Trade Signal Generator")
print("=" * 50)
print(f"\n1. Fetching {SYMBOL} {TIMEFRAME}m bars...")
df = get_bars(SYMBOL, TIMEFRAME, 200)
print(f" Got {len(df)} bars")
print("\n2. Generating trade signals...")
points = generate_trade_signals(df)
buys = sum(1 for p in points if p["label"] == "BUY")
sells = sum(1 for p in points if p["label"] == "SELL")
print(f" BUY signals: {buys}")
print(f" SELL signals: {sells}")
print(f" Total points: {len(points)}")
if points:
print("\n3. Submitting to InnovaTrading...")
result = submit_indicator(
"trade_signals",
points,
SYMBOL,
TIMEFRAME,
{
"atr_period": ATR_PERIOD,
"sl_multiplier": SL_ATR_MULTIPLIER,
"tp_multipliers": [TP1_ATR_MULTIPLIER, TP2_ATR_MULTIPLIER, TP3_ATR_MULTIPLIER],
"buys": buys,
"sells": sells
}
)
print(f" Submitted {result['points_received']} points")
print(f" Expires: {result['expires_at']}")
else:
print("\n No trade setups found")
print("\n" + "=" * 50)
if __name__ == "__main__":
main()
/**
* Complete Trade Signal Generator
* Entry + SL + TP1 + TP2 + TP3
*/
const axios = require("axios");
// === CONFIGURATION ===
const API_KEY = "YOUR_API_KEY";
const BASE_URL = "https://api.innova-trading.com";
const SYMBOL = "EURUSD";
const TIMEFRAME = 60;
// Trading parameters
const ATR_PERIOD = 14;
const SL_ATR_MULTIPLIER = 1.5;
const TP1_ATR_MULTIPLIER = 1.5;
const TP2_ATR_MULTIPLIER = 3.0;
const TP3_ATR_MULTIPLIER = 4.5;
async function getBars(symbol, timeframe, limit = 500) {
const response = await axios.get(
`${BASE_URL}/api/external/bars/${symbol}/${timeframe}`,
{
params: { limit },
headers: { Authorization: `Bearer ${API_KEY}` },
}
);
return response.data.bars;
}
async function submitIndicator(indicatorId, points, symbol, timeframe, metadata = {}) {
const response = await axios.post(
`${BASE_URL}/api/external/indicators/${indicatorId}`,
{
symbol,
timeframe,
indicator_name: "Trade Signals (Entry + SL + TPs)",
version: "1.0",
points,
metadata,
},
{
headers: {
Authorization: `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
}
);
return response.data;
}
function calculateATR(bars, period = 14) {
const tr = [];
for (let i = 1; i < bars.length; i++) {
const high = bars[i].high;
const low = bars[i].low;
const prevClose = bars[i - 1].close;
const tr1 = high - low;
const tr2 = Math.abs(high - prevClose);
const tr3 = Math.abs(low - prevClose);
tr.push(Math.max(tr1, tr2, tr3));
}
const atr = new Array(bars.length).fill(null);
for (let i = period; i < bars.length; i++) {
let sum = 0;
for (let j = i - period; j < i; j++) {
sum += tr[j];
}
atr[i] = sum / period;
}
return atr;
}
function detectBullishSetup(bars, index) {
if (index < 3) return false;
for (let i = index - 2; i <= index; i++) {
if (bars[i].close <= bars[i].open) return false;
}
return true;
}
function detectBearishSetup(bars, index) {
if (index < 3) return false;
for (let i = index - 2; i <= index; i++) {
if (bars[i].close >= bars[i].open) return false;
}
return true;
}
function generateTradeSignals(bars) {
const atr = calculateATR(bars, ATR_PERIOD);
const points = [];
for (let i = Math.max(ATR_PERIOD, 3); i < bars.length; i++) {
const curr = bars[i];
const atrValue = atr[i];
if (atrValue === null) continue;
const barTime = curr.time;
// Bullish setup
if (detectBullishSetup(bars, i)) {
const entry = curr.close;
const sl = entry - atrValue * SL_ATR_MULTIPLIER;
const tp1 = entry + atrValue * TP1_ATR_MULTIPLIER;
const tp2 = entry + atrValue * TP2_ATR_MULTIPLIER;
const tp3 = entry + atrValue * TP3_ATR_MULTIPLIER;
points.push({
time: barTime,
type: "low",
price: entry,
label: "BUY",
color: "#3b82f6",
shape: "arrowUp",
size: 2,
});
points.push({
time: barTime,
type: "low",
price: sl,
label: "SL",
color: "#ef4444",
shape: "square",
size: 1,
});
[tp1, tp2, tp3].forEach((tpPrice, idx) => {
points.push({
time: barTime,
type: "high",
price: tpPrice,
label: `TP${idx + 1}`,
color: "#22c55e",
shape: "circle",
size: 1,
});
});
}
// Bearish setup
else if (detectBearishSetup(bars, i)) {
const entry = curr.close;
const sl = entry + atrValue * SL_ATR_MULTIPLIER;
const tp1 = entry - atrValue * TP1_ATR_MULTIPLIER;
const tp2 = entry - atrValue * TP2_ATR_MULTIPLIER;
const tp3 = entry - atrValue * TP3_ATR_MULTIPLIER;
points.push({
time: barTime,
type: "high",
price: entry,
label: "SELL",
color: "#f97316",
shape: "arrowDown",
size: 2,
});
points.push({
time: barTime,
type: "high",
price: sl,
label: "SL",
color: "#ef4444",
shape: "square",
size: 1,
});
[tp1, tp2, tp3].forEach((tpPrice, idx) => {
points.push({
time: barTime,
type: "low",
price: tpPrice,
label: `TP${idx + 1}`,
color: "#22c55e",
shape: "circle",
size: 1,
});
});
}
}
return points;
}
async function main() {
console.log("=".repeat(50));
console.log("Complete Trade Signal Generator");
console.log("=".repeat(50));
console.log(`\n1. Fetching ${SYMBOL} ${TIMEFRAME}m bars...`);
const bars = await getBars(SYMBOL, TIMEFRAME, 200);
console.log(` Got ${bars.length} bars`);
console.log("\n2. Generating trade signals...");
const points = generateTradeSignals(bars);
const buys = points.filter((p) => p.label === "BUY").length;
const sells = points.filter((p) => p.label === "SELL").length;
console.log(` BUY signals: ${buys}`);
console.log(` SELL signals: ${sells}`);
console.log(` Total points: ${points.length}`);
if (points.length > 0) {
console.log("\n3. Submitting to InnovaTrading...");
const result = await submitIndicator("trade_signals", points, SYMBOL, TIMEFRAME, {
atr_period: ATR_PERIOD,
sl_multiplier: SL_ATR_MULTIPLIER,
tp_multipliers: [TP1_ATR_MULTIPLIER, TP2_ATR_MULTIPLIER, TP3_ATR_MULTIPLIER],
buys,
sells,
});
console.log(` Submitted ${result.points_received} points`);
console.log(` Expires: ${result.expires_at}`);
} else {
console.log("\n No trade setups found");
}
console.log("\n" + "=".repeat(50));
}
main().catch(console.error);
Quick Reference
Point Format
point = {
"time": 1765540800, # Unix timestamp (REQUIRED)
"type": "high" | "low", # Position on candle (REQUIRED)
"price": 1.1725, # Exact price (REQUIRED)
"label": "BUY", # Text to display
"color": "#3b82f6", # Hex color
"shape": "arrowUp", # circle, arrowUp, arrowDown, square
"size": 2 # 1 (small), 2 (medium), 3 (large)
}
Recommended Colors
| Element | Color | Hex |
|---|---|---|
| Buy | Blue | #3b82f6 |
| Sell | Orange | #f97316 |
| Stop Loss | Red | #ef4444 |
| Take Profit | Green | #22c55e |
| Neutral | Yellow | #eab308 |
| Weak | Gray | #94a3b8 |
Available Shapes
| Shape | Common Use |
|---|---|
arrowUp | Buy signals |
arrowDown | Sell signals |
circle | Levels, TPs |
square | Stop Loss, S/R |
Next Steps
Continuous Integration
Automate updates
API Reference
Complete documentation