smtm-1.6.10/0000755000232200023220000000000011016367577012762 5ustar pbuilderpbuildersmtm-1.6.10/README0000644000232200023220000001056710671376603013647 0ustar pbuilderpbuilder smtm --- A global stock ticker for X11 and Windoze 1. Introduction smtm, which is a not overly clever acronym for Show Me The Money, is a financial ticker and portfolio application for quotes from exchanges around the world (provided they are carried on Yahoo!). It creates and automatically updates a window with quotes from Yahoo! Finance. It can also display the entire variety of charts available at Yahoo! Finance. When called with one or several symbols, it displays these selected stocks. When smtm is called without arguments, it reads the symbols tickers from a file, by default ~/.smtmrc. This file can be created explicitly by calling the Save option from the File menu. Beyond stocks, smtm can also display currencies (from the Philadephia exchange), US mutual funds, options on US stocks, several precious metals and quite possibly more; see the Yahoo! Finance website for full information. 2. How to get started Built using Perl/Tk it requires at least the following modules Date::Manip Finance::YahooQuote LWP::UserAgent MIME::Base64 HTML::Parser Tk Tk::PNG all of which are readily available for most Unix variants, Linux distributions and the ActiveState Perl implementation common on win*. Debian users just say 'apt-get install smtm'. For others, and following Perl convention, the installation should work as perl Makefile.PL # optionally "perl Makefile.PL verbose" make make test # the tests are somewhat limited make install but I do not test this regularly as I install the Debian packages myself. 3. How to use it 'smtm --help' gives a brief synopis, 'perldoc smtm' shows the full manual page. Several options are available and can be set from both a resource file ~/.smtmrc, the command-line and the menus once smtm is running. Additional resource files, e.g. for additional portfolios, are available in the examples/ directory of the source distribution. But the simplest case is possibly to just supply ticker symbols on the command-line: 'smtm DELL IBM MSFT'. 4. Disclaimer (taken straight from the GPL) NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. In short: if it breaks, you can keep the pieces. This is Free Software, use it as you see fit, but don't come running or screaming if it doesn't work as intended. 5. Copyright Copyright (C) 1999 - 2007 Dirk Eddelbuettel This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. smtm-1.6.10/smtm0000755000232200023220000021432011016366272013661 0ustar pbuilderpbuilder#!/usr/bin/perl -w # # smtm --- A global stock ticker for X11 and Windoze # # Copyright (C) 1999 - 2008 Dirk Eddelbuettel # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # $Id: smtm.pl,v 1.122 2008/05/25 22:44:35 edd Exp $ use strict; # be careful out there, my friend use English; # explicit variable names #use Data::Dumper; # FIXME use Date::Manip; # for date calculations use File::Spec; # portable filename operations use Finance::YahooQuote; # fetch quotes from Yahoo! use Getopt::Long; # parse command-line arguments use HTTP::Request::Common; # still needed to get charts use IO::File; # needed for new_tmpfile or Tk complains use POSIX qw(strftime); # strftime function use MIME::Base64; # to encode graphics directly for Photo widget use Text::ParseWords; # parse .csv files more reliably use Tk; # who needs gates in a world full o'windows? use Tk::Balloon; # widget for context-sensitive help use Tk::FileSelect; # widget for selecting files use Tk::PNG; # as of May 2005, Yahoo! send png charts use vars qw{%options %chart}; # need to define here for SUB {} below my # seperate for Makefile.PL $VERSION = "1.6.10"; # updated from the debian/rules Makefile my $date = # inner expression updated by RCS sprintf("%s", q$Date: 2008/05/25 22:44:35 $ =~ /\w*: (\d*\/\d*\/\d*)/); my (@Labels, # labels which carry the stock info @Buttons, # buttons which contain the labels, $BFrame, # frame containing the buttons $BFont, # font used for display on buttons + details $Header, # frame for column headings $headertext, # string for column headings display %coldisp, # hash of selected columns %Dat); # hash of hashes and lists for global data my $Main = new MainWindow; # create main window if ($OSNAME =~ m/MSWin32/) { # branch out for OS $Main->setPalette("gray95"); # light gray background $BFont = $Main->fontCreate(-family => 'courier', -size => 8); $ENV{HOME} = "C:/TEMP" unless $ENV{HOME}; $ENV{TZ} = "GMT" unless $ENV{TZ}; # Date::Time needs timezone info } else { # $BFont = $Main->fontCreate(-family => 'lucidasanstypewriter', -size => 10); $BFont = $Main->fontCreate(-family => 'fixed', -size => 10); # $BFont = $Main->fontCreate(-family => 'courier', -size => 10); } # general options for user interface and behaviour, sort-of ugly global $options{file} = File::Spec->catfile($ENV{HOME}, ".smtmrc"); #default rc file $options{sort} = 'n'; # sort by name $options{timeout} = 180; # default timeout used in LWP code $options{columns} = 'nrla'; # default colums: name,last, rel.chg, abs. chg $options{percent} = 0; # default to percentage display, not bps $options{paused} = 0; # default to not paused, i.e. update $options{delay} = 5; # wait this many minutes ($options{firewall}, $options{proxy}, $options{wide}) = (undef,undef,undef); # global hash for chart options $chart{length} = '1'; # one-year chart is default chart $chart{log_scale} = 1; # plot on logarithmic scale $chart{volume} = 1; # show volume on seperate pane $chart{size} = 'm'; # plot size, default small (m medium, l large) $chart{style} = 'l'; # plot type, line ('c' candle, 'b' for bar) $chart{ma} = (); # placeholder hash for mov.avg. options $chart{ema} = (); # placeholder hash for exp.mov.avg. options $chart{technical} = (); # placeholder hash for tech. analysis options $chart{bollinger} = 0; # show bollinger bands $chart{parabolic_sar} = 0; # show parabolic sar $chart{comparison} = ""; # compare to this symbol (eg stock) my $today = ParseDate("today"); # current time, date for return calculations my $symbolcounter = 0; # needed for several pos. in same stock my %commandline_options = ("file=s" => \$options{file}, "time=i" => \$options{delay}, "fwall:s" => \$options{firewall}, "proxy=s" => \$options{proxy}, "wide" => \$options{wide}, "percent" => \$options{percent}, "columns=s" => \$options{columns}, "sort=s" => \$options{sort}, "nookbutton"=> \$options{nookbutton}, "timeout=i" => \$options{timeout}, "chart=s" => \$chart{length}, "gallery" => \$options{gallery}, "verbose" => \$options{verbose}, "help" => \$options{help}); # exit with helpful message if unknown command-line option, or help request help_exit() if (!GetOptions(%commandline_options) or $options{help}); if ($#ARGV==-1) { # if no argument given if (-f $options{file}) { # if file exists read_config(); # load from file init_data(undef); # this indirectly calls buttons() } else { # else use default penguin portfolio warn("No arguments given, and no file found. Using example portfolio.\n"); init_data(("RY.TO::50::48:20000104", "C::50:USDCAD:50.50:20000103", "DBK.DE::50:EURCAD:86.5:20010102", "HSBA.L::50:GBPCAD:967.02:20010101")) } } else { # else init_data(@ARGV); # use the given arguments } MainLoop; # and launch event loop under X11 #----- Functions ------------------------------------------------------------ sub menus { # create the menus # copy selected colums from string into hash for my $i (0..length($options{columns})-1) { $coldisp{substr($options{columns}, $i, 1)} = 1; } $Main->optionAdd("*tearOff", "false"); my $MF = $Main->Frame()->pack(-side => 'top', -anchor => 'n', -expand => 1, -fill => 'x'); my @M; $M[0] = $MF->Menubutton(-text => 'File', -underline => 0, )->pack(-side => 'left'); $M[0]->AddItems(["command"=> "~Open", -command => \&select_file_and_open], ["command"=> "~Save", -command => \&file_save], ["command"=> "Save ~As",-command => \&select_file_and_save], ["command"=> "E~xit", -command => sub { exit }]); $M[1] = $MF->Menubutton(-text => 'Edit', -underline => 0, )->pack(-side => 'left'); $M[1]->AddItems(["command" => "~Add Stock", -command => \&add_stock]); $M[1]->AddItems(["command" => "~Delete Stock(s)", -command => \&del_stock]); my $CasX = $M[1]->cascade(-label => '~Columns'); my %colbutton_text = ('s' => '~Symbol', 'n' => '~Name', 'l' => '~Last Price', 'a' => '~Absolute Change', 'r' => '~Relative Change', 'V' => '~Volume traded', 'p' => 'Position ~Change', 'v' => '~Position Value', 'h' => '~Holding Period', 'R' => 'Annual Re~turn', 'd' => '~Drawdown', 'e' => '~Earnings per Share', 'P' => 'P~rice Earnings Ratio', 'D' => 'Di~vidend Yield', 'm' => '~Market Captialization', 'f' => '~FilePosition' ); foreach (qw/s n l a r V p v h R d e P D m f/) { $CasX->checkbutton(-label => $colbutton_text{$ARG}, -variable => \$coldisp{$ARG}, -command => \&update_display); } my $CasS = $M[1]->cascade(-label => '~Sort'); my %sortbutton_text = ('n' => '~Name', 'r' => '~Relative Change', 'a' => '~Absolute Change', 'p' => 'Position ~Change', 'v' => '~Position Value', 'V' => '~Volume Traded', 'h' => '~Holding Period', 'R' => 'Annual Re~turn', 'd' => '~Drawdown', 'e' => '~Earnings per Share', 'P' => 'P~rice Earnings Ratio', 'D' => 'Di~vidend Yield', 'm' => '~Market Captialization', 'f' => '~FilePosition'); foreach (qw/n r a p v V h R d e P D m f/) { $CasS->radiobutton(-label => $sortbutton_text{$ARG}, -command => \&update_display, -variable => \$options{sort}, -value => $ARG); } $M[1]->AddItems(["command" => "Change ~Update Delay", -command => \&chg_delay]); $M[1]->AddItems(["command" => "Update ~Now", -command => \&update_display_variables]); $M[1]->checkbutton(-label => "~Wide window title", -variable => \$options{wide}, -command => \&update_display); $M[1]->checkbutton(-label => "~Percent instead of bps", -variable => \$options{percent}, -command => \&update_display); $M[1]->checkbutton(-label => "Susp~end updates", -variable => \$options{paused}); $M[2] = $MF->Menubutton(-text => 'Charts', -underline => 0, )->pack(-side => 'left'); my $CasC = $M[2]->cascade(-label => "~Timeframe"); my %radiobutton_text = ('t' => 'Weekly Thumbnail', 'b' => '~Intraday', 'w' => '~Weekly', '3' => '~Three months', '6' => '~Six months', '1' => '~One year', '2' => 'Two ~years', '5' => '~Five years', 'm' => '~Max years'); foreach (qw/t b w 3 6 1 2 5 m/) { $CasC->radiobutton(-label => $radiobutton_text{$ARG}, -variable => \$chart{length}, -value => $ARG); } my $CasPS = $M[2]->cascade(-label => "Plot ~Size"); my %radiobutton_ps = ('s' => '~Small', 'm' => '~Medium', 'l' => '~Large'); foreach (qw/s m l/) { $CasPS->radiobutton(-label => $radiobutton_ps{$ARG}, -variable => \$chart{size}, -value => $ARG); } my $CasPT = $M[2]->cascade(-label => "Plot T~ype"); my %radiobutton_pt = ('l' => '~Line chart', 'b' => '~Bar chart', 'c' => '~Candle chart'); foreach (qw/l b c/) { $CasPT->radiobutton(-label => $radiobutton_pt{$ARG}, -variable => \$chart{style}, -value => $ARG); } my $CasMA = $M[2]->cascade(-label => '~Moving Averages'); my %mabutton_text = ('5' => '5 days', '10' => '10 days', '20' => '20 days', '50' => '50 days', '100' => '100 days', '200' => '200 days'); foreach (qw/5 10 20 50 100 200/) { $CasMA->checkbutton(-label => $mabutton_text{$ARG}, -variable => \$chart{ma}{$ARG}); } my $CasEMA = $M[2]->cascade(-label => '~Exp. Moving Avg.'); foreach (qw/5 10 20 50 100 200/) { $CasEMA->checkbutton(-label => $mabutton_text{$ARG}, -variable => \$chart{ema}{$ARG}); } my $CasTA = $M[2]->cascade(-label => 'Te~chnical Analysis'); # see http://help.yahoo.com/help/us/fin/chart/chart-12.html my %ta_text = ('m26_12_9' => 'MACD (MA Conv./Divergence)', 'f14' => 'MFI (Money Flow)', 'p12' => 'ROC (Rate of Change)', 'r14' => 'RSI (Relative Strength Index)', 'ss' => 'Stochastic (slow)', 'fs' => 'Stochastic (fast)', 'w14' => 'Williams %R'); foreach (sort {$ta_text{$a} cmp $ta_text{$b}} keys %ta_text) { $CasTA->checkbutton(-label => $ta_text{$ARG}, -variable => \$chart{technical}{$ARG}); } $M[2]->checkbutton(-label => "~Logarithmic scale", -variable => \$chart{log_scale}); $M[2]->checkbutton(-label => "~Volume and its MA", -variable => \$chart{volume}); $M[2]->checkbutton(-label => "~Bollinger Bands", -variable => \$chart{bollinger}); $M[2]->checkbutton(-label => "~Parabolic SAR", -variable => \$chart{parabolic_sar}); $M[2]->AddItems(["command" => "Enter ~Comparison Symbol(s)", -command => \&get_comparison_symbol]); $M[2]->checkbutton(-label => "Chart ~Gallery", -variable => \$options{gallery}, -command => \&show_gallery); $M[3] = $MF->Menubutton(-text => 'Help', -underline => 0, )->pack(-side => 'right'); $M[3]->AddItems(["command" => "~Manual", -command => \&help_about]); $M[3]->AddItems(["command" => "~License", -command => \&help_license]); $Main->configure(-title => "smtm"); # this will be overridden later $Main->resizable(0,0); # don't allow width or height resizing $Main->iconname("smtm"); } sub buttons { # create all display buttons @{$Dat{NA}} = sort @{$Dat{Arg}}; $Main->resizable(1,1); $BFrame->destroy() if Tk::Exists($BFrame); $BFrame = $Main->Frame()->pack(-side=>'top', -fill=>'x'); $BFrame->Label->repeat($options{delay}*1000*60, \&update_display_variables); $Header->destroy() if Tk::Exists($Header); $Header = $BFrame->Label(-anchor => 'w', -font => $BFont, -borderwidth => 3, -relief => 'groove', -textvariable => \$headertext, )->pack(-side => 'top', -fill => 'x'); my $balloon = $BFrame->Balloon(); foreach (0..$#{$Dat{Arg}}) { # set up the buttons $Buttons[$ARG]->destroy() if Tk::Exists($Buttons[$ARG]); $Buttons[$ARG] = $BFrame->Button(-command => [\&show_details, $ARG], -font => $BFont, -relief => 'flat', -borderwidth => -4, -textvariable => \$Labels[$ARG] )->pack(-side => 'top', -fill => 'x'); $Buttons[$ARG]->bind("", [\&edit_stock, $ARG]); $Buttons[$ARG]->bind("", [\&view_image, $ARG]); $balloon->attach($Buttons[$ARG], -balloonmsg => "Mouse-1 for details, " . "Mouse-2 to edit, ". "Mouse-3 for chart"); } $Main->resizable(0,0); # are we dealing with firewalls, and do we need to get the info ? if (defined($options{firewall}) and ($options{firewall} eq "" or $options{firewall} !~ m/.*:.*/)) { get_firewall_id(); # need to get firewall account + password } else { update_display_variables(); # else populate those buttons } } sub sort_func { # sort shares for display my @a = split /;/, $a; my @b = split /;/, $b; if ($options{sort} eq 'r') { # do we sort by returns (relative change) my $achg = $Dat{Bps}{$a[0]} || 0; my $bchg = $Dat{Bps}{$b[0]} || 0; if (defined($achg) and defined($bchg)) { return $bchg <=> $achg # apply descending (!!) numerical comparison || $a[1] cmp $b[1] # with textual sort on names to break ties } else { return $a[1] cmp $b[1]; # or default to textual sort on names } } elsif ($options{sort} eq 'a') { # do we sort by absolute change return $b[5] <=> $a[5] || $a[1] cmp $b[1] # or default to textual sort on names } elsif ($options{sort} eq 'p') { # do we sort by profit/loss amount return $Dat{PLContr}{$b[0]} <=> $Dat{PLContr}{$a[0]} || $a[1] cmp $b[1] # or default to textual sort on names } elsif ($options{sort} eq 'v') { # do we sort by profit/loss amount return $Dat{Value}{$b[0]} <=> $Dat{Value}{$a[0]} || $a[1] cmp $b[1] # or default to textual sort on names } elsif ($options{sort} eq 'V') { # do we sort by volume traded return $b[7] <=> $a[7] || $a[1] cmp $b[1] # or default to textual sort on names } elsif ($options{sort} eq 'h') { # do we sort by days held return $Dat{DaysHeld}{$b[0]} <=> $Dat{DaysHeld}{$a[0]} || $a[1] cmp $b[1] # or default to textual sort on names } elsif ($options{sort} eq 'R') { # do we sort by annual return return $Dat{Return}{$b[0]} <=> $Dat{Return}{$a[0]} || $a[1] cmp $b[1] # or default to textual sort on names } elsif ($options{sort} eq 'd') { # sort by drawdown my $a = defined($Dat{Drawdown}{$a[0]}) ? $Dat{Drawdown}{$a[0]} : 0; my $b = defined($Dat{Drawdown}{$b[0]}) ? $Dat{Drawdown}{$b[0]} : 0; return $b <=> $a || $a[1] cmp $b[1] # or default to textual sort on names } elsif ($options{sort} eq 'e') { return $Dat{EPS}{$b[0]} <=> $Dat{EPS}{$a[0]} || $a[1] cmp $b[1] # or default to textual sort on names } elsif ($options{sort} eq 'P') { return $Dat{PE}{$b[0]} <=> $Dat{PE}{$a[0]} || $a[1] cmp $b[1] # or default to textual sort on names } elsif ($options{sort} eq 'D') { return $Dat{DivYield}{$b[0]} <=> $Dat{DivYield}{$a[0]} || $a[1] cmp $b[1] # or default to textual sort on names } elsif ($options{sort} eq 'm') { my $a = $Dat{MarketCap}{$a[0]} ne "N/A" ? $Dat{MarketCap}{$a[0]} : 0; my $b = $Dat{MarketCap}{$b[0]} ne "N/A" ? $Dat{MarketCap}{$b[0]} : 0; return $b <=> $a || $a[1] cmp $b[1] # or default to textual sort on names } elsif ($options{sort} eq 'f') { # ordered by file position return $Dat{ID}{$a[0]} <=> $Dat{ID}{$b[0]} } else { # alphabetical sort return $a[1] cmp $b[1]; } } sub update_display_variables { # gather data, and update display strings if (not $options{paused}) { update_data(); # fetch the data from the public servers compute_positions(); # update position hashes update_display(); # and update the ticker display show_gallery() if $options{gallery}; } } sub update_data { # gather data from Yahoo! servers $today = ParseDate("today"); # current time and date for return calculations my $count = 0; # count 'defined' elements in Dat{FXarr} foreach my $val ($Dat{FXarr}) { $count++ if defined($val)}; if ($count > 0) { # if there are cross-currencies my $array = getquote(@{$Dat{FXarr}}); # get FX crosses foreach my $ra (@$array) { next unless $ra->[0]; $ra->[0] =~ s/\=X//; # reduce back to pure cross symbol $Dat{FX}{uc $ra->[0]} = $ra->[2]; # and store value in FX hash } } undef $Dat{Data}; # NA: name,symbol,price,last date (m/d/y),time,change,percent,volume,avg vol, # bid, ask, previous,open,day range,52 week range,eps,p/e, # div pay date,annual div amt, divyld, cap if (scalar(@{$Dat{NA}})>-1) { # if there are stocks for Yahoo! North America fill_with_dummies(@{$Dat{NA}}); ## call just as the symbol, i.e. without the number key past ':' my @syms = map { (split(/:/, $ARG))[0]} @{$Dat{NA}}; my $array = getquote(@syms); # get North American quotes my $i=0; foreach my $ra (@$array) { $ra->[0] = @{$Dat{NA}}[$i++]; # store with supplied symbol + key $Dat{Data}{uc $ra->[0]} = join(";", @$ra); # store all info } } } # As getquote() may return empty, we have to intialize the %Dat hash # so that later queries don't hit a void sub fill_with_dummies { my (@arr) = @_; foreach $ARG (@arr) { $Dat{Data}{uc $ARG} = join(";", (uc $ARG, "-- N/A --", 0, "1/1/1970", "00:00", 0, "0.00%", 0, "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-")); } } # Use the name supplied from Yahoo!, unless there is a user-supplied # GivenName in the rc file. In case we have data problems, return N/A sub get_pretty_name { my ($pretty, $default) = @_; if (not defined($pretty) or $pretty eq "" or $default eq "-- N/A --") { return $default; } else { return $pretty; } } sub compute_positions { undef %{$Dat{Price}}; undef %{$Dat{Change}}; undef %{$Dat{Bps}}; undef %{$Dat{PLContr}}; undef %{$Dat{Value}}; undef %{$Dat{Volume}}; undef %{$Dat{Return}}; undef %{$Dat{DaysHeld}}; # We have to loop through once to compute all column entries, and to store # them so that we can find the largest each to compute optimal col. width foreach (values %{$Dat{Data}}) { my @arr = split (';', $ARG); my $symbol = uc $arr[0]; $Dat{Name}{$symbol} = $arr[1] || "-- No connection"; $Dat{Price}{$symbol} = $arr[2] || 0; $Dat{Change}{$symbol} = $arr[5] || 0; $Dat{Change}{$symbol} = 0 if $Dat{Change}{$symbol} eq "N/A"; my $pc = $arr[6] || "0.00%"; $pc =~ s/\%//; # extract percent change $pc = 0 if $pc eq "N/A"; my $fx = $Dat{FX}{ $Dat{Cross}{$symbol} } || 1; my $shares = $Dat{Shares}{$symbol} || 0; $Dat{Bps}{$symbol} = 100*$pc * ($shares < 0 ? -1 : 1); my $plcontr = $shares * $Dat{Change}{$symbol} * $fx; $Dat{PLContr}{$symbol} = $plcontr; my $value = $shares * $Dat{Price}{$symbol} * $fx; $Dat{Value}{$symbol} = $value; $Dat{Volume}{$symbol} = $arr[7] || 0; ($Dat{YearLow}{$symbol}, $Dat{YearHigh}{$symbol}) = (undef, undef); ($Dat{YearLow}{$symbol}, $Dat{YearHigh}{$symbol}) = split / - /, $arr[14]; if (defined($Dat{YearHigh}{$symbol}) and $Dat{YearHigh}{$symbol} ne "N/A" and $Dat{YearHigh}{$symbol} != 0) { $Dat{Drawdown}{$symbol} = 100.0*($Dat{Price}{$symbol}/$Dat{YearHigh}{$symbol}-1.0); } else { $Dat{Drawdown}{$symbol} = undef; } if ($Dat{PurchPrice}{$symbol} and $Dat{PurchDate}{$symbol}) { $Dat{DaysHeld}{$symbol} = Delta_Format(DateCalc($Dat{PurchDate}{$symbol}, $today, undef, 2), 0, "%dt"); if ( $Dat{DaysHeld}{$symbol} > 365 ) { $Dat{Return}{$symbol} = ($Dat{Price}{$symbol} / $Dat{PurchPrice}{$symbol} - 1) * 100 * 365 / $Dat{DaysHeld}{$symbol} * ($shares < 0 ? -1 : 1); } else { # don't annualize $Dat{Return}{$symbol} = ($Dat{Price}{$symbol} / $Dat{PurchPrice}{$symbol} - 1) * 100 * ($shares < 0 ? -1 : 1); } } else { $Dat{DaysHeld}{$symbol} = undef; $Dat{Return}{$symbol} = undef; } $Dat{EPS}{$symbol} = $arr[15] || 0; $Dat{PE}{$symbol} = $arr[16] || 0; $Dat{DivDate}{$symbol} = $arr[17] || 0; $Dat{DivAmount}{$symbol} = $arr[18] || 0; $Dat{DivYield}{$symbol} = $arr[19] || 0; $Dat{MarketCap}{$symbol} = "N/A"; # default to NA if (defined($arr[20]) and # need to regularise oddball market string $arr[20] ne "N/A") { # before the dot, the dot, first decimal, remaining decimal, units my ($pre,$p1,$p2,$s) = ($arr[20] =~ m/(\d*)\.(\d)(\d*)(B|M|K)$/); #print "$arr[20] -> $pre DOT $p1 $p2 $s\n"; $Dat{MarketCap}{$symbol} = "$pre" . "." . $p1 . $s if defined($p1) and defined($s); } foreach ("EPS","PE", "DivYield") { $Dat{$ARG}{$symbol} = 0 if $Dat{$ARG}{$symbol} eq "N/A"; } } } sub update_display { my $pl = 0; # profit/loss counter my $nw = 0; # networth counter my $shares = 0; # net shares positions my $max_sym = 0; foreach my $key (keys %{$Dat{Symbol}}) { $max_sym = length($key) if (length($key) > $max_sym); } my $max_len = 0; foreach my $key (keys %{$Dat{Name}}) { my $txt = get_pretty_name($Dat{GivenName}{$key}, $Dat{Name}{$key}) || "-- No connection"; $txt =~ s/\s*$//; # eat trailing white space, if any my $len = length($txt) > 16 ? 16 : length($txt); $max_len = $len if ($len > $max_len); } my $max_price = 0; foreach my $val (values %{$Dat{Price}}) { $max_price = $val if ($val > $max_price); } my $max_change = 0.01; # can't take log of zero below my $min_change = 0.01; foreach my $val (values %{$Dat{Change}}) { $max_change = $val if ($val > $max_change); $min_change = $val if ($val < $min_change); } my $max_bps = 1; # can't take log of zero below my $min_bps = 1; foreach my $val (values %{$Dat{Bps}}) { $max_bps = $val if ($val > $max_bps); $min_bps = $val if ($val < $min_bps); } my $max_plc = 1; # can't take log of zero below my $min_plc = 1; foreach my $val (values %{$Dat{PLContr}}) { $max_plc = $val if ($val > $max_plc); $min_plc = $val if ($val < $min_plc); } my $max_value = 1; # can't take log of zero below foreach my $val (values %{$Dat{Value}}) { $max_value = $val if ($val > $max_value); } my $max_volume = 1; # can't take log of zero below foreach my $val (values %{$Dat{Volume}}) { $max_volume = $val if (($val ne "N/A") and ($val > $max_volume)); } my $max_held = 0; # foreach my $val (values %{$Dat{DaysHeld}}) { $max_held = $val if (defined($val) and $val > $max_held); } my $max_ret = 0; # my $min_ret = 0; # foreach my $val (values %{$Dat{Return}}) { $max_ret = $val if (defined($val) and $val > $max_ret); $min_ret = $val if (defined($val) and $val < $min_ret); } my $max_ddown = 0; foreach my $val (values %{$Dat{Drawdown}}) { $max_ddown = $val if (defined($val) and $val < $max_ddown); } my $max_eps = 0; my $min_eps = 0; # foreach my $val (values %{$Dat{EPS}}) { $max_eps = $val if (defined($val) and $val ne "-" and $val ne "N/A" and $val > $max_eps); $min_eps = $val if (defined($val) and $val ne "-" and $val ne "N/A" and $val < $min_eps); } my $max_pe = 0; foreach my $val (values %{$Dat{PE}}) { $max_pe = $val if (defined($val) and $val ne "-" and $val ne "N/A" and $val > $max_pe); } my $max_divyld = 0; foreach my $val (values %{$Dat{DivYield}}) { $max_divyld = $val if (defined($val) and $val ne "-" and $val ne "N/A" and $val > $max_divyld); } my $max_mktcap = 0; foreach my $val (values %{$Dat{MarketCap}}) { my $nval = $val; $nval =~ s/(B|M|K)$//; $max_mktcap = $nval if (defined($nval) and $nval ne "N/A" and $nval ne "-" and $nval > $max_mktcap); } my $max_fpos = 0; foreach my $val (values %{$Dat{ID}}) { $max_fpos = $val if (defined($val) and $val > $max_fpos); } # transform as necessary $max_price = 3 + digits($max_price); # dot and two digits $max_change = 3 + max(digits($max_change), digits($min_change)); $max_bps = max(3+$options{percent}, max(digits($max_bps),digits($min_bps))); $max_plc = max(3, max(digits($max_plc),digits($min_plc))); $max_value = max(3, digits($max_value)); $max_volume = digits($max_volume); $max_ret = 2 + max(digits($max_ret),digits($min_ret)); $max_held = max(3, digits($max_held)); $max_ddown = 2 + max(2, 1+digits(-$max_ddown)); # 1 decimals,dot,minus,digitb $max_eps = 2 + max(digits($max_eps),digits($min_eps)); $max_pe = 2 + digits($max_pe); $max_divyld = 2 + digits($max_divyld); $max_mktcap = 3 + digits($max_mktcap); $max_fpos = max(2, digits($max_fpos)); $headertext = ""; $headertext .= "Sym " . " " x ($max_sym-3) if $coldisp{s}; $headertext .= "Name " . " " x ($max_len-4) if $coldisp{n}; # $headertext .= " "; # transition from leftflush to rightflush $headertext .= " " x ($max_price-4) . "Last " if $coldisp{l}; $headertext .= " " x ($max_change-3) . "Chg " if $coldisp{a}; $headertext .= " " x ($max_bps-4) . "%Chg " if $coldisp{r} and $options{percent}; $headertext .= " " x ($max_bps-3) . "Bps " if $coldisp{r} and not $options{percent}; $headertext .= " " x ($max_volume-3) . "Vol " if $coldisp{V}; $headertext .= " " x ($max_plc-3) . "P/L " if $coldisp{p}; $headertext .= " " x ($max_value-3) . "Net " if $coldisp{v}; $headertext .= " " x ($max_held-3) . "Len " if $coldisp{h}; $headertext .= " " x ($max_ret-3) . "Ret " if $coldisp{R}; $headertext .= " " x ($max_ddown - 4) . "Ddwn " if $coldisp{d}; $headertext .= " " x ($max_eps - 3) . "EPS " if $coldisp{e}; $headertext .= " " x ($max_pe - 2) . "PE " if $coldisp{P}; $headertext .= " " x ($max_divyld - 3) . "Yld " if $coldisp{D}; $headertext .= " " x ($max_mktcap - 3) . "Cap " if $coldisp{m}; $headertext .= "FP " if $coldisp{f}; chop $headertext; # get trailing ' ' print "$headertext\n" if $options{verbose}; # Now apply all that information to the display my $i = 0; foreach (sort sort_func values %{$Dat{Data}}) { my @arr = split (';', $ARG); my $symbol = uc $arr[0]; my $name = get_pretty_name($Dat{GivenName}{$symbol}, $Dat{Name}{$symbol}) || "-- No connection"; if (not defined $Dat{Bps}{$symbol}) { $Buttons[$i]->configure(-foreground => 'white', -activeforeground => 'white'); } elsif ($Dat{Bps}{$symbol} < 0) { # if we're losing money on this one $Buttons[$i]->configure(-foreground => 'red', -activeforeground => 'red'); } else { $Buttons[$i]->configure(-foreground => 'black', -activeforeground => 'black'); } $Labels[$i] = ""; $Labels[$i] .= sprintf("%*s ", -$max_sym, $Dat{Symbol}{$symbol}) if $coldisp{s}; $Labels[$i] .= sprintf("%*s ", -$max_len, substr($name,0,$max_len)) if $coldisp{n}; $Labels[$i] .= sprintf("%$max_price.2f ", $Dat{Price}{$symbol}) if $coldisp{l}; $Labels[$i] .= sprintf("%$max_change.2f ", $Dat{Change}{$symbol}) if $coldisp{a}; $Labels[$i] .= sprintf("%$max_bps.0f ", $Dat{Bps}{$symbol}) if $coldisp{r} and not $options{percent}; $Labels[$i] .= sprintf("%" . ($max_bps + 1) . ".2f ", ($Dat{Bps}{$symbol}) / 100) if $coldisp{r} and $options{percent}; $Labels[$i] .= sprintf("%$max_volume.0d ", ($Dat{Volume}{$symbol} ne "N/A" ? $Dat{Volume}{$symbol} : 0)) if $coldisp{V}; $Labels[$i] .= sprintf("%$max_plc.0f ", $Dat{PLContr}{$symbol}) if $coldisp{p}; $Labels[$i] .= sprintf("%$max_value.0f ", $Dat{Value}{$symbol}) if $coldisp{v}; if ($coldisp{h}) { if (defined($Dat{DaysHeld}{$symbol})) { $Labels[$i] .= sprintf("%$max_held.0f ", $Dat{DaysHeld}{$symbol}); } else { $Labels[$i] .= sprintf("%*s ", $max_held, "NA"); } } if ($coldisp{R}) { if (defined($Dat{Return}{$symbol})) { $Labels[$i] .= sprintf("%$max_ret.1f ", $Dat{Return}{$symbol}); } else { $Labels[$i] .= sprintf("%*s ", $max_ret, "NA"); } } if ($coldisp{d}) { # drawdown if (defined($Dat{Drawdown}{$symbol})) { $Labels[$i] .= sprintf("%$max_ddown.1f ", $Dat{Drawdown}{$symbol}); } else { $Labels[$i] .= sprintf("%*s ", $max_ddown, "NA"); } } $Labels[$i] .= sprintf("%$max_eps.1f ", $Dat{EPS}{$symbol}) if $coldisp{e}; $Labels[$i] .= sprintf("%$max_pe.1f ", $Dat{PE}{$symbol}) if $coldisp{P}; $Labels[$i] .= sprintf("%$max_divyld.1f ", $Dat{DivYield}{$symbol}) if $coldisp{D}; if ($coldisp{m}) { if ($Dat{MarketCap}{$symbol} ne "N/A") { $Labels[$i] .= sprintf("%*s ", $max_mktcap, $Dat{MarketCap}{$symbol}); } else { $Labels[$i] .= sprintf("%*s ", $max_mktcap, "NA"); } } $Labels[$i] .= sprintf("%$max_fpos.0f ", $Dat{ID}{$symbol}) if $coldisp{f}; chop $Labels[$i]; print "$Labels[$i]\n" if $options{verbose}; $nw += $Dat{Value}{$symbol}; $pl += $Dat{PLContr}{$symbol}; $Dat{Map}[$i++] = $symbol; } my $bps = $nw - $pl != 0 ? 100*100*($pl/($nw-$pl)) : 0; my $txt = ($options{percent} ? sprintf("%.2f%%", $bps / 100) : sprintf("%.0f Bps", $bps)) . " at " . POSIX::strftime("%H:%M", localtime); $txt = $txt . sprintf(" p/l %.0f net %.0f", $pl, $nw) if ($options{wide}); $Main->configure(-title => $txt); $Main->iconname($txt); # also set the icon name } sub digits { # calculate nb of digits sprintf will need my $x = shift; my $count = 0; $count = $x =~ s/[BKM]$//; # rounded(log10(0.5) gives 0 even though this has 1 leading decimal $x *= 10 if (abs($x) > 0 and abs($x) < 1); $x *= 10 if ($x<0); # add one for minus sign $x = abs($x) if ($x < 0); # need absolute value of neg. values if ($x != 0) { return int(log($x)/log(10)+1) + $count;# this gives the rounded log10 of x } else { return 1; } } sub max { my ($a,$b) = @_; $a > $b ? return $a : $b; } sub show_details { # display per-share details my $key = shift; my $TL = $Main->Toplevel; # new toplevel widget ... $TL->resizable(0,0); # no resizing my (@text) = ("Symbol", "Name", "Price", "Date", "Time", "Change", "Percent. Change", "Volume", "Average Volume", "Bid", "Ask", "Previous", "Open", "Day Range", "52 Week Range", "Earnings/Share", "Price/Earnings", "Dividend Date", "Dividend Amount", "Dividend Yield", "Market Capital"); my $Text = $TL->Text(-height => 1 + $#text + 7, # 7 computed position values -width => 39, -font => $BFont, )->pack(); my @arr = split (';', $Dat{Data}{ $Dat{Map}[$key] }); my $symbol = $arr[0]; $arr[0] = $Dat{Symbol}{$arr[0]}; $arr[1] = substr(get_pretty_name($Dat{GivenName}{$symbol}, $Dat{Name}{$symbol}) || "-- No connection", 0, 22); $TL->title("Details for $arr[1]"); foreach (0..$#text) { $Text->insert('end', sprintf("%-16s %s\n", $text[$ARG], $arr[$ARG])); } my $fx = $Dat{FX}{ $Dat{Cross}{$symbol} } || 1; my $shares = $Dat{Shares}{$symbol} || 0; $Text->insert('end', sprintf("%-16s %d\n%-16s %.2f\n%-16s %.2f\n", "Shares Held", $shares, "Value Change", $shares * $Dat{Change}{$symbol} * $fx, "Total Value", $shares * $Dat{Price}{$symbol} * $fx)); $Text->insert('end', sprintf("%-16s %s\n", "Days Held", defined($Dat{DaysHeld}{$symbol}) ? sprintf("%d years and %d days", $Dat{DaysHeld}{$symbol}/365, $Dat{DaysHeld}{$symbol} % 365) : "NA")); $Text->insert('end', sprintf("%-16s %s\n", "Purchase Price", $Dat{PurchPrice}{$symbol} ? sprintf("%.2f",$Dat{PurchPrice}{$symbol}) : "NA")); if ( $shares != 0 ) { my $fx = $Dat{FX}{ $Dat{Cross}{$symbol} } || 1; my $gl = ($Dat{Price}{$symbol} - $Dat{PurchPrice}{$symbol}) * ($shares < 0 ? -1 : 1) * $fx; $Text->insert('end', sprintf("%-16s %s\n", "Profit or Loss", sprintf("%.2f", $gl * $shares))); } else { $Text->insert('end', sprintf("%-16s %s\n", "Profit or Loss", "NA")); } if ( defined($Dat{Return}{$symbol}) && $Dat{DaysHeld}{$symbol} > 365 ) { $Text->insert('end', sprintf("%-16s %s\n", "Annual. Return", defined($Dat{Return}{$symbol}) ? sprintf("%.2f%%", $Dat{Return}{$symbol}) : "NA")); } else { $Text->insert('end', sprintf("%-16s %s\n", "YTD Return", defined($Dat{Return}{$symbol}) ? sprintf("%.2f%%", $Dat{Return}{$symbol}) : "NA")); } button_or_mouseclick_close($TL,$Text); } sub button_or_mouseclick_close { my ($A,$B) = @_; if ($options{nookbutton}) { $B->bind("", sub { $A->destroy}); # also close on Button-1 } else { $A->Button(-text => 'Ok', -command => sub { $A->destroy(); } )->pack(-side => 'bottom'); } } sub add_image_close_button($$) { my ($arg, $new) = @_; if ($options{nookbutton}) { $Dat{Label}[$arg]->bind("", sub { $Dat{Image}[$arg]->delete; $Dat{Chart}[$arg]->destroy(); delete $Dat{Chart}[$arg] or die "Cannot delete chart\n"; delete $Dat{Image}[$arg] or die "Cannot delete image\n"; delete $Dat{Label}[$arg] or die "Cannot delete label\n"; }); } elsif ($new) { $Dat{Chart}[$arg]->Button(-text => 'Ok', -command => sub { $Dat{Image}[$arg]->delete; $Dat{Chart}[$arg]->destroy(); delete $Dat{Chart}[$arg] or die "Cannot delete chart\n"; delete $Dat{Image}[$arg] or die "Cannot delete image\n"; delete $Dat{Label}[$arg] or die "Cannot delete label\n"; }, )->pack(-side => 'bottom') or die "Cannot create button\n"; } } sub view_image { my ($widget,$arg) = @_; my @arr = split (';', $Dat{Data}{ $Dat{Map}[$arg] }); my $url = charturl(lc( $Dat{Symbol}{$arr[0]} )); my $ua = LWP::UserAgent->new; $ua->env_proxy; $ua->proxy('http', $options{proxy}) if $options{proxy}; $ua->timeout($options{timeout}); # time out after this many secs my $resp = $ua->request(GET $url); if ($resp->is_error) { # error in retrieving the chart; my $new = 0; # by default we renew my ($TL, $PH); if (!exists($Dat{Chart}[$arg])) { $Dat{Chart}[$arg] = $Main->Toplevel; # new toplevel widget ... $new = 1; # remember that this is a first } $TL = $Dat{Chart}[$arg]; # most likely 404 (not found); #$TL->resizable(0,0); # no resizing $TL->title ("Error"); # Yahoo returns HTML, not a NULL, $Dat{Chart}[$arg] = $TL; # store for later update my $Text = $TL->Label(-padx =>5, # so need to check return code -pady =>5, -text =>"The chart for $arr[1] is not available." )->pack; $Dat{Label}[$arg] = $Text; # store the label $Dat{Photo}[$arg] = "placeholder"; # and an image placeholder add_image_close_button($arg, $new); } else { my $new = 0; # by default we renew my ($TL, $PH); if (!exists($Dat{Chart}[$arg])) { $Dat{Chart}[$arg] = $Main->Toplevel; # new toplevel widget ... $new = 1; # remember that this is a first } ## test if Tk object still Exists as users may have killed it if (defined($Dat{Chart}[$arg]) and Exists($Dat{Chart}[$arg])) { $Dat{Chart}[$arg]->title("Graph for $arr[1] at " . POSIX::strftime("%H:%M", localtime)); $TL = $Dat{Chart}[$arg]; #$TL->resizable(0,0); # no resizing if (exists($Dat{Image}[$arg])) { # if we have a previous image $Dat{Image}[$arg]->delete; # delete it (to reclaim memory) } ## can pass the web-request response to Photo widget once base64 encoded $Dat{Image}[$arg] = $TL->Photo(-data => encode_base64($resp->content), ## as of May 2005, png is used -format => "gif"); -format => "png"); $PH = $Dat{Image}[$arg]; if (exists($Dat{Label}[$arg])) { # if we have a previous label $Dat{Label}[$arg]->destroy(); # destroy it (to make new one visible) } $Dat{Label}[$arg] = $TL->Label(-image => $PH)->pack(); ## add_image_close_button($arg, $new); } } } sub charturl { # initially (almost) verbatim from Dj's my $symbol = shift; # YahooChart, now completely rewritten my $url; # and very significantly extended my $len = $chart{length}; if ($len =~ m/t/o) { # if 'm' for thumbnail $url = "http://ichart.yahoo.com/v?s=$symbol"; ## really small } elsif ($len =~ m/(b|w)/o) { # if 'b' or 'w' for intra-day or 5 day ## next line no longer needed, IIRC we once used i for what we now use b ##$len = 'b' if $len eq 'i'; # intraday chart uses Yahoo! code 'b' $url = "http://ichart.yahoo.com/$len?s=$symbol"; #$url = "http://ichart.yahoo.com/v?s=$symbol"; ## really small } else { # everything else, ie three month onwards $len .= 'y' if $len=~ m/(1|2|5|m)/o;# code for year is '1y' ... 'my' $len .= 'm' if $len =~ m/(3|6)/o; # code for month is '3m' or '6m' my $params = "s"; # always set splits foreach (keys %{$chart{ma}}) { # for all possible moving avg options $params .= ",m$ARG" if $chart{ma}{$ARG}; } foreach (keys %{$chart{ema}}){ # for all possible exp. mov avg options $params .= ",e$ARG" if $chart{ema}{$ARG}; } $params .= ",b" if $chart{bollinger}; # maybe set Bollinger Bands $params .= ",p" if $chart{parabolic_sar}; # maybe set Parabolic SAR my $log = $chart{log_scale} ? "on" : "off"; # maybe switch to log scale my $pane = $chart{volume} ? "vm" : ""; # maybe add volume on new pane foreach (keys %{$chart{technical}}) { # for all tech. analysis opt. $pane .= ",$ARG" if $chart{technical}{$ARG};# add on new pane if selected } #$url = "http://cchart.yimg.com/z?" . $url = "http://ichart.yimg.com/z?" . "&s=$symbol&p=$params&t=$len&c=$chart{comparison}" . "&l=$log&z=$chart{size}&q=$chart{style}&a=$pane"; } print "URL $url\n" if $options{verbose}; return $url; } sub default_directory { my $directory = File::Spec->catfile($ENV{HOME}, ".smtm"); unless (-d $directory) { warn("Default directory $directory not found, creating it.\n"); mkdir($directory, 0750) or die "Could not create $directory: $!"; } return $directory; } sub select_file_and_open { my $selfile = $Main->getOpenFile(-defaultextension => ".smtm", -initialdir => default_directory(), -filetypes => [ ['SMTM', '.smtm' ], ['All Files', '*',], ], -title => "Load an SMTM file"); if (defined($selfile)) { # if user has hit Accept, do nothing on Cancel $options{file} = $selfile; read_config(); init_fx(); buttons(); } } sub select_file_and_save { my $selfile = $Main->getSaveFile(-defaultextension => ".smtm", -initialdir => default_directory(), -title => "Save an SMTM file"); if (defined($selfile)) { # if user has hit Accept, do nothing on Cancel $options{file} = $selfile; file_save(); } } sub read_config { # get the data from the resource file undef $Dat{ID}; # make sure we delete the old symbols, if any undef $Dat{Arg}; # make sure we delete the old symbols, if any undef $Dat{Map}; # make sure we delete the old symbols, if any undef $Dat{Name}; # make sure we delete the old symbols, if any undef $Dat{Symbol}; # make sure we delete the old symbols, if any undef $Dat{GivenName}; # make sure we delete the old symbols, if any undef $Dat{Shares}; # make sure we delete the old symbols, if any undef $Dat{Cross}; # make sure we delete the old symbols, if any undef $Dat{PurchPrice}; # make sure we delete the old symbols, if any undef $Dat{PurchDate}; # make sure we delete the old symbols, if any open (FILE, "<$options{file}") or die "Cannot open $options{file}: $!\n"; while () { # loop over all lines in the file next if (m/(\#|%)/); # ignore comments, if any next if (m/^\s*$/); # ignore empty lines, if any next if (m/.*=$/); # ignore non-assignments if (m/^\s*\$?(\S+)=(\S+)\s*$/) { # if assignment, then it must be an option my ($arg,$val) = ($1,$2); if ($val =~ m/^X:/) { # currency symbol like GBPEUR=X insert_stock($ARG); } elsif ($arg eq "retsort") { # test for one legacy option $options{sort}='r' if $val; # old option $retsort was always = 1 } elsif ($arg =~ m/chart::(\w*)/){# test for chart option my $key = $1; warn "No chart option $key known\n" unless exists($chart{$key}); if (index($val, ":") > -1) { foreach (split /:/, $val) { my $cmd = "\$chart{$key}{$ARG}=1\n"; print "Setting from rcfile: $cmd" if $options{verbose}; eval $cmd; # store option } } else { my $cmd = "\$chart{$key}='$val'\n"; print "Setting from rcfile: $cmd" if $options{verbose}; eval $cmd; # store option } } else { # else normal option warn "No option $arg known\n" unless exists($options{$arg}); my $cmd = "\$options{$arg}='$val'\n"; print "Setting from rcfile: $cmd" if $options{verbose}; eval $cmd; # store option } } else { # or else it is stock information insert_stock($ARG); } } close(FILE); for my $i (0..length($options{columns})-1) { $coldisp{substr($options{columns}, $i, 1)} = 1; } } sub insert_stock { # insert one stock into main data structure my $arg = shift; chomp $arg; my @arr = split ':', $arg; # split along ':' $arr[0] = uc $arr[0]; # uppercase the symbol my $key = $arr[0] . ':' . $symbolcounter++; push @{$Dat{Arg}}, $key; # store symbol $Dat{ID}{$key} = $symbolcounter; $Dat{Symbol}{$key} = defined($arr[0]) ? $arr[0] : ""; $Dat{GivenName}{$key} = defined($arr[1]) ? $arr[1] : ""; $Dat{Shares}{$key} = defined($arr[2]) ? $arr[2] : 0; $Dat{Cross}{$key} = defined($arr[3]) ? $arr[3] : ""; $Dat{PurchPrice}{$key} = defined($arr[4]) ? $arr[4] : 0; $Dat{PurchDate}{$key} = defined($arr[5]) ? $arr[5] : 0; } sub edit_stock { my ($widget,$arg) = @_; my $key = $Dat{Map}[$arg]; my $TL = $Main->Toplevel; # new toplevel widget ... $TL->title ("Edit Stock"); $TL->resizable(0,0); # no resizing my $FR = $TL->Frame->pack(-fill => 'both', -fill => 'x'); my $row = 0; my @data = ( $Dat{Symbol}{$key}, $Dat{GivenName}{$key} || $Dat{Name}{$key}, $Dat{Shares}{$key}, $Dat{Cross}{$key}, $Dat{PurchPrice}{$key}, $Dat{PurchDate}{$key} ); foreach ('Symbol', 'Name', 'Nb of Shares', 'Cross-currency', 'Purchase Price', 'Purchase Date') { my $E = $FR->Entry(-textvariable => \$data[$row], -relief => 'sunken', -width => 20); my $L = $FR->Label(-text => $ARG, -anchor => 'e', -justify => 'right'); Tk::grid($L, -row => $row, -column => 0, -sticky => 'e'); Tk::grid($E, -row => $row++, -column => 1, -sticky => 'ew'); $FR->gridRowconfigure(1, -weight => 1); $E->focus if $ARG eq 'Symbol (required)'; } $TL->Button(-text => 'Ok', -command => sub { # 0 is the symbol, not stored $Dat{GivenName}{$key} = defined($data[1]) ? $data[1] : ""; $Dat{Shares}{$key} = defined($data[2]) ? $data[2] : 0; $Dat{Cross}{$key} = defined($data[3]) ? $data[3] : ""; $Dat{PurchPrice}{$key} = defined($data[4]) ? $data[4] : 0; $Dat{PurchDate}{$key} = defined($data[5]) ? $data[5] : 0; $TL->destroy(); init_fx(); } )->pack(-side => 'bottom'); } sub init_fx { # find unique crosscurrencies undef $Dat{FXarr}; my %hash; # to compute a unique subset of the FX crosses foreach my $key (keys %{$Dat{Cross}}) { my $val = $Dat{Cross}{uc $key}; # the actual cross-currency if ($val ne "" and not $hash{$val}) { push @{$Dat{FXarr}}, $val."=X"; # store this as Yahoo's symbol $hash{$val} = 1; # store that's we processed it } } } sub show_gallery { # update the pictures in 'gallery' mode view_image($Main, $ARG) foreach (0..$#{$Dat{Arg}}); } sub init_data { # fill all arguments into main data structure my @args = @_; if (defined($main::options{proxy})) { $Finance::YahooQuote::PROXY = $options{proxy}; } if (defined($options{firewall}) and $options{firewall} ne "" and $options{firewall} =~ m/.*:.*/) { my @q = split(':', $main::options{firewall}, 2); $Finance::YahooQuote::PROXYUSER = $q[0]; $Finance::YahooQuote::PROXYPASSWD = $q[1]; } menus(); # create frame, and populate with menus if (defined $args[0]) { # if we had arguments undef $Dat{Arg}; # unset previous ones foreach $ARG (@args) { # and fill insert_stock($ARG); # new ones } } init_fx(); buttons(); } sub file_save { # store in resource file my $file = $options{file}; open (FILE, ">$file") or die "Cannot open $file: $!\n"; print FILE "\#\n\# smtm version $VERSION resource file saved on ", strftime("%c", localtime); print FILE "\n\#\n"; foreach my $key (keys %options) { print FILE "$key=", eval("\$options{$key}"),"\n" if eval("defined(\$options{$key})"); } foreach my $key (keys %chart) { # hash args get unrolled into a string joined by ':' if (ref($chart{$key}) and ref($chart{$key}) eq "HASH") { print FILE "chart::$key="; foreach my $chart (keys %{$chart{$key}}) { print FILE "$chart:" if $chart{$key}{$chart}; } print FILE "\n"; } else { print FILE "chart::$key=", eval("\$chart{$key}"),"\n" if eval("defined(\$chart{$key})"); } } foreach (0..$#{$Dat{Arg}}) { my $key = @{$Dat{Arg}}[$ARG]; print FILE join(':', ($Dat{Symbol}{$key}, $Dat{GivenName}{$key}, $Dat{Shares}{$key}, $Dat{Cross}{$key}, $Dat{PurchPrice}{$key}, $Dat{PurchDate}{$key})), "\n"; } close(FILE); } sub add_stock { my $TL = $Main->Toplevel; # new toplevel widget ... $TL->title ("Add Stock"); $TL->resizable(0,0); # no resizing my $FR = $TL->Frame->pack(-fill => 'both'); my $row = 0; my @data = ("", "", "", "", "", "" ); foreach ('Symbol', 'Name', 'Nb of Shares', 'Cross-currency', 'Purchase Price', 'Purchase Date') { my $E = $FR->Entry(-textvariable => \$data[$row], -relief => 'sunken', -width => 20); my $L = $FR->Label(-text => $ARG, -anchor => 'e', -justify => 'right'); Tk::grid($L, -row => $row, -column => 0, -sticky => 'e'); Tk::grid($E, -row => $row++, -column => 1, -sticky => 'ew'); $FR->gridRowconfigure(1, -weight => 1); $E->focus if $ARG eq 'Symbol (required)'; } $TL->Button(-text => 'Ok', -command => sub { $ARG = join(':', @data); $TL->destroy(); insert_stock($ARG); init_fx(); buttons(); } )->pack(-side => 'bottom'); } sub del_stock { # delete one or several stocks my $TL = $Main->Toplevel; # new toplevel widget ... $TL->resizable(0,0); # no resizing $TL->title ("Delete Stock(s)"); my $LB = $TL->Scrolled("Listbox", -selectmode => "multiple", -scrollbars => "e", -font => $BFont, -width => 16 )->pack(); my (@data); # array of symbols in displayed order my $prefsort = $options{sort}; $options{sort} = 'n'; foreach (sort sort_func values %{$Dat{Data}}) { my @arr = split (';', $ARG); $LB->insert('end', $arr[1]); push @data, $arr[0]; } $options{sort} = $prefsort; $TL->Label(-text => 'Select stocks to be deleted')->pack(); $TL->Button(-text => 'Delete', -command => sub { my @A; # temp. array foreach (0..$#data) { push @A, $data[$ARG] unless $LB->selectionIncludes($ARG); } @{$Dat{Arg}} = @A; $TL->destroy(); buttons(); } )->pack(-side => 'bottom'); } sub chg_delay { # window to modify delay for update my $TL = $Main->Toplevel; # new toplevel widget ... $TL->resizable(0,0); # no resizing $TL->title ("Modify Delay"); my $SC = $TL->Scale(-from => 1, -to => 60, -orient => 'horizontal', -sliderlength => 15, -variable => \$options{delay})->pack(); $TL->Label(-text => 'Select update delay in minutes')->pack(); $TL->Button(-text => 'Ok', -command => sub { $TL->destroy(); buttons(); } )->pack(-side => 'bottom'); } sub get_comparison_symbol { # window to modify delay for update my $TL = $Main->Toplevel; # new toplevel widget ... $TL->resizable(0,0); # no resizing $TL->title ("Enter Comparison Symbol"); my $FR = $TL->Frame->pack(-fill => 'both'); my $data = $chart{comparison}; my $label = 'Comparison Symbol'; my $E = $FR->Entry(-textvariable => \$data, -relief => 'sunken', -width => 20); my $L = $FR->Label(-text => 'Comparison Symbol', -anchor => 'e', -justify => 'right'); Tk::grid($L, -row => 0, -column => 0, -sticky => 'e'); Tk::grid($E, -row => 0, -column => 1, -sticky => 'ew'); $FR->gridRowconfigure(1, -weight => 1); $E->focus; $TL->Button(-text => 'Ok', -command => sub { $chart{comparison} = "$data"; $TL->destroy(); } )->pack(-side => 'bottom'); } sub help_about { # show a help window my $TL = $Main->Toplevel; # uses pod2text on this very file :-> $TL->resizable(0,0); # no resizing $TL->title("Help about smtm"); my $Text = $TL->Scrolled("Text", -width => 80, -scrollbars => 'e')->pack(); button_or_mouseclick_close($TL,$Text); open (FILE, "pod2text \"$PROGRAM_NAME\" | "); while () { $Text->insert('end', $ARG); # insert what pod2text show when applied } # to this file, the pod stuff is below close(FILE); } sub help_license { # show a license window my $TL = $Main->Toplevel; # uses pod2text on this very file :-> $TL->resizable(0,0); # no resizing $TL->title("Copying smtm"); my $Text = $TL->Text(-width => 77, -height => 21)->pack(); button_or_mouseclick_close($TL,$Text); open (FILE, "< $PROGRAM_NAME"); while () { # show header last if m/^$/; next unless (m/^\#/ and not m/^\#\!/); $ARG =~ s/^\#//; # minus the leading '#' $Text->insert('end', $ARG); } $Text->insert('end', "\n smtm version $VERSION as of $date"); close(FILE); } sub get_firewall_id { my ($user,$passwd); my $TL = $Main->Toplevel; # new toplevel widget ... $TL->resizable(0,0); # no resizing $TL->title ("Specify Firewall ID"); my $FR = $TL->Frame->pack(-fill => 'both'); my $row = 0; my @data = ( "", "" ); foreach ('Firewall Account', 'Firewall Password') { my $E = $FR->Entry(-textvariable => \$data[$row], -relief => 'sunken', -width => 20) if $row eq 0; $E = $FR->Entry(-textvariable => \$data[$row], -relief => 'sunken', -show => '*', -width => 20) if $row eq 1; my $L = $FR->Label(-text => $ARG, -anchor => 'e', -justify => 'right'); Tk::grid($L, -row => $row, -column => 0, -sticky => 'e'); Tk::grid($E, -row => $row, -column => 1, -sticky => 'ew'); $FR->gridRowconfigure(1, -weight => 1); $E->focus if $row++ eq 0; } $TL->Button(-text => 'Ok', -command => sub { $options{firewall} = "$data[0]:$data[1]"; $TL->destroy(); update_display_variables(); } )->pack(-side => 'bottom'); } sub help_exit { # command-line help print STDERR " smtm -- Display/update a global stock ticker, profit/loss counter and charts smtm version $VERSION of $date Copyright (C) 1999 - 2008 by Dirk Eddelbuettel smtm comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions. For details, select Help->License or type Alt-h l once smtm runs. Usage: smtm [options] [symbol1 symbol2 symbol3 ....] Options: --time minutes minutes to wait before update of display (default value: $options{delay}) --file rcfile file to store and/or retrieve selected shares (default value: $options{file}) --proxy proxyadr network address and port of firewall proxy (default value: none, i.e. no proxy) --fwall [id:pw] account and password for firewall, if the --fwall option is used but not firewall id or passwd are give, a window will prompt for them (default value: none, i.e. no firewall) --columns set select the displayed columns by adding the respective letter to the variable set; choose from 's' for stock symbol, 'n' for the name, 'l' for last price. 'a' for absolute price change, 'r' for relative price change, 'V' for the volume traded, 'p' for the profit or loss in the position, 'v' for the value of the position, 'h' for the length of the holding period, 'R' or the annualised return 'd' for the drawdown from the 52-week high, 'e' for earnings per share, 'P' for the price/earnings ratio, 'D' for the dividend yield, 'm' for market capitalization and lastly, 'f' for the 'file position' (i.e. the position in which the stock were specified) --chart len select length of data interval shown in chart, choose one of 'b' (intra-day), 'w' (1 week), '3' (3 months), '6' (6 months), '1' (1 year), '2' (2 year), '5' (5 year) or 'm' (max years) (default: $chart{length}) 't' selects a five-day thumbnail, this is not available for all symbols. --gallery show and update charts of all available symbols --timeout len timeout value in seconds for libwww-perl UserAgent (default value: $options{timeout}) --wide display the holdings value and change in the window title --percent show relative performance in percent instead of bps --sort style sort display of shares by specified style, choose 'r' for relative change, 'a' for absolute change 'p' for position change, 'v' for position value, 'V' for trading volume, 'h' for holding period, 'R' for annual return, 'd' for drawdown, 'e' for earnings, 'P' for price/earnings, 'D' for dividend yield, 'm' for market capitalization, 'f' for the 'file position' and 'n' for name. (default value: $options{sort}) --nookbutton close other windows via left mouseclick, suppress button --verbose more output on stdout (not used much currently) --help print this help and version message Examples: smtm T::10:USDCAD BCE.TO::10 smtm --time 15 \"T:Ma Bell:200:USDCAD:62:19960520\" smtm --file ~/.smtm/telcos.smtm --columns nlarV smtm --proxy http://192.168.100.100:80 --fwall foobar:secret \n"; exit 0; } __END__ # that's it, folks! Documentation below #---- Documentation --------------------------------------------------------- =head1 NAME smtm - Display and update a configurable ticker of global stock quotes =head1 SYNOPSYS smtm [options] [stock_symbol ...] =head1 OPTIONS --time min minutes to wait before update --file smtmrc to store/retrieve stocks selected --proxy pr network address and port of firewall proxy --fwall [id:pw] account and password for firewall --chart len select length of data interval shown in chart (must be one of b, w, 3, 6, 1, 2, 5, m or t) --timeout len timeout in seconds for libwww-perl UserAgent --wide also display value changes and holdings --percent show relative performance in percent instead of bps --sort style sort display by specified style (must be one r, a, p, v, n, v, V or h) --columns set choose the columns to display (can be any combination of s, n, l, a, r, v, p, V, R, h) --nookbutton close other windows via left mouseclick, suppress button --help print a short help message =head1 DESCRIPTION B, which is a not overly clever acronym for B, is a financial ticker and portfolio application for quotes from exchanges around the world (provided they are carried on Yahoo!). It creates and automatically updates a window with quotes from Yahoo! Finance. It can also display the entire variety of charts available at Yahoo! Finance. When called with one or several symbols, it displays these selected stocks. When B is called without arguments, it reads the symbols tickers from a file, by default F<~/.smtmrc>. This file can be created explicitly by calling the Save option from the File menu. Beyond stocks, B can also display currencies (from the Philadephia exchange), US mutual funds, options on US stocks, several precious metals and quite possibly more; see the Yahoo! Finance website for full information. B can also aggregate the change in value for both individual positions and the the entire portfolio. For this, the number of shares is needed, as well as the cross-currency expression pair. The standard ISO notation is used. As an example, GBPUSD translates from Pounds into US Dollars. To compute annualised returns, the purchase date and purchase price can also be entered. B displays the full name of the company, the absolute price change and the relative percentage change in basispoints (i.e., hundreds of a percent) or in percentages if the corresponding option has been selected. Other information that can be displayed are the traded volume, the profit/loss, the aggregate positon value, the holding period length, the annualised return, the drawdown, the earnings per share, the price/earnings ratio, the dividend yield, and the market capitalization. Note that the return calculation ignores such fine points as dividends, and foreign exchange appreciation or depreciation for foreigns stocks. All display columns can be selected, or deselected, individually. Losers are flagged in red. B can be used for stocks from the USA, Canada, various European exchanges, various Asian exchanges (Singapore, Taiwan, HongKong, Kuala Lumpur, ...) Australia and New Zealand. It should work for other markets supported by Yahoo. US mutual funds are also available, but less relevant as their net asset value is only computed after the market close. Some fields might be empty if Yahoo! does not supply the full set of fields; the number of supported fields varies even among US exchanges. The sorting order can be chosen among eight different options. The quotes and charts are delayed, typically 15 minutes for NASDAQ and 20 minutes otherwise, see F for details. New Zealand is rumoured to be somewhat slower with a delay of one hour. However, it is worth pointing out that (at least some) US) indices are updated in real time at Yahoo!, and therefore available in real time to B. Intra-day and five-day charts are updated during market hours by Yahoo!, other charts with longer timeframes are updated only once a week by Yahoo!. B supports both simple proxy firewalls (via the I<--proxy> option) and full-blown firewalls with account and password authorization (via the I<--fwall> option). Firewall account name and password can be specified as command line arguments after I<--fwall>, or else in a pop-up window. This setup has been in a few different environments. B can display two more views of a share position. Clicking mouse button 1 launches a detailed view with price, date, change, volume, bid, ask, high, low, year range, price/earnings, dividend, dividend yield, market capital information, number of shares held and annualised return. However, not all of that information is available at all exchanges. Clicking the right mouse button display a chart of the corresponding stock; this only works for US and Canadian stocks. The type of chart can be specified either on the command-line, or via the Chart menu. Choices are intraday, five day, three months, six months, one year, two years, five years or max years. The default chart is a five day chart. The middle mouse button opens an edit window to modify and augment the information stored per stock. See F for help on Yahoo! Finance charts. B has been written and tested under Linux. It should run under any standard Unix, success with Solaris, HP-UX and FreeBSD is confirmed (but problems are reported under Solaris when a threaded version of Perl is used). It also runs under that other OS from Seattle using the B implementation from F. In either case, it requires the F module for windowing, and the F module (also known as F) for data retrieval over the web. The excellent F modules is also required for the date parsing and calculations. With recent versions of ActivePerl, only Date::Manip needs to be installed on top of the already provided modules. =head1 EXAMPLES smtm CSCO NT creates a window following the Cisco and Nortel stocks. smtm MSFT:Bill SUNW:Scott ORCL:Larry follows three other tech companies and uses the override feature for the displayed name. [ Historical note: We once needed that for European stocks as Yahoo! did not supply the company name way back in 1999 or so. This example just documents a now ancient feature. ] smtm BT.A.L::10:GBPCAD T::10:USDCAD \ BCE.TO::10 13330.PA::10:EURCAD \ "555750.F:DT TELECOM:10:EURCAD" creates a window with prices for a handful of telecom companies on stock exchanges in London, New York, Toronto, Paris and Frankfurt. Note how a names is specified to override the verbose default for the German telco. Also determined are the number of shares, here 10 for each of the companies. Lastly, this example assumes a Canadian perspective: returns are converted from British pounds, US dollars and Euros into Canadian dollars. Quotation marks have to be used to prevent the shell from splitting the argument containing spaces. [ Historical note: The Deutsche Telecom stock can now also be referenced as DTEGn.DE; similarly other stock previously available only under their share number are now accessible using an acronym reflecting their company name.] =head1 MENUS Four menus are supported: I, I, I and I. The I menu offers to load or save to the default file, or to 'save as' a new file. I is also available. The I menu can launch windows to either add a new stock or delete one or several from a list box. Submenus for column selection based on various criteria are available. Similarly, the I menu allows to select one of eight different sort options. Further, one can modify the delay time between updates and choose between the default title display or the wide display with changes in the position and total position value. The I menu allows to select the default chart among the eight choices intraday, five day, three months, six months, one year, two years, five years or 'max' years. Chart sizes can be selected among three choices. Plot types can be selected among line chart, bar chart and the so-called candlestick display. For both moving averages and exponential moving averages, six choices are avilable (5, 10, 20, 50, 100 and 200 days, respectively) which can all be selected (or deselected) individually. Similarly, any one of seven popular technical analysis charts can be added. Logarithmic scale can be turned on/off. Volume bar charts as also be selected or deselected. Similarly, Bollinger bands and the parabolic SAR can be selected. A selection box can be loaded to enter another symbol (or several of these, separated by comma) for performance comparison. Lastly, the gallery command can launch the display of a chart for each and every stock symbol currenly loaded in the smtm display. Note that intra-day and intra-week charts do not offer all the various charting options longer-dated charts have available. Once charts are shown, they are also updated regularly at the same interval the main displayed is updated at. Lastly, the I menu can display either the text from the manual page, or the copyright information in a new window. =head1 DISPLAY The main window is very straightforward. For each of the stocks, up to eleven items can be displayed: its symbol, its name, its most recent price, the change from the previous close in absolute terms, the change in relative terms, the volume, the profit or loss, the total position value, the holding period, the annualised return (bar F/X effects or dividends) and the drawdown relative to the 52-week high. The relative change is either expressed in basispoints (bps), which are 1/100s of a percent, or in percent; this can be controlled via a checkbutton as well as an command-line option. Further display options are earnings per share, price/earnings ratio, dividend yield and market capitalization. This display window is updated in regular intervals; the update interval can be specified via a menu or a command-line option. The window title displays the relative portfolio profit or loss for the current day in basispoints, i.e., hundreds of a percent, or in percent if the corresponding option is chosen, as well as the date of the most recent update. If the I<--wide> options is used, the net change and ney value of the portfolio (both in local currency) are also displayed. Clicking on any of the stocks with the left mouse button opens a new window with all available details for a stock. Unfortunately, the amount of available information varies. Non-North American stocks only have a limited subset of information made available via the csv interface of Yahoo!. For North American stocks, not all fields all provided by all exchanges. Clicking on the details display window itself closes this window. Clicking on any of the stocks with the right mouse button opens a new window with a chart of the given stock in the default chart format. This option was initially available only for North American stocks but now works across most if not all markets, thanks to expanded support by Yahoo!. Clicking on the chart window itself closes this window. Finally, the middle mouse button opens an edit window. =head1 CHART DISPLAY (AKA 'GALLERY' MODE) In 'gallery' mode, chart windows are opened for all active securities. These charts are automatically updated whenever the display is updated. This mean that only the intra-daily and intra-weekly chart timeframe selection are meaningful -- all others are updated at the source, i.e. Yahoo!, daily or weekly, and there is no little point in downloading the same chart over and over again. However, for intra-daily and intra-weekly charts, this is a very useful feature. It should be noted that not all chart size, chart timeframe and chart option permutations actually lead to existing charts. For example, logarithmic scale does seem to exist for shorter-dated time frames. Neither does the 'small' chart size. =head1 BUGS Closing the stock addition or deletion windows have been reported to cause random segmentation violation under Linux. This appears to be a bug in Perl/Tk which will hopefully be solved, or circumvented, soon. This bug does not bite under Solaris, FreeBSD or NT or other Linux distributions. Update: This problem appears to have disappeared with Perl 5.6.*. Problems with undefined symbols have been reported under Solaris 2.6 when Perl has been compiled with thread support. Using an unthreaded Perl binary under Solaris works. How this problem can be circumvented is presently unclear. It is not clear whether the market capitalization information is comparable across exchange. Some differences could be attributable to 'total float' versus 'free float' calculations. =head1 SEE ALSO F, F, F, F, F See F for help on Yahoo! Finance charts. =head1 COPYRIGHT smtm is (c) 1999 - 2008 by Dirk Eddelbuettel Updates to this program might appear at F. If you enjoy this program, you might also want to look at my beancounter program F, as well as the Finance::YahooQuote module at F which was originally written by Dj Padzensky, and that is used by both B and B. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. There is NO warranty whatsoever. The information that you obtain with this program may be copyrighted by Yahoo! Inc., and is governed by their usage license. See F for more information. =head1 ACKNOWLEDGEMENTS The Perl code by Dj Padzensky, in particular his B module (originally on the web at F and now maintained by me at F) and his Finance::YahooChart module (on the web at F) were most helpful. They provided the initial routines for downloading stock data and determining the Yahoo! Chart url. Earlier version of B use a somewhat rewrittem variant (which still reflected their heritage), newer version rely directly on B now that Yahoo! uses a similar backend across the globe. Dj's code contribution is most gratefully acknowledged. =head1 CPAN The remaining sections pertain to the CPAN registration of B. The script category is a little mismatched but as there is no Finance section, F was as good as the other choices. =head1 SCRIPT CATEGORIES Networking =head1 PREREQUISITES On Windows, F can use the Perl distribution from F. On both Unix and Windows, B requires the C module for windowing, the C module for data retrieval over the web, and the excellent C module for the date parsing and calculations. Finance::YahooQuote is used for actual data access. Tk::PNG is used to display the png charts since Yahoo! switched from gif to png around May 2005. =head1 COREQUISITES None. =head1 OSNAMES F is not OS dependent. It is known to run under Linux, several commercial Unix variants and Windows =head1 README B, which is a not overly clever acronym for B, is a financial ticker and portfolio application for quotes from exchanges around the world (provided they are carried on Yahoo!). It creates and automatically updates a window with quotes from Yahoo! Finance. It can also display the entire variety of charts available at Yahoo! Finance. Fairly extensive documentation for B is available at F. =cut smtm-1.6.10/smtm.10000644000232200023220000005041210026221470014003 0ustar pbuilderpbuilder.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.14 .\" .\" Standard preamble: .\" ======================================================================== .de Sh \" Subsection heading .br .if t .Sp .ne 5 .PP \fB\\$1\fR .PP .. .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. | will give a .\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to .\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C' .\" expand to `' in nroff, nothing in troff, for use with C<>. .tr \(*W-|\(bv\*(Tr .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' 'br\} .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} .\" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .hy 0 .if n .na .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "SMTM 1" .TH SMTM 1 "2004-03-17" "perl v5.8.3" "User Contributed Perl Documentation" .SH "NAME" smtm \- Display and update a configurable ticker of global stock quotes .SH "SYNOPSYS" .IX Header "SYNOPSYS" .Vb 1 \& smtm [options] [stock_symbol ...] .Ve .SH "OPTIONS" .IX Header "OPTIONS" .Vb 15 \& --time min minutes to wait before update \& --file smtmrc to store/retrieve stocks selected \& --proxy pr network address and port of firewall proxy \& --fwall [id:pw] account and password for firewall \& --chart len select length of data interval shown in chart \& (must be one of b, w, 3, 6, 1, 2, 5 or m) \& --timeout len timeout in seconds for libwww-perl UserAgent \& --wide also display value changes and holdings \& --percent show relative performance in percent instead of bps \& --sort style sort display by specified style \& (must be one r, a, p, v, n, v, V or h) \& --columns set choose the columns to display (can be any combination \& of s, n, l, a, r, v, p, V, R, h) \& --nookbutton close other windows via left mouseclick, suppress button \& --help print a short help message .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" \&\fBsmtm\fR, which is a not overly clever acronym for \fBShow Me The Money\fR, is a financial ticker and portfolio application for quotes from exchanges around the world (provided they are carried on Yahoo!). It creates and automatically updates a window with quotes from Yahoo! Finance. It can also display the entire variety of charts available at Yahoo! Finance. When called with one or several symbols, it displays these selected stocks. When \fBsmtm\fR is called without arguments, it reads the symbols tickers from a file, by default \&\fI~/.smtmrc\fR. This file can be created explicitly by calling the Save option from the File menu. Beyond stocks, \fBsmtm\fR can also display currencies (from the Philadephia exchange), \s-1US\s0 mutual funds, options on \s-1US\s0 stocks, several precious metals and quite possibly more; see the Yahoo! Finance website for full information. .PP \&\fBsmtm\fR can also aggregate the change in value for both individual positions and the the entire portfolio. For this, the number of shares is needed, as well as the cross-currency expression pair. The standard \s-1ISO\s0 notation is used. As an example, \s-1GBPUSD\s0 translates from Pounds into \s-1US\s0 Dollars. To compute annualised returns, the purchase date and purchase price can also be entered. .PP \&\fBsmtm\fR displays the full name of the company, the absolute price change and the relative percentage change in basispoints (i.e., hundreds of a percent) or in percentages if the corresponding option has been selected. Other information that can be displayed are the traded volume, the profit/loss, the aggregate positon value, the holding period length, the annualised return, the drawdown, the earnings per share, the price/earnings ratio, the dividend yield, and the market capitalization. Note that the return calculation ignores such fine points as dividends, and foreign exchange appreciation or depreciation for foreigns stocks. All display columns can be selected, or deselected, individually. .PP Losers are flagged in red. \fBsmtm\fR can be used for stocks from the \&\s-1USA\s0, Canada, various European exchanges, various Asian exchanges (Singapore, Taiwan, HongKong, Kuala Lumpur, ...) Australia and New Zealand. It should work for other markets supported by Yahoo. \s-1US\s0 mutual funds are also available, but less relevant as their net asset value is only computed after the market close. Some fields might be empty if Yahoo! does not supply the full set of fields; the number of supported fields varies even among \s-1US\s0 exchanges. The sorting order can be chosen among eight different options. .PP The quotes and charts are delayed, typically 15 minutes for \s-1NASDAQ\s0 and 20 minutes otherwise, see \fIhttp://finance.yahoo.com\fR for details. New Zealand is rumoured to be somewhat slower with a delay of one hour. However, it is worth pointing out that (at least some) \s-1US\s0) indices are updated in real time at Yahoo!, and therefore available in real time to \fBsmtm\fR. Intra-day and five-day charts are updated during market hours by Yahoo!, other charts with longer timeframes are updated only once a week by Yahoo!. .PP \&\fBsmtm\fR supports both simple proxy firewalls (via the \fI\-\-proxy\fR option) and full-blown firewalls with account and password authorization (via the \&\fI\-\-fwall\fR option). Firewall account name and password can be specified as command line arguments after \fI\-\-fwall\fR, or else in a pop-up window. This setup has been in a few different environments. .PP \&\fBsmtm\fR can display two more views of a share position. Clicking mouse button 1 launches a detailed view with price, date, change, volume, bid, ask, high, low, year range, price/earnings, dividend, dividend yield, market capital information, number of shares held and annualised return. However, not all of that information is available at all exchanges. Clicking the right mouse button display a chart of the corresponding stock; this only works for \s-1US\s0 and Canadian stocks. The type of chart can be specified either on the command\-line, or via the Chart menu. Choices are intraday, five day, three months, six months, one year, two years, five years or max years. The default chart is a five day chart. The middle mouse button opens an edit window to modify and augment the information stored per stock. .PP See \fIhttp://help.yahoo.com/help/us/fin/chart/\fR for help on Yahoo! Finance charts. .PP \&\fBsmtm\fR has been written and tested under Linux. It should run under any standard Unix, success with Solaris, HP-UX and FreeBSD is confirmed (but problems are reported under Solaris when a threaded version of Perl is used). It also runs under that other \s-1OS\s0 from Seattle using the \fBActivePerl\fR implementation from \&\fIhttp://www.activestate.com\fR. In either case, it requires the \&\fIPerl/Tk\fR module for windowing, and the \fI\s-1LWP\s0\fR module (also known as \&\fIlibwww-perl\fR) for data retrieval over the web. The excellent \&\fIDate::Manip\fR modules is also required for the date parsing and calculations. With recent versions of ActivePerl, only Date::Manip needs to be installed on top of the already provided modules. .SH "EXAMPLES" .IX Header "EXAMPLES" .Vb 1 \& smtm CSCO NT .Ve .PP creates a window following the Cisco and Nortel stocks. .PP .Vb 1 \& smtm MSFT:Bill SUNW:Scott ORCL:Larry .Ve .PP follows three other tech companies and uses the override feature for the displayed name. [ Historical note: We once needed that for European stocks as Yahoo! did not supply the company name way back in 1999 or so. This example just documents a now ancient feature. ] .PP .Vb 3 \& smtm BT.A.L::10:GBPCAD T::10:USDCAD \e \& BCE.TO::10 13330.PA::10:EURCAD \e \& "555750.F:DT TELECOM:10:EURCAD" .Ve .PP creates a window with prices for a handful of telecom companies on stock exchanges in London, New York, Toronto, Paris and Frankfurt. Note how a names is specified to override the verbose default for the German telco. Also determined are the number of shares, here 10 for each of the companies. Lastly, this example assumes a Canadian perspective: returns are converted from British pounds, \s-1US\s0 dollars and Euros into Canadian dollars. Quotation marks have to be used to prevent the shell from splitting the argument containing spaces. [ Historical note: The Deutsche Telecom stock can now also be referenced as DTEGn.DE; similarly other stock previously available only under their share number are now accessible using an acronym reflecting their company name.] .SH "MENUS" .IX Header "MENUS" Four menus are supported: \fIFile\fR, \fIEdit\fR, \fIChart\fR and \fIHelp\fR. The \&\fIFile\fR menu offers to load or save to the default file, or to 'save as' a new file. \fIExit\fR is also available. .PP The \fIEdit\fR menu can launch windows to either add a new stock or delete one or several from a list box. Submenus for column selection based on various criteria are available. Similarly, the \fISort\fR menu allows to select one of eight different sort options. Further, one can modify the delay time between updates and choose between the default title display or the wide display with changes in the position and total position value. .PP The \fICharts\fR menu allows to select the default chart among the eight choices intraday, five day, three months, six months, one year, two years, five years or 'max' years. Chart sizes can be selected among three choices. Plot types can be selected among line chart, bar chart and the so-called candlestick display. For both moving averages and exponential moving averages, six choices are avilable (5, 10, 20, 50, 100 and 200 days, respectively) which can all be selected (or deselected) individually. Similarly, any one of seven popular technical analysis charts can be added. Logarithmic scale can be turned on/off. Volume bar charts as also be selected or deselected. Similarly, Bollinger bands and the parabolic \s-1SAR\s0 can be selected. A selection box can be loaded to enter another symbol (or several of these, separated by comma) for performance comparison. Lastly, the gallery command can launch the display of a chart for each and every stock symbol currenly loaded in the smtm display. Note that intra-day and intra-week charts do not offer all the various charting options longer-dated charts have available. Once charts are shown, they are also updated regularly at the same interval the main displayed is updated at. .PP Lastly, the \fIHelp\fR menu can display either the text from the manual page, or the copyright information in a new window. .SH "DISPLAY" .IX Header "DISPLAY" The main window is very straightforward. For each of the stocks, up to eleven items can be displayed: its symbol, its name, its most recent price, the change from the previous close in absolute terms, the change in relative terms, the volume, the profit or loss, the total position value, the holding period, the annualised return (bar F/X effects or dividends) and the drawdown relative to the 52\-week high. The relative change is either expressed in basispoints (bps), which are 1/100s of a percent, or in percent; this can be controlled via a checkbutton as well as an command-line option. Further display options are earnings per share, price/earnings ratio, dividend yield and market capitalization. This display window is updated in regular intervals; the update interval can be specified via a menu or a command-line option. .PP The window title displays the relative portfolio profit or loss for the current day in basispoints, i.e., hundreds of a percent, or in percent if the corresponding option is chosen, as well as the date of the most recent update. If the \fI\-\-wide\fR options is used, the net change and ney value of the portfolio (both in local currency) are also displayed. .PP Clicking on any of the stocks with the left mouse button opens a new window with all available details for a stock. Unfortunately, the amount of available information varies. Non-North American stocks only have a limited subset of information made available via the csv interface of Yahoo!. For North American stocks, not all fields all provided by all exchanges. Clicking on the details display window itself closes this window. Clicking on any of the stocks with the right mouse button opens a new window with a chart of the given stock in the default chart format. This option was initially available only for North American stocks but now works across most if not all markets, thanks to expanded support by Yahoo!. Clicking on the chart window itself closes this window. Finally, the middle mouse button opens an edit window. .SH "CHART DISPLAY (AKA 'GALLERY' MODE)" .IX Header "CHART DISPLAY (AKA 'GALLERY' MODE)" In 'gallery' mode, chart windows are opened for all active securities. These charts are automatically updated whenever the display is updated. This mean that only the intra-daily and intra-weekly chart timeframe selection are meaningful \*(-- all others are updated at the source, i.e. Yahoo!, daily or weekly, and there is no little point in downloading the same chart over and over again. .PP However, for intra-daily and intra-weekly charts, this is a very useful feature. It should be noted that not all chart size, chart timeframe and chart option permutations actually lead to existing charts. For example, logarithmic scale does seem to exist for shorter-dated time frames. Neither does the 'small' chart size. .SH "BUGS" .IX Header "BUGS" Closing the stock addition or deletion windows have been reported to cause random segmentation violation under Linux. This appears to be a bug in Perl/Tk which will hopefully be solved, or circumvented, soon. This bug does not bite under Solaris, FreeBSD or \s-1NT\s0 or other Linux distributions. Update: This problem appears to have disappeared with Perl 5.6.*. .PP Problems with undefined symbols have been reported under Solaris 2.6 when Perl has been compiled with thread support. Using an unthreaded Perl binary under Solaris works. How this problem can be circumvented is presently unclear. .PP It is not clear whether the market capitalization information is comparable across exchange. Some differences could be attributable to \&'total float' versus 'free float' calculations. .SH "SEE ALSO" .IX Header "SEE ALSO" \&\fIFinance::YahooQuote.3pm\fR, \fIFinance::YahooChart.3pm\fR, \fI\s-1LWP\s0.3pm\fR, \&\fIlwpcook.1\fR, \fITk::UserGuide.3pm\fR .PP See \fIhttp://help.yahoo.com/help/us/fin/chart/\fR for help on Yahoo! Finance charts. .SH "COPYRIGHT" .IX Header "COPYRIGHT" smtm is (c) 1999 \- 2004 by Dirk Eddelbuettel .PP Updates to this program might appear at \&\fIhttp://dirk.eddelbuettel.com/code/smtm.html\fR. If you enjoy this program, you might also want to look at my beancounter program \&\fIhttp://dirk.eddelbuettel.com/code/beancounter.html\fR, as well as the Finance::YahooQuote module at \&\fIhttp://dirk.eddelbuettel.com/code/yahooquote.html\fR which was originally written by Dj Padzensky, and that is used by both \fBsmtm\fR and \fBbeancounter\fR. .PP This program is free software; you can redistribute it and/or modify it under the terms of the \s-1GNU\s0 General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. There is \s-1NO\s0 warranty whatsoever. .PP The information that you obtain with this program may be copyrighted by Yahoo! Inc., and is governed by their usage license. See \&\fIhttp://www.yahoo.com/docs/info/gen_disclaimer.html\fR for more information. .SH "ACKNOWLEDGEMENTS" .IX Header "ACKNOWLEDGEMENTS" The Perl code by Dj Padzensky, in particular his \&\fBFinance::YahooQuote\fR module (originally on the web at \&\fIhttp://www.padz.net/~djpadz/YahooQuote/\fR and now maintained by me at \&\fIhttp://dirk.eddelbuettel.com/code/yahooquote.html/\fR) and his Finance::YahooChart module (on the web at \&\fIhttp://www.padz.net/~djpadz/YahooChart/\fR) were most helpful. They provided the initial routines for downloading stock data and determining the Yahoo! Chart url. Earlier version of \fBsmtm\fR use a somewhat rewrittem variant (which still reflected their heritage), newer version rely directly on \fBFinance::YahooQuote\fR now that Yahoo! uses a similar backend across the globe. Dj's code contribution is most gratefully acknowledged. .SH "CPAN" .IX Header "CPAN" The remaining sections pertain to the \s-1CPAN\s0 registration of \&\fBsmtm\fR. The script category is a little mismatched but as there is no Finance section, \fINetworking\fR was as good as the other choices. .SH "SCRIPT CATEGORIES" .IX Header "SCRIPT CATEGORIES" Networking .SH "PREREQUISITES" .IX Header "PREREQUISITES" On Windows, \fIsmtm\fR can use the Perl distribution from \&\fIhttp://www.activestate.com\fR. On both Unix and Windows, \fBsmtm\fR requires the \f(CW\*(C`Tk\*(C'\fR module for windowing, the \f(CW\*(C`LWP\*(C'\fR module for data retrieval over the web, and the excellent \f(CW\*(C`Date::Manip\*(C'\fR module for the date parsing and calculations. .SH "COREQUISITES" .IX Header "COREQUISITES" None .SH "OSNAMES" .IX Header "OSNAMES" \&\fIsmtm\fR is not \s-1OS\s0 dependent. It is known to run under Linux, several commercial Unix variants and Windows .SH "README" .IX Header "README" \&\fBsmtm\fR, which is a not overly clever acronym for \fBShow Me The Money\fR, is a financial ticker and portfolio application for quotes from exchanges around the world (provided they are carried on Yahoo!). It creates and automatically updates a window with quotes from Yahoo! Finance. It can also display the entire variety of charts available at Yahoo! Finance. Fairly extensive documentation for \&\fBsmtm\fR is available at \fIhttp://dirk.eddelbuettel.com/code/smtm.html\fR. smtm-1.6.10/pod2htmi.tmp0000644000232200023220000000000310026221467015206 0ustar pbuilderpbuilder . smtm-1.6.10/BUGS0000644000232200023220000000106407322467033013437 0ustar pbuilderpbuilder Closing the stock addition or deletion windows have been reported to cause random segmentation violation under Linux. This appears to be a bug in Perl/Tk which will hopefully be solved, or circumvented, soon. This bug does not bite under Solaris, FreeBSD or NT. [ UPDATE: It also seems to have disappeared under Perl 5.6.*. ] Problems with undefined symbols have been reported under Solaris 2.6 when Perl has been compiled with thread support. Using an unthreaded Perl binary under Solaris works. How this problem can be circumvented is presently unclear. smtm-1.6.10/pod2htmd.tmp0000644000232200023220000000000310026221467015201 0ustar pbuilderpbuilder . smtm-1.6.10/META.yml0000644000232200023220000000106510364326430014221 0ustar pbuilderpbuilder# http://module-build.sourceforge.net/META-spec.html #XXXXXXX This is a prototype!!! It will change in the future!!! XXXXX# name: smtm version: 1.6.8 version_from: smtm installdirs: site requires: Date::Manip: 5 Finance::YahooQuote: 0.2 HTML::Parser: 2.2 LWP::UserAgent: 1.23 MIME::Base64: 2.12 Tk: 800.015 Tk::PNG: 2.005 distribution_type: module generated_by: ExtUtils::MakeMaker version 6.17 smtm-1.6.10/debian/0000755000232200023220000000000011016367750014175 5ustar pbuilderpbuildersmtm-1.6.10/debian/Makefile0000644000232200023220000000346210242011413015620 0ustar pbuilderpbuilder # Makefile for smtm # Copyright (C) 1999 - 2005 Dirk Eddelbuettel # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. file= smtm version:= $(shell pwd | cut -d- -f2) prefix= /usr/local mandir= $(prefix)/share/man/man1 bindir= $(prefix)/bin all: $(file) $(file): ifeq ($(shell hostname --fqdn),sonny.eddelbuettel.com) @echo "Copying freshest source file" cp -afv $(HOME)/progs/perl-tk/smtm/$(file).pl $(file) @echo "Setting to release version " ${version} perl -p -i -e "s/version = \".*\";/version = \""$(version)"\";/" $(file) @chmod 755 $(file) endif @true install: $(file) $(file).1 install -p -m 0755 $(file) $(bindir)/. install -p -D -m 0755 $(file).1 $(mandir)/$(file).1 $(file).html: $(file) pod2html --flush $< > $@ -rm -f pod2html-itemcache pod2html-dircache $(file).1: $(file) pod2man $< > $@ clean: -rm -f $(file).1 *~ distclean: clean realclean: clean FILES= $(file) $(file).html Makefile.PL COPYING BUGS README THANKS TODO \ examples/* t/* dist: $(file).html tar zip tar: tar cvfz ../$(file)_$(version).tar.gz $(FILES) zip: zip ../$(file)_$(version).zip $(FILES) smtm-1.6.10/debian/compat0000644000232200023220000000000110671377427015402 0ustar pbuilderpbuilder5smtm-1.6.10/debian/changelog0000644000232200023220000005356511016367750016065 0ustar pbuilderpbuildersmtm (1.6.10) unstable; urgency=low * Bug fix release to accommodate Perl 5.10 array changes in two spots -- Dirk Eddelbuettel Sun, 25 May 2008 17:48:23 -0500 smtm (1.6.9.1) unstable; urgency=low * Debian bug fix release: - debian/rules: Remove bashism (Closes: #477620) - debian/control: Updated Standards-Version to 3.7.3 - debian/copyright: Added parseable Copyright statement * smtm.pl: Update copyright to 2008 -- Dirk Eddelbuettel Wed, 23 Apr 2008 21:33:40 -0500 smtm (1.6.9) unstable; urgency=low * Bug fix / update release: Updated chart URL at Yahoo! * Debian updates: - Standards-Version: increased to 3.7.2 - debian/compat created, debhelper Build-Depends updated -- Dirk Eddelbuettel Mon, 10 Sep 2007 21:30:51 -0500 smtm (1.6.8) unstable; urgency=low * Really apply the change to Depends: and not only Build-Depends: * debian/control: Remove Depends: on libtk-png-perl, but qualify Depends: on perl-tk to be perl-tk (>= 1:804.000) -- Dirk Eddelbuettel Fri, 20 Jan 2006 21:39:36 -0600 smtm (1.6.7) unstable; urgency=low * Debian-only bug fix release: We no longer need to Depends: libtk-png-perl as newer perl-tk packages include the PNG graph functionality * debian/control: Remove Depends: on libtk-png-perl, but qualify Depends: on perl-tk to be perl-tk (>= 1:804.000) * debian/control: Upgraded to Standards-Version: 3.6.2 * debian/rules: Set DH_COMPAT=4 -- Dirk Eddelbuettel Fri, 20 Jan 2006 20:54:51 -0600 smtm (1.6.6) unstable; urgency=low * Bug fix release: - [smtm] Switch to using Tk::PNG to display png charts as Yahoo no longer ships gif files, and Tk by default cannot deal with PNG - [smtm] Updated documentation a little bit - [smtm] Use DBK.DE as symbol in the example portfolio - [Makefile.PL, README] Mention the new Tk::PNG requirement - [debian/control] Add libtk-png-perl to Depends -- Dirk Eddelbuettel Sun, 15 May 2005 22:34:33 -0500 smtm (1.6.5) unstable; urgency=low * Bug fix release: - [smtm] Make chart updates in gallery mode more robust to the possibility of windows having been closed by the user (Closes: #261806) - [smtm] Make code yet more robust to irregular data from Yahoo! -- Dirk Eddelbuettel Tue, 3 Aug 2004 21:52:29 -0500 smtm (1.6.4) unstable; urgency=low * Debian-only bug fix release: Needed explicit Depends on libdate-manip-perl -- Dirk Eddelbuettel Fri, 4 Jun 2004 07:50:42 -0500 smtm (1.6.3) unstable; urgency=low * Bug fix release: - [smtm] Fix main window resizing bug following 'edit_stock()' is called (via the middle-mouse button). (Closes: #241777) -- Dirk Eddelbuettel Sat, 3 Apr 2004 10:18:08 -0600 smtm (1.6.2) unstable; urgency=low * Minor release with new feature - The 'show_details' function (bound to Button-1) now displays absolute profit or loss (converted to local currency as well). Thanks to Rober A. Schmied for the patch to which we only added the FX bit. - Percentage returns will not be annualized for positions held less than year, also due to Robert A. Schmied. * Bug fixes - Gallery mode works again after the innocent-looking call resizable(0,0) has been removed in the view_image function. - Resizable(0,0) calls added in other functions. -- Dirk Eddelbuettel Wed, 17 Mar 2004 22:06:00 -0600 smtm (1.6.1) unstable; urgency=low * Bug fix release: - The 'show_details' function (bound to Button-1) now displays correct information on dividend date, amount and yields. Display of market capitalization was also improved. That to Robert A. Schmied for pointing out the initial problem, and for supplying a patch. -- Dirk Eddelbuettel Tue, 9 Mar 2004 21:15:35 -0600 smtm (1.6.0) unstable; urgency=low * New major release: - In 'gallery' mode, smtm now updates chart windows along with the normal data allowing for automatically updated intra-daily or intra-weekly charts (longer horizons are updated less frequently than daily at Yahoo!). Gallery mode can be launched either via the command-line option '--gallery', or via the Chart->Gallery menu entry. - Small updates to documentation -- Dirk Eddelbuettel Tue, 6 Jan 2004 20:38:16 -0600 smtm (1.5.6) unstable; urgency=low * Bug fix release: - smtm: correct small error where defensive assignment of number of share was not used - smtm: use pack(-fill ...) throughtout, not pack(fill => ...), as this seems to trip up some 5.8.* versions of Perl. Thanks to Bruce Bowler for reporting this - smtm: use LWP::UserAgent->new(), not RequestAgent->new(), as this seems to trip up some ActiveState version. Thanks to Chris Eidem and others for reporting this. -- Dirk Eddelbuettel Wed, 15 Oct 2003 20:47:06 -0500 smtm (1.5.5) unstable; urgency=low * Bug fix release: - smtm: Chart images are no longer saved to a tempfile, but rather passed directly (in base64 encoding) to the Photo widget - smtm: The Photo widget is now deleted on plugging a memory hole - Makefile.PL: Depend on MIME::Base64 - debian/control: Depends: on libmime-base64-perl | perl (>= 5.8.0) [ MIME::Base64 is a package with perl 5.6.*, but included in 5.8.* ] - t/use?.t: Added to see if Finance::YahooQuote and Tk can be loaded. - debian/control: Added Build-Depends for test -- Dirk Eddelbuettel Sun, 4 May 2003 16:10:51 -0500 smtm (1.5.4) unstable; urgency=low * Bug fix release: - Cross-Currency symbols like 'GBPEUR=X' now load from smtm rc files * Minor new feature added: - 'Suspend update' option added to GUI -- Dirk Eddelbuettel Sun, 27 Apr 2003 07:59:29 -0500 smtm (1.5.3) unstable; urgency=low * Bug fix release with the following code changes: - Fixed a display bug in add_stock and edit_stock GUI functions -- Dirk Eddelbuettel Mon, 6 Jan 2003 21:49:35 -0600 smtm (1.5.2) unstable; urgency=low * New minor release with the following code changes: - Quote information code has been outsourced to Finance::YahooQuote now that we added the extra proxy logic (that was in smtm) into YahooQuote. Smtm requires Finance::YahooQuote 0.18 or higher. - Small code cleanup for program initialization. -- Dirk Eddelbuettel Thu, 26 Dec 2002 19:27:00 -0600 smtm (1.5.1) unstable; urgency=low * Bug fix release with the following code changes - Test for a few more non-numeric arguments before attempting to actually do numeri operations, this was mostly for the new columns introduced in 1.5.0 - Applied small patch by Cord Beerman to suppress a Perl 5.8.0 gripe (Closes: #161210) -- Dirk Eddelbuettel Wed, 25 Sep 2002 21:39:17 -0500 smtm (1.5.0) unstable; urgency=low * New minor release with the following code changes: - New display columns and sort options for earnings, p/e ratio, dividend yields and market capitalization (Closes: #151155) - New sort option "file order" for display as in the .smtm file which allows for thematic grouping of stocks and indices. Thanks to Yin Zhou for a very nice patch (though several changes were still made) as well as most of the content of the new example file indices.smtm - Updated documentation accordingly - First upload to the scripts section of CPAN required a few additional entries to the POD documentation -- Dirk Eddelbuettel Tue, 6 Aug 2002 22:34:35 -0500 smtm (1.4.0) unstable; urgency=low * New release with the following code changes: - generalised country support: as Yahoo! now appears to serve all world regions from the core servers, we no longer have to bucket for different global regions -- the net effect is that we should now have global coverage - took initial patch by Cord Beerman to cope better with bad Yahoo! data but made the patch more concise (Closes: #151149) - minor documentation updates -- Dirk Eddelbuettel Thu, 27 Jun 2002 22:36:00 -0500 smtm (1.3.0) unstable; urgency=low * New release with the following code changes: - completely rewritten charting part now supporting all of the available charts options at Yahoo! Finance: o eight different chart lengths from intra-day to max. years o three different chart sizes o three different chart styles: line, bar and candle o any combination of six different moving average timeframes o any combination of six exponential moving average timeframes o six different technical analysis charts o volume, bollinger bands and parabolic sar o as well as relative comparison to any other plot symbols - new "chart" menu entry regrouping all available chart options - "gallery" command to plot `a gallery' of the currently selected chart type at once for all currently followed stocks - rewrite of option handling, now using two hashes for general options and chart options, as well as the resource file reading and writing to support all the new chart options - updated default portfolio - updated documentation -- Dirk Eddelbuettel Sun, 14 Apr 2002 22:22:56 -0500 smtm (1.2.4) unstable; urgency=low * Bug fix release with the following code changes - Yahoo! changed chart URLs for charts other than intraday or weekly; smtm code corrected. Thanks to David Talmage for the heads-up - Added 'six month' and 'max years' chart data options - Updated help texts for charts -- Dirk Eddelbuettel Mon, 11 Mar 2002 22:10:12 -0600 smtm (1.2.3) unstable; urgency=low * New release with the following code change - new optional display column 'drawdown' with percentage decrease relativ to the 52week high - new sort option drawdown - small documentation updates and corrections * debian/control: Spelling correction (Closes: #125366) -- Dirk Eddelbuettel Tue, 15 Jan 2002 20:26:15 -0600 smtm (1.2.2) unstable; urgency=low * Bug fix release with the following code changes - Yahoo! Europe switched to using ";" as field sep, and "," for decimals, added patch to transform this -- Dirk Eddelbuettel Thu, 2 Aug 2001 21:38:40 -0500 smtm (1.2.1) unstable; urgency=low * Bug fix release with the following code changes - consistent use of net position change - fixed small bug in display of short position - examples/worldindices.smtm: Added ^EUN - some editing cleanup -- Dirk Eddelbuettel Mon, 9 Jul 2001 21:52:07 -0500 smtm (1.2.0) unstable; urgency=low * New release with the following code changes - added support for options (extension .X on Yahoo! Finance) - corrected return calculating for short positions - added several new example files: currencies, global, mutualfunds, options and worldindices - alphabetical name sort in case of ties when sorting by returns - more tests on missing return data, does not cover everything though - use different Yahoo! URL for German stocks - smaller default font * debian/control: Upgraded Standards-Version -- Dirk Eddelbuettel Tue, 22 May 2001 22:04:58 -0500 smtm (1.1.2) unstable; urgency=low * New release with the following code changes - much better support for the Asian 'Tiger' countries Singapore, HongKong, Thailand, Taiwan, ... as well as Australia, New Zealand (thanks to Kwok Chern Yue for the initial patch) - more information retrieved and displayed for European stocks -- Dirk Eddelbuettel Tue, 18 Jul 2000 23:41:49 -0400 smtm (1.1.1) unstable; urgency=low * Bug fix release * Corrected small display snafu in details window -- Dirk Eddelbuettel Thu, 15 Jun 2000 21:30:20 -0400 smtm (1.1.0) unstable; urgency=low * New release with following code changes - for a given stock, multiple positions can now be tracked which answers to the single most frequent feature request (thanks to James Fidell for the inital patch) - European stocks can now show intra-day and weekly charts (thanks to Patrick Koppen for the initial patch) - Australian/New Zealand stocks now show more details - corrected error in European price verification heuristic - corrected bad modes on ~/.smtm directory creation (thanks to Eduardo PĂŠrez Ureta for pointing this out) -- Dirk Eddelbuettel Wed, 3 May 2000 22:03:58 -0400 smtm (1.0.3) unstable; urgency=low * New release with the following code changes - more robust splitting of .csv data by using quotewords() from the Text::ParseWords modules - for UK shares, switched back to UK server - UK server now provides more info, so we use it - Australia server now supplies charts, so we use them - if needed, provide a default timezone for the other OS -- Dirk Eddelbuettel Wed, 26 Apr 2000 22:55:30 -0400 smtm (1.0.2) unstable; urgency=low * Changed to recognise .OB as a North American exchange so that the over the counter bulletin board (OTC BB) can be followed -- Dirk Eddelbuettel Wed, 5 Apr 2000 20:56:34 -0400 smtm (1.0.1) unstable; urgency=low * Corrected variable assignment in get_firewall_id so that we actually keep the firewall id. Thought I had fixed this ages ago... -- Dirk Eddelbuettel Thu, 23 Mar 2000 20:19:25 -0500 smtm (1.0.0) unstable; urgency=low * New release with the following code changes o uses different server for European quotes - we now get company names along with price data - new server appears to be more reliable as well o displayed length of stock name now has an upper limit o changed File->Exit menu shortcut to 'Alt-f x' o also changed a few Edit menu shortcuts o added Caldera to the default portfolio o a few small display enhancements and corrections * Changes from a (modified) patch by Mark Gelinas o unavailable charts now signaled with error window o purchase date and price information is now saved o column selection properly init'ed from conffile (Closes: #60337) o corrected a short cut key for sort and chart menu o added purchase prices and dates to default portfolio * Changes from a (modified) patch by Mark Gelinas o new option --percent, as well as a new checkbutton, to switch between basispoint and percent display of relative performance o modified --help display and pod documentation accordingly * debian/menu: Added as supplied by Dan Willet -- Dirk Eddelbuettel Tue, 21 Mar 2000 21:44:27 -0500 smtm (0.9.9) unstable; urgency=low * New release with the following code changes o display routine enhanced once more: - any column can now be turned on or off for the display - new 'header' row with column labels - new columns volume, holding period and annualised return o purchase date and price information added to per-stock info o new file load / save windows using the default Tk widgets - use a default directory ~/.smtm for SMTM files o new 'Edit Stock' window available with middle mouse button o data sanity check added for European quotes - prevent the 'dropped decimal point' misfeatures - if current price > day_high, set to yesterday + change o data fields are pre-initialised before data retrieval - if Yahoo! data is unavailable, no unintialised data encountered - this makes the European site more reliable o improved 'Add Stock' window with much cleaner layout o improved 'Delete Stock' window with stock name instead of symbol o improved 'Firewall Id' window with cleaner layout o new sort options volume, holding period and annualised return o three additional fields displayed in 'details window' o simpler and more compact menu structure o firewall info retrieved earlier, if needed o balloon help over display buttons * debian/control: Added Build-Depends * debian/control: Added Depends: on libdate-manip-perl -- Dirk Eddelbuettel Mon, 28 Feb 2000 22:44:49 -0500 smtm (0.9.1) unstable; urgency=low * New release with the following code changes - applied patch by Hamish Moffatt for stocks from Australia + New Zealand - optional share names again work for US/Canada - if unset, set $HOME to C:/TEMP under Win?? - Makefile uses -D to create the $mandir if need be -- Dirk Eddelbuettel Sat, 29 Jan 2000 11:56:13 -0500 smtm (0.9.0) frozen unstable; urgency=low * New release with the following code changes - Rewritten display routines so that each column now uses the optimial, i.e. minimal, column size (Closes: #55397) - Added sorting options for different sorting criteria - European shares are no longer in a distinct block but mixed with the North American ones and consistently sorted - More discrete window title with relative basispoint change - Uppercasing of the symbol cleaned up, `BRKa' now works - Empty lines are now allowed in ~/.smtmrc - Added a BUGS file to the distribution set - More code cleanups -- Dirk Eddelbuettel Thu, 20 Jan 2000 20:59:12 -0500 smtm (0.8.3) unstable; urgency=low * New release with the following code changes: - Details window now also reports number of shares held, daily change (in local currency) and total position value (in local currency) - Delete temporary file for chart data -- Dirk Eddelbuettel Tue, 11 Jan 2000 18:59:55 -0500 smtm (0.8.2) unstable; urgency=low * New release with the following code changes: - Reverted the change made in 0.7.0 and use destroy(), not withdraw() as the latter does not release the memory used - New option `--nookbutton' to suppress the `Ok' button on subordinate windows and close on left-mouse click instead, default behaviour is the initial smtm behaviour - New option `--timeout len' to set the timeout used with libwww-perl's UserAgent -- Dirk Eddelbuettel Wed, 22 Dec 1999 15:28:13 -0500 smtm (0.8.1) unstable; urgency=low * Do not save the firewall info in the resource file as it might contain a secure password -- Dirk Eddelbuettel Sun, 19 Dec 1999 20:50:02 -0500 smtm (0.8.0) unstable; urgency=low * New release with the following code changes: - Charts are now displayed upon right-mouse click - Chart type can be selected in a new menu, or on the cmd line - New option for sort by intra-day percentage change - New menu for immediate screen update - Chart and details window now close on mouse click - Also set iconname() with title() information - Also set activeforeground to red for losers - Selected options are also saved with stocks in File->Save - Version number shown in --help and Help->Manual - Version number automatically updated from debian/rules -- Dirk Eddelbuettel Sat, 18 Dec 1999 21:58:45 -0500 smtm (0.7.0) unstable; urgency=low * New release with the following code changes: - Added support for simple proxy firewalls via --proxy http://1.2.3.4:80 - Added support for account+password firewalls: info can be specified via cmd-line args or in a new "account / password" window - Added test for previous_close != 0 to avoid potential division by zero - Replaced destroy() with withdraw() for closing windows, seems to avoid triggering a segfault error which is presumably inside perl/tk - Renamed option variables for clarity (yeah right) - Added LNUX to default portfolio -- Dirk Eddelbuettel Mon, 13 Dec 1999 21:19:39 -0500 smtm (0.6.0) unstable; urgency=low * New release with the following code changes: - Allow for additional specification of number of shares held as well as the (ISO) cross-currency pair to map into domestic monies - Use this info to display net portfolio gain or loss in window title - Additional option --wide, and menu selector, for `wide' display with per share gain or loss and total holdings - menus now have underlined shortcuts for ALT-x - more code cleanup -- Dirk Eddelbuettel Tue, 7 Dec 1999 21:21:14 -0500 smtm (0.5.2) unstable; urgency=low * New release with the following code changes: - Some cleanup of global data structures - Small logic fix at startup with no file or args - Now allows for name as optional argument in rc file, ie instead of writing `BT.A.L' you can now write `BT.A.L:BRIT TELECOM' and the optional name will be displayed to overcome the fact that Yahoo! UK does not supply one - The optional name is preserved when saving as well, no support yet to specify it in the `Add Stock' window -- Dirk Eddelbuettel Thu, 2 Dec 1999 23:41:31 -0500 smtm (0.5.1) unstable; urgency=low * New release with the following code changes: - New `Details' window opens when clicking on a stock - Added firewall proxy support via env.vars thanks to Behan Webster - Additional menu to set delay between data updates - Added labels to selection and deletion windows - Corrected window size for license window - Main display uses one digit more for price and price change -- Dirk Eddelbuettel Wed, 1 Dec 1999 22:09:06 -0500 smtm (0.5.0) unstable; urgency=low * Initial Debian (and upstream) release. -- Dirk Eddelbuettel Fri, 26 Nov 1999 20:57:11 -0500 smtm-1.6.10/debian/menu0000644000232200023220000000016010671400416015052 0ustar pbuilderpbuilder?package(smtm):needs="X11" section="Applications/Network/Communication"\ title="smtm" command="/usr/bin/smtm" smtm-1.6.10/debian/rules0000755000232200023220000000361511003771532015253 0ustar pbuilderpbuilder#! /usr/bin/make -f # -*- makefile -*- # debian/rules file for the Debian/GNU Linux smtm package # Copyright (C) 1999 - 2008 by Dirk Eddelbuettel package := $(shell grep Package debian/control | sed 's/^Package: //') version := $(shell head -1 debian/changelog | \ perl -nle 'm/\S+\s+\((\S+)\)/ && print $$1') debtmp := $(shell pwd)/debian/$(package) srcdir := ../../../progs/perl-tk/smtm # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 update: cp -af $(srcdir)/smtm.pl smtm chmod 0555 smtm # update the $$VERSION field in the perl file perl -p -i -e \ "s/VERSION = \".*\";/VERSION = \""$(version)"\";/" $(package) perl Makefile.PL make dist mv -vf smtm-$(version).tar.gz .. build: build-stamp build-stamp: dh_testdir perl Makefile.PL INSTALLDIRS=vendor $(MAKE) $(MAKE) test pod2html --flush $(package) > $(package).html pod2man $(package) > $(package).1 touch build-stamp clean: dh_testdir dh_testroot rm -f build-stamp -test -f Makefile && $(MAKE) realclean dh_clean pod2html-dircache pod2html-itemcache binary-indep: build dh_testdir dh_testroot dh_clean -k dh_installdirs usr/bin usr/share/man/man1 $(MAKE) install PREFIX=$(debtmp)/usr -rmdir -v $(debtmp)/usr/lib/perl \ $(debtmp)/usr/lib/ \ $(debtmp)/usr/share/perl5 dh_perl dh_installdocs smtm.html TODO THANKS BUGS dh_installexamples examples/* dh_installmenu # dh_installinit # dh_installcron # dh_installmanpages # dh_undocumented dh_installchangelogs dh_compress dh_fixperms # dh_suidregister dh_installdeb dh_gencontrol # dh_md5sums dh_builddeb binary-arch: build source diff: @echo >&2 'source and diff are obsolete - use dpkg-source -b'; false binary: binary-indep binary-arch .PHONY: build clean binary-indep binary-arch binary smtm-1.6.10/debian/copyright0000644000232200023220000000104611016366356016132 0ustar pbuilderpbuilderThis is the Debian GNU/Linux version of the smtm stock ticker program. It provides a configurable Perl program to display one or more stock quotes from Yahoo! Finance sites. This package was both written and put together for Debian by Dirk Eddelbuettel . The sources can also be obtained from http://dirk.eddelbuettel.com/code/smtm/ Copyright (C) 1999 - 2008 Dirk Eddelbuettel License: GPL On a Debian GNU/Linux systems, the complete text of GNU General Public License can be found in the file /usr/share/common-licenses/GPL. smtm-1.6.10/debian/control0000644000232200023220000000260611003770701015572 0ustar pbuilderpbuilderSource: smtm Section: misc Priority: optional Maintainer: Dirk Eddelbuettel Standards-Version: 3.7.3 Build-Depends: debhelper (>= 5.0) Build-Depends-Indep: libwww-perl, libdate-manip-perl, libfinance-yahooquote-perl (>= 0.18), perl-tk (>= 1:804.000) Package: smtm Architecture: all Depends: ${perl:Depends}, libdate-manip-perl, libmime-base64-perl, perl-tk (>= 1:804.000), libfinance-yahooquote-perl (>= 0.18) Description: Show Me The Money is a configurable Perl/Tk stock ticker program smtm, which is a not overly clever acronym for Show Me The Money, is a simple stock ticker and charting application. It creates and automatically updates a window with stock quotes from Yahoo! Finance, as well as optional charts from Yahoo! Finance. . smtm is fully configurable -- it can display the stock symbol and the full name of the company, the price change, the percentage change, the volume traded, the profit or loss, the value of the holding, the length of the holding period, annualised percentage returns and more. The display can be sorted on almost any of the columns. Losers are flagged in red. smtm can be used for most global stock symbols, North American mutual funds and options, currencies and some commodities -- anything supported Yahoo! Finance. . Stock quotes are normally delayed, 15 minutes for NASDAQ and 20 minutes otherwise, see Yahoo! Finance for details. smtm-1.6.10/t/0000755000232200023220000000000007757716415013233 5ustar pbuilderpbuildersmtm-1.6.10/t/use1.t0000644000232200023220000000016607655300257014266 0ustar pbuilderpbuilder#!/usr/bin/env perl -w use strict; use Test; BEGIN { plan tests => 1 } use Finance::YahooQuote; ok(1); exit; __END__ smtm-1.6.10/t/use2.t0000644000232200023220000000014507655300571014263 0ustar pbuilderpbuilder#!/usr/bin/env perl -w use strict; use Test; BEGIN { plan tests => 1 } use Tk; ok(1); exit; __END__ smtm-1.6.10/TODO0000644000232200023220000000436107602725422013447 0ustar pbuilderpbuilder * Keep the information retrieved and have a details window with high/low bid/ask volume .... Would make more sense if Yahoo! UK gave as much detail as Yahoo! NA does. ==> DONE as of 0.5.1 * Maybe not keep the stocks selected simply in @ARGV, but a global hash and also keep a number of shares for each symbol to that we get hard dollar changes for the portfolio ==> DONE as of 0.6.0 * By the same token, also store the reference currency. The file format would then be a comma (or whatever) separated list like BT.A.L,100,EUR BCE.TO,200,CAD or maybe use the Yahoo currency ticker? ==> DONE as of 0.6.0 * And then again, maybe allow for a text string as well to overcome the lacking name string when using the non-US site. Ergo: BT.A.L,100,EUR,British Telecom ==> DONE as of 0.5.2 * User request: Right-mouse click on button to launch browser on Yahoo page ==> maybe, but Yahoo UK doesn't show a chart anyway ==> DONE as of 0.8.0, didn't even need an external browser. Perl/Tk rules. * User request: Allow for purchase price to show total return ==> needed in a stock ticker ? should also allow for purchase date for annualised return ==> DONE as of 0.9.9 * User request: Do not update between 9 and 5, say ==> conflict with local timezones in NA and, say European trading hours maybe add cmd line option for an expression that will be eval'ed ? * Timeout variable ==> DONE as of 0.8.2 * Button preference variable ==> DONE as of 0.8.2 * The "stock detail" window should include how much it contributed to net loss/gain for the day, if appropriate, along with all "other" information like nb of shares, position value etc. ==> as of 0.8.3, provides nb of shares, position value and change value * Would be nice to reorganize smtm so that several windows could be updated from one session, rather than running several Perl sessions * Would be nice to have a few (intra-day) chart windows update automatically * (From a discussion with Jon Solworth) Would be nice to set the background of individual entries to distinguish "thematically" * Should drop the ad-hoc configurarion reading/writing code and probably use one of the Config:: modules from CPAN smtm-1.6.10/Makefile.PL0000644000232200023220000000266710671376613014744 0ustar pbuilderpbuilder# # Makefile.PL for smtm # # smtm --- A global stock ticker for X11 and Windoze # # Copyright (C) 1999 - 2007 Dirk Eddelbuettel # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # use ExtUtils::MakeMaker; WriteMakefile( 'NAME' => 'smtm', 'VERSION_FROM' => 'smtm', 'PREREQ_PM' => { "Date::Manip" => 5.0, "Finance::YahooQuote" => 0.2, "LWP::UserAgent" => 1.23, "MIME::Base64" => 2.12, "HTML::Parser" => 2.20, "Tk" => 800.015, "Tk::PNG" => 2.005 }, ($] >= 5.005 ? ('ABSTRACT' => 'Stock quote monitor and portfolio tool', 'AUTHOR' => 'Dirk Eddelbuettel (edd@debian.org)') : ()), EXE_FILES => ['smtm'], 'dist' => { COMPRESS => 'gzip', SUFFIX => '.gz', }, ); smtm-1.6.10/COPYING0000644000232200023220000004307007020000474013775 0ustar pbuilderpbuilder GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. smtm-1.6.10/smtm.html0000644000232200023220000004634210026221470014616 0ustar pbuilderpbuilder smtm - Display and update a configurable ticker of global stock quotes


