How to Build A Live Stock Ticker - Part 1
Home :: Web Design :: PHP
Jan 22, 2007 7:40 pm
by: Shane Goodwin
In this two-part tutorial, we will be building a stock ticker to retrieve and display stock quotes from Yahoo Finance. In part 2 we will learn how to make the quotes update automatically using AJAX. This stock ticker can easily be included as part of your site since all of the necessary code resides in a single div. It is recommended that you are comfortable writing code for CSS and HTML before continuing this tutorial. This is a PHP script so it would be helpful to understand PHP, but we will be going over the PHP code line by line so if you are not familiar with it, that's OK.
The HTML
To be honest, there really isn't much HTML to do here. The reason is that we will be coding most of the HTML within PHP a little later, so it is not included in this section.The HTML is:
<html>
<head></head>
<body>
<div id="quotes">
</div>
</body>
</html>
And believe it or not, that's all of the basic HTML used in this tutorial. Go ahead and save the file - you will need to use the .php extension instead of .html (i.e. "example.php"). Continue to save it regularly.
The PHP - The Class
Obviously the PHP is going to do the heavy work for our stock ticker. The PHP code we create will go inside the div tags of our HTML. We will be creating a class to retrieve stock quotes from Yahoo. For those that already understand PHP, here is the code to create the class: (the $url variable MUST all be on one line.)
<?php
error_reporting(0);
class getStock {
function getQuote($stock) {
$url = sprintf("http://finance.yahoo.com/d/quotes.csv?s=$stock&f=sl1c1p2&e=.csv", $stock);
$fp = @fopen($url, 'r');
$data = @fgetcsv($fp, 1000, ', ');
fclose($fp);
$this->symbol = $data[0];
$this->price = number_format($data[1],2);
$this->change = number_format($data[2],2);
$this->percent = number_format($data[3],1);
}
}
This may look intimidating, but really it's all pretty simple. Let's start with defining the class:
<?php
error_reporting(0);
class getStock {
function getQuote($stock) {
The "<?php" tag is the beginning PHP tag to tell the server that this is a PHP script and it needs to process the information that follows. The following line disables PHP error checking so that we do not get ugly errors when a stock fails to get its price information from Yahoo (this does happen from time to time). Then we set up a class to hold the function we will be creating. You can name the class whatever you want, but I have called it "getStock". An opening curly bracket "{" is used to hold everything in the class. We will also include a closing curly bracket "}" when we are finished writing the class. Next, a function is created within the class so we can look up multiple stock symbols simultaneously. The function name is "getQuote()", but once again you can give it any name you want. We need to tell it what information to pass into the function by placing "$stock" inside the "()". "$stock" is a variable that will hold the stock symbol we want to look up. We will assign "$stock" a stock symbol later on, but for now just understand that it is a placeholder for our stock symbol. We also give this function an opening curly bracket.
The next bit of code is:
$url = sprintf("http://finance.yahoo.com/d/quotes.csv?s=$stock&f=sl1c1p2&e=.csv",$stock);
This piece of code sets up the variable "url". We use the $ symbol to tell the server that this is a variable. "$url" stores the yahoo url from which we will be retrieving our stock quotes. If you look at the url closely, you will notice the variable "$stock" we wrote earlier is inside it. However, we cannot simply place the variable inside the url and expect the server to know that "$stock" is a variable and not part of the url itself. So we use the "sprintf()" function to set the server straight. This function contains two parts: the url itself with the variable inside ("http://finance.yahoo.com/...") and the phrase that needs to be replaced (,$stock).
There are some things about the Yahoo url itself that are important to understand. First of all, this url sends back data in a Comma Separated Value (csv) file format which allows us to easily extract and use the data. The ?s= defines the symbol we are retrieving. The most important part though is the series of letters that appear after &f=. These letters are special tags that tell Yahoo which information we need it to send back to us. The "s" is for symbol, "l1" (l as in letter and the number 1) is the price, "c1" is the change in price that day, and "p2" is the percentage change. These particular tags return the information I am interested in. However, the Yahoo database contains 85 such tags - you can see them all at Gummy-Stuff.org. To retrieve additional information, just add the tags you want to the end of &f=.
The next line of code is:
$fn = @fopen($url, 'r');
This line is fairly simple to understand. We are creating another variable called "fn". Its task is to open "$url" and read information from it using the "fopen()" function. The "@" before "fopen" merely suppresses any errors which may arise while retrieving the stock price information. The 'r' means that we are only reading from it - we obviously don't need to write information into what Yahoo is providing. It would just return an error. And that's all this line does.
Next we have:
$data = @fgetcsv ($fn, 1000, ",");
Now, remember how I said that the yahoo url sends back data in a csv file format? This means that each special tag's information is sent back as a comma separated file. We could simply write out this information using Yahoo's formatting using echo "$fn" ("echo" is simply a way to write content to be displayed in a browser). It would look like "symbol name","price","price change","percent change" with no spaces in between. Since we want to format this data to our own liking we need to convert this information into something into something better by using the "fgetcsv()" function. "fgetcsv()" basically converts the information yahoo stored in the "$fn" variable into an array. The "1000" establishes the maximum character length in which all of the information can be stored. If you plan on using more special tags to retrieve information, be sure to increase the maximum number of characters here - a common length is 4096; otherwise, not all of your data will be returned. The last part "," tells the server where to split the file into separate array parts. Finally, we place this whole "fgetcsv()" function into the variable "$data".
"$data" is now an array and contains 4 parts (symbol, price, price change, percentage change). We now need to access each part individually. In PHP, the array parts are called by "$variable name[number]". In our script, the variable name is "data". For the number, you can start with any number, but after that the array parts are assigned sequentially. In English, this means we can call the the first special character in our yahoo url using "$data[0]", "$data[100]", or even "$data[19434]". However, the very next special character has to be "$data[1]", "$data[101]", or "$data[19435]" and the next special character is "$data[2]", etc.
The next line of code is short and simple:
fclose($fn);
Now that we are done reading the Yahoo csv file, we need to close it. We do this using the fclose() function to close the $fn connection. This is an extremely important step! If you do not close this connection it will remain open and place a strain on your server as the number of calls to the server increases everytime you run this script. As I found out, the server's administrator may step in and prevent the entire PHP script from running. In it's place will be a beautiful message along the lines of "$fn disabled for security reasons".
Since we know how to access the different parts of the "$data" array, we can now format each part:
$this->symbol = $data[0];
$this->price = number_format($data[1],2);
$this->change = number_format($data[2],2);
$this->percent = number_format($data[3],1);
}
}
You should recognize the different parts of "$data" here. What we are doing is creating a variable for each "$data" part. Later, we are going to call these variable from outside of the class brackets. Because of this, we need to make sure the server understands that the variables we are calling are within this "getStock" class. We do this by using "$this->variable name". We also want to format the numbers that are returned by Yahoo so that they all look the same. For example, some stock symbols return prices with four decimal places while most only return 2 decimal places. Also, if a stock is an even number such as $80, the "$data" price will write out $80 instead of $80.00. We can make them all look the same by using the "number_format()" function. We place the information we want to be formatted inside the parenthesis followed by a "," followed by the number of decimal places we want displayed. In our script we will use the 2 decimal places for prices and 1 decimal place for the percentage.
If you included additional special tags in the url, you will need to also assign them a variable here. For example, if you had"...&f=sl1c1p2v..." you would then need to set up a variable to catch the volume ("v" is the special tag for volume). This could look like "$this->volume = $data[4];".
And the final step is to close the "getQuote" function and the "getStock" class by adding the closing curly brackets "}". And that concludes our PHP class for getting stock quotes. We will now be able to use this class by giving the stock quotes we want and handling the results it returns. So on to the next part of the tutorial...
The PHP - The Writing
Now we have a class set up that we can call on to submit a stock symbol and get back the information we want. We still need to give "$stock" a value and actually print our data on the screen. Here is the complete code for this:
$stocks = array('^DJI','GOOG','YHOO');
$count = 0;
$quote = new getStock;
echo "<b>STOCK QUOTES</b>n";
echo "<table class="t" border="0">";
foreach ($stocks as $stock) {
$quote->getQuote($stocks[$count++]);
echo '<tr><td class="sym">'.$quote->symbol.'</td>'."\n";
echo '<td class="qte">$' .$quote->price. ','."\n";
echo '<span style="';
if ($quote->change > 0) {
echo 'color:#006600;">+' .$quote->change. ', +' .$quote->percent. '%';
} elseif ($quote->change < 0) {
echo 'color:#a32900;">' .$quote->change. ', -' .$quote->percent. '%';
} else {
echo 'font-size:100%;">' .$quote->change. ', ' .$quote->percent. '%';
}
echo '</span></td></tr>'."\n";
}
echo "</table>n";
?>
Now this may look like a lot of code, but it's no worse than the first part above. For one thing, half of the code here is nothing more than simple HTML written in PHP! I want to go over a few things before we dive into this. First, when writing text to be displayed in the browser using the echo command, the text must be enclosed in quotations. This make writing HTML to the browser a little tricky because it uses quotations in its code. So to let the PHP code know which quotations are for PHP and which ones are for HTML, we have to "escape" the HTML quotation using a "" (no quotations). Secondly, we can use a "\n" to add a line break in our HTML code. You will only see these spaces when viewing the code source, so it's not necessary to include them, but it makes things look a lot neater.
So with that cleared up, let's get started breaking it all down:
$stocks = array('^DJI','GOOG','YHOO');
$count = 0;
$quote = new getStock;
echo '<b>STOCK QUOTES</b>'."\n";
echo '<table class="t" border="0">';
The first part creates an array called "stocks" with the symbols "^DJI", "GOOG", and "YHOO" in it. Next we create the variable "count" with a value of 0. It will be used as a counter for us to indicate which stock symbol we are at as we retrieve the stock price information. Next we need to call on the class we set up earlier by writing "new" followed by the name of our class, "getStock", and assigning it to a variable called "quote". The next line simply writes a title to the browser for our stock symbol list and uses the "n" code to keep our HTML code neat. Finally we create a table to format the stock information and escape the necessary quotations.
On to the next part:
foreach ($stocks as $stock) {
$quote->getQuote($stocks[$count++]);
We need a way to run through each stock symbol in our "$stocks" array individually. This can be accomplished using PHP's "foreach" command. This allows us to run through an array of information and assign a temporary variable to each one as we come to it. So, when our PHP code is executed, the server interpreting the code will take the first stock symbol, "^DJI", assign it the variable "stock", and run it through whatever code we have inside the "foreach" function. Then it will get the second stock symbol, "GOOG", assign it the variable "stock", and run it through the code. This process continues until all of the array elements have been used. Since this is a function, we need to enclose all of the code to be used in a "{".
The next line makes use of our "count" variable to make the server move on the next stock symbol of our array. Remember from earlier that we can reference the different parts of an array using the name of the array followed by [number]; in our function, we can reference the different parts of the array using "$stocks[number]". So, "^DJI" can be called by "$stocks[1]", "GOOG" can be called by "$stocks[2]", and "YHOO" can be called by "$stocks[3]".
We are using the "count" variable here and a simple PHP shorthand math function to cycle through all the stock symbols. The "++" code here following "$count" is a shorthand math function to add one to the current value. Since "count" was originally assigned a value of "0", the first time we pass through the "foreach" function, "count" will actually equal "1" and it will refer to "^DJI". The second time it will equal "2" and refer to "GOOG", and the third time it will equal "3" and refer to "YHOO". The "$quote->getQuote" part refers to our "getStock" class that assigned to "$quote" earlier and "getQuote" is the name of the function inside that class that we will use.
To better understand what is going on here I will put everything together and simulate the progression of a stock symbol through the code. "^DJI" is referred to in its array as "$stocks[1]". It is assigned the temporary variable "$stock" using the "foreach" command. We then run this "$stock" through the "getQuote" function defined in our class. Since "$stock" now has a value of "^DJI", the server will run the function "getQuote" with "^DJI" as its value. The "url" variable we created inside our class will now replace "$stock" with "^DJI" and so return the stock symbol, price, price change and percentage for the Dow Jones Industrial Average. Now "$data[0]" is "^DJI", "$data[1]" is the price of the Dow, "$data[2] is the price change of the Dow, and "$data[3]" is the percentage change of the Dow. In the next part of code we will be writing this information to the browser. When that finishes, it will grab the next stock symbol, "GOOG", also referred to as "$stocks[2]", assign it the variable "$stock" and repeat the whole process. Get it? Complicated, ...yet simple when you think about it.
The next part of the code will write the "$data" information for each stock symbol to the browser.
echo '<tr><td class="sym">'.$quote->symbol.'</td>'."\n";
echo '<td class="qte">$' .$quote->price. ','."\n";
echo '<span style="';
This section is much simpler than the last. What it does is write the stock symbol and price to the browser. Remember in our class that we assigned all of the "$data" parts different variables. "$data[0]" was "$this->symbol", "$data[1]" was "$this->price", etc. Since we are now writing code outside of the class, we can no longer refer to it as "$this". However, since we assigned the class a variable of "$quote" we can refer to the different parts as "$quote->symbol", "$quote->price", "$quote->change", and "$quote->percent". So in our table we first create a new row for the particular stock we are working with, and place the stock symbol in a table column with class "sym", and the stock price in another table column with "qte". The different classes will later allow us to style all the different parts as we would like them to appear. When combining PHP variables with normal text inside an echo command, the variable cannot be enclosed within quotes. We string them together using a "." So, if you look at the line for the stock price you will notice that just before "$stock->price" there is a "$" symbol. To connect them you would write 'echo "$" . $stock->price' .
The next line of code changes the color of the price change and percentage change based on whether the stock is up, down, or the same.
echo '<span style="';
if ($quote->change > 0) {
echo 'color:#006600;">+' .$quote->change. ', +' .$quote->percent. '%';
} elseif ($quote->change < 0) {
echo 'color:#a32900;">' .$quote->change. ', -' .$quote->percent. '%';
} else {
echo 'font-size:100%;">' .$quote->change. ', ' .$quote->percent. '%';
}
echo "</span></td></tr>n";
Here we have used an "if, else" function to assign different colored fonts to the price and percentage changes. If the stock price is up today, the stock change and percentage change will be positive and will be written in green; if the price is down, the stock change and percentage change will be written in red; if the price is unchanged, we don't need to change the color. However we need to finish out the style command so we just write the font-size as being 100%, thereby leaving it unchanged. If the stock change is negative, Yahoo automatically returns a "-" next to the price. However, if the price is positive, Yahoo doesn't return anything. Since I think it would look better to have a "+" sign if the price change is positive, I have written it into the code following "color:#006600;">
The final part of the PHP code is short and simple.
}
echo "</table>n";
?>
The "}" closes out our "foreach" command now that all of the information has been written to the browser. We then close the table and write the ending tag for PHP "?>".
The Complete Stock Price Page
To make this page appear in a browser, we simply need to include our PHP function in between the DIV tags of our HTML.
<html>
<head></head>
<body>
<div id="quotes">
<?php
error_reporting(0);
class getStock {
function getQuote($stock) {
$url = sprintf("http://finance.yahoo.com/d/quotes.csv?s=$stock&f=sl1c1p2&e=.csv", $stock);
$fp = @fopen($url, 'r');
$data = @fgetcsv($fp, 1000, ', ');
fclose($fp);
$this->symbol = $data[0];
$this->price = number_format($data[1],2);
$this->change = number_format($data[2],2);
$this->percent = number_format($data[3],1);
}
}
$stocks = array('^DJI','GOOG','YHOO');
$count = 0;
$quote = new getStock;
echo '<b>STOCK QUOTES</b>'."\n";
echo '<table class="t" border="0">';
foreach ($stocks as $stock) {
$quote->getQuote($stocks[$count++]);
echo '<tr><td class="sym">'.$quote->symbol.'</td>'."\n";
echo '<td class="qte">$' .$quote->price. ','."\n";
echo '<span style="';
if ($quote->change > 0) {
echo 'color:#006600;">+' .$quote->change. ', +' .$quote->percent. '%';
} elseif ($quote->change < 0) {
echo 'color:#a32900;">' .$quote->change. ', -' .$quote->percent. '%';
} else {
echo 'font-size:100%;">' .$quote->change. ', ' .$quote->percent. '%';
}
echo '</span></td></tr>'."\n";
}
echo '</table>'."\n";
?>
</div>
</body>
</html>
Congratulations! You now have a PHP "widget" that can display stock symbols on your page. Make sure the yahoo url inside the class is all on one line or an error will result (the "&f=..." portion must come right after the "$stock" with no spaces or lines in between. You can change or add new stock symbols in the array to customize your stock list by changing the stock quotes in the "$stocks" array or adding additional stocks to the list. You can incorporate this into your website by simply placing the "quotes" div with all of the PHP code anywhere on your site. Then use CSS to position your "quotes" div where you want it on your page. Also use CSS to change the style of everything you want. For example, make all of the columns the same width by applying a width to the "sym" and "qte" classes, make the quotes be in bold by applying "font-weight:bold;" to class "qte", or give the table a background color to class "t" to make it stand out on your page.
Part 2 of this series of tutorials harnesses the power of AJAX to automatically update the stock prices of each stock at a predetermined interval. This simply expands on what we have written in this tutorial so if you understand what is going on with this script, then check out that tutorial to really energize your website!
Note: As I stated earlier in my explanation, the yahoo url enclosed in the "$url" variable MUST be on one line or an error will result in your code.
Related Articles: