JSPM

@neural-trader/brokers

2.1.1
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 27
  • Score
    100M100P100Q66866F
  • License MIT OR Apache-2.0

Broker integrations for Neural Trader - Alpaca, Interactive Brokers, TD Ameritrade

Package Exports

  • @neural-trader/brokers
  • @neural-trader/brokers/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@neural-trader/brokers) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

@neural-trader/brokers

npm version License TypeScript

Enterprise-grade broker integrations for Neural Trader with unified API supporting Alpaca, Interactive Brokers, Binance, and Coinbase. Built with Rust for maximum performance and reliability.

Table of Contents

Features

  • Multi-Broker Support: Alpaca, Interactive Brokers, Binance, Coinbase with unified interface
  • Order Management: Market, limit, stop, stop-limit orders with advanced time-in-force options
  • Account Management: Real-time balance, positions, and portfolio tracking
  • Paper Trading: Full-featured simulation mode for risk-free strategy testing
  • WebSocket Streaming: Real-time order updates and execution notifications
  • Crypto & Equities: Support for both traditional and digital asset trading
  • Rust Performance: Lightning-fast order execution with sub-millisecond latency
  • Type Safety: Full TypeScript definitions for all APIs
  • Error Recovery: Automatic retry logic and connection recovery
  • Rate Limiting: Built-in rate limit management per broker requirements

Installation

# Install with required dependencies
npm install @neural-trader/brokers @neural-trader/core

# Or with yarn
yarn add @neural-trader/brokers @neural-trader/core

# Install type definitions
npm install --save-dev @types/node

Dependencies

This package requires:

  • @neural-trader/core - Core functionality and types
  • @neural-trader/execution - Order execution engine (installed automatically)

Quick Start

Basic Usage

import { BrokerClient, listBrokerTypes } from '@neural-trader/brokers';

// List available brokers
console.log('Available brokers:', listBrokerTypes());
// Output: ['alpaca', 'interactive_brokers', 'binance', 'coinbase']

// Connect to Alpaca for equities trading
const client = new BrokerClient({
  brokerType: 'alpaca',
  apiKey: process.env.ALPACA_API_KEY,
  apiSecret: process.env.ALPACA_SECRET,
  baseUrl: 'https://paper-api.alpaca.markets',
  paperTrading: true
});

await client.connect();
console.log('Connected to broker');

// Place a market order
const order = await client.placeOrder({
  symbol: 'AAPL',
  side: 'buy',
  orderType: 'market',
  quantity: 100,
  timeInForce: 'day'
});

console.log(`Order placed: ${order.orderId}`);
console.log(`Status: ${order.status}`);

// Check account balance
const balance = await client.getAccountBalance();
console.log(`Cash: $${balance.cash.toFixed(2)}`);
console.log(`Equity: $${balance.equity.toFixed(2)}`);

// Cleanup
await client.disconnect();

Supported Brokers

Alpaca

  • Asset Types: US Equities, ETFs, Crypto (via Alpaca Crypto)
  • Paper Trading: Yes (full feature parity)
  • API Base: https://paper-api.alpaca.markets (paper), https://api.alpaca.markets (live)
  • Authentication: API Key + Secret

Interactive Brokers

  • Asset Types: Stocks, Options, Futures, Forex, Bonds
  • Paper Trading: Yes (IB Gateway required)
  • API Base: Local gateway connection (port 4001/7496)
  • Authentication: Account credentials

Binance

  • Asset Types: Cryptocurrencies (500+ pairs)
  • Paper Trading: Testnet available
  • API Base: https://testnet.binance.vision (testnet), https://api.binance.com (live)
  • Authentication: API Key + Secret

Coinbase

  • Asset Types: Cryptocurrencies (200+ assets)
  • Paper Trading: Sandbox available
  • API Base: https://api-public.sandbox.pro.coinbase.com (sandbox), https://api.coinbase.com (live)
  • Authentication: API Key + Secret + Passphrase

Core Concepts

Order Types

// Market Order - Execute immediately at best available price
await client.placeOrder({
  symbol: 'AAPL',
  side: 'buy',
  orderType: 'market',
  quantity: 100,
  timeInForce: 'day'
});

// Limit Order - Execute only at specified price or better
await client.placeOrder({
  symbol: 'AAPL',
  side: 'sell',
  orderType: 'limit',
  quantity: 100,
  limitPrice: 175.50,
  timeInForce: 'gtc'
});