NAME

smtm - Display and update a configurable ticker of global stock quotes


SYNOPSYS

 smtm [options] [stock_symbol ...]


OPTIONS

 --time min      minutes to wait before update 
 --file smtmrc   to store/retrieve stocks selected 
 --proxy pr      network address and port of firewall proxy 
 --fwall [id:pw] account and password for firewall 
 --chart len     select length of data interval shown in chart
                 (must be one of b, w, 3, 6, 1, 2, 5 or m)
 --timeout len   timeout in seconds for libwww-perl UserAgent
 --wide          also display value changes and holdings
 --percent       show relative performance in percent instead of bps
 --sort style    sort display by specified style
                 (must be one r, a, p, v, n, v, V or h)
 --columns set   choose the columns to display (can be any combination
                 of s, n, l, a, r, v, p, V, R, h)
 --nookbutton    close other windows via left mouseclick, suppress button
 --help          print a short help message


DESCRIPTION

smtm, which is a not overly clever acronym for Show Me The Money, is a financial ticker and portfolio application for quotes from exchanges around the world (provided they are carried on Yahoo!). It creates and automatically updates a window with quotes from Yahoo! Finance. It can also display the entire variety of charts available at Yahoo! Finance. When called with one or several symbols, it displays these selected stocks. When smtm is called without arguments, it reads the symbols tickers from a file, by default ~/.smtmrc. This file can be created explicitly by calling the Save option from the File menu. Beyond stocks, smtm can also display currencies (from the Philadephia exchange), US mutual funds, options on US stocks, several precious metals and quite possibly more; see the Yahoo! Finance website for full information.

