File Coverage

blib/lib/Finance/Quote/TSP.pm
Criterion Covered Total %
statement 23 60 38.3
branch 0 12 0.0
condition 0 6 0.0
subroutine 9 11 81.8
pod 0 4 0.0
total 32 93 34.4


line stmt bran cond sub pod time code
1             #!/usr/bin/perl -w
2             # vi: set ts=2 sw=2 noai ic showmode showmatch:
3             #
4             # Copyright (C) 1998, Dj Padzensky <djpadz@padz.net>
5             # Copyright (C) 1998, 1999 Linas Vepstas <linas@linas.org>
6             # Copyright (C) 2000, Yannick LE NY <y-le-ny@ifrance.com>
7             # Copyright (C) 2000, Paul Fenwick <pjf@cpan.org>
8             # Copyright (C) 2000, Brent Neal <brentn@users.sourceforge.net>
9             # Copyright (C) 2001, Rob Sessink <rob_ses@users.sourceforge.net>
10             # Copyright (C) 2004, Frank Mori Hess <fmhess@users.sourceforge.net>
11             # Trent Piepho <xyzzy@spekeasy.org>
12             #
13             # This program is free software; you can redistribute it and/or modify
14             # it under the terms of the GNU General Public License as published by
15             # the Free Software Foundation; either version 2 of the License, or
16             # (at your option) any later version.
17             #
18             # This program is distributed in the hope that it will be useful,
19             # but WITHOUT ANY WARRANTY; without even the implied warranty of
20             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21             # GNU General Public License for more details.
22             #
23             # You should have received a copy of the GNU General Public License
24             # along with this program; if not, write to the Free Software
25             # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26             # 02110-1301, USA
27             #
28             #
29             # This code is derived from version 0.9 of the AEX.pm module.
30              
31 5     5   2533 use strict;
  5         16  
  5         200  
32              
33 5     5   30 use constant DEBUG => $ENV{DEBUG};
  5         10  
  5         309  
34 5     5   30 use if DEBUG, 'Smart::Comments';
  5         11  
  5         27  
35              
36             package Finance::Quote::TSP;
37              
38 5     5   297 use vars qw( $TSP_URL $TSP_MAIN_URL @HEADERS );
  5         12  
  5         271  
39              
40 5     5   31 use LWP::UserAgent;
  5         19  
  5         38  
41 5     5   132 use HTTP::Request::Common;
  5         12  
  5         359  
42 5     5   40 use POSIX;
  5         10  
  5         31  
43              
44             our $VERSION = '1.58_01'; # TRIAL VERSION
45              
46             # URLs of where to obtain information
47             $TSP_URL = 'https://www.tsp.gov/data/fund-price-history.csv';
48             $TSP_MAIN_URL = 'http://www.tsp.gov';
49             @HEADERS = ('user-agent' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.61 Safari/537.36');
50              
51 5     5 0 21 sub methods { return (tsp => \&tsp) }
52              
53             {
54             my @labels = qw/name date isodate currency close/;
55 5     5 0 14 sub labels { return (tsp => \@labels); }
56             }
57              
58             sub format_name {
59 0     0 0   my $name = shift;
60 0           $name =~ s/ //g;
61 0           $name = lc($name);
62              
63 0 0         return $1 if $name =~ /^(.)fund$/;
64 0           return $name;
65             }
66              
67             # ==============================================================================
68             sub tsp {
69 0     0 0   my $quoter = shift;
70 0           my @symbols = @_;
71              
72 0 0         return unless @symbols;
73              
74 0           my %info;
75             my @line;
76              
77             # Ask for the last 7 days
78 0           my $startdate = strftime("%Y-%m-%d", localtime (time - 7*24*3600));
79 0           my $enddate = strftime("%Y-%m-%d", localtime time);
80              
81 0           my $ua = $quoter->user_agent;
82 0           my $url = "$TSP_URL?startdate=$startdate&enddate=$enddate&Lfunds=1&InvFunds=1&download=1";
83 0           my $reply = $ua->get($url, @HEADERS);
84             ### [<now>] url : $url
85             ### [<now>] reply: $reply
86            
87 0 0 0       unless (($reply->is_success) && (@line = split(/\n/, $reply->content)) && (@line > 1)) {
      0        
88 0           foreach my $symbol (@symbols) {
89 0           $info{$symbol, "success"} = 0;
90 0           $info{$symbol, "errormsg"} = "TSP fetch failed. No data for $symbol.";
91             }
92             ### Failure: %info
93 0 0         return wantarray ? %info : \%info;
94             }
95              
96 0           my @header = split(/,/, $line[0]);
97 0           my %column = map { format_name($header[$_]) => $_ } 0 .. $#header;
  0            
98 0           my @latest = split(/,/, $line[1]);
99              
100             ### [<now>] header: @header
101             ### [<now>] column: %column
102             ### [<now>] latest: @latest
103              
104 0           foreach (@symbols) {
105 0           my $symbol = lc $_;
106              
107 0 0         if(exists $column{$symbol}) {
108 0           $info{$_, 'success'} = 1;
109 0           $quoter->store_date(\%info, $_, {isodate => $latest[$column{'date'}]});
110 0           ($info{$_, 'last'} = $latest[$column{$symbol}]) =~ s/[^0-9]*([0-9.,]+).*/$1/s;
111 0           $info{$_, 'currency'} = 'USD';
112 0           $info{$_, 'method'} = 'tsp';
113 0           $info{$_, 'source'} = $TSP_MAIN_URL;
114 0           $info{$_, 'symbol'} = $_;
115             }
116             else {
117 0           $info{$_, 'success'} = 0;
118 0           $info{$_, 'errormsg'} = "Fund not found";
119             }
120             }
121              
122 0 0         return %info if wantarray;
123 0           return \%info;
124             }
125             1;
126              
127             =head1 NAME
128              
129             Finance::Quote::TSP - Obtain fund prices for US Federal Government Thrift Savings Plan
130              
131             =head1 SYNOPSIS
132              
133             use Finance::Quote;
134              
135             $q = Finance::Quote->new;
136              
137             %info = $q->fetch('tsp','c'); #get value of C - Common Stock Index Investment Fund
138             %info = $q->fetch('tsp','l2040'); #get value of the L2040 Lifecycle Fund
139             %info = $q->fetch('tsp','lincome'); #get value of the LINCOME Lifecycle Fund
140              
141             =head1 DESCRIPTION
142              
143             This module fetches fund information from the "Thrift Savings Plan"
144              
145             http://www.tsp.gov
146              
147             The quote symbols are
148              
149             C common stock fund
150             F fixed income fund
151             G government securities fund
152             I international stock fund
153             S small cap stock fund
154             LX lifecycle fund X (eg 2050 or INCOME)
155              
156             =head1 LABELS RETURNED
157              
158             The following labels are returned by Finance::Quote::TSP :
159              
160             date latest date, eg. "21/02/10"
161             isodate latest date, eg. "2010-02-21"
162             last latest available price, eg. "16.1053"
163             currency "USD"
164             method "tsp"
165             source TSP URL
166              
167             =head1 SEE ALSO
168              
169             Thrift Savings Plan, http://www.tsp.gov
170              
171             =cut