@stoqey/ib (Low-Level SDK)Guides & Resources
Automated Trading Bot Quickstart
Complete step-by-step example building an automated algorithmic trading bot with @stoqey/ib.
Building a Basic Trading Bot
This guide demonstrates how to create a complete Node.js script that:
- Connects to IB Gateway / TWS paper trading account (
7497). - Requests account balance & cash availability.
- Subscribes to real-time market quotes for a target stock.
- Triggers a limit buy order when target conditions are met.
Full TypeScript Code
import {
IBApi,
EventName,
Contract,
SecType,
Order,
OrderAction,
OrderType,
TickType,
} from "@stoqey/ib";
// Configure client instance for paper trading
const ib = new IBApi({
host: "127.0.0.1",
port: 7497, // TWS Paper Trading
clientId: 42,
});
let nextOrderId = 0;
let hasPlacedOrder = false;
// Define Target Instrument
const stockContract: Contract = {
symbol: "AAPL",
secType: SecType.STK,
currency: "USD",
exchange: "SMART",
};
// 1. Connection Initialization
ib.once(EventName.nextValidId, (orderId: number) => {
console.log(`Connected! Next Valid Order ID: ${orderId}`);
nextOrderId = orderId;
// Request real-time quote for AAPL (reqId = 1)
ib.reqMktData(1, stockContract, "", false, false);
});
// 2. Listen for Real-Time Price Updates
ib.on(EventName.tickPrice, (reqId: number, tickType: TickType, price: number) => {
// TickType 4 = LAST price, TickType 1 = BID, TickType 2 = ASK
if (tickType === 4 && price > 0) {
console.log(`Current AAPL Last Price: $${price}`);
// Trigger condition: place limit order if price drops below $220
if (price < 220.0 && !hasPlacedOrder && nextOrderId > 0) {
hasPlacedOrder = true;
placeLimitBuyOrder(price);
}
}
});
// 3. Place Order Function
function placeLimitBuyOrder(currentPrice: number) {
const buyOrder: Order = {
orderId: nextOrderId,
action: OrderAction.BUY,
orderType: OrderType.LMT,
lmtPrice: Number((currentPrice * 0.999).toFixed(2)), // Limit price 0.1% below last
totalQuantity: 10,
tif: "DAY",
};
console.log(`Submitting Limit BUY order for 10 AAPL @ $${buyOrder.lmtPrice}...`);
ib.placeOrder(nextOrderId, stockContract, buyOrder);
}
// 4. Order Execution & Status Listener
ib.on(EventName.orderStatus, (orderId: number, status: string, filled: number, remaining: number, avgFillPrice: number) => {
console.log(`[Order ${orderId}] Status: ${status} | Filled: ${filled} | Avg Price: $${avgFillPrice}`);
if (status === "Filled") {
console.log("Order filled! Cleaning up connection...");
ib.cancelMktData(1);
ib.disconnect();
}
});
// Start bot
ib.connect();