Finance::QuoteOptions - Perl extension for retrieving options pricing and series information from the web.


  use Finance::QuoteOptions;
  my $q=Finance::QuoteOptions->new('DIA');
  die 'Retrieve Failed' unless $q->retrieve;

  #Expiration dates in ISO format (YYYYMMDD)
  my @expirations = @{$q->expirations};

  #Calls/Puts for next expiration, sorted by strike price
  my @calls = @{$q->calls(0)};
  my @puts = @{$q->puts(0)};

  #Data from an individual option
  my $strike = $q->option('XYZAB')->{strike};
  my $symbol = $q->option('XYZAB')->{symbol};
  my $bid = $q->option('XYZAB')->{bid};
  my $ask = $q->option('XYZAB')->{ask};


A 'screen-scraper' utility using WWW::Mechanize and HTML::TokeParser to retrieve and parse options information from either Yahoo Finance or the Chicago Board Options Exchange (CBOE) web site. The CBOE probably has better data but Yahoo is much faster. By default, Yahoo Finance is used as the source.

The Yahoo address used, using DIA as an example, is:

The CBOE address used is:

CBOE Blacklist Warning

The CBOE site has two interfaces for retrieving option information: a page where you can download a CSV file and a web page that displays an HTML table. At the time of writing this module (2007-2008), there was a big warning not to do any kind of automated retrieval of the CSV information. So I wrote this module to use the web page, even though the CSV file would be so simple to process.

Unfortunately, although I could find no such warning on the web portion of the CBOE site, I still got blacklisted from using the web portion, after a couple of weeks of using this code and tens of thousands of queries. I was blacklisted on June 4, 2007. Sometime before February 2009 the blacklist was removed. However I assume the block would be replaced if this code is used again.

As of February 2009, the HTML page also has the warning from the CSV page.

So if you're doing many queries, use Yahoo as your source. Yahoo is much faster anyway. It does have less data than CBOE, but the only difference I've seen were options with zero volume and open interest. Give it a try for 'KB'.


The following methods are available:

my $q = Finance::QuoteOptions->new;
my $q = Finance::QuoteOptions->new('DIA');

The first version creates the new object but doesn't set the target symbol. Use symbol() to set the target symbol. The second version creates the new object and sets the target symbol in one step.


Sets or retrieves the current data source. The default is Yahoo Finace. Only acceptable options are yahoo and cboe. Submitting anything else will set the source to yahoo.

Always returns currently selected source.


Sets or retrieves the target symbol for the query.


Sets or retrieves the proxy setting for the query. Set this before issuing a retrieve command.

This is currently untested. If you are behind a proxy, please email the author if you use this feature and let him know how it works.


Retrieves data from designated source, for N expiration dates starting from now. Retrieves all available expiration dates if N is not specified. If you are only interested in the upcoming expiration, call << $q->retrieve(1) >> as this will be a few times faster.

Returns success() value for last http access.