// Stop Order - Trigger market order when price reaches stop price
await client.placeOrder({
  symbol: 'AAPL',
  side: 'sell',
  orderType: 'stop',
  quantity: 100,
  stopPrice: 165.00,
  timeInForce: 'day'
});

// Stop-Limit Order - Trigger limit order at stop price
await client.placeOrder({
  symbol: 'AAPL',
  side: 'sell',
  orderType: 'stop_limit',
  quantity: 100,
  stopPrice: 165.00,
  limitPrice: 164.50,
  timeInForce: 'day'
});

Time In Force Options

  • day - Order valid until market close
  • gtc - Good 'til canceled (90 days max)
  • ioc - Immediate or cancel
  • fok - Fill or kill (entire order must execute)
  • opg - Execute at market open
  • cls - Execute at market close

Account Information

// Get detailed account information
const balance = await client.getAccountBalance();
console.log('Account Details:');
console.log(`  Cash: $${balance.cash}`);
console.log(`  Equity: $${balance.equity}`);
console.log(`  Buying Power: $${balance.buyingPower}`);
console.log(`  Margin Used: $${balance.marginUsed || 0}`);

// Get all open positions
const positions = await client.getPositions();
positions.forEach(pos => {
  console.log(`${pos.symbol}: ${pos.quantity} shares @ $${pos.entryPrice}`);
  console.log(`  Current P&L: $${pos.unrealizedPl}`);
});

Examples

Cryptocurrency Trading (Binance)

import { BrokerClient } from '@neural-trader/brokers';

const binance = new BrokerClient({
  brokerType: 'binance',
  apiKey: process.env.BINANCE_API_KEY,
  apiSecret: process.env.BINANCE_SECRET,
  baseUrl: 'https://testnet.binance.vision',
  paperTrading: true
});

await binance.connect();

// Place crypto order (BTC/USDT)
const btcOrder = await binance.placeOrder({
  symbol: 'BTCUSDT',
  side: 'buy',
  orderType: 'limit',
  quantity: 0.01,
  limitPrice: 42000.00,
  timeInForce: 'gtc'
});

console.log(`BTC Order ID: ${btcOrder.orderId}`);

// Monitor order status
const status = await binance.getOrderStatus(btcOrder.orderId);
console.log(`Order Status: ${status.status}`);
console.log(`Filled: ${status.filledQuantity}/${status.quantity}`);

await binance.disconnect();

Multi-Broker Portfolio Management

import { BrokerClient } from '@neural-trader/brokers';

// Manage positions across multiple brokers
const brokers = [
  new BrokerClient({ brokerType: 'alpaca', /* ... */ }),
  new BrokerClient({ brokerType: 'binance', /* ... */ }),
  new BrokerClient({ brokerType: 'coinbase', /* ... */ })
];

// Connect to all brokers
await Promise.all(brokers.map(b => b.connect()));

// Get consolidated portfolio view
const portfolios = await Promise.all(
  brokers.map(async broker => ({
    broker: broker.config.brokerType,
    balance: await broker.getAccountBalance(),
    positions: await broker.getPositions()
  }))
);

// Calculate total portfolio value
const totalEquity = portfolios.reduce(
  (sum, p) => sum + p.balance.equity,
  0
);
console.log(`Total Portfolio Value: $${totalEquity.toFixed(2)}`);

// Cleanup
await Promise.all(brokers.map(b => b.disconnect()));

Order Management with Error Handling

import { BrokerClient } from '@neural-trader/brokers';

async function placeOrderWithRetry(
  client: BrokerClient,
  order: OrderRequest,
  maxRetries = 3
): Promise<OrderResponse> {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await client.placeOrder(order);
    } catch (error) {
      console.error(`Order attempt ${attempt} failed:`, error.message);

      if (attempt === maxRetries) {
        throw new Error(`Failed to place order after ${maxRetries} attempts`);
      }

      // Wait before retry (exponential backoff)
      await new Promise(resolve =>
        setTimeout(resolve, Math.pow(2, attempt) * 1000)
      );
    }
  }
}

// Usage
const client = new BrokerClient({ /* config */ });
await client.connect();

try {
  const order = await placeOrderWithRetry(client, {
    symbol: 'AAPL',
    side: 'buy',
    orderType: 'limit',
    quantity: 100,
    limitPrice: 170.00,
    timeInForce: 'day'
  });

  console.log(`Order placed successfully: ${order.orderId}`);
} catch (error) {
  console.error('Failed to place order:', error);
}

await client.disconnect();

Advanced Order Monitoring

import { BrokerClient } from '@neural-trader/brokers';

const client = new BrokerClient({ /* config */ });
await client.connect();

