Skip to main content
Glama
streaming-example.js8.04 kB
const axios = require("axios"); const { LightstreamerClient, Subscription } = require("lightstreamer-client"); const pidCrypt = require("pidcrypt"); const IG_API_URL = "https://demo-api.ig.com/gateway/deal"; const IG_API_KEY = ""; const IG_USERNAME = ""; const IG_PASSWORD = ""; const ATR_PERIOD = 10; const SUPER_TREND_MULTIPLIER = 3; const pastResult = []; const pastSuperTrend = []; let lastSentTrend; let supertrend; const { calculateSupertrend } = require("../src/indicators/supertrend"); // Removed RSI import as it's no longer needed require("pidcrypt/rsa"); require("pidcrypt/asn1"); // Function to encrypt the password using RSA with OAEP padding function _pwdEncrypter(password, encryptionKey, timestamp) { let rsa = new pidCrypt.RSA(); let decodedKey = pidCryptUtil.decodeBase64(encryptionKey); let asn = pidCrypt.ASN1.decode(pidCryptUtil.toByteArray(decodedKey)); let tree = asn.toHexTree(); rsa.setPublicKeyFromASN(tree); const result = pidCryptUtil.encodeBase64( pidCryptUtil.convertFromHex(rsa.encrypt(password + "|" + timestamp))); return result; } // Function to obtain the encryption key async function getEncryptionKey() { try { const response = await axios.get(`${IG_API_URL}/session/encryptionKey`, { headers: { "Content-Type": "application/json", "X-IG-API-KEY": IG_API_KEY, }, }); const { encryptionKey, timeStamp } = response.data; return { encryptionKey, timeStamp }; } catch (error) { console.error( "Error obtaining the encryption key:", error.response ? error.response.data : error.message ); throw error; } } // Function to obtain session tokens async function getSessionTokens() { try { const { encryptionKey, timeStamp } = await getEncryptionKey(); const encryptedPassword = _pwdEncrypter(IG_PASSWORD, encryptionKey, timeStamp); const response = await axios.post( `${IG_API_URL}/session`, { identifier: IG_USERNAME, password: encryptedPassword, encryptedPassword: true, }, { headers: { "Content-Type": "application/json", Version: "2", "X-IG-API-KEY": IG_API_KEY, }, } ); const { lightstreamerEndpoint } = response.data; return { CST: response.headers.cst, X_SECURITY_TOKEN: response.headers["x-security-token"], LS_ENDPOINT: lightstreamerEndpoint, }; } catch (error) { console.error( "Error obtaining session tokens:", error.response ? error.response.data : error.message ); throw error; } } // Function to connect to Lightstreamer and subscribe to market prices function connectToStreaming(tokens) { const lsClient = new LightstreamerClient(tokens.LS_ENDPOINT); lsClient.connectionDetails.setUser("Z5U9VN"); lsClient.connectionDetails.setPassword( `CST-${tokens.CST}|XST-${tokens.X_SECURITY_TOKEN}` ); lsClient.addListener({ onListenStart: () => { console.log("ListenStart"); }, onStatusChange: (status) => { console.log("Connection status:", status); }, }); lsClient.connect(); // Define the items and fields to subscribe to const items = ["CHART:CS.D.EURUSD.CSD.IP:1MINUTE"]; const fields = [ "BID_OPEN", "BID_CLOSE", "BID_LOW", "BID_HIGH", "UTM", "CONS_END", ]; // Change subscription mode from "DISTINCT" to "MERGE" const subscription = new Subscription("MERGE", items, fields); subscription.setRequestedMaxFrequency(0.5); subscription.addListener({ onSubscription: () => { console.log("Subscribed to market prices"); }, onUnsubscription: () => { console.log("Unsubscribed from market prices"); }, onSubscriptionError: (code, message) => { console.error(`Subscription error: ${code} - ${message}`); }, onItemUpdate: (updateInfo) => { const item = updateInfo.getItemName(); const bidOpen = parseFloat(updateInfo.getValue("BID_OPEN")); const bidClose = parseFloat(updateInfo.getValue("BID_CLOSE")); const bidLow = parseFloat(updateInfo.getValue("BID_LOW")); const bidHigh = parseFloat(updateInfo.getValue("BID_HIGH")); const utm = new Date(Number(updateInfo.getValue("UTM"))).toLocaleString(); const candleEnd = updateInfo.getValue("CONS_END") === "1"; console.log("raw utm", updateInfo.getValue("UTM")); console.log("utm", utm); console.log("candleEnd", candleEnd); if (candleEnd) { console.log( `Update time ${utm} for ${item}: BID_OPEN = ${bidOpen}, BID_CLOSE = ${bidClose}, BID_LOW = ${bidLow} BID_HIGH = ${bidHigh}` ); pastResult.push({ o: bidOpen, h: bidHigh, l: bidLow, c: bidClose, }); supertrend = calculateSupertrend( pastResult, ATR_PERIOD, SUPER_TREND_MULTIPLIER ); console.log("Updated supertrend: ", supertrend); // Determine current trend const lastSupertrend = supertrend[supertrend.length - 1]; const lastClose = pastResult[pastResult.length - 1].c; let currentTrend = null; if (lastSupertrend !== null && lastSupertrend !== undefined) { currentTrend = lastClose > lastSupertrend ? "Uptrend" : "Downtrend"; } else { currentTrend = "Uptrend"; // Default to Uptrend if Supertrend is not available } console.log("Current trend based on supertrend: ", currentTrend); // Check for trend change if (currentTrend !== lastSentTrend) { // Create a new trade const newTradeAction = currentTrend === "Uptrend" ? "BUY" : "SELL"; const newTrade = { action: newTradeAction, entryPrice: lastClose, status: "open", entryTime: new Date(), }; console.log(`New trade created: ${JSON.stringify(newTrade)}`); lastSentTrend = currentTrend; } } // Add your logic here to handle live price updates }, }); lsClient.subscribe(subscription); } async function fetchHistoricalData(tokens) { try { const response = await axios.get( `${IG_API_URL}/prices/CS.D.EURUSD.CSD.IP`, { params: { max: 100, // Fetch the most recent 100 candlesticks pageSize: 100, resolution: "MINUTE", }, headers: { "Content-Type": "application/json", "X-IG-API-KEY": IG_API_KEY, CST: tokens.CST, Version: 3, "X-SECURITY-TOKEN": tokens.X_SECURITY_TOKEN, }, } ); const historicalData = response.data.prices.map((price) => ({ o: price.openPrice.bid, c: price.closePrice.bid, l: price.lowPrice.bid, h: price.highPrice.bid, t: new Date(price.snapshotTimeUTC).toLocaleString(), })); pastResult.push(...historicalData); console.log("Fetched historical data:", historicalData); return historicalData; } catch (error) { console.error( "Error fetching historical data:", error.response ? error.response.data : error.message ); throw error; } } // Main function to initialize streaming and fetch historical data (async () => { try { const tokens = await getSessionTokens(); const historicalData = await fetchHistoricalData(tokens); supertrend = calculateSupertrend( historicalData, ATR_PERIOD, SUPER_TREND_MULTIPLIER ); pastSuperTrend.push(...supertrend); console.log('historicalData:', historicalData) console.log("Initial supertrend: ", supertrend); if (historicalData.length > 0 && pastSuperTrend.length > 0) { lastSentTrend = historicalData[historicalData.length - 1].c > pastSuperTrend[pastSuperTrend.length - 1] ? "Uptrend" : "Downtrend"; } connectToStreaming(tokens); } catch (error) { console.error("Error initializing streaming:", error.message); process.exit(1); } })();

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/kea0811/ig-trading-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server