UNPKG

betfair-exchange-api

Version:

A TypeScript client for the Betfair Exchange API

165 lines (164 loc) 8.44 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const stream_api_client_1 = require("./stream-api-client"); async function main() { try { // Replace with your app key and session token const appKey = 'YOUR_APP_KEY'; const sessionToken = 'YOUR_SESSION_TOKEN'; // Create and connect the stream client const streamClient = new stream_api_client_1.BetfairStreamClient(appKey, sessionToken); // Event handlers streamClient.on('connected', () => { console.log('Connected to Betfair Stream API'); }); streamClient.on('disconnected', () => { console.log('Disconnected from Betfair Stream API'); }); streamClient.on('error', (error) => { console.error('Stream error:', error.message); }); streamClient.on('connection', (connection) => { console.log(`Connection established with ID: ${connection.connectionId}`); }); streamClient.on('status', (status) => { console.log(`Status: ${status.statusCode}${status.errorMessage ? ' - ' + status.errorMessage : ''}`); // If authentication successful, subscribe to markets if (status.id === 1 && status.statusCode === 'SUCCESS') { console.log('Authentication successful, subscribing to markets...'); // Example: Subscribe to Horse Racing markets (eventTypeId: 7) streamClient.subscribeToMarkets({ eventTypeIds: ['7'], // Horse Racing marketTypes: ['WIN'], // Win markets only }, { fields: ['EX_BEST_OFFERS', 'EX_TRADED', 'EX_MARKET_DEF'], ladderLevels: 3, }, 1000, // conflateMs - conflation rate in milliseconds 5000 // heartbeatMs - heartbeat interval in milliseconds ); // Also subscribe to orders streamClient.subscribeToOrders({ includeOverallPosition: true, }, 1000, // conflateMs 5000 // heartbeatMs ); } }); streamClient.on('marketChange', (marketChange) => { console.log(`Market change received: ${marketChange.ct}`); // Process market data if (marketChange.mc && marketChange.mc.length > 0) { marketChange.mc.forEach(market => { console.log(`Market ID: ${market.id}`); // Market definition (when available) if (market.marketDefinition) { console.log(` Status: ${market.marketDefinition.status}`); console.log(` In play: ${market.marketDefinition.inPlay}`); console.log(` Market time: ${market.marketDefinition.marketTime}`); if (market.marketDefinition.runners) { console.log(' Runners:'); market.marketDefinition.runners.forEach(runner => { console.log(` ID: ${runner.id}, Status: ${runner.status}`); }); } } // Runner changes if (market.rc && market.rc.length > 0) { console.log(' Runner changes:'); market.rc.forEach(runner => { console.log(` Runner ID: ${runner.id}`); // Best available to back if (runner.batb && runner.batb.length > 0) { console.log(' Best available to back:'); runner.batb.forEach(([level, price, size]) => { console.log(` Level ${level}: ${price} @ ${size}`); }); } // Best available to lay if (runner.batl && runner.batl.length > 0) { console.log(' Best available to lay:'); runner.batl.forEach(([level, price, size]) => { console.log(` Level ${level}: ${price} @ ${size}`); }); } // Last traded price if (runner.ltp !== undefined) { console.log(` Last traded price: ${runner.ltp}`); } // Traded volume if (runner.tv !== undefined) { console.log(` Traded volume: ${runner.tv}`); } }); } }); } }); streamClient.on('orderChange', (orderChange) => { console.log(`Order change received: ${orderChange.ct}`); // Process order data if (orderChange.oc && orderChange.oc.length > 0) { orderChange.oc.forEach(order => { console.log(`Market ID: ${order.id}`); // Process runner changes if (order.orc && order.orc.length > 0) { order.orc.forEach(runnerOrder => { console.log(` Runner ID: ${runnerOrder.id}`); // Unmatched orders if (runnerOrder.uo && runnerOrder.uo.length > 0) { console.log(' Unmatched orders:'); runnerOrder.uo.forEach(unmatchedOrder => { console.log(` Order ID: ${unmatchedOrder.id}`); console.log(` Side: ${unmatchedOrder.side === 'B' ? 'Back' : 'Lay'}`); console.log(` Price: ${unmatchedOrder.p}`); console.log(` Size: ${unmatchedOrder.s}`); console.log(` Status: ${unmatchedOrder.status === 'E' ? 'Executable' : 'Execution Complete'}`); console.log(` Matched: ${unmatchedOrder.sm}`); console.log(` Remaining: ${unmatchedOrder.sr}`); }); } // Matched backs if (runnerOrder.mb && runnerOrder.mb.length > 0) { console.log(' Matched backs:'); runnerOrder.mb.forEach(([price, size]) => { console.log(` ${price} @ ${size}`); }); } // Matched lays if (runnerOrder.ml && runnerOrder.ml.length > 0) { console.log(' Matched lays:'); runnerOrder.ml.forEach(([price, size]) => { console.log(` ${price} @ ${size}`); }); } }); } }); } }); // Connect to the stream console.log('Connecting to Betfair Stream API...'); streamClient.connect(); // Keep the process running console.log('Press Ctrl+C to exit'); // Simple heartbeat mechanism to keep connection alive // (should be run every few minutes, not seconds as we're doing here for demonstration) const heartbeatInterval = setInterval(() => { if (streamClient.isAuthenticated()) { console.log('Sending heartbeat...'); streamClient.sendHeartbeat(); } }, 30000); // Send heartbeat every 30 seconds // Handle process termination process.on('SIGINT', () => { console.log('Disconnecting...'); clearInterval(heartbeatInterval); streamClient.disconnect(); process.exit(0); }); } catch (error) { console.error('Error:', error.message); } } main();