// Place order
const order = await client.placeOrder({
  symbol: 'TSLA',
  side: 'buy',
  orderType: 'limit',
  quantity: 50,
  limitPrice: 250.00,
  timeInForce: 'day'
});

// Monitor order until filled or cancelled
async function monitorOrder(orderId: string): Promise<void> {
  const checkInterval = 1000; // 1 second
  const maxWaitTime = 300000; // 5 minutes
  const startTime = Date.now();

  while (Date.now() - startTime < maxWaitTime) {
    const status = await client.getOrderStatus(orderId);

    console.log(`Order ${orderId}:`);
    console.log(`  Status: ${status.status}`);
    console.log(`  Filled: ${status.filledQuantity}/${status.quantity}`);
    console.log(`  Avg Fill Price: $${status.averagePrice || 'N/A'}`);

    if (status.status === 'filled') {
      console.log('Order filled successfully!');
      return;
    }

    if (status.status === 'cancelled' || status.status === 'rejected') {
      console.log(`Order ${status.status}`);
      return;
    }

    await new Promise(resolve => setTimeout(resolve, checkInterval));
  }

  console.log('Order monitoring timeout - cancelling order');
  await client.cancelOrder(orderId);
}

await monitorOrder(order.orderId);
await client.disconnect();

Integration Patterns

Integration with Strategies

import { BrokerClient } from '@neural-trader/brokers';
import { Strategy } from '@neural-trader/strategies';
import { MarketDataProvider } from '@neural-trader/market-data';

// Create trading strategy
const strategy = new Strategy({
  name: 'momentum-strategy',
  symbols: ['AAPL', 'MSFT', 'GOOGL'],
  parameters: {
    rsiPeriod: 14,
    rsiOverbought: 70,
    rsiOversold: 30
  }
});

// Connect broker and data provider
const broker = new BrokerClient({
  brokerType: 'alpaca',
  apiKey: process.env.ALPACA_API_KEY,
  apiSecret: process.env.ALPACA_SECRET,
  paperTrading: true
});

const dataProvider = new MarketDataProvider({
  provider: 'alpaca',
  apiKey: process.env.ALPACA_API_KEY,
  apiSecret: process.env.ALPACA_SECRET
});

await broker.connect();
await dataProvider.connect();

// Execute strategy signals through broker
strategy.on('signal', async (signal) => {
  console.log(`Signal: ${signal.action} ${signal.symbol}`);

  try {
    if (signal.action === 'buy') {
      const order = await broker.placeOrder({
        symbol: signal.symbol,
        side: 'buy',
        orderType: 'market',
        quantity: signal.quantity,
        timeInForce: 'day'
      });
      console.log(`Buy order placed: ${order.orderId}`);
    } else if (signal.action === 'sell') {
      const order = await broker.placeOrder({
        symbol: signal.symbol,
        side: 'sell',
        orderType: 'market',
        quantity: signal.quantity,
        timeInForce: 'day'
      });
      console.log(`Sell order placed: ${order.orderId}`);
    }
  } catch (error) {
    console.error(`Failed to execute signal:`, error);
  }
});

// Start strategy with real-time data
await strategy.start(dataProvider);

Integration with Backtesting

import { BrokerClient, validateBrokerConfig } from '@neural-trader/brokers';
import { BacktestEngine } from '@neural-trader/backtesting';

// Create backtest engine with broker simulation
const backtest = new BacktestEngine({
  initialCapital: 100000,
  commission: 0.001, // 0.1% per trade
  slippage: 0.0005,  // 0.05% slippage
  startDate: '2023-01-01',
  endDate: '2023-12-31'
});

// Define strategy that uses broker API patterns
backtest.addStrategy(async (context) => {
  const { data, portfolio } = context;

  // Simulate broker order placement
  if (data.rsi < 30) {
    // Buy signal
    const quantity = Math.floor(portfolio.cash / data.close / 2);
    if (quantity > 0) {
      await context.placeOrder({
        symbol: data.symbol,
        side: 'buy',
        orderType: 'market',
        quantity: quantity,
        timeInForce: 'day'
      });
    }
  } else if (data.rsi > 70) {
    // Sell signal
    const position = portfolio.positions.get(data.symbol);
    if (position && position.quantity > 0) {
      await context.placeOrder({
        symbol: data.symbol,
        side: 'sell',
        orderType: 'market',
        quantity: position.quantity,
        timeInForce: 'day'
      });
    }
  }
});

// Run backtest
const results = await backtest.run(['AAPL', 'MSFT']);

