NAME
Finance::Shares::Sample - Price data on a single share
SYNOPSIS
use Finance::Shares::Simple;
use Finance::Shares::Simple qw(ymd_from_string
string_from_ymd);
Simplest
Graph a series of stock quotes.
my $ss = new Finance::Shares::Sample(
source => 'gsk,csv',
epic => 'GSK.L',
);
$ss->output( 'Glaxo' );
Typical
Get a series of stock quotes and graph them using specific settings. Calculate some trend lines from the Finance::Shares::Sample data and superimpose them on the graph.
my $s = new Finance::Shares::Sample(
source => {
user => 'guest',
password => 'a94Hq',
database => 'London',
},
dates_by => 'weeks',
epic => 'GSK.L',
start_date => '2001-09-01',
end_date => '2002-08-31'
graph => {
file => {
landscape => 1,
paper => 'A4',
},
heading => 'GlaxoSmithKline',
background => [1, 1, 0.9],
color => [0, 0, 0.8],
price => {
percent => 50,
},
analysis => {
percent => 30,
low => -100,
high => 100,
},
volume => {
percent => 20,
},
},
lines => {
color => [1, 0, 0],
},
);
# construct data for lines, and then...
$graph->add_price_line( $line1, 'Support' );
$graph->add_volume_line( $line2, 'Average' );
$graph->add_analysis_line( $line3, 'RSI' );
$s->output( 'Glaxo' );
DESCRIPTION
This module is principally a data structure holding stock quotes. Price and volume data are held for a particular share over a specified period. This data can be read from a CSV file or from an array, but more usually it is fetched from Finance::Shares::MySQL which in turn handles getting the data from the internet.
Facilities are provided to graph the data together with other, user-calculated lines.
All options can be given to the constructor, or to seperate fetch and graph functions. This module cooperates closely with Finance::Shares::MySQL and PostScript::Graph::Stock. See those manpages for further details.
The Data
This object is used as a data structure common to a number of modules. Therefore, unusually, most of the internal data is made available directly. The hash and array refs documented here can be relied upon to exist as soon as the object has been constructed, although dates
, prices
and volumes
are by far the most useful. Other values are made available for reading, but changing them will probably cause chaos.
alines
An array of all data sets derived for the analysis chart section. See plines.
dates
An array ref indicating a list of dates in YYYY-MM-DD format. These are the dates of all known data points. If any prices exist, there should be one for each date. If any volumes exist, there should be one for each date.
dtype
The value given to 'dates_by' (etc.) controlling how the data is distributed. One of 'days', 'weekdays', 'alldays', 'weeks', 'months'.
idx
A hash ref acting as an index into the dates
, prices
or volumes
arrays.
my $s = new Finance::Shares::Sample(...);
my $i = $s->{idx}{'2002-09-01'};
my $closing_price = $s->{prices}[$i];
This is the same as the following:
my $closing_price = $s->{price}{'2002-09-01'}[3];
The first method would be best for comparing closing prices with the days before and after, while the second would be better to compare the closing price with the highest of the day.
labels
An array ref indicating a label for each line across a PostScript::Graph::Stock chart. Some of these labels may be blank (or a single space) if there is too little room to show them all. Not every label has data associated with it e.g. weekends when 'days' are specified.
lblmax
A scalar holding the length of the longest label. Used by PostScript::Graph::Stock.
order
A hash ref. Keyed by YYYY-MM-DD dates, there is an entry for each date
known. The value is the label number. Used to convert dates to points on a PostScript::Graph::Stock chart.
plines
An array of all data sets derived from the prices. Each entry is a pseudo-hash with the following keys:
- data
-
An array ref similar to
prices
orvolumes
. - style
-
Either a PostScript::Graph::Style object or a hash ref holding options for one.
- key
-
The string to be shown next to the style in the chart's Key.
- show
-
True if to be drawn, false otherwise.
- func
-
String identifying the function creating the data.
- params
-
Any parameters passed to
func
which are needed to uniquely identify the line.
price
A hash ref. Keyed by YYYY-MM-DD dates, the values are array refs indicating (open, high, low, close) prices.
Note that some of the entries here may be aggregates. For example, when processing the data by 'weeks', Friday's values are over-written with the week's averages. The closes
array should be used when analysing price data. These values are held for plotting each days' spread on a PostScript::Graph::Stock chart.
prices
An array ref indicating the closing price (if any) for every date
known. This is the data that should be processed when analysing price movement. Each entry has the form:
[ 'YYYY-MM-DD', price ]
vlines
An array of all data sets derived from the volume data. See plines.
volume
A hash ref keyed by YYYY-MM-DD dates and used while preparing the data (See price
). Use the volumes
array when analysing volume data.
volumes
An array ref. If volume data was read in there should be a value here corresponding with each date in the dates
array. Each entry has the form:
[ 'YYYY-MM-DD', volume ]
Managing Styles
Often the data will be output as a graph in PostScript format. The PostScript::Graph::Stock object used for this provides facilities ensuring that each line drawn on each chart is different from the previous one.
Lines can be given styles directly. See PostScript::Graph::Style for details. However each graph also has a PostScript::Graph::Sequence which is used unless the style option auto =
'none'> is given. How the styles vary can be altered in two ways. It is possible to change the order of change using auto or the values of the settings themselves using setup.
Example 1
my $sample = new Finance::Shares::Sample(
price_lines => {
line => {},
},
);
my $graph = $sample->graph();
my $sequence = $graph->price_sequence();
$sequence->setup( 'red', [1, 0.75, 0.5] );
$sequence->setup( 'green', [0.4, 0.8] );
$sequence->setup( 'blue', [0.1] );
$sequence->auto( 'green', 'red', 'blue' );
# prepare line data
$sample->add_price_line($data1, 'One');
$sample->add_price_line($data2, 'Two');
$sample->add_price_line($data3, 'Three');
$sample->add_price_line($data4, 'Four');
$sample->output( 'graph' );
The four lines added to the price chart will be in various shades of orange. There are a few things to notice about this example.
- *
-
The order is important. The sequence settings must be made before any lines are added.
- *
-
Six colours are generated in this sequence, all combinations of 3 red and 2 green. If more than six lines were drawn, the styles would be repeated.
- *
-
The green settings vary fastest. The colours generated would be, in order:
Red Green Blue 1.0 0.4 0.1 1.0 0.8 0.1 0.75 0.4 0.1 0.75 0.8 0.1 0.5 0.4 0.1 0.5 0.8 0.1
- *
-
There is no need to specify a style provided both lines and points are wanted. In fact, there is no need to specify the sequence data either. However, the defaults assume a minimal black and white printer.
If a hash of style options is given to each line, remember to set up line and/or point sub-hashes, even if they are empty. It is the presence of these sub-hashes which determines whether each gets drawn. In this example, only lines are drawn on the price line - no points.
- *
-
In practice the data for the lines would be constructed by another module such as Finance::Shares::Averages. These support modules add lines in the right way.
- *
-
Finally, notice that price_sequence() is used with add_price_line(). Use the right sequence to control the lines.
There is no need to be limited to one sequence. It is possible to have most of the lines controlled by one sequence but special indicators having their own styles.
Example 2
my $sample = new Finance::Shares::Sample(
price_lines => {
color => 0.5,
line => {},
},
);
# prepare line data
$sample->add_price_line($data1, 'One');
$sample->add_price_line($data2, 'Two');
my $style2 = {
color => [1, 0, 0],
dashes => [],
};
$sample->add_price_line($data3, 'Three', $style2);
$sample->add_price_line($data4, 'Four');
In this example lines One, Two and Four will be grey, with different dash patterns. Line Three will be in solid red.
However, when a PostScript::Graph::Style object is used (rather than a hash ref), it is necessary to explicitly specify the sequence.
Example 3
my $sample = new Finance::Shares::Sample(
price_lines => {
color => 0.5,
line => {},
},
);
# prepare line data
$sample->add_price_line($data1, 'One');
$sample->add_price_line($data2, 'Two');
my $graph = $sample->graph();
my $sequence = $graph->price_sequence();
my $style2 = new PostScript::Graph::Style(
sequence => $sequence,
color => [1, 0, 0],
dashes => [],
);
$sequence->reset();
$sample->add_price_line($data3, 'Three', $style2);
$sample->add_price_line($data4, 'Four');
Passing a style object is the only way of giving the same style to more than one line (boundary lines for example). Notice the reset command after $style2 is created. The other styles are not created until output is called, so they would otherwise start with the second default.
See PostScript::Graph::Style for details on what is available.
CONSTRUCTOR
new( [options] )
options
can be a hash ref or a list of hash keys and values (or omitted altogether).
source
and epic
must be specified, with start_date
and end_date
also required if the source is a mysql database.
Recognized keys are:
source
This can be a Finances::Shares::MySQL object or a hash ref holding options suitable for creating one. Alternatively it may be the name of a CSV file or an array ref holding similar data.
Example 1
Using an existing MySQL object.
my $db = new Finance::Shares::MySQL;
my $ss = new Finance::Shares::Sample (
source => $db,
);
Example 2
Creating our own MySQL connection.
my $ss = new Finance::Shares::Sample (
source => {
user => 'wally',
password => '123jiM',
database => 'London',
},
);
Several attempts (see tries
below) are made to fetch the data from the internet (see "fetch_batch" in Finance::Shares::MySQL). Then the data is extracted from the MySQL database, filtered according to opts
and stored as date, price and volume data.
!Yahoo Finance provide a suitable source of CSV files in the right format. If that is what you want you might like to look at Finance::Shares::MySQL and Finance::Shares::Sample.
The CSV file is read and converted to price and/or volume data, as appropriate. The comma seperated values are interpreted by Text::CSV_XS and so are currently unable to tolerate white space. See the array
option for how the field contents are handled.
Optionally, the directory may be specified seperately.
Example 3
my $ss = new Finance::Shares::Sample (
source => 'quotes.csv',
directory => '~/shares',
);
If source
is an array ref it should point to a list of arrays with fields date, open, high, low, close and volume.
Example 4
my $data = [
['2002-08-01',645.13,645.13,586.00,606.36,33606236],
['2002-08-02',574.75,620.88,558.00,573.00,59618288],
['2002-08-05',589.88,589.88,560.11,572.42,20300730],
['2002-08-06',571.89,599.00,545.30,585.92,26890880],
['2002-08-07',565.11,611.00,560.11,567.11,24977940] ];
my $ss = new Finance::Shares::Sample (
source => $data,
);
Three formats are recognized:
Date, Open, High, Low, Close, Volume
Date, Open, High, Low, Close
Date, Volume
Examples
[2001-04-26, 345, 400, 300, 321, 12345678],
[Apr-1-01, 234.56, 240.00, 230.00, 239.99],
[13/4/01, 987654],
The first field must be a date. Attempts are made to recognize the format in turn:
The Finance::Shares::MySQL format is tried first, YYYY-MM-DD.
European format dates are tried next using Date::Pcalc's Decode_Date_EU().
Finally US dates are tried, picking up the !Yahoo format, Mar-01-99.
The four price values are typically decimals and the volume is usually an integer in the millions. If the option dates
is weeks the average price and volume data for the week is given under the last known day. Average prices are also calculated for months.
dates_by
Control how the data are stored. Suitable values are 'days', 'weekdays', 'alldays', 'weeks', 'months'. (Default: 'days')
Shortcut for: dates =>{ by => ... }
directory
Specifies the directory, if file
is an unqualified file name.
end_date
The last day of price data, in YYYY-MM-DD format. Only used if epic
is given. See fetch.
epic
The market abbreviation for the stock. The data is fetched from Yahoo, so there probably should be a suffix indicating the stock exchange (e.g. BSY.L for BSkyB on the London Stock Exchange).
If this is given, the stock data is fetched depending on which of mysql
, file
or array
is set. Remember to include start_date
, end_date
and possibly table
if mysql
is being used.
graph
If present, the contents is used in a call to graph. It should be reference to a hash containing options suitable for a PostScript::Graph::Stock object. See "new" in PostScript::Graph::Stock.
The hash referenced here contains a 'dates' key with a sub-hash value used by both this and the PostScript::Graph::Stock modules. For details of the keys available within 'dates' see prepare_dates.
lines
A sub-hash containing style options for price, volume and/or analysis lines. It is passed straight to Finance::Shares::Sample. All PostScript::Graph::Style settings can be used within the three sub-hashes. See Finance::Shares::Sample for further details.
Example
my $ss = new Finance::Shares::Sample (
lines => {
price => {
},
volume => {
},
analysis => {
},
},
);
show
Setting this to 0 prevents the PostScript::Graph::Stock graph from being created. (Default: 1)
Individual charts within the PostScript::Graph::Stock object can be hidden by setting their percent
option to 0.
start_date
The first day of price data, in YYYY-MM-DD format. Only used if epic
is given. See fetch.
strict
A number of functions can behave strictly according to their definitions or run in a more relaxed way that might be more benficial. For example, strictly a 20-day moving average does not exist for the first 20 days. So with 'strict' set to 1, the function doesn't exist for that period. But if it is 0, the average so far is returned. Bollinger bands require 20 days of data from the function they follow. With 'strict' set, there would have to be at least 40 days data before the first test could be made. Without 'strict' a shorter period may be given to the Bollinger Band function, so this lead time might be reduced to 10 days. (Default: 0)
table
The MySQL table name for the stock. Only used if epic
is given. See fetch.
tries
Specify the number of times an attempt is made to fetch the data from the internet. (Default: 3)
add_price_line( lineid, data, key [, style [, show]] )
- lineid
-
A string uniquely identifying the line.
- data
-
An array ref indicating a list of points. Each point has a date and a price value.
- key
-
The text to be shown next with the style in the Price Key box to the right of the chart.
- style
-
This can either be a PostScript::Graph::Style object or a hash ref holding options for one.
- show
-
True if to be drawn, false otherwise.
Add a line to the price chart to be drawn in the style specified identified by some key text. See "add_price_line" in PostScript::Graph::Stock.
add_volume_line( lineid, data, key [, style [, show]] )
See add_price_line.
add_analysis_line( data, key [, style [, show [, func, params]]] )
See add_price_line.
build_graph()
Construct the graph and add all lines to it. This should not need to be called in most circumstances as it is called automatically by output. However, it is provided so that several samples are to be printed to the same PostScript::File. See "build_graph" in PostScript::Graph::Stock.
Setting the constructor option show
to 0 prevents the graph being built.
output( file [, dir] )
The graph is constructed and written out to a PostScript file. A suitable suffix (.ps, .epsi or .epsf) will be appended to the file name. This is a convenience method, identical to calling output on the PostScript::Graph::Stock object returned by graph. Both these examples do the same thing.
Example 1
my $ss = new Finance::Shares::Sample(...);
$ss->fetch( $epic, $start_date, $end_date );
$sg->output( $epic );
Example 2
my $ss = new Finance::Shares::Sample(
...
epic => $epic,
start_date => $start_date,
end_date => $end_date,
);
my $graph = $ss->graph();
$graph->output();
Setting the constructor option show
to 0 prevents the graph being built.
ACCESS METHODS
See DESCRIPTION for the data items that are directly available.
dates_by
Return a string indicating how the dates are spread. One of 'data', 'days', 'workdays', 'weeks', 'months'.
line_data( chart [, func, params] )
Return the requested points data.
chart
should be one of 'price', 'volume' or 'analysis'. func
and params
are as specified when the line was added.
graph_stock
Return the PostScript::Graph::Stock object used to output the graph.
SUPPORT METHODS
prepare_dates( data )
This splits raw CSV-style data into the date labels, prices and volumes needed for a stock graph. data
should be a reference to an array of arrays. The inner arrays should hold a date in YYYY-MM-DD format, opening, high, low and closing prices followed by the volume. Either the prices or the volume may be omitted.
Example
$data = [
['2001-06-01',454.50,475.00,448.50,461.00,8535680],
['2001-06-04',465.00,465.00,458.50,459.00,3254045],
['2001-06-05',458.25,464.00,455.00,462.00,4615016],
];
The dates are filtered and labelled according to the 'dates' sub-hash options passed to the constructor. Suitable values for keys found within 'dates' are processed by this method and so are listed here.
by
This string determines how the dates are distributed across the X axis.
- days
-
The dates are those present in the data, in chronological order (the default).
- alldays
-
Every day between the first and last day is listed, whether there is data for that day or not.
- weekdays
-
Every day except Saturdays and Sundays. Occasional holidays are ignored, just showing as days with no data.
- weeks
-
Only the data for last trading day of each week is presented. No attempt is made to take the rest of the week into account - those days are just hidden. If any trading is recorded for that week, the latest day is given; if not the last working day is shown, with no data.
- months
-
As weeks, but showing the last trading day of each month.
changes_only
The date labels are made up of weekday, day, month and year. Which sections are shown by default depends on the dates setting. If this is 1, each part is only shown if it has changed from the previous label. If 0, all the selected parts are shown. (Default: 1)
days
This allows the weekday abbreviations to be presented in a different language. It should be an array ref containing strings. Monday = 1, so there should probably be a dummy string for 0. (Defaults to English).
months
This allows the month abbreviations to be presented in a different language. It should be an array ref containing strings. January = 1, so there should probably be a dummy string for 0. (Defaults to English).
show_day
Show the date of day within the month. (Default: depends on dates
)
show_month
Show the month. (Default: depends on dates
)
show_weekday
Show the day of the week. (Default: depends on dates
)
show_year
Show the month. (Default: depends on dates
)
Values returned
order
-
A hash ref. Keyed by date, the integer values indicate the order of labelled dates. Used for locating valid dates within the dates array.
price
-
A hash ref. Keyed by the YYYY-MM-DD date, each entry points to a list of price data.
[ Open, High, Low, Close ]
volume
-
A hash ref. If present the Volume (or averaged volume) of trades is keyed by the YYYY-MM-DD date.
dates
-
An array ref. Each date in this list (in YYYY-MM-DD format) represents a labelled point on the graph - typically a day, week or month. However, not all of these may be visible as labels if there is not enough room across the axis. This should be the 'X' value used in constructing all superimposed lines.
labels
-
An array ref. The labels to be printed.
labelmax
-
The length of the longest label.
known_date( date )
Adjust the YYYY-MM-DD date given to one of the dates with data. It actually returns the date given or the first one after it rather than the closest. Returns undef if no date is found.
graph
All options should be given as the constructor option, graph
. This should only need to be called if the underlying PostScript::Graph::Stock object (which is returned) is needed.
BUGS
Please report those you find to the author.
AUTHOR
Chris Willmot, chris@willmot.co.uk
SEE ALSO
Finance::Shares::MySQL, Finance::Shares::Model, PostScript::Graph::Style and PostScript::Graph::Stock.