NAME

Finance::Shares::Momentum - functions dealing with rates of change

SYNOPSIS

    use Finance::Shares::Sample;
    use Finance::Shares::Momentum;

    my $s = new Finance::Shares::Sample(...);

    my $id1 = $s->momentum(
        graph  => 'prices',
        line   => 'close',
        period => 10,
        strict => 0,
        scaled => 1,
        shown  => 1,
        style  => {...}, # PostScript::Graph::Style
        key    => 'My Momentum Line',
    );
    my $id2 = $s->ratio(...);
    my $id3 = $s->gradient(...);
    
    my $id4 = $s->rising(
        ...
        style    => {...}, # PostScript::Graph::Style
        key      => 'Rising Trends',
        weight   => 50,
        decay    => 0.66,
        ramp     => 0,
        cutoff   => {...}, # PostScript::Graph::Style
        gradient => {...}, # PostScript::Graph::Style
        smallest => 10,
    );
    my $id5 = $s->falling(...);

    my $id6 = $s->oversold(
        ...
        gradient => {...}, # PostScript::Graph::Style
        sd => 2.5,
    );
    my $id7 = $s->undersold(...);
    

DESCRIPTION

This package provides additional methods for Finance::Shares::Sample objects. Some functions analyse how another line changes over time and produce lines on the cycles graph. Others are pseudo-tests producing digital output on the tests graph, although they don't trigger signals (use the test test for that, see "Tests" in Finance::Shares::Models).

Once a line has been constructed it may be referred to by a text identifier returned by the function. The functions may also be referred to by their text names in a model specification (short or full version):

    mom     momentum
    roc     ratio               (Rate of Change)
    grad    gradient
    obv     on_balance_volume
    adx     direction
    
    rise    rising
    fall    falling
    over    oversold
    under   undersold
    ext     extend

Common options

They all take the following parameters in hash key/value format. All of these keys are optional.

graph

A string indicating the graph for display: one of prices, volumes, cycles or signals. (Default: 'prices')

line

A string indicating the data/function to be analysed - normally the closing prices. (Default: 'close')

period

The number of readings used in the analysis. The actual time spanned depends on how the sample was configured.

strict

Where appropriate, setting this to 0 might produce a better looking line by including some (possibly dubious) guesses. Set as 1 to ensure the line is accurate and reliable. (Default: 1)

scaled

Set this to 1 to make comparison easier. It ensures the values all lie within +/- 100. Particularly useful for ratio which normally produces values of +/-1.

shown

A flag controlling whether the function is graphed. 0 to not show it, 1 to add the line to the named graph. (Default: 1)

style

A hash ref holding settings suitable for the PostScript::Graph::Style object used when drawing the line. By default lines and points are plotted, with each line in a slightly different style. (Default: undef)

key

If given this becomes the visual identifier, shown on the Chart key panel.

Pseudo-test options

In addition, the pseudo-tests rising, falling, oversold and undersold also recognize these keys.

smallest

[rising and falling only.] This is the smallest daily change that will be considered. For example,

    $s->falling(
        line     => 'close',
        period   => 10,
        smallest => 5,
    );

This will only produce 'true' if the closing price was 5p or more lower than the day before, according to the 10 day smoothed gradient.

sd

[oversold and undersold only.] Short for standard deviation, this defines the point beyond which stock is deemed oversold or undersold. The following table gives some idea how standard deviation relates to the number of quotes within the normal area or in the under/oversold region.

    sd      within  above or below
    3.00    99.74%       0.13%
    2.58    99%          0.5%
    2.33    98%          1%
    2.06    96%          2%
    2.00    95.46%       2.27%
    1.65    90%          5%
    1.29    80%         10%
    1.15    75%         12.5%
    1.00    68.26%      15.87%
    0.85    60%         20%
    0.68    50%         25%
weight

How important the test should appear. Most tests implement this as the height of the results line.

decay

If the condition is met over a continuous period, the results line can be made to decay. This factor is multiplied by the previous line value, so 0.95 would produce a slow decay while 0 signals only the first date in the period.

ramp

An alternative method for conditioning the test line. This amount is added to the test value with each period.

gradient

Determine whether, and how, the gradient line will be shown. It can be '0' for hide or '1' for show but the most useful is a PostScript::Graph::Style object or a hash ref holding style settings.

cutoff

Determine whether, and how, the boundary line will be shown. It can be '0' for hide or '1' for show but the most useful is a PostScript::Graph::Style object or a hash ref holding style settings.

Example script

Sometimes it is useful to see how the parts fit within the whole. Here is a fairly minimal script that marks suitable buy points on a chart. Signals are triggered when the volume rises in an undersold period. Or more explicitly:

    if
        the sample has been undersold
            (prices lower than 1 std dev)
        in the last 5 days
    and
        the 10 day 'on balance volume'
        is rising
    then
        a buy signal highlights the low price

