Giter Club home page Giter Club logo

stocksocket's Introduction

StockSocket

Real-Time Yahoo Finance Stock data.

This module opens a Websocket connection with Yahoo for reliable, fast, and lightweight market data.

npm Build Status codecov npm

const StockSocket = require("stocksocket");

StockSocket.addTicker("TSLA", stockPriceChanged);

function stockPriceChanged(data) {
  //Choose what to do with your data as it comes in.
  console.log(data);
}

Installation

This is a Node.js module available through the npm registry.

If this is a brand new project, make sure to create a package.json first with the npm init command.

Installation is done using the npm install command:

$ npm install stocksocket

How does it work?

  • Yahoo Finance uses Websockets to transfer stock data when you open their page on your browser.
  • This module leverages that functionality by opening its own direct WebSocket connection with Yahoo (skipping the need for the browser in the process).
  • As a result, this module is far more lightweight and quick than previous versions of this module (which used Puppeteer and inefficient web-scraping).

Sample Output

Pre-Market

{
  id: 'TSLA',
  price: 610.0977172851562,
  time: '1623352065000',
  exchange: 'NMS',
  quoteType: 'EQUITY',
  marketHours: 'PRE_MARKET',
  changePercent: 1.8901244401931763,
  change: 11.31768798828125,
  priceHint: '2'
}

Regular Market (Contains Real-Time Volume Updates)

{
  id: 'TSLA',
  price: 610.0977172851562,
  time: '1623352065000',
  exchange: 'NMS',
  quoteType: 'EQUITY',
  marketHours: 'REGULAR_MARKET',
  changePercent: 1.8901244401931763,
  dayVolume: '21090676',
  change: 11.31768798828125,
  priceHint: '2'
}

Post-Market

{
  id: 'TSLA',
  price: 610.0977172851562,
  time: '1623352065000',
  exchange: 'NMS',
  quoteType: 'EQUITY',
  marketHours: 'POST_MARKET',
  changePercent: 1.8901244401931763,
  change: 11.31768798828125,
  priceHint: '2'
}

Cryptocurrencies

{
  id: 'ETH-USD',
  price: 2465.013916015625,
  time: '1623352142000',
  currency: 'USD',
  exchange: 'CCC',
  quoteType: 'CRYPTOCURRENCY',
  marketHours: 'REGULAR_MARKET',
  changePercent: -4.241476535797119,
  dayVolume: '29413464064',
  dayHigh: 2615.832763671875,
  dayLow: 2463.379150390625,
  change: -109.18408203125,
  shortName: 'Ethereum USD',
  lastSize: '29413464064',
  priceHint: '2',
  vol_24hr: '29413464064',
  volAllCurrencies: '29413464064',
  fromcurrency: 'ETH',
  lastMarket: 'CoinMarketCap',
  circulatingSupply: 116236768,
  marketcap: 286525260000
}

Docs


addTicker(stockticker, callback)

Start data stream for a specific ticker

var stockticker = "TSLA";

StockSocket.addTicker(stockticker, stockPriceChanged);

function stockPriceChanged(data) {
  console.log(data);
}

stockticker (type: String)

String object containing a stock ticker to be added.

callback (type: Function)

Callback Function that receives each price update


addTickers([stocktickers], callback)

Start data stream for an array of tickers

var stocktickers = ["TSLA", "NNDM", "AAPL", "MARA"];

StockSocket.addTickers(stocktickers, stockPriceChanged);

function stockPriceChanged(data) {
  console.log(data);
}

stocktickers (type: Array)

Array of string objects containing the stock tickers

callback (type: Function)

Callback Function that receives each price update


removeTicker(stockticker)

Stop data stream for a specific ticker.

var stockticker = "TSLA";

StockSocket.removeTicker(stockticker);

stockticker (type: String)

String object containing a stock ticker to be added.


removeTickers([stocktickers])

Stop data stream for various tickers

var stocktickers = ["TSLA", "NNDM", "AAPL", "MARA"];

StockSocket.removeTickers(stocktickers);