smtm can also aggregate the change in value for both individual positions and the the entire portfolio. For this, the number of shares is needed, as well as the cross-currency expression pair. The standard ISO notation is used. As an example, GBPUSD translates from Pounds into US Dollars. To compute annualised returns, the purchase date and purchase price can also be entered.

smtm displays the full name of the company, the absolute price change and the relative percentage change in basispoints (i.e., hundreds of a percent) or in percentages if the corresponding option has been selected. Other information that can be displayed are the traded volume, the profit/loss, the aggregate positon value, the holding period length, the annualised return, the drawdown, the earnings per share, the price/earnings ratio, the dividend yield, and the market capitalization. Note that the return calculation ignores such fine points as dividends, and foreign exchange appreciation or depreciation for foreigns stocks. All display columns can be selected, or deselected, individually.

Losers are flagged in red. smtm can be used for stocks from the USA, Canada, various European exchanges, various Asian exchanges (Singapore, Taiwan, HongKong, Kuala Lumpur, ...) Australia and New Zealand. It should work for other markets supported by Yahoo. US mutual funds are also available, but less relevant as their net asset value is only computed after the market close. Some fields might be empty if Yahoo! does not supply the full set of fields; the number of supported fields varies even among US exchanges. The sorting order can be chosen among eight different options.

