A Stock Ticker in JavaScript Using the Yahoo Finance API

The JavaScript below implements a simple stock ticker. To see it in action, copy it into an .html file, and open that file in a web browser that runs JavaScript.

By default, the ticker starts off tracking a single stock, specifically, Google.  You can add more stocks by entering their symbols in the Symbol textbox and clicking the Add button.  It’s all pretty uncomplicated at the moment.

Note that if you’re running from “file://” you’ll need to disable the no-same-origin policy on that browser. On Chrome, for example, you can do that with the command-line option “–disable-web-security”. I’d supply an online version, but I’m using the Yahoo API to get the quotes, and providing a running version might violate Yahoo’s terms of service.

<html>
<body>

<div id="divMain"></div>

<script type='text/javascript'>

// main

function main()
{
	new StockTracker
	(
		[
			new Stock("NASDAQ", "GOOG"),
		]
	).initialize();
}

// class

function Stock(exchange, symbol, priceLast)
{
	this.exchange = exchange;
	this.symbol = symbol;
	this.priceLast = priceLast;
}
{
	Stock.prototype.domElementUpdate = function(parentDomElement)
	{
		if (this.domElement == null)
		{
			var tr = document.createElement("tr");

			var td = document.createElement("td");
			tr.appendChild(td);

			var td = document.createElement("td");			
			tr.appendChild(td);

			this.domElement = tr;

			parentDomElement.appendChild(this.domElement);
		}

		var tdsAll = this.domElement.getElementsByTagName("td");

		var priceAsString;

		if (this.priceLast == null)
		{
			priceAsString = "?";
		}
		else
		{
			var centsPerDollar = 100;
			var cents = Math.floor(this.priceLast * centsPerDollar) % centsPerDollar;
			var dollarsAsString = "" + Math.floor(this.priceLast);
			var centsAsString = (cents < 10 ? "0" : "") + cents;
			priceAsString = dollarsAsString + "." + centsAsString;
		}

		tdsAll[0].innerHTML = this.symbol;
		tdsAll[1].innerHTML = priceAsString;
	}

	Stock.prototype.update = function()
	{
		this.updateUsingWebServiceYahoo();
	}

	/*
	Stock.prototype.updateUsingWebServiceGoogle = function()
	{
		// API deprecated in 2011, but still works as of 2014.
	
		var requestURL = 
			"https://www.google.com/finance/info?q="
			+ this.exchange + ":" + this.symbol;

		var request = new XMLHttpRequest();
		request.open("GET", requestURL, false);
		try
		{
			request.send(null);
			var responseAsString = request.responseText;
			responseAsString = responseAsString.substr("////".length);

			var responseAsArray = JSON.parse(responseAsString);
			var responseAsObject = responseAsArray[0];
	
			this.priceLast = responseAsObject["l"]; // "latest"
		}
		catch(e)
		{
			this.priceLast = "?";
		}
	}
	*/

	Stock.prototype.updateUsingWebServiceYahoo = function()
	{
		var requestURL = 
			"https://finance.yahoo.com/webservice/v1/symbols/"
			+ this.symbol
			+ "/quote?format=json";

		var request = new XMLHttpRequest();
		request.open("GET", requestURL, false);
		try
		{
			request.send(null);
			var responseAsString = request.responseText;

			var responseAsArray = JSON.parse(responseAsString);
			var responseAsObject = responseAsArray.list.resources[0].resource;
	
			this.priceLast = parseFloat(responseAsObject.fields.price);

		}
		catch(e)
		{
			this.priceLast = "?";
		}
	}

}

