—#!/usr/bin/perl -w
# vi: set ts=2 sw=2 noai ic showmode showmatch:
#
# Copyright (C) 1998, Dj Padzensky <djpadz@padz.net>
# Copyright (C) 1998, 1999 Linas Vepstas <linas@linas.org>
# Copyright (C) 2000, Yannick LE NY <y-le-ny@ifrance.com>
# Copyright (C) 2000, Paul Fenwick <pjf@cpan.org>
# Copyright (C) 2000, Brent Neal <brentn@users.sourceforge.net>
# Copyright (C) 2001, Rob Sessink <rob_ses@users.sourceforge.net>
# Copyright (C) 2004, Frank Mori Hess <fmhess@users.sourceforge.net>
# Trent Piepho <xyzzy@spekeasy.org>
#
# 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., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA
#
#
# This code is derived from version 0.9 of the AEX.pm module.
use
strict;
use
if
DEBUG,
'Smart::Comments'
;
package
Finance::Quote::TSP;
use
LWP::UserAgent;
use
POSIX;
our
$VERSION
=
'1.64_03'
;
# TRIAL VERSION
# URLs of where to obtain information
@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'
);
sub
methods {
return
(
tsp
=> \
&tsp
) }
{
my
@labels
=
qw/name date isodate currency close/
;
sub
labels {
return
(
tsp
=> \
@labels
); }
}
sub
format_name {
my
$name
=
shift
;
$name
=~ s/ //g;
$name
=
lc
(
$name
);
return
$1
if
$name
=~ /^(.)fund$/;
return
$name
;
}
# ==============================================================================
sub
tsp {
my
$quoter
=
shift
;
my
@symbols
=
@_
;
return
unless
@symbols
;
my
%info
;
my
@line
;
# Ask for the last 7 days
my
$startdate
= strftime(
"%Y-%m-%d"
,
localtime
(
time
- 7*24*3600));
my
$enddate
= strftime(
"%Y-%m-%d"
,
localtime
time
);
my
$ua
=
$quoter
->user_agent;
my
$url
=
"$TSP_URL?startdate=$startdate&enddate=$enddate&Lfunds=1&InvFunds=1&download=1"
;
my
$reply
=
$ua
->get(
$url
,
@HEADERS
);
### [<now>] url : $url
### [<now>] reply: $reply
unless
((
$reply
->is_success) && (
@line
=
split
(/\n/,
$reply
->content)) && (
@line
> 1)) {
foreach
my
$symbol
(
@symbols
) {
$info
{
$symbol
,
"success"
} = 0;
$info
{
$symbol
,
"errormsg"
} =
"TSP fetch failed. No data for $symbol."
;
}
### Failure: %info
return
wantarray
?
%info
: \
%info
;
}
my
@header
=
split
(/,/,
$line
[0]);
my
%column
=
map
{ format_name(
$header
[
$_
]) =>
$_
} 0 ..
$#header
;
my
@latest
=
split
(/,/,
$line
[1]);
### [<now>] header: @header
### [<now>] column: %column
### [<now>] latest: @latest
foreach
(
@symbols
) {
my
$symbol
=
lc
$_
;
if
(
exists
$column
{
$symbol
}) {
$info
{
$_
,
'success'
} = 1;
$quoter
->store_date(\
%info
,
$_
, {
isodate
=>
$latest
[
$column
{
'date'
}]});
(
$info
{
$_
,
'last'
} =
$latest
[
$column
{
$symbol
}]) =~ s/[^0-9]*([0-9.,]+).*/$1/s;
$info
{
$_
,
'currency'
} =
'USD'
;
$info
{
$_
,
'method'
} =
'tsp'
;
$info
{
$_
,
'source'
} =
$TSP_MAIN_URL
;
$info
{
$_
,
'symbol'
} =
$_
;
}
else
{
$info
{
$_
,
'success'
} = 0;
$info
{
$_
,
'errormsg'
} =
"Fund not found"
;
}
}
return
%info
if
wantarray
;
return
\
%info
;
}
1;
=head1 NAME
Finance::Quote::TSP - Obtain fund prices for US Federal Government Thrift Savings Plan
=head1 SYNOPSIS
use Finance::Quote;
$q = Finance::Quote->new;
%info = $q->fetch('tsp','c'); #get value of C - Common Stock Index Investment Fund
%info = $q->fetch('tsp','l2040'); #get value of the L2040 Lifecycle Fund
%info = $q->fetch('tsp','lincome'); #get value of the LINCOME Lifecycle Fund
=head1 DESCRIPTION
This module fetches fund information from the "Thrift Savings Plan"
The quote symbols are
C common stock fund
F fixed income fund
G government securities fund
I international stock fund
S small cap stock fund
LX lifecycle fund X (eg 2050 or INCOME)
=head1 LABELS RETURNED
The following labels are returned by Finance::Quote::TSP :
date latest date, eg. "21/02/10"
isodate latest date, eg. "2010-02-21"
last latest available price, eg. "16.1053"
currency "USD"
method "tsp"
source TSP URL
=head1 SEE ALSO
Thrift Savings Plan, http://www.tsp.gov
=cut