The quotes and charts are delayed, typically 15 minutes for NASDAQ and 20 minutes otherwise, see http://finance.yahoo.com for details. New Zealand is rumoured to be somewhat slower with a delay of one hour. However, it is worth pointing out that (at least some) US) indices are updated in real time at Yahoo!, and therefore available in real time to smtm. Intra-day and five-day charts are updated during market hours by Yahoo!, other charts with longer timeframes are updated only once a week by Yahoo!.

smtm supports both simple proxy firewalls (via the --proxy option) and full-blown firewalls with account and password authorization (via the --fwall option). Firewall account name and password can be specified as command line arguments after --fwall, or else in a pop-up window. This setup has been in a few different environments.

smtm can display two more views of a share position. Clicking mouse button 1 launches a detailed view with price, date, change, volume, bid, ask, high, low, year range, price/earnings, dividend, dividend yield, market capital information, number of shares held and annualised return. However, not all of that information is available at all exchanges. Clicking the right mouse button display a chart of the corresponding stock; this only works for US and Canadian stocks. The type of chart can be specified either on the command-line, or via the Chart menu. Choices are intraday, five day, three months, six months, one year, two years, five years or max years. The default chart is a five day chart. The middle mouse button opens an edit window to modify and augment the information stored per stock.

See http://help.yahoo.com/help/us/fin/chart/ for help on Yahoo! Finance charts.

