=head1 NAME

Finance::Shares::Lesson4 - Drawing moving averages

=head1 DESCRIPTION

An N-day moving average plots the average of the previous N days' data.  They are much used in computerized stock market
analysis as they can smooth out minor fluctuations in the market.  The downside is that the results always turn in
N days late, but then you can't have everything.

This script, called F<04averages.pl> can be found in the F<tutorial> directory of the Finance::Shares package.

    #!/usr/bin/perl
    use strict;
    use warnings;
    use Getopt::Long;
    use Finance::Shares::Sample;
    use Finance::Shares::Averages;
    use Finance::Shares::Chart;

    my $help;
    my $stock = 'GM';
    my $dates = 'days';
    my $start = '2000-08-01';
    my $end   = '2001-07-31';
    my $mode  = 'cache';
    my $usage = <<END;
    Usage:
	$0 [ options ]

    where options can be any (or none) of the following:
      -c <code>  |  --code=<code>    Stock code like 'BA.L'
      -d <dmw>   | --dates=<dmw>     'days', 'weeks' or 'months'
      -s <date>  | --start=<date>    First date, as 'YYYY-MM-DD'
      -e <date>  |   --end=<date>    Last date, as 'YYYY-MM-DD'
      -m <mode>  |  --mode=<mode>    'cache', 'offline' or 'online'
      -h         |  --help           Show this help
    END

    GetOptions (
	'help|h'    => \$help,
	'code|c=s'  => \$stock,
	'dates|d=s' => \$dates,
	'start|s=s' => \$start,
	'end|e=s'   => \$end,
	'mode|m=s'  => \$mode,
    ) or $help = 1;
    print $usage and exit if $help;

    # Create MySQL object giving access to the data
    my $fss = new Finance::Shares::Sample(
	source => {
	    user     => 'test',
	    password => 'test',
	    database => 'test',
	},

	mode        => $mode,
	symbol      => $stock,
	start_date  => $start,
	end_date    => $end,
	dates_by    => $dates,
    );

    # Create Chart object showing the data
    my $fsc = new Finance::Shares::Chart(
	sample          => $fss,
	background      => [ 1, 1, 0.9 ],
	bgnd_outline    => 1,
	dots_per_inch   => 72,
	file => {
	    landscape => 1,
	},
	x_axis => {
	    show_lines  => 0,
	    show_year   => 1,
	},
	prices => {
	    percent => 70,
	    points => {
		width => 1.5,
		color => [ 0.4, 0.4, 0.7 ],
	    },
	},
	volumes => {
	    percent => 30,
	    bars => {
		color => [ 0.5, 0.8, 0.6 ],
		width => 1,
	    },
	},
    );

    # place your function(s) here

    $fsc->output($stock);
    print "$stock quotes from $start to $end saved as $stock.ps\n";

There are a few changes from previous scripts which are worth pointing out.  Single letter options are now
accepted and $usage reflects that.  The defaults are different, providing a larger, more realistic sample.
Some new options appear in the Chart constructor.  Look them up in L<Finance::Shares::Chart>.

=over 4

=item 1.

Near the end of the script is a comment.  Add this call after it:

    # place your function(s) here
    $fss->simple_average();

Run the script, and you should see a moving average added to the prices graph, with a Key panel appearing at the
side.  Err, that's it, more or less.  Notice that all the function modules implement methods called on a B<Sample>
object.  Try adding these too:

    $fss->weighted_average();
    $fss->exponential_average();

You might find it easier to see as weeks rather than days.  Invoke the script as e.g.

    $ 04average.pl -d 'weeks'

=item 2.

All function methods take hash key/value style parameters.  Draw two moving averages on the chart, with periods of
3 and 14, like this:

    $fss->simple_average(
	period => 3,
    );

Signals might be generated when the faster moving average (3) crosses the slower moving one (14).  If it crosses
up, the prices are starting to rise, so buy; when it crosses down, the prices are already falling, so sell.

=item 3.

Just like the price and volume data, it is possible to give each line a B<Style>.

    $fss->simple_average(
	period => 14,
	style => {
	    width => 2,
	    color => [ 1, 0, 0 ],
	},
    );

The Style module tries to ensure that each style is slightly different.  In this case, it is still changing the
dash pattern of the lines.  Often this is useful, because you don't have to think about giving every line
a different style.  However, if you wish to turn off this automatic style selection, add the following line to the
B<style> group:

	    auto => 'none',

=item 4.

The automatic style selection is controlled by a B<Sequence> object.  There is a default sequence for each graph,
and this can be used to ensure each line has a different appearance.  Remove any changes you have made to the
script, then add these lines after the 'place your functions' comment.

    # place your function(s) here
    my $pstyle = {
	same => 1,
	line => {
	    width => 2,
	    color => [1, 0, 0],
	    outer_dashes => [],
	},
    };

    $fss->simple_average(
	period => 3,
	style => $pstyle,
    );
    $fss->simple_average(
	period => 14,
	style => $pstyle,
    );
    $fss->simple_average(
	period => 28,
	style => $pstyle,
    );

Run it.  These 3 lines are all controlled by the same style, but the default sequence object is changing their
dash styles.  The B<same> option works just like the top-level Chart option, 'bgnd_outline'.  Setting the
B<outer_dashes> pattern to '[]' (meaning 'no dashes') has the effect of providing a continuous 'outer_color'.
Comment them out to see what they do.

=item 5.

Now to take charge of the sequence.  Change the start of these changed lines to read as follows. Notice that the
B<color> line has gone.

    # place your function(s) here
    my $pseq = $fsc->sequence('prices');
    $pseq->auto( 'red' );
    my $pstyle = {
	sequence => $pseq,
	same => 1,
	line => {
	    width => 2,
	    outer_dashes => [],
	},
    };

The colours can be specified directly.  Try this:

    # place your function(s) here
    my $pseq = $fsc->sequence('prices');
    $pseq->setup( 'color',
	[1,0,0], [0.5,0.5,0], [1,1,0] );
    $pseq->auto( 'color' );
    my $pstyle = {
	...
    };
    
=item 6.

All functions can be applied to any data or even other functions and moving averages are no exception.  The data
to be averaged is specified by the B<graph> and B<line> keys.

    $fss->simple_average(
	period => 3,
	graph => 'volumes',
	line => 'volume',
	style => $pstyle,
    );
 
B<graph> can be one of prices, volumes, cycles, tests.  B<line> must be an identifier for a line on the
specified chart.  Add this code to the end of the script.  It lists all the line IDs for the prices graph.

    my @lines = $fss->known_lines( 'prices' );
    print join('; ', @lines), "\n";

=item 7.

Finally, these are all the keys recognized by the B<..._average> methods.

    $fss->simple_average(
	period => 28,
	graph => 'prices',
	line => 'low',
	style => $pstyle,
	strict => 1,
	show => 1,
	key => 'LOW Prices !!!',
	id => 'not-the-usual',
    );
 
A 28 day moving average cannot strictly be calculated until the 28th day.  This sort of thing is enfored when
B<strict> is true; otherwise most functions can produce something sensible like 'the average so far'.  B<show>
enables the Sample to hold working lines without them necessarily being visible on the chart.  B<key> and B<id>
allow user over-rides of these.  Take care replacing B<id>, though; it is probably better to use the internal ones
which can be obtained by calling e.g.

    my $id = line_id('graph', 'line');

=back

See L<Finance::Share::Averages> for full details of the moving average functions.  L<PostScript::Graph::Style> is
the place to go for all the stuff on Styles and Sequences.

=cut