stocktickers (type: Array)

Array of string objects containing the stock tickers to be removed.


removeAllTickers()

Stop data stream for all tickers

StockSocket.removeAllTickers();

License

MIT

stocksocket's People

Contributors

gregtuc avatar therealshark avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

stocksocket's Issues

Not working

on starting it is just giving message "StockSocket has opened a WebSocket Connection with Yahoo." else the callback is not getting executed

Refactor page selectors

  • Current Functionality: A for loop cycles through an array of potential JS path's to find the proper path for the inputted ticker.
  • New Functionality: A new JS path was found that eliminates the differences between pages for crypto and standard stocks, and makes the selectors less sensitive to being broken.
  • Selector to use for refactoring: document.getElementsByClassName('.Fz(36px))');

Sweet client

Hey, nice socket client! We use yahoo as a fallback data provider.
I lead engineering at Fey and we're looking for engineers (Backend | TS/Node). Wondering if you'd be interested to learn more?

Cant read the yahoo page

I am getting this error for each headless page it open.

Error: Evaluation failed: TypeError: Failed to execute 'observe' on 'MutationObserver': parameter 1 is not of type 'Node'.
at puppeteer_evaluation_script:26:16
at ExecutionContext._evaluateInternal (Q:\Node\Trader\node_modules\puppeteer\lib\cjs\puppeteer\common\ExecutionContext.js:218:19)
at processTicksAndRejections (node:internal/process/task_queues:94:5)
at async ExecutionContext.evaluate (Q:\Node\Trader\node_modules\puppeteer\lib\cjs\puppeteer\common\ExecutionContext.js:107:16)
at async startDataFeed (Q:\Node\Trader\node_modules\stocksocket\stocksocket.js:76:5)

And my project contains only the code example.

Automatically switch selectors based on active-trading period

  • Automatically switch selectors based on the active trading period.

  • Pre-Market selector: "#quote-header-info > div.Pos\(r\) > div.D\(ib\) > p > span"

  • Post-Market selector: "#quote-header-info > div.Pos\(r\) > div > p > span"

  • Standard-Market selector: #quote-header-info > div.Pos\(r\) > div > div > span"

  • Crypto selector (24/7): "#quote-header-info > div.D\(ib\) > div > div > span"

Potential Memory Leak with 11+ Tickers

  • Warning of potential memory leak after 11 or more tickers are added.
  • Likely source: The puppeteer processes are never actually closed, and the system interprets it as a memory leak.
  • Likely solution: Add two methods: stopAll(), and stop() which kill puppeteer processes when called.

Scrape daily-change data for prices

  • In addition to price data, price-change data should be scraped as well and added as a property to each data object returned to the callback function.
  1. Get the selectors for the price-change data (on Yahoo, it appears directly next to the price).
  2. Using a similar approach to as was used with the standard price data, create an array of selectors (as the selectors will break from premarket -> standard market -> postmarket, or for crypto) and then loop through them to find which is valid.
  3. When the standard price changes, query for the price-change element and group it in with the response.

Setup Testing using Selenium + Mocha

  • Setup testing that can check for the presence of selectors used to scrape data from Yahoo.
  • Tests should check to verify access to standard stocks, crypto stocks, pre-market stock data, and post-market stock data.

Licensing Issue

Hey :)

i think directly using the finStreamer from yahoo is problematic because of copyright reasons. Its rather easy to reverse engineer the code though. After i used this library initially, i independently realized, that yahoo uses websockets and built my own (naive) implementation. I just need the current pricedata so my PricingData is rather simple, but it can easily be extended.

I think just reverse engineering the datastructure and building it yourself (like i did) is certainly the safer approach :)

const WebSocket = require("ws");
const { Type, Field } = require("protobufjs");

var PricingData = new Type("PricingData")
  .add(new Field("symbol", 1, "string"))
  .add(new Field("price", 2, "float"));

module.exports = class StockTicker {
  #client = null;
  #updateCallback = null;
  #symbols = [];

  constructor(symbols, updateCallback) {
    this.symbols = symbols;
    this.#updateCallback = updateCallback;
  }

  get symbols() {
    return this.#symbols;
  }

  set symbols(newSymbols) {
    if (Array.isArray(newSymbols)) {
      this.#symbols = newSymbols;
      if (this.#client) {
        this.#sendSymbolMessage();
      }
    } else {
      throw new TypeError("stocks needs to be an array of strings");
    }
  }

  #sendSymbolMessage() {
    console.log("Requesting symbols", this.symbols);
    this.#client.send(JSON.stringify({ subscribe: this.symbols }));
  }

  #onMessage(data) {
    const binary = Buffer.from(data, "base64");
    try {
      const msg = PricingData.decode(binary);
      const msgObj = PricingData.toObject(msg, { longs: Number });
      console.log(msgObj);

      if (this.#updateCallback) {
        this.#updateCallback(msgObj);
      }
    } catch (e) {
      console.log(e);
    }
  }

  activate() {
    if (this.#client) {
      console.warn("Already Active");
      return;
    }
    this.#client = new WebSocket("wss://streamer.finance.yahoo.com/");
    this.#client.once("open", () => {
      console.log("connected to yahoo finance socket");
      this.#sendSymbolMessage();
    });

    this.#client.on("message", this.#onMessage.bind(this));
  }
  deactivate() {
    if (!this.#client) {
      console.warn("Already Inactive");
      return;
    }
    this.#client.terminate();
    this.#client = null;
  }
};

Overhaul price reading process

  • Current Functionality: Insert headless puppeteer instances and use mutation observers to detect changes in HTML text. This method is effective but needlessly intensive WRT resources and can error out if the DOM is ever changed.

  • New Functionality: Intercept Yahoo Finance websocket traffic directly.

General Steps:

  1. Convert the data (which is received as a base64 string) to a bytes array.
  2. Import protobuf files from Yahoo and decode the bytes array into a JS object.
  • Image of Websocket traffic:
    image

  • Image of New Data Response:
    image

Testing

Setup continuous integration, unit tests, and continually upgrade them

Volume

Hi Greg,

Great Work.

How can we add realtime volume updates to this script?

Thanks in advance.

Add support for pre-market data

  • Modify constant variable "potentialSelectors" on line 35 of StockSocket.js by adding the selector for pre-market data to the head (important) of the array list.
  • Note for above: The selector should be trimmed to make it less sensitive to slight selector changes.

How to pull curent market data?

I want to pull the current data and not updates, I was wondering if this module supports this, or if I should use another module.
Thanks.

Need help regarding starting the file.

Hi, first of all I must thank you for creating such wonderful yahoo live streamer ! I am Vishvesh Upadhyay from India. All the questions below are for NSE (National Stock Exchange) India.

I am very new to programming world ! and almost first time using Node.Js and JS program / module.

I am currently using yahooquery with sqlite3 on google colab I am facing quite an issue regarding timing of the price-volume data.

I need your guidance on how use your StockSocket. (because in python i just pip install -- and run code from Spyder and it gives me the result, I downloaded you repo and create package with npm init and npm install but dont know how to start the actual web streaming !)

  1. Can you guide me how to setup it ? (I just need some direction for how to run it and get live streaming data then after I will use it with my python code)

  2. I am running a python code which is fetching currently 40 tickers at once in almost 1 to 1.2 seconds. With your code is it possible to stream 40 tickers (or my target 160 tickers) simultaneously and reliably ?

  3. If possible i need your views on if connection is dropped or disconnected then is there any mechanism to reconnect it automatically ?

  4. Also i need your suggestion for my project. I am creating an stock alert system (then planning to upgrade it to full fledged algo system). My plan is to get data live data from StockSocket -> then feed it to Python - Pandas -> then to Sqlite3 Local database -> fetch multi timeframe OHLCV candle from DB using Pandas -> then running different analysis on them -> create alert system (max time for all tasks is up to 5-7 secs) and then evolve it to full fledged algo system.

Thanks and reply soon !

Regards,
Vishvesh Upadhyay.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.