smtm has been written and tested under Linux. It should run under any standard Unix, success with Solaris, HP-UX and FreeBSD is confirmed (but problems are reported under Solaris when a threaded version of Perl is used). It also runs under that other OS from Seattle using the ActivePerl implementation from http://www.activestate.com. In either case, it requires the Perl/Tk module for windowing, and the LWP module (also known as libwww-perl) for data retrieval over the web. The excellent Date::Manip modules is also required for the date parsing and calculations. With recent versions of ActivePerl, only Date::Manip needs to be installed on top of the already provided modules.


EXAMPLES

  smtm CSCO NT

creates a window following the Cisco and Nortel stocks.

  smtm MSFT:Bill SUNW:Scott ORCL:Larry

follows three other tech companies and uses the override feature for the displayed name. [ Historical note: We once needed that for European stocks as Yahoo! did not supply the company name way back in 1999 or so. This example just documents a now ancient feature. ]

  smtm  BT.A.L::10:GBPCAD   T::10:USDCAD \
        BCE.TO::10   13330.PA::10:EURCAD \
        "555750.F:DT TELECOM:10:EURCAD"

creates a window with prices for a handful of telecom companies on stock exchanges in London, New York, Toronto, Paris and Frankfurt. Note how a names is specified to override the verbose default for the German telco. Also determined are the number of shares, here 10 for each of the companies. Lastly, this example assumes a Canadian perspective: returns are converted from British pounds, US dollars and Euros into Canadian dollars. Quotation marks have to be used to prevent the shell from splitting the argument containing spaces. [ Historical note: The Deutsche Telecom stock can now also be referenced as DTEGn.DE; similarly other stock previously available only under their share number are now accessible using an acronym reflecting their company name.]