console.log('Backtest Results:');
console.log(`  Total Return: ${(results.totalReturn * 100).toFixed(2)}%`);
console.log(`  Sharpe Ratio: ${results.sharpeRatio.toFixed(2)}`);
console.log(`  Max Drawdown: ${(results.maxDrawdown * 100).toFixed(2)}%`);
console.log(`  Win Rate: ${(results.winRate * 100).toFixed(2)}%`);

// After successful backtest, deploy to live broker
if (results.sharpeRatio > 2.0 && results.maxDrawdown < 0.2) {
  console.log('Strategy passed validation - deploying to live trading');

  const broker = new BrokerClient({
    brokerType: 'alpaca',
    apiKey: process.env.ALPACA_API_KEY,
    apiSecret: process.env.ALPACA_SECRET,
    paperTrading: true // Start with paper trading
  });

  await broker.connect();
  console.log('Live trading initialized');
}

API Reference

BrokerClient

Main class for interacting with brokers.

class BrokerClient {
  constructor(config: BrokerConfig);

  // Connection Management
  connect(): Promise<boolean>;
  disconnect(): Promise<void>;
  isConnected(): Promise<boolean>;

  // Order Management
  placeOrder(order: OrderRequest): Promise<OrderResponse>;
  cancelOrder(orderId: string): Promise<boolean>;
  cancelAllOrders(symbol?: string): Promise<number>;
  getOrderStatus(orderId: string): Promise<OrderResponse>;
  listOrders(filters?: OrderFilters): Promise<OrderResponse[]>;

  // Account Management
  getAccountBalance(): Promise<AccountBalance>;
  getPositions(): Promise<JsPosition[]>;
  getPosition(symbol: string): Promise<JsPosition | null>;

  // Market Data (Basic)
  getQuote(symbol: string): Promise<Quote>;

  // Configuration
  get config(): BrokerConfig;
  updateConfig(updates: Partial<BrokerConfig>): void;
}

Types

interface BrokerConfig {
  brokerType: 'alpaca' | 'interactive_brokers' | 'binance' | 'coinbase';
  apiKey: string;
  apiSecret: string;
  baseUrl?: string;
  paperTrading?: boolean;
  websocketEnabled?: boolean;
  timeout?: number;
}

interface OrderRequest {
  symbol: string;
  side: 'buy' | 'sell';
  orderType: 'market' | 'limit' | 'stop' | 'stop_limit';
  quantity: number;
  limitPrice?: number;
  stopPrice?: number;
  timeInForce: 'day' | 'gtc' | 'ioc' | 'fok' | 'opg' | 'cls';
  extendedHours?: boolean;
  clientOrderId?: string;
}

interface OrderResponse {
  orderId: string;
  clientOrderId?: string;
  symbol: string;
  side: 'buy' | 'sell';
  orderType: string;
  quantity: number;
  filledQuantity: number;
  remainingQuantity: number;
  limitPrice?: number;
  stopPrice?: number;
  averagePrice?: number;
  status: 'pending' | 'open' | 'filled' | 'partially_filled' | 'cancelled' | 'rejected';
  timeInForce: string;
  createdAt: string;
  updatedAt?: string;
  filledAt?: string;
}

interface AccountBalance {
  cash: number;
  equity: number;
  buyingPower: number;
  marginUsed?: number;
  availableForTrading: number;
  currency: string;
}

interface JsPosition {
  symbol: string;
  quantity: number;
  entryPrice: number;
  currentPrice: number;
  marketValue: number;
  costBasis: number;
  unrealizedPl: number;
  unrealizedPlPercent: number;
  side: 'long' | 'short';
}

interface OrderFilters {
  symbol?: string;
  status?: string;
  side?: 'buy' | 'sell';
  limit?: number;
  after?: string;
  until?: string;
}

Utility Functions

// List all supported broker types
function listBrokerTypes(): string[];

// Validate broker configuration
function validateBrokerConfig(config: BrokerConfig): boolean;

// Check if broker supports feature
function brokerSupportsFeature(
  brokerType: string,
  feature: 'options' | 'crypto' | 'futures' | 'forex'
): boolean;

Configuration

Environment Variables

# Alpaca
ALPACA_API_KEY=your_alpaca_key
ALPACA_SECRET=your_alpaca_secret

# Interactive Brokers
IB_ACCOUNT=your_account_number
IB_HOST=localhost
IB_PORT=4001

# Binance
BINANCE_API_KEY=your_binance_key
BINANCE_SECRET=your_binance_secret

