smtm-1.6.11/ 0000755 0000000 0000000 00000000000 12564114244 007451 5 ustar smtm-1.6.11/smtm.html 0000644 0000000 0000000 00000044011 12564114012 011310 0 ustar
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, 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
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.]
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 - 2008 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. 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.
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.11/pod2htmi.tmp 0000644 0000000 0000000 00000000003 10026221467 011707 0 ustar
.
smtm-1.6.11/THANKS 0000644 0000000 0000000 00000005360 10671376557 010406 0 ustar Behan 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...
smtm-1.6.11/MANIFEST 0000644 0000000 0000000 00000000445 10026226571 010603 0 ustar BUGS
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.11/smtm 0000755 0000000 0000000 00000214320 11016366272 010362 0 ustar #!/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.11/pod2htmd.tmp 0000644 0000000 0000000 00000000003 12564114012 011676 0 ustar
.
smtm-1.6.11/COPYING 0000644 0000000 0000000 00000043070 07020000474 010476 0 ustar 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.11/META.yml 0000644 0000000 0000000 00000001065 10364326430 010722 0 ustar # 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.11/Makefile.PL 0000644 0000000 0000000 00000002667 10671376613 011445 0 ustar #
# 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.11/README 0000644 0000000 0000000 00000010567 10671376603 010350 0 ustar
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.11/debian/ 0000755 0000000 0000000 00000000000 12564114244 010673 5 ustar smtm-1.6.11/debian/Makefile 0000644 0000000 0000000 00000003462 10242011413 012321 0 ustar
# 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.11/debian/compat 0000644 0000000 0000000 00000000001 10671377427 012103 0 ustar 5 smtm-1.6.11/debian/changelog 0000644 0000000 0000000 00000054503 12564113034 012550 0 ustar smtm (1.6.11) unstable; urgency=low
* debian/rules: Use DESTDIR for required MakeMaker change in Perl 5.22
(Closes: #795680)
* debian/rules: Add build-arch and build-indep targets [lintian]
* debian/control: Add Depends: on ${misc:Depends} [lintian]
* debian/control: Update Standards-Version: to 3.9.6 [lintian]
* debian/copyright: Refer to version'ed GPL [lintian]
-- Dirk Eddelbuettel Sun, 16 Aug 2015 08:47:25 -0500
smtm (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.11/debian/rules 0000755 0000000 0000000 00000003551 12564112737 011764 0 ustar #! /usr/bin/make -f
# -*- makefile -*-
# debian/rules file for the Debian/GNU Linux smtm package
# Copyright (C) 1999 - 2015 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-arch build-indep
build-arch: build-stamp
build-indep: 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 DESTDIR=$(debtmp)
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.11/debian/copyright 0000644 0000000 0000000 00000001067 12564113175 012634 0 ustar This 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 - 2015 Dirk Eddelbuettel
License: GPL-2
On a Debian GNU/Linux systems, the complete text of GNU General Public
License (version 2) can be found in the file /usr/share/common-licenses/GPL-2.
smtm-1.6.11/debian/control 0000644 0000000 0000000 00000002627 12564112757 012314 0 ustar Source: smtm
Section: misc
Priority: optional
Maintainer: Dirk Eddelbuettel
Standards-Version: 3.9.6
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}, ${misc: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.11/debian/menu 0000644 0000000 0000000 00000000160 10671400416 011553 0 ustar ?package(smtm):needs="X11" section="Applications/Network/Communication"\
title="smtm" command="/usr/bin/smtm"
smtm-1.6.11/examples/ 0000755 0000000 0000000 00000000000 07757716415 011307 5 ustar smtm-1.6.11/examples/worldindices.smtm 0000644 0000000 0000000 00000000534 07305031133 014651 0 ustar #
# 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.11/examples/southamerica.smtm 0000644 0000000 0000000 00000000124 07461412572 014657 0 ustar # minimal file with four South American stocks
TELMEXL.MX
EBTP4.SA
EDC.CR
STG.SN
smtm-1.6.11/examples/global.smtm 0000644 0000000 0000000 00000000525 07302620161 013425 0 ustar #
# 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.11/examples/mutualfunds.smtm 0000644 0000000 0000000 00000000256 07302621575 014547 0 ustar #
# 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.11/examples/indices.smtm 0000644 0000000 0000000 00000002063 07524112032 013601 0 ustar #
# 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.11/examples/telcos.smtm 0000644 0000000 0000000 00000000326 07302620420 013453 0 ustar #
# 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.11/examples/options.smtm 0000644 0000000 0000000 00000000316 07302620056 013661 0 ustar #
# 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.11/examples/currencies.smtm 0000644 0000000 0000000 00000000145 07302620735 014334 0 ustar #
# currency examples
#
# see http://finance.yahoo.com/m3?u for more
#
^XAD
^XBP
^XCD
^XEU
^XJY
^XSF
smtm-1.6.11/TODO 0000644 0000000 0000000 00000004361 07602725422 010150 0 ustar
* 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.11/smtm.1 0000644 0000000 0000000 00000051247 12564114012 010515 0 ustar .\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
.\"
.\" Standard preamble:
.\" ========================================================================
.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. \*(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-
.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" ''
. ds C`
. ds C'
'br\}
.\"
.\" Escape single quotes in literal strings from groff's Unicode transform.
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.\"
.\" If the F register is turned on, we'll generate index entries on stderr for
.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
.\" entries marked with X<> in POD. Of course, you'll have to process the
.\" output yourself in some meaningful fashion.
.\"
.\" Avoid warning from groff about undefined register 'F'.
.de IX
..
.nr rF 0
.if \n(.g .if rF .nr rF 1
.if (\n(rF:(\n(.g==0)) \{
. if \nF \{
. de IX
. tm Index:\\$1\t\\n%\t"\\$2"
..
. if !\nF==2 \{
. nr % 0
. nr F 2
. \}
. \}
.\}
.rr rF
.\"
.\" 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 "2008-05-25" "perl v5.20.2" "User Contributed Perl Documentation"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
.nh
.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 10
\& \-\-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
.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 \- 2008 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. 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.
.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.11/t/ 0000755 0000000 0000000 00000000000 07757716415 007734 5 ustar smtm-1.6.11/t/use1.t 0000644 0000000 0000000 00000000166 07655300257 010767 0 ustar #!/usr/bin/env perl -w
use strict;
use Test;
BEGIN { plan tests => 1 }
use Finance::YahooQuote; ok(1);
exit;
__END__
smtm-1.6.11/t/use2.t 0000644 0000000 0000000 00000000145 07655300571 010764 0 ustar #!/usr/bin/env perl -w
use strict;
use Test;
BEGIN { plan tests => 1 }
use Tk; ok(1);
exit;
__END__
smtm-1.6.11/BUGS 0000644 0000000 0000000 00000001064 07322467033 010140 0 ustar
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.