MENUS

Four menus are supported: File, Edit, Chart and Help. The File menu offers to load or save to the default file, or to 'save as' a new file. Exit is also available.

The Edit menu can launch windows to either add a new stock or delete one or several from a list box. Submenus for column selection based on various criteria are available. Similarly, the Sort menu allows to select one of eight different sort options. Further, one can modify the delay time between updates and choose between the default title display or the wide display with changes in the position and total position value.

The Charts menu allows to select the default chart among the eight choices intraday, five day, three months, six months, one year, two years, five years or 'max' years. Chart sizes can be selected among three choices. Plot types can be selected among line chart, bar chart and the so-called candlestick display. For both moving averages and exponential moving averages, six choices are avilable (5, 10, 20, 50, 100 and 200 days, respectively) which can all be selected (or deselected) individually. Similarly, any one of seven popular technical analysis charts can be added. Logarithmic scale can be turned on/off. Volume bar charts as also be selected or deselected. Similarly, Bollinger bands and the parabolic SAR can be selected. A selection box can be loaded to enter another symbol (or several of these, separated by comma) for performance comparison. Lastly, the gallery command can launch the display of a chart for each and every stock symbol currenly loaded in the smtm display. Note that intra-day and intra-week charts do not offer all the various charting options longer-dated charts have available. Once charts are shown, they are also updated regularly at the same interval the main displayed is updated at.

Lastly, the Help menu can display either the text from the manual page, or the copyright information in a new window.


DISPLAY

The main window is very straightforward. For each of the stocks, up to eleven items can be displayed: its symbol, its name, its most recent price, the change from the previous close in absolute terms, the change in relative terms, the volume, the profit or loss, the total position value, the holding period, the annualised return (bar F/X effects or dividends) and the drawdown relative to the 52-week high. The relative change is either expressed in basispoints (bps), which are 1/100s of a percent, or in percent; this can be controlled via a checkbutton as well as an command-line option. Further display options are earnings per share, price/earnings ratio, dividend yield and market capitalization. This display window is updated in regular intervals; the update interval can be specified via a menu or a command-line option.

The window title displays the relative portfolio profit or loss for the current day in basispoints, i.e., hundreds of a percent, or in percent if the corresponding option is chosen, as well as the date of the most recent update. If the --wide options is used, the net change and ney value of the portfolio (both in local currency) are also displayed.

Clicking on any of the stocks with the left mouse button opens a new window with all available details for a stock. Unfortunately, the amount of available information varies. Non-North American stocks only have a limited subset of information made available via the csv interface of Yahoo!. For North American stocks, not all fields all provided by all exchanges. Clicking on the details display window itself closes this window. Clicking on any of the stocks with the right mouse button opens a new window with a chart of the given stock in the default chart format. This option was initially available only for North American stocks but now works across most if not all markets, thanks to expanded support by Yahoo!. Clicking on the chart window itself closes this window. Finally, the middle mouse button opens an edit window.