Note that success() does not indictate whether there are options available for the queried stock. To make that determination, check expirations() after issuing a retrieve() to see if any options have been retrieved. For example:

  if (@{$q->expirations}) {
        #There are options
  } else {
        #There are no options

Returns arrayref of all expiration dates in the format YYYYMMDD sorted by date.

Returns undef if not found.


Returns an arrayref containing all calls or puts for a given expiration, sorted by strike price.

Returns undef if expiration is not found.

Parameter can take three forms:

  • Number of Expirations Out

    Parameter '0' is the next expiration, '1' is two expirations out and so on.

  • Integer YYYYMM.

    If there happen to be two expirations in the same month, only the first will be returned. Use expirations() to check for multiple expirations. See " Notes" for more information about multiple expirations.

  • Integer YYYYMMDD.

    This specifies the exact expiration date.

The arrayref is an array of hashes containing all calls or puts for a given expiration. The hashes referenced within the array look like:

      strike => 000.00,
      symbol => 'ABCD',
      bid => 000.00,
      ask => 000.00,
      last => 000.00,
      open => 0000,
      volume => 0000,
      change => 0000,
      in_the_money => 1

Returns undef if not found. The in_the_money key is only found if using Yahoo as a data source. It is not set when using the CBOE. in_the_money contains either 0 or 1.


Returns an arrayref of call or put symbols for a given expiration. Parameter is the number of expirations out starting from zero.

Returns undef if not found.


Returns an arrayref of call or put strike prices for a given expiration. Parameter is the number of expirations out starting from zero.

Returns undef if not found.


Returns hashref with all of the data for a single option symbol. If a symbol has somehow been duplicated, the nearest symbol by date will be returned. Parameter is case-insensitive.

The hash has the same structure as calls() or puts() above with the addition of a exp key containing the expiration date.

Returns undef if not found.


Returns arrayref containing all data retrieved. See "Internal Data Structure" below.


All three are directly copied from the WWW::Mechanize object. See it's documentation for more details. Retrieving full options data for a symbol requires multiple http requests. Only the last request will be reported here.

success() Returns a boolean telling whether the last request was successful. If there hasn’t been an operation yet, returns false. This does not indicate if options are available for a stock. See retrieve() above.

response() Return the current response as an HTTP::Response object.

status() Returns the HTTP status code of the response.


Returns Finance::QuoteOption version.

Internal Data Structure

The methods provided will slice and dice the options data in various ways. However, the data is maintained in a single data structure that can be directly accessed. Yes, this is bad OO practice, but hey, I think someone once said there's more than one way to do it.

Everything is stored in an arrayref retrieved by the data() method. Each array element is a hashref. Each referenced hash has the keys exp, calls and puts:

 @data (
   \%expiration1 {
      exp => YYYYMMDD,
      calls => \@calldata,
      puts => \@putdata
   \%expiration2 {
      exp => YYYYMMDD,
      calls => \@calldata,
      puts => \@putdata

The arrays referenced by calls and puts are each arrays of hashrefs. The final hashes contain all the data for an individual option:

 @callorputdata (
   \%option1 {
      strike => 000.00,
      symbol => 'ABCD',
      bid => 000.00,
      ask => 000.00,
      last => 000.00,
      open => 0000,
      volume => 0000,
      change => 0000,
      in_the_money => 1
   \%option2 {

So, to enumerate all available expiration dates:

 print $_->{exp},"\n" foreach @{$q->data};

Or to display the number of puts and calls along with the symbol and strike price of the first and last call options of each expiration:

 foreach (@{$q->data}) {
   print "\n",$_->{exp},":\n";
   print 'Calls: ', scalar @{$_->{calls}},"\n";
   print 'Puts: ', scalar @{$_->{puts}},"\n";
   print 'First Call: ',  $_->{calls}->[0]->{symbol},
      " Strike $_->{calls}->[0]->{strike} \n";
   print 'Last Call: ',  $_->{calls}->[-1]->{symbol},
      " Strike $_->{calls}->[-1]->{strike} \n";


WWW::Mechanize and HTML::TokeParser each have their own complex set of dependencies. So be prepared for a wait if doing a CPAN install on a basic Perl distribution.

Be sure to read "CBOE Blacklist Warning".

HTML::TokeParser's ability to jump from tag to tag should make this code impervious to web page additions or changes which surround the actual options information we're after. That is, as long as the structure of the tables containing the basic information doesn't change.

The CBOE site is much slower than Yahoo. In my testing Yahoo took about one second to retrieve all options for a stock whereas the CBOE site took five to fifteen seconds.

Because of the way the CBOE site is structured, there might be a problem if there are options with more than one expiration date in a single month. right now, they'll all end up in the same expiration. I could fix this by drilling down into the details for every option but then the CBOE retrieval would get even slower. So be careful if weeklys, monthlies or quarterlies are available for a stock. See for more information.

Feel free to contact me at the address below if you have any questions, problems or suggestions.


None by default.







Kirk Bocek, <quoteoptions <AT>>

Version 0.20 contributions by Dan Descaleau, <ddascalescu <AT>>


Copyright (C) 2007,2008,2009 by Kirk Bocek

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.5 or, at your option, any later version of Perl 5 you may have available.

3 POD Errors

The following errors were encountered while parsing the POD:

Around line 948:

L<> starts or ends with whitespace

Around line 958:

Expected text after =item, not a bullet

Around line 1025:

Non-ASCII character seen before =encoding in 'hasn’t'. Assuming UTF-8