function StockTracker(stocksToTrack)
{
	this.stocksToTrack = stocksToTrack;
}
{
	// constants
	StockTracker.Newline = "<br />";

	// instance methods

	StockTracker.prototype.initialize = function()
	{
		var millisecondsPerTimerTick = 2000;

		setInterval
		(
			this.handleEventTimerTick.bind(this),
			millisecondsPerTimerTick
		);

		this.handleEventTimerTick();
	}

	StockTracker.prototype.update = function()
	{
		for (var i = 0; i < this.stocksToTrack.length; i++)
		{
			var stock = this.stocksToTrack[i];
			stock.update();
		}

		this.domElementUpdate();
	}

	// dom

	StockTracker.prototype.domElementUpdate = function()
	{
		var divTracker = document.createElement("div");

		if (this.domElement == null)
		{
			var labelSymbolToAdd = document.createElement("label");
			labelSymbolToAdd.for = "inputSymbolToAdd";
			labelSymbolToAdd.innerHTML = "Add Stock by Symbol:";
			divTracker.appendChild(labelSymbolToAdd);

			var inputSymbolToAdd = document.createElement("input");
			inputSymbolToAdd.id = "inputSymbolToAdd";
			divTracker.appendChild(inputSymbolToAdd);

			var buttonSymbolAdd = document.createElement("button");
			buttonSymbolAdd.innerHTML = "Add";
			buttonSymbolAdd.onclick = this.buttonSymbolAdd_Click.bind(this);
			divTracker.appendChild(buttonSymbolAdd);

			var tableQuotes = document.createElement("table");
			tableQuotes.id = "tableQuotes";
			tableQuotes.border = "1px solid";

			var tr = document.createElement("tr");

			//var td = document.createElement("td");
			//td.innerHTML = "Exchange";
			//tr.appendChild(td);

			var td = document.createElement("td");
			td.innerHTML = "Symbol";
			tr.appendChild(td);

			var td = document.createElement("td");
			td.innerHTML = "Price";
			tr.appendChild(td);

			tableQuotes.appendChild(tr);

			for (var i = 0; i < this.stocksToTrack.length; i++)
			{
				var stock = this.stocksToTrack[i];
				stock.domElementUpdate(tableQuotes);
			}		

			divTracker.appendChild(tableQuotes);

			this.domElement = divTracker;
			var divMain = document.getElementById("divMain");
			divMain.appendChild(this.domElement);
		}

		var tableQuotes = document.getElementById("tableQuotes");

		for (var i = 0; i < this.stocksToTrack.length; i++)
		{
			var stock = this.stocksToTrack[i];
			stock.domElementUpdate(tableQuotes);
		}
	}

	// events

	StockTracker.prototype.buttonSymbolAdd_Click = function(e)
	{
		var inputSymbolToAdd = document.getElementById("inputSymbolToAdd");
		var stockToAddAsString = inputSymbolToAdd.value;

		var exchange;
		var symbol;

		if (stockToAddAsString.indexOf(":") == -1)
		{
			exchange = null;
			symbol = stockToAddAsString;
		}
		else
		{
			var stockToAddAsStrings = stockToAddAsString.split(":");
			exchange = stockToAddAsStrings[0] 
			symbol = stockToAddAsStrings[1];
		}
		
		var stock = new Stock
		(
			exchange, symbol
		);
		this.stocksToTrack.push(stock);

		this.update();
	}

	StockTracker.prototype.handleEventTimerTick = function()
	{
		this.update();	
	}
}

// run

main();

</script>
</body>
</html>
This entry was posted in Uncategorized and tagged , , . Bookmark the permalink.

2 Responses to A Stock Ticker in JavaScript Using the Yahoo Finance API

  1. Sheena says:

    Hello! does this also work for other stock exchanges? For example, i need a stock ticker for the Philippine Stock Exchange. Is there a way to customize it to also display prices in pesos? Thank you very much!

  2. Good questions. I’m not sure about the answers. It mostly depends on whether Yahoo supports those features or not. If they do provide data for the Phillipine exchange, you might be able to track a stock from this exchange by adding it below the entry for Google in the main() function, like “new Stock(‘PSE’, ‘MYSTOCK’), and it might be possible to change the currency by adding a new parameter to the requestURL created in the Stock.prototype.updateUsingWebServiceYahoo() function. But those are just guesses. I haven’t tested any of this, so I can’t say for sure. Sorry!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s