NAME
Finance::Shares::Model - Apply tests to series of stock quotes
SYNOPSIS
use Finance::Shares::Model;
There are two ways to use this module. Either all the data can be given to the constructor, with the model run immediately, or tests can be administered piece by piece in a script.
These two approaches are illustrated here. Both draw circles around the volume where a day's highest price is more than 3% above the previous closing price.
Packaged model
my $fsm = new Finance::Shares::Model(
sources => [
db => {
# Finance::Shares::MySQL options
},
],
charts => [
main => {
# Finance::Shares::Chart options
},
],
files => [
myfile => {
# PostScript::File options
},
],
functions => [
env => {
function => 'envelope',
percent => 3,
},
],
tests => [
good_vol => {
graph1 => 'prices', line1 => 'env_high',
graph2 => 'prices', line2 => 'high',
test => 'ge',
graph => 'tests',
signal => [ 'highlight_volume' ],
},
],
signals => [
highlight_volume => [ 'mark', {
graph => 'volumes',
line => 'volume',
key => 'price above envelope',
style => {
point => {
color => [1, 0, 0],
shape => 'circle',
size => 15,
},
},
}],
],
groups => [
main => {
source => 'db',
functions => ['env'],
tests => ['good_vol'],
chart => 'main',
file => 'myfile',
},
],
samples => [
stock1 => {
# Finance::Shares::Sample options
},
],
);
$fsm->output();
Low level control
use Finance::Shares::Model;
use Finance::Shares::MySQL;
use Finance::Shares::Sample;
use Finance::Shares::Bands;
use Finance::Shares::Chart;
use PostScript::File;
my $sql = new Finance::Shares::MySQL(...);
my $psf = new PostScript::File(...);
my $fss = new Finance::Shares::Sample(
source => $sql,
file => $psf,
...
);
my $fsm = new Finance::Shares::Model;
$fsm->add_sample( $fss );
$fsm->add_signal('highlight_volume', 'mark', undef, {
graph => 'volumes',
line => 'volume',
key => 'price above envelope',
style => {
point => {
color => [1, 0, 0],
shape => 'circle',
size => 15,
},
},
});
my ($high, $low) = $fss->envelope( percent => 3 );
$fsm->test(
graph1 => 'prices', line1 => $high,
graph2 => 'prices', line2 => 'high',
test => 'ge',
graph => 'tests',
signal => [ 'highlight_volume' ],
);
my $fsc = new Finance::Shares::Chart(
sample => $fss,
...
);
$fsc->output('myfile');
DESCRIPTION
This module provides the testing enviroment for the Finance::Shares suite. A model brings a group of Finance::Shares::Samples together and applies tests to them all. The tests usually rely on functions from other modules such as Finance::Shares::Averages, and the results are displayed on a Finance::Shares::Chart.
Either the Finance::Shares::Model constructor is passed no options or it is passed details of the whole model.
If the constructor has no options, nothing will happen until add_sample has been called at least once (and add_signals if signals are used in the tests). Tests are applied to all samples, which don't need to have anything in common with each other. However, if the date ranges are completely different it would probably be better to run seperate models. This is because the Model's date range covered by each of the tests is made from all dates in all samples.
Model specification
If the constructor has any options, it is assumed to be the full specification and the model is normally run immediately. This specification can either be coded into a script as constructor options, or it can be a file passed to the script fs_model
. See fs_model for more details. A full list of keys that may be found in the package directory under model/all_options while model/minimal shows what is essential.
The specification consists of eight resources: sources, files, charts, functions, tests, signals, groups and samples. If the name is plural, it should refer to an array holding several named hashes each describing one of them. A singular name indicates the default settings used throughout and given the name 'default'.
Example 1
functions => [
slow => {...},
g => {...},
vol5 => {...},
],
These are part of a list of key/value pairs, so each specification would normally be terminated by a comma.
The key/value pairs are a named group of settings, typically used to constuct an object. The name can be used anywhere else in the model specification; whenever that object needs referred to.
Example 2
files => [
stock1 => { ... },
stock2 => { ... },
],
charts => [
chart1 => {
file => 'stock2',
...
}
],
In an array, the first entry is treated as the default and is used where that resource is not specified.
Example 3
file => {
paper => 'A4',
landscape => 1,
},
Here, the file takes on the name 'default', so would be saved as default.ps.
Notice that the singular resource name must refer to a hash. There is no singular item 'signal' as individual signals are specified as arrays and not hashes.
Sources
A source
entry is anything that can be passed to the Finance::Shares::Sample option of the same name. So this could be one of the following.
- array
-
The array ref should point to quotes data held in sub-arrays.
- string
-
This should be the name of a CSV file holding quotes data.
- hash
-
A hash ref holding options for creating a new Finance::Shares::MySQL object.
- object
-
A Finance::Shares::MySQL object created elsewhere.
There must be at least one source, and the hash ref is probably the most useful. See Finance::Shares::MySQL for full details, but the top level keys that can be used here include:
hostname port
user password
database exchange
start_date end_date
mode tries
Example 4
sources => [
database => {
user => 'me',
password => 'Gu355',
database => 'mystocks',
},
test => 'test_file.csv',
],
Files
Each hash ref holds options for creating a PostScript::File object. It will be created once and any charts using it will be added on a new page.
If the files
(plural) resource has been declared, it contains one or more named hash refs. These key names become the name of the file, with '.ps' appended. Any chart resource using this name as it's file
entry specifies (one of) the layout(s) that will appear there. Each sample using that chart specification is therefore put in that chart's file.
See PostScript::File for full details but these are the more useful sub-hash keys:
paper eps
height width
bottom top
left right
clip_command clipping
dir file
landscape headings
reencode
Example 5
files => [
retail => { ... },
],
samples => [
sample1 => {
symbol => 'TSCO.L',
file => 'retail',
...
},
],
Here the Tesco sample will appear as a page in the file retail.ps.
On the other hand, the specification may be held in a file
(singular) hash. In this case the sample specification holds no file
entry, so every chart will appear in the default file. Where the files
(plural) resource is used, the default will be the first entry in the array (unless another entry has the key name 'default', when it is used instead).
The way to put all samples' charts into the same file is to have only one file, as in the example above (under 'named'). Each sample's chart will find its way there either because it was specified or because it is the default (and it happens to have a name).
Where the default has been declared as a file
(singular) resource hash, it has no explicit name, so will be stored in a file called default.ps.
Charts
These are Finance::Shares::Chart options. It is probably a good idea to pre-define repeated elements (e.g. colours, styles) and use the perl variables as values in the hash or sub-hashes. See Finance::Shares::Chart for full details, but these top level sub-hash keys may be used in a chart resource:
prices volumes
cycles tests
x_axis key
png ghostscript
dots_per_inch reverse
bgnd_outline background
heading_font normal_font
heading
Each graph sub-hash may contain the following keys, as well as 'points' for prices and 'bars' for volumes.
percent show_dates
layout y_axis
When the model is run, three keys are filled internally and should NOT be specified here:
- sample
-
The Finance::Shares::Sample object created from the samples resource is assigned to this.
- file
-
This is specified in the samples resource. Where this is not named explicitly, the default name is assumed. The name should be a key from the files resource. The corresponding PostScript::File object will be assigned in its place.
- page
-
The samples hashes may have a field, 'page' which is assigned here.
Functions
This array ref lists all the functions known to the model. Like the other resources, they may or may not be used. However, unlike the others, the sub-hashes are not all the same format. The only requirement is that they have an additional key, function
which holds the name of the method. However, these keys are common:
graph line
period percent
strict shown
style key
Example 6
functions => {
grad1 => {
function => 'gradient',
period => 1,
style => $fn_style,
},
grad_env => {
function => 'envelope',
percent => 5,
graph => 'cycles',
line => 'grad1',
style => $fn_style,
},
expo => {
function => 'exponential_average',
},
},
Here grad1
is constructed from the Finance::Shares::Momentum method, gradient which uses closing prices by default and puts its results on the cycles graph. The Finance::Shares::Bands method envelope uses this to add lines 5% above and below the grad1 line. Another function expo
uses all default values when evaluating the exponential_average method from Finance::Shares::Averages. $fn_style
would probably be a hash ref holding PostScript::Graph::Style options.
If the function
(singular) version is used, the function defined there takes on the name 'default'.
Tests
See "test" for details of the keys allowed in these named sub-hashes:
graph1 line1
graph2 line2
test signals
shown style
graph key
decay ramp
weight
Example 7
tests => [
high_vol => {
graph1 => 'volumes',
line1 => 'v250000',
test => 'ge',
signal => ['good_vol', 'record'],
graph2 => 'volumes',
line2 => 'volume',
key => 'high volume',
},
],
functions => [
v250000 => {
function => 'value',
graph => 'volumes',
value => 250000,
shown => 0,
},
...
],
This will produce a line on the tests graph in the default style. The software generates keys describing each line, but they can get very long. It is often best to declare your own. See Example 8 for the signal definitions.
The function v250000
uses the value method from Finance::Shares::Sample and is not visible because the signal 'good_vol' will show where it is relevent. There would be no problem giving the same name to different resources, but calling the signal 'good_vol' and the test 'high_vol' makes the example clearer.
If the test
(singular) version is used, the test defined there takes on the name 'default'.
Signals
Only the plural signals
version is available. The named entries are array refs and not hash refs like all the others. They list the parameters for the add_signal method. See "add_signal".
Example 8
signals => [
good_vol => [ 'mark', undef, {
graph => 'volumes',
line => 'volume',
key => 'volume over 250000',
}],
record => [ 'print_values', {
message => '$date: vv between hh and ll',
lines => {
vv => 'volumes::volume',
hh => 'prices::highest price',
ll => 'prices::lowest price',
},
masks => {
vv => '%d',
hh => '%7.2f',
ll => '%7.2f',
},
}],
],
The good_vol
signal rings all volumes above 250000 and record
prints out the volume and price range for that day. It is even more important to provide a key to 'mark' type signals. Using the default keys quickly leads to half the page being taken up with the Key panels.
Like functions, the specifications vary according to the type of signal used - the first entry in the array ref. The second entry may be omitted if it would be undef
. The third is often a hash ref passed to the signal handler, although this may be different for custom signals. See "print_values" for an explanation of the record
signal entries.
Samples
A model may run tests and evaluate functions for several samples. This is where the individual samples are specified, and there must be at least one. The order is significant in that it affects how the charts are added to the file(s). The sub-hash entries include options for creating a Finance::Shares::Sample object:
start_date end_date
symbol dates_by
There are, however, some significant additions.
- source
-
This should be the name of the sources resource to use. That value then becomes the
source
entry for the Finance::Shares::Sample constructor. - file
-
The name of the files resource specifying where the chart will go.
- chart
-
One chart is created per sample, and this should be the name of the charts resource holding the Finance::Shares::Chart constructor options to use.
- page
-
As mentioned under "Charts", it is possible to specify a page identifier for every chart here. Bear in mind, though, that this becomes the PostScript page 'number' and as such should be short and have no embedded spaces. The stock symbol is ideal.
- functions
-
(Note the plural.) This should be an array ref holding the names of all the function lines to be evaluated for the sample. There is no 'default' - omitting this key means no functions are evaluated. The functions will be evaluated in the order they appear.
- tests
-
(Note the plural.) This should be an array ref holding the names of all the tests to be performed on the sample. There is no 'default' - omitting this key means no tests are done. They will be evaluated in the order they appear.
- groups
-
(Note the plural.) If present, this should be an array ref holding names of zero or more groups of settings. The settings are added in the order the group names are given, so later groups can override earlier settings. These can always be overridden by specifying the key directly. Notice that subsequent keys override previous ones, so if two groups both have lists of functions only the second list will be used.
If no 'groups' entry is present, the default group is assumed. To prevent this, set to '[]'.
Although it is possible to specify different dates for each sample, this should be used with care. The date range includes every date needed for every sample and an attempt is made to calculate functions and tests for them all. If there is no reason for the overlap it would be better to run seperate models only differing by stock symbol and price.
As with other resources, sample
(singlular) may be used if only one is required.
Example 9
samples => [
1 => { symbol => MSFT, dates_by => 'weekdays', },
2 => { symbol => MSFT, dates_by => 'weeks', },
3 => { symbol => HPQ, dates_by => 'weekdays', },
],
Note that the sample names are ignored.
It is possible to use sample
(singular) to specify just one sample.
Example 10
sample => {
symbol => 'BSY.L',
start_date => '2002-10-01',
end_date => '2002-12-31',
dates_by => 'days',
functions => [ 'simple3', 'expo20' ],
tests => [ 'simple_above_expo' ],
},
The default source, file and chart entries are assumed.
Groups
To avoid repetition it is possible to name a collection of samples settings which are used together. If a groups (or group) resource exists, the default group will be used in every sample that doesn't have a 'group' entry.
Example 11
groups [
basic => {
file => 'file1',
chart => 'price_only',
start_date => '2002-01-01',
end_date => '2002-12-31',
dates_by => 'weeks',
},
gradient => {
chart => 'inc_cycles',
functions => [qw(simple3 grad1 chan10)],
},
vol_tests => {
chart => 'inc_signals',
functions => [qw(v250000 expo5 expo20)],
tests => [qw(high_vol move_up and)],
},
],
samples [
1 => {
symbol => 'BSY.L',
page => 'BSY',
},
2 => {
symbol => 'BSY.L',
page => 'BSYm',
dates_by => 'months',
groups => [qw(basic gradient)],
},
3 => {
symbol => 'PSON.L',
file => 'file2',
groups => ['vol_tests'],
},
],
Assume the named references are all defined in their appropriate resource arrays. Both BSkyB samples will appear on file1.ps, but only the 'months' chart will have any lines on it. The Pearson sample will use the same dates but the chart using the 'inc_signals' specification will be written to file2.ps.
The tests
The tests currently available are:
gt 1st line moves above 2nd
lt 1st moves below 2nd
ge 1st moves above or touches 2nd
le 1st moves below or touches 2nd
eq 1st touches 2nd
ne 1st doesn't touch 2nd
min Smallest of 1st and 2nd
max Largest of 1st and 2nd
sum 1st + 2nd
diff 1st - 2nd
and Logical 1st AND 2nd
or Logical 1st OR 2nd
not Logical NOT 1st
test Logical value of 1st
Tests produce data lines in the standard format. This means that data, functions and tests can be used interchangeably. Tests can all be shown on any graph (or hidden). Wherever a 'line' is expected, it can be a data, function or test line. I think a circular reference is not possible because of the declaration order, but it would be a Very Bad Thing (TM) so be aware of the possibility.
not and test are unary, only working on the first line given. The line values are converted to digital form, taking one of two values. On the tests graph, these are 0 and the weight given to the test (up to 100). Other graphs have suitable minimum and maximum values depending on the Y axis scale.
test might be considered as not(not(...)). It uses a divide
value to convert the source line to 'on' or 'off'. This can be further conditioned by having this value decay over time. Another use of test is to trigger signals on pseudo-test functions like rising
or undersold
.
All the logical tests (and, or, not and test) can be performed for their signals only if the logical
option is set.
The signals
The results lines are analog in that they can take a range of values. Indeed they can be made to decrease over time. But at any particular time they have a level or state. Signals, on the other hand, are a form of output that is inherently digital - either it has been invoked or it hasn't. All tests can have zero or more signals associated with them which are invoked when some critical change of state happens, like when one line crosses over another. Currently the following signals are available:
mark Places a mark on a graph
mark_buy Draws a blue up arrow
mark_sell Draws a red down arrow
print_values Write function/test values to a file
print Print a message on the console
custom Invoke a user defined callback
CONSTRUCTOR
A model can be specified completely in the option hash given to new(), so the whole process is very simple:
my $fsm = new Finance::Shares::Model(
# model specified here
);
$fsm->output();
The specification format is described in "Recipes".
new( [ options ] )
options
can be a hash ref or a list of hash keys and values. Most of the top level keys are outlined above. However, there are a few others described here which control how the module behaves.
- cgi_file
-
Specify the name of the
file
orfiles
hash to be printed to STDOUT rather than to a file with that name. (Default: 'STDOUT') - directory
-
If the file names are not absolute paths, they will be placed in this directory. (Default: undef)
- show_lines
-
This is provided to assist debugging. Setting this to 1 makes the model print out all the lines it knowns, sample by sample. (Default: 0)
- run
-
Setting this to 0 prevents the constructor from running the model. A model is assumed if there are ANY parameters: if no parameters are given, this defaults to 0, otherwise the default is 1.
- verbose
-
Gives some control over the number of messages sent to STDERR during the process.
0 Only fatal messages 1 Minimal 2 Report each process 3+ Debugging
MAIN METHODS
add_sample( sample )
This adds stock quote data to the model. sample
must be a Finance::Shares::Sample object. The results of the tests are written back to the sample which would typically be displayed on a Finance::Shares::Chart.
Multiple samples can be added. These might be for the same stock sampled over days, weeks and months, or for different stocks and different dates. Bear in mind that all tests are conducted on all dates, so it makes sense to keep the date ranges as similar as possible.
add_signal( id, signal, [ object [, args ]] )
Register a callback function which will be invoked when some test evaluates 'true'.
- id
-
A string identifying the signal. This must be unique.
- signal
-
This must be a known signal name, see "SIGNALS".
- object
-
Use 'undef' here for those signals that need to use the Finance::Shares::Sample, such as 'mark_buy'. When registering print, this is the message to print and when registering a custom function, this is the function reference.
- args
-
Any arguments that will be passed to the signal function.
See the individual signal handling methods for the arguments that signal requires.
test( options )
A test is added to the model and the resulting line added to each Sample. Signals are invoked when a date is encountered that passes the test. Tests may be binary (working on two lines) or unary (just working on one).
The method returns the identifier string for the resulting data line.
options
may be either a list or a hash ref. Either way it should contain parameters passed as key => value pairs, with the following as known keys.
- graph1
-
The graph holding
line1
. Must be one of 'prices', 'volumes', 'cycles' or 'tests'. - line1
-
A string identifying the only line for a unary test or the first line for a binary test.
- graph2
-
The graph holding
line2
. Must be one of 'prices', 'volumes', 'cycles' or 'tests'. Defaults tograph1
. - line2
-
A string identifying the second line for a binary test. For a unary test this must be undefined.
- test
-
The name of the test to be applied, e.g 'gt' or 'lt'. Note this is a string and not a function reference.
- logical
-
[Only logical tests and, or, not and test.] When '1', the results line is not generated. Only useful when signals are triggered and the line is not needed for other tests. (Default: 0)
- shown
-
True if the results should be shown on a graph.
- style
-
If present, this should be either a PostScript::Graph::File object or a hash ref holding options for creating one.
- graph
-
The destination graph, where
line
will be displayed. Must be one of 'prices', 'volumes', 'cycles' or 'tests'.If not specified,
graph1
is used. This is a little odd as the scales are usually meaningless. However, as mostly the result is an on-or-off function, the line is suitably scaled so the shape is clear enough. - key
-
The string which will appear in the Key panel identifying the test results.
- divide
-
[Only for not and test.] This sets the point dividing 'true' from 'false' and should be a value within the range of
line1
values. (Default: 0) - limit
-
[Only for sum and diff.] When 1, the result is clipped within the graphs axes. Setting this to 0 allows the axis to accomodate all the arithmetic results.
- 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.
- signals
-
This should be an array ref holding one or more of the signals registered with this model.
The results line would typically be shown on the 'tests' graph. Most tests are either true or false, so the line is flat by default. The line can be conditioned, however, so its value changes over time. Here are some examples of how the relevant parameters interact.
Example 1
decay => 0.5,
ramp => 0,
An exponential decay, halving with each period.
decay => 0.95,
ramp => 0,
A much shallower decaying curve.
weight => 100,
decay => 1,
ramp => -20,
A straight line decline which disappears after five days.
weight => 100,
decay => 1.983,
ramp => -99,
An inverted curve with the first 5 days scoring more than 85 then dropping rapidly to 0 after 7 days.
output( [psfile,] [filename [, directory]] )
psfile
can either be a PostScript::File object, a hash ref suitable for constructing one or undefined.
The charts are constructed and written out to the PostScript file. A suitable suffix (.ps, .epsi or .epsf) will be appended to filename
.
If no filename is given, the PostScript text is returned. This can then be piped to gs for conversion into other formats, or output directly from a cgi script.
Example 1
my $file = $fsm->output();
The PostScript is returned as a string. The PostScript::File object has been constructed using defaults which produce a landscape A4 page.
Example 2
$fsm->output('myfile');
The default A4 landscape page(s) is/are saved as myfile.ps.
Example 3
my $pf = new PostScript::File(...);
my $file = $fsm->output($pf);
The pages are formatted according to the PostScript::File parameters. The same result would have been obtained had $pf been a hash ref.
Example 4
my $pf = new PostScript::File(...);
$fsm->output($pf, 'shares/myfile', $dir);
The specially tailored page(s) is/are written to $dir/shares/myfile.ps.
Note that it is not possible to print the charts individually once output() has been called. However, it is possible to output them seperately to their own files, then call this to output a file showing them all.
SIGNALS
Before they can be used signals must have been registered with the Model using add_signal. The name must then be given to test as (part of) the signal value.
Most parameters are given when it is registered, but the date and Y value of the signal is also passed to the handler.
mark
A point is drawn on a graph when the test evaluates 'true'. The following parameters may be passed to add_signal within a hash ref.
Example
$fsm->add_signal('note_price', 'mark', undef, {
graph => 'prices',
line => 'high',
});
- graph
-
One of prices, volumes, cycles or tests. If you have specified a particular graph for the test, you probably want to set this to the same.
- value
-
If present, this should be a suitable Y coordinate. No bounds checking is done.
- line
-
The Y coordinate may be obtained from the line identified by this string. By default, the test line value is used.
graph
should be set if this is given. - key
-
Optional string appearing in the Key panel.
- style
-
An optional hash ref containing options for a PostScript::Graph::Style, or a PostScript::Graph::Style object. It should only have a point group defined (line makes no sense). (Default: green circle).
- shown
-
Optional flag, true if the mark is to be shown (Default: 1)
mark_buy
A convenience form of 'mark' providing a blue up arrow as the default style. See the signal "mark" for details.
Example
$fsm->add_signal('buy01', 'mark_buy', undef, {
graph => 'prices',
value => 440,
});
mark_sell
A convenience form of 'mark' providing a red down arrow as the default style. See the signal "mark" for details.
Example
$fsm->add_signal('sell01', 'mark_sell', undef, {
graph => 'prices',
line => 'high',
});
This is the lightweight print signal. See "print_values" for another which can show 'live' values.
It prints a string to STDOUT when the test evaluates 'true'.
Register the signal like this:
$fsm->add_signal('msg1', 'print', 'Some message');
or even
$fsm->add_signal('msg2', 'print');
Note that this is slighty different from all the others - there is no undef
(the object placeholder).
print_values
This is the heavy duty print signal. See "print" for a lighter weight one.
This signal is intended for constructing data files from significant events. There is a message template which can include line identifiers. When the message is output for a particular date, the line values are substituted for their identifiers.
It prints a string to a file or to STDOUT when the test evaluates 'true'. The following parameters may be passed to add_signal within a hash ref.
- message
-
This is the string that is output. It may include
$date
and any number of identifiers, which will be replaced with suitable values. Note thatmessage
should be given in single quotes or with the '$' sign escaped. $date looks like a variable but is just a placeholder for the signal's date. - mask
-
If given this should be a printf format string specifying the format of $value, e.g. '%6.2f'.
- masks
-
If given, this provides a
mask
for each of the line values. In the same format aslines
. - lines
-
If a string or a reference to an array of strings, these are line identifiers, formed by concatenating the graph, '::' and the line key. If a hash ref is given, the line identifiers are the values associated with keys used in
message
. The default line identifiers are as follows, not that spaces are allowed within the string.prices::opening price prices::closing price prices::lowest price prices::highest price volumes::volume
Note that a case insensitive regex match is used to pick out the identifier (or hash key) within
message
. So avoid special characters as the results will not be what you expect.[Future releases may change the graph::user_key identifiers to text identifiers as used in the model specification.]
- file
-
If given, this should be an already open file handle. It defaults to
\*STDOUT
.
Example 1
my $fsm = new Finance::Shares::Model;
$fsm->add_signal('value', 'print_value', undef, {
message => 'Signal is $value at $date',
});
Output the value of the test line.
Example 2
my $fss = Finance::Shares::Sample;
my $avgline = $fss->simple_average(
graph => 'prices',
period => 3,
key => 'simple 3 day average',
);
$fsm->add_signal('note_vol', 'print_value', undef, {
message => '$date: Volume=vv, average=avg',
lines => {
avg => 'prices::simple 3 day average',
vv => 'volumes::volume',
},
});
Show the value of other lines.
Example 3
my $sfile;
open $sfile, '>', 'signals.txt';
$fsm->add_signal('csv', 'print_value', undef, {
message => '$date,open,high,low,close,volume',
lines => {
open => 'prices::opening price',
high => 'prices::highest price',
low => 'prices::lowest price',
close => 'prices::closing price',
volume => 'volumes::volume',
},
masks => {
open => '%6.2f',
high => '%6.2f',
low => '%6.2f',
close => '%6.2f',
volume => '10d',
},
file => $sfile,
});
$fsm->test(
graph1 => 'prices', line1 => 'close',
graph1 => 'prices', line2 => $avgline,
test => 'gt',
signal => 'csv',
);
close $sfile;
Construct a CSV file 'signals.txt' holding quotes for all the dates when the signal fires.
custom
Use this to register your own callbacks which should look like this:
sub custom_func {
my ($id, $date, $value, @args) = @_;
...
}
where the parameters are:
$id The identifier given to add_signal()
$date The date of the signal
$value The value of the test invoking the signal
@args Optional arguments given to add_signal()
You would register your function with a call to add_signal with 'custom' as the signal type:
$fsm->add_signal( 'myFunc', 'custom', \&custom_func,
@args );
Example
my $fss = new Finance::Shares::Sample(...);
my $fsm = new Finance::Shares::Model;
# A comparison line
my $level = $fss->value(
graph => 'volumes', value => 250000
);
# The callback function
sub some_func {
my ($id, $date, $value, @args) = @_;
...
}
# Registering the callback
$fsm->add_signal( 'MySignal', 'custom', \&some_func,
3, 'blind', $mice );
# Do the test which may invoke the callback
$fsm->test(
graph1 => 'volumes', line1 => 'volume',
graph1 => 'volumes', line2 => $level,
test => 'gt',
signal => 'custom',
);
Here &some_func will be be called with a parameter list like this when the volume moves above 250000:
('MySignal', '2002-07-30', 250064, 3, 'blind', $mice)
SUPPORT METHODS
signal( signal [, object [, param ]] )
All callbacks of the type indicated by signal
will be invoked.
- signal
-
This can be either a single signal name, or an array ref containing signal names. Allowed names include:
mark_buy mark_sell print custom
- object
-
An object may be given when the signal was registered with add_signal. But if it was not, this will be the first parameter passed instead.
- param
-
The second parameter passed to the callback function. Any number of arguments may be passed here as an array ref.
Any other registered parameters are passed after param
.
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
Finance::Shares::MySQL, Finance::Shares::Sample, Finance::Shares::Chart.
Most models use functions from one or more of Finance::Shares::Averages, Finance::Shares::Bands and Finance::Shares::Momentum as well.
There is also an introduction, Finance::Shares::Overview and a tutorial beginning with Finance::Shares::Lesson1.