CHART DISPLAY (AKA 'GALLERY' MODE)

In 'gallery' mode, chart windows are opened for all active securities. These charts are automatically updated whenever the display is updated. This mean that only the intra-daily and intra-weekly chart timeframe selection are meaningful -- all others are updated at the source, i.e. Yahoo!, daily or weekly, and there is no little point in downloading the same chart over and over again.

However, for intra-daily and intra-weekly charts, this is a very useful feature. It should be noted that not all chart size, chart timeframe and chart option permutations actually lead to existing charts. For example, logarithmic scale does seem to exist for shorter-dated time frames. Neither does the 'small' chart size.


BUGS

Closing the stock addition or deletion windows have been reported to cause random segmentation violation under Linux. This appears to be a bug in Perl/Tk which will hopefully be solved, or circumvented, soon. This bug does not bite under Solaris, FreeBSD or NT or other Linux distributions. Update: This problem appears to have disappeared with Perl 5.6.*.

Problems with undefined symbols have been reported under Solaris 2.6 when Perl has been compiled with thread support. Using an unthreaded Perl binary under Solaris works. How this problem can be circumvented is presently unclear.

It is not clear whether the market capitalization information is comparable across exchange. Some differences could be attributable to 'total float' versus 'free float' calculations.


SEE ALSO

Finance::YahooQuote.3pm, Finance::YahooChart.3pm, LWP.3pm, lwpcook.1, Tk::UserGuide.3pm

See http://help.yahoo.com/help/us/fin/chart/ for help on Yahoo! Finance charts.


COPYRIGHT

smtm is (c) 1999 - 2004 by Dirk Eddelbuettel <edd@debian.org>

Updates to this program might appear at http://dirk.eddelbuettel.com/code/smtm.html. If you enjoy this program, you might also want to look at my beancounter program http://dirk.eddelbuettel.com/code/beancounter.html, as well as the Finance::YahooQuote module at http://dirk.eddelbuettel.com/code/yahooquote.html which was originally written by Dj Padzensky, and that is used by both smtm and beancounter.

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. There is NO warranty whatsoever.

The information that you obtain with this program may be copyrighted by Yahoo! Inc., and is governed by their usage license. See http://www.yahoo.com/docs/info/gen_disclaimer.html for more information.


ACKNOWLEDGEMENTS

The Perl code by Dj Padzensky, in particular his Finance::YahooQuote module (originally on the web at http://www.padz.net/~djpadz/YahooQuote/ and now maintained by me at http://dirk.eddelbuettel.com/code/yahooquote.html/) and his Finance::YahooChart module (on the web at http://www.padz.net/~djpadz/YahooChart/) were most helpful. They provided the initial routines for downloading stock data and determining the Yahoo! Chart url. Earlier version of smtm use a somewhat rewrittem variant (which still reflected their heritage), newer version rely directly on Finance::YahooQuote now that Yahoo! uses a similar backend across the globe. Dj's code contribution is most gratefully acknowledged.


CPAN

The remaining sections pertain to the CPAN registration of smtm. The script category is a little mismatched but as there is no Finance section, Networking was as good as the other choices.


SCRIPT CATEGORIES

Networking


PREREQUISITES

On Windows, smtm can use the Perl distribution from http://www.activestate.com. On both Unix and Windows, smtm requires the Tk module for windowing, the LWP module for data retrieval over the web, and the excellent Date::Manip module for the date parsing and calculations.


COREQUISITES

None


OSNAMES

smtm is not OS dependent. It is known to run under Linux, several commercial Unix variants and Windows


README

smtm, which is a not overly clever acronym for Show Me The Money, is a financial ticker and portfolio application for quotes from exchanges around the world (provided they are carried on Yahoo!). It creates and automatically updates a window with quotes from Yahoo! Finance. It can also display the entire variety of charts available at Yahoo! Finance. Fairly extensive documentation for smtm is available at http://dirk.eddelbuettel.com/code/smtm.html.

smtm-1.6.10/MANIFEST0000644000232200023220000000044510026226571014102 0ustar pbuilderpbuilderBUGS COPYING MANIFEST META.yml Makefile.PL README THANKS TODO smtm smtm.1 smtm.html examples/currencies.smtm examples/global.smtm examples/indices.smtm examples/mutualfunds.smtm examples/options.smtm examples/southamerica.smtm examples/telcos.smtm examples/worldindices.smtm t/use1.t t/use2.t smtm-1.6.10/examples/0000755000232200023220000000000007757716415014606 5ustar pbuilderpbuildersmtm-1.6.10/examples/indices.smtm0000644000232200023220000000206307524112032017100 0ustar pbuilderpbuilder# # smtm version 1.4.0 resource file saved on 07/31/02 03:32:28 PM # wide=1 nookbutton=1 delay=1 timeout=60 percent=0 columns=arln sort=f chart::style=l chart::bollinger=1 chart::ma= chart::volume=1 chart::parabolic_sar=0 chart::length=1 chart::ema=20: chart::size=m chart::comparison= chart::technical=r14:p12: chart::log_scale=1 ^DJI::0::0:0 DIA::0::0:0 ^DJX::0::0:0 ^IXIC::0::0:0 ^NDX::0::0:0 QQQ::0::0:0 ^SPX::0::0:0 SPY::0::0:0 ^OEX::0::0:0 ^VIX::0::0:0 ^MID::0::0:0 ^SML::0::0:0 ^NYA::0::0:0 ^TV.N::0::0:0 ^TIC.N::0::0:0 ^STI.N::0::0:0 ^TV.O::0::0:0 ^TIC.O::0::0:0 ^STI.O::0::0:0 ^XAX::0::0:0 ^RUA::0::0:0 ^TMW::0::0:0 ^TYX::0::0:0 ^TNX::0::0:0 ^XAU::0::0:0 ^HUI::0::0:0 ^BIX::0::0:0 ^BKX::0::0:0 ^XBD::0::0:0 ^BTK::0::0:0 BBH::0::0:0 ^SOXX::0::0:0 SMH::0::0:0 ^YLS::0::0:0 WMH::0::0:0 ^XTC::0::0:0 ^XAL::0::0:0 ^XOI::0::0:0 ^XNG::0::0:0 ^OSX::0::0:0 ^DJU::0::0:0 ^XUH::0::0:0 ^DJUSCH::0::0:0 ^DJUSCY::0::0:0 ^DJUSEN::0::0:0 ^DJUSFN::0::0:0 ^DJUSFV::0::0:0 ^DJUSHC::0::0:0 ^DJUSIV::0::0:0 ^DJUSNC::0::0:0 ^DJUSRE::0::0:0 ^DJUSTC::0::0:0 ^DJUSTL::0::0:0 ^DJUSUT::0::0:0 smtm-1.6.10/examples/worldindices.smtm0000644000232200023220000000053407305031133020150 0ustar pbuilderpbuilder# # smtm example file with several stock market indices from around the world # it appears that several of these are in fact updated in real time # # use http://finance.yahoo.com/l to search for other symbols # ^DJI::0::0:0 ^EUN::0::0:0 ^FCHI::0::0:0 ^FTSE::0::0:0 ^GDAXI::0::0:0 ^HSI::0::0:0 ^IXIC::0::0:0 ^N225::0::0:0 ^SPX::0::0:0 ^TSE::0::0:0 smtm-1.6.10/examples/global.smtm0000644000232200023220000000052507302620161016724 0ustar pbuilderpbuilder# # simple example file for stocks from Australia, New Zealand, Germany, # France, Britain, Italy, Spain, Sweden, Canada and the US # # you probably want to look at a particular exchange's page in Yahoo # (e.g. fr.finance.yahoo.com for France) to search for stocks # TLSCB.AX CDL.NZ 555750.F 13046.PA BPA.L OL.MI TEF.MC VOLV-A.ST BCE.TO T smtm-1.6.10/examples/mutualfunds.smtm0000644000232200023220000000025607302621575020046 0ustar pbuilderpbuilder# # smtm example file with different US mutual funds # # use http://finance.yahoo.com/l to search for other symbols # # default to one-year chart $chart=1 # EMF FSPTX VFINX smtm-1.6.10/examples/currencies.smtm0000644000232200023220000000014507302620735017633 0ustar pbuilderpbuilder# # currency examples # # see http://finance.yahoo.com/m3?u for more # ^XAD ^XBP ^XCD ^XEU ^XJY ^XSF smtm-1.6.10/examples/options.smtm0000644000232200023220000000031607302620056017160 0ustar pbuilderpbuilder# # smtm example file with different US options # see http://biz.yahoo.com/opt/ for more on Yahoo! option's coverage # # use http://finance.yahoo.com/l to search for other symbols # CYQJE.X MSQJP.X QQQLX.X smtm-1.6.10/examples/southamerica.smtm0000644000232200023220000000012407461412572020156 0ustar pbuilderpbuilder# minimal file with four South American stocks TELMEXL.MX EBTP4.SA EDC.CR STG.SN smtm-1.6.10/examples/telcos.smtm0000644000232200023220000000032607302620420016752 0ustar pbuilderpbuilder# # a simple Telecom stocks example # all returns are translated into Canadian dollars # 13330.PA::10:EURCAD:0:0 555750.F::10:EURCAD:0:0 TEF.MC::10:EURCAD:0.0 BCE.TO::10::0:0 BT.A.L::10:GBPCAD:0:0 T::10:USDCAD:0:0 smtm-1.6.10/THANKS0000644000232200023220000000536010671376557013705 0ustar pbuilderpbuilderBehan Webster for a one-line patch with proxy support Chris Steigies for pointing out a div-by-zero error as well as other errors (which often were server related) Anibal Acero for another one-line patch with proxy support Lars Steinke for bugging me into adding firewall id/passwd support Koos Pol for suggesting to uppercase the symbol and to add version info Brian Campbell for a patch with different UI configs I mostly adapted, as well as good discussion on UI preferences Joey Hess for bugging me to rewrite the display Tom Fawcett for an enhancement to the Makefile Hamish Moffatt for the Australian / New Zealand patch Pierre Abbat for a note on (bare-bones) metals price info on Yahoo Mark Gelinas for a very thorough patch that moved things towards 1.0.0 Dan Willet for supplying a Debian menu file Owen Wild for a patch with --percent support James Fidell for a thorough patch to allow multiple positions for a given stock (single most popular feature request) Ruben Schattevoy for a patch to split .csv better (but we use another module anyway) Eduardo Pérez Ureta for pointing out that the mkdir mode was off Patrick Koppen for the initial patch for European charts Mattia Monga for pointing out that Date::Manip 5:38 was breaking smtm Dwight Johnson for pointing out that Date::Manip 5:38 was breaking smtm Sullivan Beck for accepting my Date::Manip patch upstream :) Kwok Chern Yue for the initial patch for better Asian support David Talmage for pointing out that most Yahoo! chart URLs were broken OGRO74@aol.com for asking for support for Mexican quotes which lead to largeish revision that does away with country restrictions Cord Beerman for an initial patch to cope better with bad Yahoo! data Yin Zhou for a (modified) patch to sort as per .smtm file order Paul Brossier for pointing out that fx symbols as GBPEUR=X didn't load Chris Eidem for reporting the LWP::UserAgent issue Bruce Bowler for suggesting to tighten use of pack(-fill, not pack(fill Robert A. Schmied for pointing out the error in 'show_details', and a patch that fixed a decent part of it, and then some more patches :) Bruce Bowler, Michael Labhard, Thomas Chiverton, "Jim", Russ Herrold for the heads-up about Yahoo!'s gif-to-png change Michael Kurlin, Clinton R Lambe, Ian Seow for noticing the required change in Yahoo!'s chart url and all the kind folks who dropped a line to either report a bug, and/or say that they liked the program...