====== Monitoring stock price ======
I wrote a [[#Download|check script]] which will read quote for a specific stock from HKEX and monitor the bid price fluctuation. If the bid price goes beyond the upper or lower threshold, alert can be send.
===== Syntax =====
check_stock_quote.pl -s -w -c
For example, to monitor the price of China Mobile, of stock code 00941:
./check_stock_quote.pl -s 00941 -w 70,80-c 65,85
OK: Current price 76.000 |'Price'=76.000;70.000,80.000;65.000,85.000
===== Configuration =====
To use this script, define a check command and use it in a service:
define command{
command_name check_stock_quote
command_line $USER1$/check_stock_quote.pl -s $ARG1$ -w $ARG2$ -c $ARG3$
}
define service{
...
service_description China Mobile 941
check_command check_stock_quote!00941!70,80!65,85
...
}
===== Use with PNP4Nagios =====
After enable performance processing, edit the auto created xml file at:''/var/log/nagios/rrd/perfdata/example-host/China_Mobile_941.xml''. Change the TEMPLATE to the custom template: **check_stock_quote**:
check_stock_quote
Create template file ''/usr/share/nagios/pnp/templates/check_stock_quote.php'':
#
# Copyright (c) 2006-2008 Joerg Linge (http://www.pnp4nagios.org)
# Plugin: check_nt -v MEMUSE
# $Id: check_nt_mem.php 367 2008-01-23 18:10:31Z pitchfork $
#
# Modified to check stock quote
#
$_my_upper_limit = $ACT[1] * 1.05;
$_my_lower_limit = $ACT[1] * 0.95;
$opt[1] = "-u $_my_upper_limit -l $_my_lower_limit --vertical-label \"Price\" --title \"$servicedesc\" ";
# set graph background color
$opt[1] .= "--color CANVAS#00004F ";
$def[1] = "DEF:var1=$rrdfile:$DS[1]:MAX ";
$def[1] .= "LINE1:var1#00FF00:\"Price\" " ;
$def[1] .= "GPRINT:var1:LAST:\"%6.2lf Last \" " ;
$def[1] .= "GPRINT:var1:AVERAGE:\"%6.2lf Average \" " ;
$def[1] .= "GPRINT:var1:MAX:\"%6.2lf Max \\n\" ";
?>
**Output sample**:
{{:nagios:pnp-stock1.png}}
===== Download =====
#!/usr/bin/perl -w
# Written by Michael Fung
# Last update: 2010-02-09
use strict;
use LWP::Simple;
use Getopt::Long;
use HTML::TableExtract;
# url to fetch the quote:
my $url = "http://www.hkex.com.hk/eng/invest/company/quote_page_e.asp?Month=1&langcode=e&WidCoID=";
# return codes for nagios:
my $OK = 0;
my $WARN = 1;
my $CRIT = 2;
my $UNKNOWN = 3;
# declare other vars:
my $w_low;
my $w_high;
my $c_low;
my $c_high;
my $output = '';
my ( $stock_code, $o_warn, $o_crit, $help );
sub syntax {
my $s;
if ($s = shift) {
printf STDERR ("Error: $s\n") unless ($help);
}
printf STDERR ("Syntax: check_stock_quote.pl -s -w -c \n");
exit(0) if $help;
exit($UNKNOWN);
}
sub end {
my $s = shift;
my $i = shift;
if ($i == $OK) {
$s = "OK: $s";
} elsif ($i == $WARNING) {
$s = "WARNING: $s";
} elsif ($i == $CRITICAL) {
$s = "CRITICAL: $s";
} else {
$s = "UNKNOWN: $s";
}
print "$s\n";
exit($i);
}
Getopt::Long::Configure('bundling');
GetOptions(
"s=s" => \$stock_code, "stock-code=s" => \$stock_code,
"w=s" => \$o_warn,
"c=s" => \$o_crit,
"h" => \$help, "help" => \$help
) || syntax();
# --- syntax checks:
syntax if ($help);
syntax("Missing required parameters.") unless ($stock_code && $o_warn && $o_crit);
($w_low, $w_high) = split(',', $o_warn);
($c_low, $c_high) = split(',', $o_crit);
syntax("Missing required parameters.") unless ($w_low && $w_high && $c_low && $c_high);
# high values must not be smaller than low values
if (($c_high < $c_low) || ($w_high < $w_low)) {
syntax("High values must not be smaller than low values.");
}
# --- fetch the page:
my $html = get($url . $stock_code)
or end("Couldn't fetch the page.",$UNKNOWN);
# find the price
my $te = HTML::TableExtract->new( headers => ["Nominal Price"] );
$te->parse($html);
# find the table with the "Nominal Price" column
my $tb = $te->first_table_found()
or end("Couldn't find the price column.",$UNKNOWN);
my $price = $tb->cell(0,0)
or end("Couldn't extract price data.",$UNKNOWN);
# --- return results:
# "Current price $price |'Price'=$price;$w_low,$w_high;$c_low,$c_high"
$output = sprintf("Current price %.3f |'Price'=%.3f;%.3f,%.3f;%.3f,%.3f", $price,$price,$w_low,$w_high,$c_low,$c_high);
if (($price > $c_high) || ($price < $c_low)) {
end($output, $CRIT);
}
elsif (($price > $w_high) || ($price < $w_low)) {
end($output, $WARN);
}
else {
end($output, $OK);
}