The Sample needs a MySQL object to provide the quotes, so that must be constucted first. Both Chart and Model need the Sample in turn, and before a signal is used, the Model needs to know all about it. We are then in a position to build all the functions (all from this module as it happens). Finally the test produces the signals and the chart is saved as 'output.ps'.

    #!/usr/bin/perl
    use strict;
    use warnings;
    use Finance::Shares::MySQL;
    use Finance::Shares::Sample;
    use Finance::Shares::Momentum;
    use Finance::Shares::Model;
    use Finance::Shares::Chart;

    my $sql = new Finance::Shares::MySQL(
            user         => 'test',
            password => 'test',
            database => 'test',
            mode     => 'offline',
        );

    my $sample = new Finance::Shares::Sample(
            source       => $sql,
            symbol       => 'AV.L',
            start_date => '2003-01-01',
            end_date => '2003-06-30',
        );

    my $chart = new Finance::Shares::Chart(
            sample   => $sample,
        );
        
    my $model = new Finance::Shares::Model;
    $model->add_sample($sample);
    $model->add_signal('buysig', 'mark_buy', undef, {
            graph   => 'prices',
            line    => 'low',
        }); 

    my $usold = $sample->undersold(
            sd      => 1,
            shown   => 0,       
        );

    my $usold_ex = $sample->extend(
            graph   => 'tests',
            line    => $usold,
            period  => 5,
            key     => 'undersold (ext)',
            weight  => 75,
        );

    my $obv = $sample->on_balance_volume(
            period  => 10,
            key     => 'obv',
        );
        
    my $vup = $sample->rising(
            graph   => 'cycles',
            line    => $obv,
            key     => 'rising OBV',
            weight  => 50,
        );

    my $both = $model->test(
            graph1  => 'tests',
            line1   => $usold_ex,
            graph2  => 'tests',
            line2   => $vup,
            test    => 'and',
            signals => ['buysig'],
            shown   => 1,
            key     => 'oversold & rising vol',
        );

    $chart->output('example');

Key strings were declared throughout to stop too much space being wasted by the Key panels. The weights have just been given to make the tests graph clearer. See the tests for examples of how to make the chart look better using PostScript::File, PostScript::Graph::Style and Finance::Shares::Chart options.

This test can be found in fs_model format in the distribution as models/momentum_ex. The following command will apply this model to all the stocks listed in the file stock/FTSE-retail.

    fs_model -m models/momentum -s -c stock/FTSE-retail

The resulting PostScript file FTSE-retail.ps has a page showing how each stock fared under the test.

MOMENTUM METHODS

momentum

Movement is calculated by subtracting the value period days/weeks/months ago.

ratio

This calculates the rate of change by dividing the current value with a correspnding one period days/weeks/months previously.

The line centers around 1 normally, but can be made to center around zero by setting strict to 0. scaled should probably be used.

gradient

This is an attempt to provide a function which performs differentiation, smoothing out abberations as it goes.

A period of 1 just produces the slope of the line to the next point. Larger values, however, take a wider spread of neighbours into account. E.g. a 10 day gradient will calculate each gradient from the weighted average of the differences from the previous 5 and subsiquent 5 days, where they exist.

on_balance_volume

This function produces a line on the cycles graph, showing how the volume varies. It presents a running total, adding the days volume if the price closed higher than the previous date or subtracting it if the price closed lower.

Being a specialized function, there are fewer options. See "DESCRIPTION" for explanation of the keys available:

   shown        scaled
   style        key
   strict       gradient

The direction of movement is more significant than the raw numbers. So it is usually scaled or passed to rising or falling.

direction

This is really three function in one. The lines are drawn on the cycles graph, indicating the direction prices are moving. Option keys include:

dir

Standing for 'direction', this determines the type of line produced. (Default: 0)

    +1  Upward movement
     0  Average of up and down
    -1  Downward movement
period

If 0, the direction line is unsmoothed. Otherwise a moving average of this period is used for smoothing. (Default: 0)

average

This should be the name (short or long) of a moving average function. It should be one of the following. (Default: 'avg')

   avg  simple_average
   wgt  weighted_average
   exp  exponential_average
    

The following keys are also supported. See "DESCRIPTION" for details.

   shown        scaled
   style        key

PSEUDO-TEST METHODS

rising

A pseudo-test producing a true/false output on the tests graph depending on whether the gradient of the specified line is sufficiently positive.

falling

A pseudo-test producing a true/false output on the tests graph depending on whether the gradient of the specified line is sufficiently negative.

oversold

A pseudo-test producing a true/false output on the tests graph depending on whether the gradient rises above a certain level. The level depends on the data sampled, so it is controlled using sd.

undersold

A pseudo-test producing a true/false output on the tests graph depending on whether the gradient falls below a certain level. The level depends on the data sampled, so it is controlled using sd.

extend

This produces a logic line on the tests graph like the other pseudo-tests, but unlike the others it doesn't really test anything. It provides a fixed period following some event on the line passed to it. It is level triggered, with the period beginning when the line moves above the value of smallest.

Example

BUGS

The complexity of this software has seriously outstripped the testing, so there will be unfortunate interactions. Please do let me know when you suspect something isn't right. A short script working from a CSV file demonstrating the problem would be very helpful.

AUTHOR

Chris Willmot, chris@willmot.org.uk

SEE ALSO

Finances::Shares::Sample, Finance::Shares::Chart and Finances::Shares::Model.

There is also an introduction, Finance::Shares::Overview and a tutorial beginning with Finance::Shares::Lesson1.

2 POD Errors

The following errors were encountered while parsing the POD:

Around line 225:

You forgot a '=back' before '=head2'

Around line 329:

=back without =over