[mythtv-users] mythstocks.pl - a stock ticker for mythtvosd

Greg Newton greg.newton at exemail.com.au
Wed Apr 9 07:29:27 UTC 2008


G'day all

Below is a little script I'm using to display stock prices using
mythtvosd. It can optionally calculate the value and change in your
portfolio, and display that at the end of the stock list.

To set up your portfolio, run mythstocks.pl with the -a option once
per stock, e.g.

./mythstocks.pl -a csco

will add Cisco (without any quantity held).

./mythstocks.pl -a msft:100000

will add 100000 shares of Mickeysoft. Alternatively you could edit
~/.mythtv/mythstocks.xml directly, which may prove less cumbersome.

You only need to define a holding quantity if you also enable display
of your portfolio totals, by

./mythstocks.pl -o showtotal:1

If your shares are not held in a major US stock market, you'll need to
determine the suffix used by Yahoo to indicate your market, and define
that with

./mythstocks.pl -o suffix:.AX

(the example is for the ASX). Alternatively you could just specify the
stocks with their suffix included (i.e. ADA.AX for Adacel on the
Australian Stock Exchange).

You can make this fire up with a remote button by doing something like
this in your .licrc file (note the backquotes):

begin
    prog = irexec
    button = 16.9-4.3
    config = mythtvosd --template="scroller"
--scroll_text="`/home/greg/mythstocks.pl`"
end

I hope someone can find this useful :-)

---- snip ----
#!/usr/bin/perl
#-----------------------------------------------------------------------------
# FILENAME: mythstocks.pl
# PROJECT:
# PURPOSE:  Read stock prices from Yahoo and print a string suitable for
#           use by mythtvosd --template="scroller"
--scroll_text="`mythstocks.pl`"
#
#-----------------------------------------------------------------------------
# REVISION HISTORY
#-----------------------------------------------------------------------------
# Rev   | Created by                 | Date       | Changes made
#-------+----------------------------+------------+---------------------------
# 0.0.1 | greg.lazybastard at gmail.com | 17/03/2008 | First test
# 0.0.2 | greg.lazybastard at gmail.com | 08/04/2008 | Move to XML portfolio
#-----------------------------------------------------------------------------
my $ver = '0.0.2';

################################################################
# Use modules
################################################################

    # Be strict about the perl
    use strict ;

    # be lazy about getting cmdline options
    use Getopt::Std ;

    # for talking http
    use LWP::Simple;

    # For storage of portfolio
    use XML::Simple;

    # For pretty timestamps
    use POSIX qw(strftime);

    # For easy parsing of csv
    use Text::CSV;

################################################################
# 'Global' constants
################################################################
    my $configfile = $ENV{'HOME'}.'/.mythtv/mythstocks.xml' ;
    my $config;
    our ($opt_p, $opt_a, $opt_r, $opt_o);

################################################################
# Read the config file if it exists, create it if not
################################################################
    read_config(\$config);
    # shortcuts to sections of the config file
    my $opt = \$config->{'section'}->{'options'};
    my $port = \$config->{'section'}->{'portfolio'};