# Coinbase
COINBASE_API_KEY=your_coinbase_key
COINBASE_SECRET=your_coinbase_secret
COINBASE_PASSPHRASE=your_passphrase

Configuration File

// config/brokers.ts
import { BrokerConfig } from '@neural-trader/brokers';

export const brokerConfigs: Record<string, BrokerConfig> = {
  alpaca: {
    brokerType: 'alpaca',
    apiKey: process.env.ALPACA_API_KEY!,
    apiSecret: process.env.ALPACA_SECRET!,
    baseUrl: 'https://paper-api.alpaca.markets',
    paperTrading: true,
    websocketEnabled: true,
    timeout: 30000
  },
  binance: {
    brokerType: 'binance',
    apiKey: process.env.BINANCE_API_KEY!,
    apiSecret: process.env.BINANCE_SECRET!,
    baseUrl: 'https://testnet.binance.vision',
    paperTrading: true,
    timeout: 10000
  }
};

Error Handling

Common Errors

import { BrokerClient } from '@neural-trader/brokers';

const client = new BrokerClient({ /* config */ });

try {
  await client.connect();
  const order = await client.placeOrder({ /* order */ });
} catch (error) {
  if (error.message.includes('Invalid API key')) {
    console.error('Authentication failed - check credentials');
  } else if (error.message.includes('Insufficient funds')) {
    console.error('Not enough buying power for order');
  } else if (error.message.includes('Market closed')) {
    console.error('Market is currently closed');
  } else if (error.message.includes('Rate limit')) {
    console.error('API rate limit exceeded - retry later');
  } else if (error.message.includes('Connection timeout')) {
    console.error('Broker connection timeout - check network');
  } else {
    console.error('Unexpected error:', error);
  }
} finally {
  await client.disconnect();
}

Retry Logic

async function connectWithRetry(
  client: BrokerClient,
  maxRetries = 3,
  delayMs = 1000
): Promise<boolean> {
  for (let i = 0; i < maxRetries; i++) {
    try {
      const connected = await client.connect();
      if (connected) return true;
    } catch (error) {
      console.error(`Connection attempt ${i + 1} failed:`, error.message);
      if (i < maxRetries - 1) {
        await new Promise(resolve => setTimeout(resolve, delayMs * (i + 1)));
      }
    }
  }
  throw new Error(`Failed to connect after ${maxRetries} attempts`);
}

Best Practices

1. Always Use Paper Trading First

// Test with paper trading before live
const client = new BrokerClient({
  brokerType: 'alpaca',
  apiKey: process.env.ALPACA_API_KEY,
  apiSecret: process.env.ALPACA_SECRET,
  paperTrading: true // Always start here
});

2. Implement Proper Error Handling

// Always wrap broker operations in try-catch
try {
  await client.placeOrder(order);
} catch (error) {
  // Log and handle errors appropriately
  console.error('Order failed:', error);
  // Notify monitoring system
  // Attempt recovery or rollback
}

3. Monitor Order Execution

// Don't assume orders are filled immediately
const order = await client.placeOrder(orderRequest);
const finalStatus = await waitForOrderCompletion(client, order.orderId);
if (finalStatus.status !== 'filled') {
  console.warn('Order not filled:', finalStatus);
}

4. Use Connection Pooling

// Reuse broker connections
let clientInstance: BrokerClient | null = null;

function getClient(): BrokerClient {
  if (!clientInstance) {
    clientInstance = new BrokerClient({ /* config */ });
  }
  return clientInstance;
}

// Cleanup on app shutdown
process.on('SIGTERM', async () => {
  if (clientInstance) {
    await clientInstance.disconnect();
  }
});

5. Respect Rate Limits

// Implement rate limiting for API calls
import pLimit from 'p-limit';

const limit = pLimit(5); // Max 5 concurrent requests

const orders = symbols.map(symbol =>
  limit(() => client.placeOrder({
    symbol,
    side: 'buy',
    orderType: 'market',
    quantity: 100,
    timeInForce: 'day'
  }))
);

await Promise.all(orders);

6. Secure Credential Management

// Never hardcode credentials
// Use environment variables or secure vaults
import { BrokerClient } from '@neural-trader/brokers';

const client = new BrokerClient({
  brokerType: 'alpaca',
  apiKey: process.env.ALPACA_API_KEY!, // From environment
  apiSecret: process.env.ALPACA_SECRET!,
  paperTrading: process.env.NODE_ENV !== 'production'
});

License

Dual-licensed under MIT OR Apache-2.0.

See LICENSE-MIT and LICENSE-APACHE for details.