UNPKG

tradestation-api-ts

Version:

A comprehensive TypeScript wrapper for TradeStation WebAPI v3

1,101 lines 50.9 kB
import { EventEmitter } from 'events'; import { HttpClient } from '../client/HttpClient'; import { StreamManager } from '../streaming/StreamManager'; import { QuoteSnapshot, BarsResponse, BarStreamParams, BarHistoryParams, OptionChainParams, OptionQuoteParams, MarketDepthParams, SymbolDetailsResponse, SymbolNames, Expirations, RiskRewardAnalysisInput, RiskRewardAnalysis, SpreadTypes, Strikes } from '../types/marketData'; export declare class MarketDataService { private readonly httpClient; private readonly streamManager; constructor(httpClient: HttpClient, streamManager: StreamManager); /** * Fetches a full snapshot of the latest Quote for the given Symbols. * For realtime Quote updates, users should use the Quote Stream endpoint. * * The Quote Snapshot endpoint provides the latest price data for one or more symbols. * This includes: * - Current prices (Last, Ask, Bid) * - Daily statistics (Open, High, Low, Close) * - Volume information * - 52-week high/low data * - Market flags (delayed, halted, etc.) * * @param symbols - List of valid symbols in comma separated format. For example: "MSFT,BTCUSD". * No more than 100 symbols per request. * @returns A Promise that resolves to a QuoteSnapshot containing both successful quotes and any errors. * The response includes: * - Quotes: Array of successful quote data * - Errors: Array of any errors for invalid symbols * @throws Error if more than 100 symbols are requested * @throws Error if the request fails due to network issues or invalid authentication * * @example * ```typescript * const snapshot = await marketData.getQuoteSnapshots(['MSFT', 'BTCUSD']); * console.log(snapshot.Quotes); * // [ * // { * // Symbol: 'MSFT', * // Open: '213.65', * // High: '215.77', * // Low: '205.48', * // PreviousClose: '214.46', * // Last: '212.85', * // Ask: '212.87', * // AskSize: '300', * // Bid: '212.85', * // BidSize: '200', * // NetChange: '-1.61', * // NetChangePct: '3.5', * // High52Week: '232.86', * // High52WeekTimestamp: '2020-09-02T00:00:00Z', * // Low52Week: '132.52', * // Low52WeekTimestamp: '2020-03-23T00:00:00Z', * // Volume: '5852511', * // PreviousVolume: '24154112', * // Close: '212.85', * // DailyOpenInterest: '0', * // TradeTime: '2020-11-18T15:19:14Z', * // MarketFlags: { * // IsDelayed: false, * // IsHalted: false, * // IsBats: false, * // IsHardToBorrow: false * // } * // } * // ] * console.log(snapshot.Errors); // Any errors for invalid symbols * ``` */ getQuoteSnapshots(symbols: string[]): Promise<QuoteSnapshot>; /** * Fetches marketdata bars for the given symbol, interval, and timeframe. * The maximum amount of intraday bars a user can fetch is 57,600 per request. * This is calculated either by the amount of barsback or bars within a timeframe requested. * * @param symbol - The valid symbol string. * @param params - Parameters for the bar history request * @param params.interval - Default: `1`. Interval that each bar will consist of - for minute bars, the number of minutes aggregated in a single bar. * For bar units other than minute, value must be `1`. For unit `Minute` the max allowed `Interval` is 1440. * @param params.unit - Default: `Daily`. The unit of time for each bar interval. Valid values are: `Minute`, `Daily`, `Weekly`, `Monthly`. * @param params.barsback - Default: `1`. Number of bars back to fetch. The maximum number of intraday bars back that a user can query is 57,600. * There is no limit on daily, weekly, or monthly bars. This parameter is mutually exclusive with `firstdate`. * @param params.firstdate - The first date formatted as `YYYY-MM-DD` or `2020-04-20T18:00:00Z`. This parameter is mutually exclusive with `barsback`. * @param params.lastdate - Defaults to current timestamp. The last date formatted as `YYYY-MM-DD` or `2020-04-20T18:00:00Z`. * This parameter is mutually exclusive with `startdate` and should be used instead of that parameter. * @param params.sessiontemplate - United States (US) stock market session templates, that extend bars returned to include those outside of the regular trading session. * Ignored for non-US equity symbols. Valid values are: `USEQPre`, `USEQPost`, `USEQPreAndPost`, `USEQ24Hour`, `Default`. * @returns A Promise that resolves to a BarsResponse containing an array of Bar objects. * @throws Error if the interval is invalid for the specified unit * @throws Error if the maximum number of intraday bars is exceeded * @throws Error if mutually exclusive parameters are specified * @throws Error if the request fails due to network issues or invalid authentication * * @example * ```typescript * // Get daily bars for the last 5 days * const bars = await marketData.getBarHistory('MSFT', { * unit: 'Daily', * barsback: 5 * }); * console.log(bars.Bars[0]); * // { * // High: "218.32", * // Low: "212.42", * // Open: "214.02", * // Close: "216.39", * // TimeStamp: "2020-11-04T21:00:00Z", * // TotalVolume: "42311777", * // DownTicks: 231021, * // DownVolume: 19575455, * // OpenInterest: "0", * // IsRealtime: false, * // IsEndOfHistory: false, * // TotalTicks: 460552, * // UpTicks: 229531, * // UpVolume: 22736321, * // Epoch: 1604523600000, * // BarStatus: "Closed" * // } * * // Get 1-minute bars for a specific date range with extended hours * const bars = await marketData.getBarHistory('MSFT', { * unit: 'Minute', * interval: '1', * firstdate: '2024-01-01T14:30:00Z', * lastdate: '2024-01-01T21:00:00Z', * sessiontemplate: 'USEQPreAndPost' * }); * ``` */ getBarHistory(symbol: string, params?: BarHistoryParams): Promise<BarsResponse>; /** * Fetches symbol details and formatting information for one or more symbols. * This endpoint provides comprehensive information about symbols, including: * - Asset type (stock, option, future, etc.) * - Trading details (exchange, currency, etc.) * - Price and quantity formatting rules * - Asset-specific information (expiration dates, strike prices, etc.) * * The endpoint supports multiple asset types: * - Stocks (STOCK) * - Stock Options (STOCKOPTION) * - Index Options (INDEXOPTION) * - Futures (FUTURE) * - Forex (FOREX) * - Crypto (CRYPTO) * * Price Display Formatting: * 1. **Decimal Format**: Used for most modern securities. * Example: For a price of `123.2` with 2 decimals, display as `123.20` * * 2. **Fraction Format**: Used for some securities that trade in fractions. * Example: For a price of `534.5` with fraction 8, display as `534 4/8` * - The denominator is specified in `PriceFormat.Fraction` * - The numerator is calculated as: `(price - floor(price)) * denominator` * * 3. **SubFraction Format**: Used for complex fractional pricing. * Example: For a price of `125.92969` with fraction 32 and subfraction 4, * display as `125'29.7` * ``` * Given: * x = Price (125.92969) * y = Fraction (32) * z = SubFraction (4) * * Calculate: * a = trunc(x) // 125 * b = trunc(frac(x) * y) // 29 * c = trunc(((frac(x) - (b/y)) * z * y) / (z/10)) // 7 * ``` * * @param symbols - Single symbol string or array of symbols. Maximum 50 symbols per request. * Examples of valid symbols: * - Stocks: "MSFT", "AAPL" * - Options: "MSFT 240119C400" (MSFT Jan 19 2024 400 Call) * - Futures: "ESH24" (E-mini S&P 500 March 2024) * - Forex: "EUR/USD" * - Crypto: "BTCUSD" * * @returns A Promise that resolves to a SymbolDetailsResponse containing: * - Symbols: Array of successfully retrieved symbol details * - Errors: Array of errors for invalid symbols * * @throws Error if more than 50 symbols are requested * @throws Error if the request fails due to network issues * @throws Error if the request fails due to invalid authentication * @throws Error if the API returns an error response * * @example * ```typescript * // Example 1: Get details for a single stock * const msftDetails = await marketData.getSymbolDetails('MSFT'); * console.log(msftDetails.Symbols[0]); * // { * // AssetType: 'STOCK', * // Country: 'US', * // Currency: 'USD', * // Description: 'MICROSOFT CORP', * // Exchange: 'NASDAQ', * // PriceFormat: { * // Format: 'Decimal', * // Decimals: '2', * // IncrementStyle: 'Simple', * // Increment: '0.01', * // PointValue: '1' * // }, * // QuantityFormat: { * // Format: 'Decimal', * // Decimals: '0', * // IncrementStyle: 'Simple', * // Increment: '1', * // MinimumTradeQuantity: '1' * // }, * // Root: 'MSFT', * // Symbol: 'MSFT' * // } * * // Example 2: Get details for multiple symbols of different types * const symbols = [ * 'MSFT', // Stock * 'MSFT 240119C400', // Option * 'ESH24', // Future * 'EUR/USD', // Forex * 'BTCUSD' // Crypto * ]; * const details = await marketData.getSymbolDetails(symbols); * * // Process successful results * details.Symbols.forEach(symbol => { * console.log(`${symbol.Symbol} (${symbol.AssetType}):`, { * description: symbol.Description, * exchange: symbol.Exchange, * priceFormat: { * format: symbol.PriceFormat.Format, * decimals: symbol.PriceFormat.Decimals, * increment: symbol.PriceFormat.Increment * }, * // Asset-specific properties * ...(symbol.AssetType === 'STOCKOPTION' && { * expiration: symbol.ExpirationDate, * strike: symbol.StrikePrice, * type: symbol.OptionType * }), * ...(symbol.AssetType === 'FUTURE' && { * expiration: symbol.ExpirationDate, * type: symbol.FutureType * }) * }); * }); * * // Handle any errors * if (details.Errors.length > 0) { * console.log('Errors:', details.Errors); * } * * // Example 3: Format prices using symbol details * const stock = details.Symbols[0]; * const price = 123.456; * * switch (stock.PriceFormat.Format) { * case 'Decimal': * console.log(price.toFixed(parseInt(stock.PriceFormat.Decimals))); * break; * case 'Fraction': * const whole = Math.floor(price); * const fraction = price - whole; * const denominator = parseInt(stock.PriceFormat.Fraction!); * const numerator = Math.round(fraction * denominator); * console.log(`${whole} ${numerator}/${denominator}`); * break; * } * ``` */ getSymbolDetails(symbols: string | string[]): Promise<SymbolDetailsResponse>; /** * Get the available option contract expiration dates for the underlying symbol. * This endpoint returns a list of expiration dates for option contracts on the specified underlying symbol. * The list includes weekly, monthly, quarterly, and LEAPS expirations where available. * * @category Market Data * @endpoint GET /v3/marketdata/options/expirations/{underlying} * * @param underlying - The symbol for the underlying security (stock or index) for which to retrieve option expirations. * Must be a valid equity or index symbol. For example: 'AAPL', 'MSFT', 'SPX', etc. * @param strikePrice - Optional. The strike price to filter expirations. If provided, only returns expirations * that have options available at this strike price. Must be a positive number. * * @returns A Promise that resolves to an Expirations object containing: * - Expirations: Array of expiration dates and their types (Weekly, Monthly, Quarterly) * Each expiration contains: * - Date: The expiration date in ISO 8601 format (e.g., "2024-01-19T00:00:00Z") * - Type: The type of expiration ("Weekly", "Monthly", "Quarterly") * * @throws Error if the underlying symbol is invalid or not found * @throws Error if the request fails due to network issues * @throws Error if the request fails due to authentication issues * * @example * ```typescript * // Get all expirations for AAPL * const expirations = await marketData.getOptionExpirations('AAPL'); * console.log(expirations.Expirations); * // [ * // { Date: "2024-01-19T00:00:00Z", Type: "Monthly" }, * // { Date: "2024-01-26T00:00:00Z", Type: "Weekly" }, * // { Date: "2024-02-16T00:00:00Z", Type: "Monthly" } * // ] * * // Get expirations for MSFT at strike price 400 * const msftExpirations = await marketData.getOptionExpirations('MSFT', 400); * ``` */ getOptionExpirations(underlying: string, strikePrice?: number): Promise<Expirations>; /** * Get the available strike prices for option contracts on the specified underlying symbol. * This endpoint returns a list of strike prices available for option trading, which can be * filtered by expiration date and spread type. * * @category Market Data * @endpoint GET /v3/marketdata/options/strikes/{underlying} * * @param underlying - The symbol for the underlying security (stock or index). * Must be a valid equity or index symbol. For example: 'AAPL', 'MSFT', 'SPX', etc. * @param expiration - Optional. The expiration date to filter strikes. * Format: YYYY-MM-DD or ISO8601 (e.g., "2024-01-19" or "2024-01-19T00:00:00Z") * @param spreadType - Optional. The type of spread to filter strikes for. * Valid values include: "Single", "Vertical", "Calendar", "Butterfly", etc. * If not provided, returns strikes for all spread types. * * @returns A Promise that resolves to a Strikes object containing: * - SpreadType: The type of spread these strikes are for * - Strikes: Array of strike price arrays. Each inner array represents * the strikes needed for a specific spread configuration. * For example: * - Single: [["150"], ["155"], ["160"]] * - Vertical: [["150", "155"], ["155", "160"]] * - Butterfly: [["145", "150", "155"], ["150", "155", "160"]] * * @throws Error if the underlying symbol is invalid * @throws Error if the expiration date format is invalid * @throws Error if the spread type is invalid * @throws Error if the request fails due to network issues * @throws Error if the request fails due to invalid authentication * * @example * ```typescript * // Get all strikes for AAPL * const strikes = await marketData.getOptionStrikes('AAPL'); * * // Get strikes for MSFT options expiring on Jan 19, 2024 * const msftStrikes = await marketData.getOptionStrikes('MSFT', '2024-01-19'); * * // Get strikes for SPY butterfly spreads expiring on Jan 19, 2024 * const butterflyStrikes = await marketData.getOptionStrikes('SPY', '2024-01-19', 'Butterfly'); * ``` */ getOptionStrikes(underlying: string, expiration?: string, spreadType?: string, options?: { expiration2?: string; }): Promise<Strikes>; /** * Streams Quote changes for one or more symbols. * * This endpoint provides real-time updates for: * - Current prices (Last, Ask, Bid) * - Daily statistics (Open, High, Low, Close) * - Volume information * - 52-week high/low data * - Market flags (delayed, halted, etc.) * * A heartbeat will be sent after 5 seconds on an idle stream to indicate that the stream is alive. * * @param symbols - List of valid symbols in comma separated format. For example: "MSFT,BTCUSD". * No more than 100 symbols per request. * @returns A Promise that resolves to an EventEmitter that emits: * - QuoteStream objects for quote updates * - Heartbeat objects every 5 seconds when idle * - StreamErrorResponse objects for any errors * @throws Error if more than 100 symbols are requested * @throws Error if the request fails due to network issues or invalid authentication * * @example * ```typescript * const stream = await marketData.streamQuotes(['MSFT', 'BTCUSD']); * * stream.on('data', (data) => { * if ('Ask' in data) { * // Handle quote update * console.log('Quote update:', data); * } else if ('Heartbeat' in data) { * // Handle heartbeat * console.log('Heartbeat:', data); * } else { * // Handle error * console.log('Error:', data); * } * }); * ``` */ streamQuotes(symbols: string[]): Promise<EventEmitter>; /** * Stream real-time and historical bars for a given symbol. * The stream will first send any historical bars requested via barsback parameter, * followed by real-time bars as trades occur. * * The maximum amount of historical bars that can be requested is 57,600. * This endpoint uses Server-Sent Events (SSE) to stream data. * * @param symbol - The valid symbol string to stream bars for. * @param params - Optional parameters for the bar stream * @param params.interval - Default: 1. Interval that each bar will consist of. * For minute bars, the number of minutes aggregated in a single bar. * For bar units other than minute, value must be 1. * For unit Minute the max allowed Interval is 1440. * @param params.unit - Default: Daily. The unit of time for each bar interval. * Valid values are: Minute, Daily, Weekly, Monthly. * @param params.barsback - Default: 1. Number of historical bars to fetch. * Maximum of 57,600 bars allowed. * @param params.sessiontemplate - US stock market session templates for extended trading hours. * Ignored for non-US equity symbols. * Valid values: USEQPre, USEQPost, USEQPreAndPost, USEQ24Hour, Default. * @returns A Promise that resolves to an EventEmitter that emits Bar objects, Heartbeats, or StreamErrorResponses. * @throws Error if more than 57,600 bars are requested * @throws Error if the interval is invalid for the specified unit * @throws Error if the request fails due to network issues or invalid authentication * * @example * ```typescript * // Example 1: Stream 1-minute bars with 100 historical bars * const minuteStream = await marketData.streamBars('MSFT', { * unit: 'Minute', * interval: '1', * barsback: 100 * }); * * // Example 2: Stream daily bars with extended hours * const dailyStream = await marketData.streamBars('AAPL', { * unit: 'Daily', * sessiontemplate: 'USEQPreAndPost' * }); * * // Example 3: Stream 5-minute bars for crypto * const cryptoStream = await marketData.streamBars('BTCUSD', { * unit: 'Minute', * interval: '5' * }); * * // Handle the stream data * stream.on('data', (data: BarStreamResponse) => { * if ('Close' in data) { * // Handle bar data * console.log('Bar:', { * time: data.TimeStamp, * open: data.Open, * high: data.High, * low: data.Low, * close: data.Close, * volume: data.TotalVolume, * status: data.BarStatus, * isRealtime: data.IsRealtime * }); * } else if ('Heartbeat' in data) { * console.log('Heartbeat:', data.Timestamp); * } else { * console.log('Error:', data.Message); * } * }); * ``` */ streamBars(symbol: string, params?: BarStreamParams): Promise<EventEmitter>; /** * Stream a chain of option spreads for a given underlying symbol, spread type, and expiration. * A maximum of 10 concurrent streams is allowed. * * For options calculations, the WebAPI uses the following: * - 90 days for historical volatility of the underlying * - Bjerksund and Stensland option pricing model * - Ask price for price of the option * * The stream provides real-time updates for: * - Greeks (Delta, Gamma, Theta, Vega, Rho) * - Implied Volatility * - Intrinsic and Extrinsic Values * - Theoretical Values (current and IV-based) * - Probability Analysis (ITM, OTM, Breakeven) * - Market Data (Bid, Ask, Last, Volume, Open Interest) * - Spread Configuration (Strikes, Legs) * * A heartbeat will be sent after 5 seconds on an idle stream to indicate that the stream is alive. * * @category Market Data * @endpoint GET /v3/marketdata/stream/options/chains/{underlying} * * @param underlying - The symbol for the underlying security on which the option contracts are based. * Must be a valid equity or index symbol. For example: 'AAPL', 'MSFT', 'SPX', etc. * @param params - Optional parameters for filtering the option chain * @param params.expiration - Date on which the option contract expires; must be a valid expiration date. * Defaults to the next contract expiration date. * Format: YYYY-MM-DD or ISO8601 (e.g., "2024-01-19" or "2024-01-19T00:00:00Z") * @param params.expiration2 - Second contract expiration date required for Calendar and Diagonal spreads. * Format: YYYY-MM-DD or ISO8601 (e.g., "2024-01-19" or "2024-01-19T00:00:00Z") * @param params.strikeProximity - Specifies the number of spreads to display above and below the priceCenter. * Default: 5 * @param params.spreadType - Specifies the name of the spread type to use. * Common values: "Single", "Vertical", "Calendar", "Butterfly", "Condor", "Straddle", "Strangle" * Default: "Single" * @param params.riskFreeRate - The theoretical rate of return of an investment with zero risk. * Defaults to the current quote for $IRX.X. * The percentage rate should be specified as a decimal value between 0 and 1. * For example, to use 4.25% for the rate, pass in 0.0425. * @param params.priceCenter - Specifies the strike price center. * Defaults to the last quoted price for the underlying security. * @param params.strikeInterval - Specifies the desired interval between the strike prices in a spread. * Must be greater than or equal to 1. * A value of 1 uses consecutive strikes; a value of 2 skips one between strikes; and so on. * Default: 1 * @param params.enableGreeks - Specifies whether or not greeks properties are returned. * Default: true * @param params.strikeRange - Filters the chain by intrinsic value: * - "ITM" (in-the-money): includes only spreads that have an intrinsic value greater than zero * - "OTM" (out-of-the-money): includes only spreads that have an intrinsic value equal to zero * - "All": includes all spreads regardless of intrinsic value * Default: "All" * @param params.optionType - Filters the spreads by a specific option type. * Valid values are "All", "Call", and "Put". * Default: "All" * * @returns A Promise that resolves to an EventEmitter that emits: * - Spread objects for option chain updates, containing: * - Greeks (Delta, Gamma, Theta, Vega, Rho) * - Implied Volatility and Standard Deviation * - Value Analysis (Intrinsic, Extrinsic, Theoretical) * - Probability Analysis (ITM, OTM, Breakeven) * - Market Data (Bid, Ask, Last, Volume, Open Interest) * - Spread Configuration (Strikes, Legs) * - Heartbeat objects every 5 seconds when idle * - StreamErrorResponse objects for any errors * * @throws Error if more than 10 concurrent streams are active * @throws Error if the strike interval is less than 1 * @throws Error if expiration2 is required but not provided for Calendar/Diagonal spreads * @throws Error if the risk-free rate is not between 0 and 1 * @throws Error if the request fails due to network issues * @throws Error if the request fails due to invalid authentication * * @example * ```typescript * // Example 1: Stream butterfly spreads for AAPL * const butterflyStream = await marketData.streamOptionChain('AAPL', { * spreadType: 'Butterfly', * strikeInterval: 5, * expiration: '2024-01-19', * strikeProximity: 3 * }); * * // Example 2: Stream calendar spreads for MSFT * const calendarStream = await marketData.streamOptionChain('MSFT', { * spreadType: 'Calendar', * expiration: '2024-01-19', * expiration2: '2024-02-16', * optionType: 'Call', * strikeRange: 'ITM' * }); * * // Example 3: Stream vertical spreads with custom risk-free rate * const verticalStream = await marketData.streamOptionChain('SPY', { * spreadType: 'Vertical', * strikeInterval: 1, * riskFreeRate: 0.0425, // 4.25% * priceCenter: 475.50, * strikeProximity: 10 * }); * * // Handle the stream data * stream.on('data', (data) => { * if ('Delta' in data) { * // Handle spread data * console.log('Spread:', { * strikes: data.Strikes, * delta: data.Delta, * gamma: data.Gamma, * theta: data.Theta, * vega: data.Vega, * rho: data.Rho, * iv: data.ImpliedVolatility, * probability: { * itm: data.ProbabilityITM, * otm: data.ProbabilityOTM, * breakeven: data.ProbabilityBE * }, * value: { * intrinsic: data.IntrinsicValue, * extrinsic: data.ExtrinsicValue, * theoretical: data.TheoreticalValue * }, * market: { * bid: data.Bid, * ask: data.Ask, * last: data.Last, * volume: data.Volume * } * }); * } else if ('Heartbeat' in data) { * console.log('Heartbeat:', data.Timestamp); * } else { * console.log('Error:', data.Message); * } * }); * ``` */ streamOptionChain(underlying: string, params?: OptionChainParams): Promise<EventEmitter>; /** * Stream price quotes and greeks for the specified option spread. * A maximum of 10 concurrent streams is allowed. * * For options calculations, the WebAPI uses the following: * - 90 days for historical volatility of the underlying * - Bjerksund and Stensland option pricing model * - Ask price for price of the option * * The stream provides real-time updates for: * - Greeks (Delta, Gamma, Theta, Vega, Rho) * - Implied Volatility and Standard Deviation * - Value Analysis (Intrinsic, Extrinsic, Theoretical) * - Probability Analysis (ITM, OTM, Breakeven) * - Market Data (Bid, Ask, Last, Volume, Open Interest) * - Spread Configuration (Strikes, Legs) * * A heartbeat will be sent after 5 seconds on an idle stream to indicate that the stream is alive. * * @category Market Data * @endpoint GET /v3/marketdata/stream/options/quotes * * @param params - Parameters for the option quotes stream * @param params.legs - Array of option legs to stream quotes for. Each leg must have: * - Symbol: The option symbol (e.g., 'MSFT 240119C400') * Format: {UNDERLYING} {YYMMDD}{C/P}{STRIKE} * Example: 'MSFT 240119C400' = MSFT Jan 19 2024 400 Call * - Ratio: Optional. The number of contracts relative to other legs. * Use positive for buy trades and negative for sell trades. * For example, a Butterfly spread would use ratios of 1, -2, 1. * Default: 1 * @param params.riskFreeRate - The theoretical rate of return of an investment with zero risk. * Defaults to the current quote for $IRX.X. * The percentage rate should be specified as a decimal value between 0 and 1. * For example, to use 4.25% for the rate, pass in 0.0425. * @param params.enableGreeks - Specifies whether or not greeks properties are returned. * Default: true * * @returns A Promise that resolves to an EventEmitter that emits: * - Spread objects for option quote updates, containing: * - Greeks (Delta, Gamma, Theta, Vega, Rho) * - Implied Volatility and Standard Deviation * - Value Analysis (Intrinsic, Extrinsic, Theoretical) * - Probability Analysis (ITM, OTM, Breakeven) * - Market Data (Bid, Ask, Last, Volume, Open Interest) * - Spread Configuration (Strikes, Legs) * - Heartbeat objects every 5 seconds when idle * - StreamErrorResponse objects for any errors * * @throws Error if no legs are provided * @throws Error if more than 10 concurrent streams are active * @throws Error if the risk-free rate is not between 0 and 1 * @throws Error if any leg symbol is invalid * @throws Error if the request fails due to network issues * @throws Error if the request fails due to invalid authentication * * @example * ```typescript * // Example 1: Stream quotes for a butterfly spread * const butterflyStream = await marketData.streamOptionQuotes({ * legs: [ * { Symbol: 'MSFT 240119C400', Ratio: 1 }, // Buy 1 contract * { Symbol: 'MSFT 240119C405', Ratio: -2 }, // Sell 2 contracts * { Symbol: 'MSFT 240119C410', Ratio: 1 } // Buy 1 contract * ], * enableGreeks: true, * riskFreeRate: 0.0425 // 4.25% * }); * * // Example 2: Stream quotes for a vertical spread * const verticalStream = await marketData.streamOptionQuotes({ * legs: [ * { Symbol: 'SPY 240119C470', Ratio: 1 }, // Buy 1 contract * { Symbol: 'SPY 240119C475', Ratio: -1 } // Sell 1 contract * ], * enableGreeks: true * }); * * // Example 3: Stream quotes for a straddle * const straddleStream = await marketData.streamOptionQuotes({ * legs: [ * { Symbol: 'AAPL 240119C190', Ratio: 1 }, // Buy 1 call * { Symbol: 'AAPL 240119P190', Ratio: 1 } // Buy 1 put * ] * }); * * // Handle the stream data with detailed processing * stream.on('data', (data) => { * if ('Delta' in data) { * // Process option analytics * const analytics = { * greeks: { * delta: data.Delta, * gamma: data.Gamma, * theta: data.Theta, * vega: data.Vega, * rho: data.Rho * }, * volatility: { * implied: data.ImpliedVolatility, * standardDev: data.StandardDeviation * }, * probabilities: { * itm: { * current: data.ProbabilityITM, * withIV: data.ProbabilityITM_IV * }, * otm: { * current: data.ProbabilityOTM, * withIV: data.ProbabilityOTM_IV * }, * breakeven: { * current: data.ProbabilityBE, * withIV: data.ProbabilityBE_IV * } * }, * value: { * intrinsic: data.IntrinsicValue, * extrinsic: data.ExtrinsicValue, * theoretical: { * current: data.TheoreticalValue, * withIV: data.TheoreticalValue_IV * } * }, * market: { * last: data.Last, * bid: data.Bid, * ask: data.Ask, * volume: data.Volume, * openInterest: data.DailyOpenInterest * } * }; * * console.log('Option Analytics:', analytics); * console.log('Spread Legs:', data.Legs); * } else if ('Heartbeat' in data) { * console.log('Heartbeat:', data.Timestamp); * } else { * console.log('Error:', data.Message); * } * }); * ``` */ streamOptionQuotes(params: OptionQuoteParams): Promise<EventEmitter>; /** * Stream market depth quotes for equities, futures and stock options. * A separate quote is returned for each price, side, and participant. * * Market depth provides a detailed view of the order book, showing: * - Bid and Ask prices at multiple levels * - Size (volume) at each price level * - Number of orders at each price level * - Market participant information * * The stream provides real-time updates for: * - Bid quotes ordered from high to low price * - Ask quotes ordered from low to high price * - Timestamp for each quote * - Market participant details * - Order count and size at each level * * A heartbeat will be sent after 5 seconds on an idle stream to indicate that the stream is alive. * * @category Market Data * @endpoint GET /v3/marketdata/stream/marketdepth/quotes/{symbol} * * @param symbol - A valid symbol for the security. * Examples: 'MSFT' (stock), 'ESH24' (future), 'MSFT 240119C400' (option) * @param params - Optional parameters for the market depth stream * @param params.maxlevels - The maximum number of market depth levels to return. * Must be a positive integer. * If omitted it defaults to 20. * * @returns A Promise that resolves to an EventEmitter that emits: * - MarketDepthQuote objects for market depth updates, containing: * - Bids: Array of bid quotes ordered from high to low price * - Asks: Array of ask quotes ordered from low to high price * Each quote contains: * - TimeStamp: When the quote was placed * - Side: 'Bid' or 'Ask' * - Price: The price level * - Size: The size at this level * - OrderCount: Number of orders at this level * - Name: Market participant identifier * - Heartbeat objects every 5 seconds when idle * - StreamErrorResponse objects for any errors * * @throws Error if maxlevels is not a positive integer * @throws Error if the request fails due to network issues * @throws Error if the request fails due to invalid authentication * * @example * ```typescript * // Example 1: Stream market depth with default parameters (20 levels) * const stream = await marketData.streamMarketDepth('MSFT'); * * // Example 2: Stream market depth with custom levels * const stream = await marketData.streamMarketDepth('MSFT', { maxlevels: 10 }); * * stream.on('data', (data) => { * if ('Bids' in data) { * // Handle market depth update * console.log('Market depth update:', data); * // Example data: * // { * // Bids: [{ * // TimeStamp: '2024-01-24T15:30:00Z', * // Side: 'Bid', * // Price: '123.45', * // Size: '100', * // OrderCount: 5, * // Name: 'NSDQ' * // }], * // Asks: [{ * // TimeStamp: '2024-01-24T15:30:00Z', * // Side: 'Ask', * // Price: '123.46', * // Size: '200', * // OrderCount: 3, * // Name: 'NSDQ' * // }] * // } * } else if ('Heartbeat' in data) { * // Handle heartbeat * console.log('Heartbeat:', data); * } else { * // Handle error * console.log('Error:', data); * } * }); * ``` */ streamMarketDepth(symbol: string, params?: MarketDepthParams): Promise<EventEmitter>; /** * Stream aggregate market depth quotes for equities, futures and stock options. * A separate quote is returned for each price and side, using aggregated data from all participants. * * Market depth aggregates provide a consolidated view of the order book, showing: * - Bid and Ask prices at multiple levels * - Total size (volume) at each price level * - Biggest and smallest order sizes at each level * - Number of participants and total order count * - Time range for orders at each level * * The stream provides real-time updates for: * - Bid quotes ordered from high to low price * - Ask quotes ordered from low to high price * - Earliest and latest timestamps for each level * - Total size and order count at each level * - Size statistics (biggest, smallest) at each level * - Number of market participants at each level * * A heartbeat will be sent after 5 seconds on an idle stream to indicate that the stream is alive. * * @category Market Data * @endpoint GET /v3/marketdata/stream/marketdepth/aggregates/{symbol} * * @param symbol - A valid symbol for the security. * Examples: 'MSFT' (stock), 'ESH24' (future), 'MSFT 240119C400' (option) * @param params - Optional parameters for the market depth stream * @param params.maxlevels - The maximum number of market depth levels to return. * Must be a positive integer. * If omitted it defaults to 20. * * @returns A Promise that resolves to an EventEmitter that emits: * - MarketDepthAggregate objects for market depth updates, containing: * - Bids: Array of bid quotes ordered from high to low price * - Asks: Array of ask quotes ordered from low to high price * Each quote contains: * - EarliestTime: First timestamp for orders at this level * - LatestTime: Most recent timestamp for orders at this level * - Side: 'Bid' or 'Ask' * - Price: The price level * - TotalSize: Total size of all orders at this level * - BiggestSize: Size of the largest order at this level * - SmallestSize: Size of the smallest order at this level * - NumParticipants: Number of market participants at this level * - TotalOrderCount: Total number of orders at this level * - Heartbeat objects every 5 seconds when idle * - StreamErrorResponse objects for any errors * * @throws Error if maxlevels is not a positive integer * @throws Error if the request fails due to network issues * @throws Error if the request fails due to invalid authentication * * @example * ```typescript * // Example 1: Stream market depth aggregates with default parameters (20 levels) * const stream = await marketData.streamMarketDepthAggregates('MSFT'); * * // Example 2: Stream market depth aggregates with custom levels * const stream = await marketData.streamMarketDepthAggregates('MSFT', { maxlevels: 10 }); * * stream.on('data', (data) => { * if ('Bids' in data) { * // Handle market depth aggregate update * console.log('Market depth aggregate update:'); * * // Display bid side * console.log('\nBids (ordered from high to low price):'); * data.Bids.forEach(bid => { * console.log(`Price: ${bid.Price}`); * console.log(`Total Size: ${bid.TotalSize}`); * console.log(`Orders: ${bid.TotalOrderCount} from ${bid.NumParticipants} participants`); * console.log(`Size Range: ${bid.SmallestSize} - ${bid.BiggestSize}`); * console.log(`Time Range: ${bid.EarliestTime} - ${bid.LatestTime}\n`); * }); * * // Display ask side * console.log('\nAsks (ordered from low to high price):'); * data.Asks.forEach(ask => { * console.log(`Price: ${ask.Price}`); * console.log(`Total Size: ${ask.TotalSize}`); * console.log(`Orders: ${ask.TotalOrderCount} from ${ask.NumParticipants} participants`); * console.log(`Size Range: ${ask.SmallestSize} - ${ask.BiggestSize}`); * console.log(`Time Range: ${ask.EarliestTime} - ${ask.LatestTime}\n`); * }); * * // Calculate and display spread * if (data.Asks.length > 0 && data.Bids.length > 0) { * const bestBid = Math.max(...data.Bids.map(b => parseFloat(b.Price))); * const bestAsk = Math.min(...data.Asks.map(a => parseFloat(a.Price))); * const spread = bestAsk - bestBid; * console.log(`\nSpread: ${spread.toFixed(4)}`); * } * * // Display total liquidity at each price level * console.log('\nLiquidity by Price Level:'); * const liquidity = new Map<string, { bidSize: number, askSize: number }>(); * * data.Bids.forEach(bid => { * liquidity.set(bid.Price, { * bidSize: parseInt(bid.TotalSize), * askSize: 0 * }); * }); * * data.Asks.forEach(ask => { * const current = liquidity.get(ask.Price) || { bidSize: 0, askSize: 0 }; * liquidity.set(ask.Price, { * ...current, * askSize: parseInt(ask.TotalSize) * }); * }); * * Array.from(liquidity.entries()) * .sort((a, b) => parseFloat(b[0]) - parseFloat(a[0])) * .forEach(([price, { bidSize, askSize }]) => { * console.log(`${price}: ${bidSize > 0 ? `Bid ${bidSize}` : ''}${bidSize > 0 && askSize > 0 ? ' | ' : ''}${askSize > 0 ? `Ask ${askSize}` : ''}`); * }); * } else if ('Heartbeat' in data) { * // Handle heartbeat * console.log('Heartbeat:', data.Timestamp); * } else { * // Handle error * console.log('Error:', data.Message); * } * }); * ``` */ streamMarketDepthAggregates(symbol: string, params?: MarketDepthParams): Promise<EventEmitter>; /** * Fetches crypto Symbol Names for all available cryptocurrency pairs. * This endpoint provides a list of all available cryptocurrency trading pairs * that can be used with other market data endpoints. * * The endpoint returns a list of cryptocurrency pairs in the format: * - BTCUSD (Bitcoin/US Dollar) * - ETHUSD (Ethereum/US Dollar) * - LTCUSD (Litecoin/US Dollar) * - BCHUSD (Bitcoin Cash/US Dollar) * * Note: While market data can be obtained for these symbols through various endpoints * (quotes, bars, etc.), they cannot be traded through the TradeStation API. * * This is a non-streaming GET endpoint that returns a static list of available pairs. * For real-time cryptocurrency data, use the Quote Stream or Bar Stream endpoints * with these symbols. * * @returns A Promise that resolves to a SymbolNames object containing an array of available crypto symbol names. * @throws Error if the request fails due to network issues * @throws Error if the request fails due to invalid authentication * @throws Error if the API returns an error response * * @example * ```typescript * // Get available crypto pairs * const cryptoSymbols = await marketData.getCryptoSymbolNames(); * console.log(cryptoSymbols.SymbolNames); * // ['BTCUSD', 'ETHUSD', 'LTCUSD', 'BCHUSD'] * * // Use with quote snapshots * const quotes = await marketData.getQuoteSnapshots(cryptoSymbols.SymbolNames); * quotes.Quotes.forEach(quote => { * console.log(`${quote.Symbol}:`, { * last: quote.Last, * bid: quote.Bid, * ask: quote.Ask, * volume: quote.Volume * }); * }); * * // Use with streaming bars * const btcStream = await marketData.streamBars('BTCUSD', { * interval: '1', * unit: 'Minute' * }); * btcStream.on('data', data => { * if ('Close' in data) { * console.log('BTC/USD:', { * price: data.Close, * volume: data.TotalVolume, * time: data.TimeStamp * }); * } * }); * ``` */ getCryptoSymbolNames(): Promise<SymbolNames>; /** * Get risk/reward analysis for an option spread. * * @category Market Data * @endpoint POST /v3/marketdata/options/riskreward * * @param analysis - The risk/reward analysis input * @returns A Promise that resolves to a RiskRewardAnalysis object * * @throws Error if no legs are provided * @throws Error if the request fails due to network issues * @throws Error if the request fails due to invalid authentication * * @example * ```typescript * const analysis = await marketData.getOptionRiskReward({ * SpreadPrice: '0.24', * Legs: [ * { * Symbol: 'AAPL 240119C150', * Ratio: 1, * OpenPrice: '3.50', * TargetPrice: '5.00', * StopPrice: '2.00' * }, * { * Symbol: 'AAPL 240119C152.5', * Ratio: -1, * OpenPrice: '2.00', * TargetPrice: '1.00', * StopPrice: '3.00' * } * ] * }); * * // Access the risk/reward metrics * console.log(`Max Profit: ${analysis.MaxProfit}`); * console.log(`Max Loss: ${analysis.MaxLoss}`); * console.log(`Breakeven Points: ${analysis.BreakevenPoints.join(', ')}`); * * // Access the profit/loss points * analysis.ProfitLossPoints.forEach(point => { * console.log(`At $${point.Price}: ${point.ProfitLoss}`); * }); * // At $150.00: -0.24 * // At $152.24: 0.00 * // At $155.00: 2.76 * // At $157.76: 0.00 * // At $160.00: -0.24 * ``` */ getOptionRiskReward(analysis: RiskRewardAnalysisInput): Promise<RiskRewardAnalysis>; /** * Get the available spread types for option chains. * This endpoint returns a list of all available option spread types and their configurations. * * Each spread type defines: * 1. Whether it uses strike intervals between legs (e.g., Vertical spreads) * 2. Whether it can use multiple expiration dates (e.g., Calendar spreads) * * Common spread types include: * - Single: Basic option position (no strike/expiration intervals) * - Vertical: Spread using different strikes, same expiration * - Calendar: Spread using same strike, different expirations * - Butterfly: Three-legged spread with specific strike intervals * - Condor: Four-legged spread with specific strike intervals * - Straddle: Combination of Call and Put at same strike/expiration * - Strangle: Combination of Call and Put at different strikes * * @category Market Data * @endpoint GET /v3/marketdata/options/spreadtypes * * @returns A Promise that resolves to a SpreadTypes object containing: * - SpreadTyp