File Coverage

blib/lib/Finance/Quote/TSP.pm
Criterion Covered Total %
statement 23 58 39.6
branch 0 12 0.0
condition n/a
subroutine 9 11 81.8
pod 0 4 0.0
total 32 85 37.6


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