################################################################
# Get command line options
# -p                        print all options
# -a symbol[:holding]       add / update a symbol
# -r symbol                 remove a symbol
# -o option:value , where option is one of
#         showtotal (0,1)
#         source    (string)
#         suffix    (string, . must be used to represent no suffix)
#         format    (string)
################################################################
    getopts('pa:r:o:');

    # p = print current settings / portfolio
    if( defined($opt_p) ) {
        printf "mythstocks v$ver\n";
        printf "\nCurrent settings (stored in %s):\n",$configfile;
        foreach( keys %{$$opt}  ) {
            printf "\t%12s: %20s\n", $_, ${$opt}->{$_}[0];
        }
        printf "\nCurrent portfolio:\n";
        foreach( keys %{$$port} ) {
            printf "\t%12s: %20s\n", $_, ${$port}->{$_}[0];
        }
        exit 0;
    }

    # a = add (or modify) a symbol and optionally holding size
    if( defined($opt_a) ) {
        my ($symbol,$holding) = split /:/, $opt_a ;
        $symbol = uc($symbol);
        if( !defined($holding) ) {
            $holding = '0';
        }
        ${$port}->{$symbol}[0] = $holding;
        write_config($config);
        printf "Symbol `%s' (holding %s)\nExiting.\n", $symbol, $holding;
        exit 0;
    }

    # r = remove symbol
    if( defined($opt_r) ) {
        $opt_r = uc($opt_r);
        if( defined( ${$port}->{$opt_r}[0] ) ) {
            delete ${$port}->{$opt_r}[0];
            write_config($config);
            printf "Removing %s from portfolio\nExiting.\n", $opt_r;
        } else {
            printf "Symbol %s not found in the portolio\nExiting.\n", $opt_r;
        }
        exit 0;
    }

    # o = set an option - no checking for validity
    if( defined($opt_o) ) {
        my ($key,$value) = split /:/, $opt_o ;
        ${$opt}->{$key}[0] = $value;
        write_config($config);
        printf "Set option `%s' to `%s'\nExiting.\n", $key, $value;
        exit 0;
    }

    # No command line options, default action is to read from yahoo

    # Nothing to do unless portfolio contains symbols
    my @syms = keys %{$$port};
    if( $#syms lt 0 ) {
        print "Use 'mythstocks.pl -a symbol[:holding]' to add symbols
to your portfolio";
        exit 0;
    }

    # Jiggery pokey to 'fake' a null suffix. Otherwise XML:Simple returns a hash
    my $suffix = ${$opt}->{'suffix'}[0];
    if( $suffix eq '.' ) {
        $suffix = '';
    }

    # build url
    my $fetchit = "http://".${$opt}->{'source'}[0]."/d/quotes.csv?s=".
        join( $suffix.',', @syms ).
        $suffix."&f=".${$opt}->{'format'}[0]."&e=.csv";

    my $response = get $fetchit;
    if( defined($response) ) {
        my $scroll_text = '';

        my $csv = Text::CSV->new();
        my @stocklines = split(/\n/,$response);
    	my $portfolio = 0.0;
    	my $portchange = 0.0;
        foreach (@stocklines) {
            if ($csv->parse($_."\n")) {
                my @columns = $csv->fields();
                my $sym = substr($columns[0],0,length($columns[0]) -
length($suffix));
                $scroll_text .= $sym.' $'.$columns[2].' ('.$columns[5].')     ';

                if( ${$port}->{uc($sym)}[0] > 0.0 ) {
        		    $portfolio += ( ${$port}->{uc($sym)}[0]  * $columns[2] );
                    $portchange += ( ${$port}->{uc($sym)}[0]  * $columns[5] );
                }
            } else {
                my $err = $csv->error_input;
                print "Failed to parse line '$_': $err";
            }
        }
        if( ${$opt}->{'showtotal'}[0] ne '0' && $portfolio > 0 ) {
            $scroll_text .= sprintf " [\$%0.2f \$%+0.2f %+0.2f%%]",
$portfolio, $portchange, ($portchange*100)/($portfolio-$portchange);
        }
        print $scroll_text;
    } else {
        print 'MythStocks regrets that it is unable to fetch stock
prices at this time ';
        die $response->status_line;
    }

sub read_config
{
    my $config_ref = shift;
    # No config file exists, create a default one.
    if( ! -e $configfile ) {
        ${$config_ref} = {
            'section' => {
                'portfolio' => {
                    'symbol' => [
                    ]
                },
                'options' => {
                    'source' => [
                        'finance.yahoo.com'
                    ],
                    'showtotal' => [
                        '0'
                    ],
                    'format' => [
                        'snl1d1t1c1ohgvw'
                    ],
                    'suffix' => [
                        '.'
                    ]
                }
            }
        };
        write_config(${$config_ref});
    }
    ${$config_ref} = XMLin($configfile,KeyAttr => {section => 'name'},
ForceArray => 1);
}
sub write_config
{
    my $config = shift;
    open CONFIG, '>'.$ENV{'HOME'}.'/.mythtv/mythstocks.xml' or die $!;
    print CONFIG XMLout($config,KeyAttr => {section => 'name'});
    close CONFIG ;
 }

---- snip ----


More information about the mythtv-users mailing list