# QuoteMedia Streaming Data Service - JavaScript Client

JavaScript streaming client that provides easy-to-use client APIs to connect and subscribe to QuoteMedia's market data streaming services.

https://quotemedia.com/

## Getting Started

The JavaScript streaming client is a library that contains all the necessary dependencies to run in both `browser` and `Node.js` environments.

### Browser Usage

Include the library file in your HTML page:
```html
<script src="qmci-streamer-2.70.0.min.js"></script>
<script>
    var Streamer = qmci.Streamer;
</script>
```

### Node.js Usage

Since the `window` object is not available in `Node.js`, it will need to be mocked before importing the library:

1. Mock the window object:
    ```javascript
    if (typeof global.window === 'undefined') {
        var window = {
            navigator: { userAgent: "atmosphere.js" },
            document: {},
            location: { protocol: 'https:' },
            JSON: JSON
        };

        window.WebSocket = require("ws");
        window.EventSource = require("eventsource");
        window.XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;

        global.window = window;
        global.location = window.location;
        global.WebSocket = window.WebSocket;
        global.EventSource = window.EventSource;
        global.navigator = window.navigator;
        global.document = window.document;
    }
    ```

2. Import the library:
    ```javascript
    var Streamer = require("<path to the library>");
    ```

3. The library is ready for use in your `Node.js` project.

## Quick Start

```javascript
var Streamer = qmci.Streamer;

// Optional: enable debug logging (may impact performance)
// Streamer.logger = console;

Streamer.login({
    host: 'https://app.quotemedia.com/auth',
    credentials: {
        wmid: 'YOUR_WMID',
        username: 'YOUR_USERNAME',
        password: 'YOUR_PASSWORD'
    }
}, function(err, sid) {
    if (err) { console.error(err); return; }

    Streamer.open({
        host: 'https://app.quotemedia.com/cache',
        cors: true,
        format: 'application/json',
        credentials: { sid: sid }
    }, function(err, stream) {
        if (err) { console.error(err); return; }

        stream.on('message', function(msg) {
            switch (Streamer.marketDataTypes.get(msg)) {
                case Streamer.marketDataTypes.PRICEDATA:
                    console.log('Price:', msg.last, msg.change);
                    break;
                case Streamer.marketDataTypes.TRADE:
                    console.log('Trade:', msg.last, msg.volume);
                    break;
            }
        });

        stream.on('error', function(err) {
            console.error('Stream error:', err);
        });

        stream.on('close', function() {
            console.log('Stream closed');
        });

        stream.subscribe(['AAPL', 'MSFT'], ['PRICEDATA', 'TRADE'], function(result) {
            console.log('Subscribed:', result.subscribed);
        });
    });
});
```

## API Reference

### Stream Methods

#### Market Data
```javascript
stream.subscribe(symbols, types, [opts], callback)
stream.unsubscribe(symbols, types, [opts], callback)
stream.subscribeExchange(exchanges, [opts], callback)
stream.unsubscribeExchange(exchanges, [opts], callback)
```


## Subscription Types

Use these with `stream.subscribe()`:

`QUOTE` · `PRICEDATA` · `TRADE` · `MMQUOTE` · `ORDERBOOK` · `INTERVAL` · `NETHOUSEPOSITION` · `LASTSALE` · `LIMITUPLIMITDOWN` · `IVGREEKS` · `IMBALANCESTATUS` · `ORDEREXECUTED`

> **Note:** `ORDERBOOK` subscription generates `BOOKORDER`, `BOOKDELETE`, `PURGEBOOK`, `PRICELEVEL`, and `MMPRICELEVEL` message types.

## Market Data Message Types

Use `Streamer.marketDataTypes.get(msg)` to identify incoming messages:

`QUOTE` · `PRICEDATA` · `TRADE` · `INTERVAL` · `LASTSALE` · `SYMBOLINFO` · `SYMBOLSTATUS` · `MMQUOTE` · `PRICELEVEL` · `MMPRICELEVEL` · `BOOKORDER` · `BOOKDELETE` · `PURGEBOOK` · `DERIVATIVEINFO` · `LIMITUPLIMITDOWN` · `IVGREEKS` · `IMBALANCESTATUS` · `NETHOUSEPOSITION` · `NEWS` · `ALERT` · `TRADENOTIFICATION` · `DIVIDEND` · `ORDEREXECUTED`

## Formatting

Use the built-in formatter to produce human-readable message strings:
```javascript
var formatter = new Streamer.formatting.Formatter();
var readable = formatter.fmt(message);
```

## Examples

The following example HTML files are included in the package:

- **enterprise-token-example.html** - Connect and subscribe using enterprise token authentication.
- **enduser-example.html** - Authenticate with end-user credentials (username/password) and subscribe to market data.
- **oauth-token-example.html** - Connect and subscribe using OAuth token authentication.
- **wmid-example.html** - Connect using webmaster ID (IP-based authentication).
- **subscription-example.html** - Subscribe and unsubscribe to trade data with detailed message handling.
- **reconnect-example.html** - Configure automatic reconnection on connection loss.
- **streaming-news-example.html** - Subscribe to news filters and handle incoming news messages.
