#!/usr/bin/perl -w
our
$VERSION
=
'1.64_04'
;
sub
methods {
return
treasurydirect
=> \
&treasurydirect
;
}
sub
labels {
my
@labels
=
qw/ method source symbol rate bid ask price date isodate /
;
return
treasurydirect
=> \
@labels
;
}
sub
treasurydirect {
my
$time
=
time
();
my
@times
=
map
{
$time
-86400
*$_
} 0..3;
for
my
$t
(
@times
) {
my
(
$d
,
$m
,
$y
) = (
localtime
(
$t
))[3,4,5];
$y
+= 1900;
$m
+= 1;
my
@quotes
= treasurydirect_ymd(
$y
,
$m
,
$d
,
@_
);
return
@quotes
if
@quotes
;
}
}
sub
treasurydirect_ymd {
my
(
$y
,
$m
,
$d
,
$quoter
,
@symbols
) =
@_
;
return
unless
@symbols
;
my
%info
;
$info
{
$_
,
'success'
} = 0
for
@symbols
;
my
$ua
=
$quoter
->user_agent;
$ua
->timeout(10);
$ua
->ssl_opts(
verify_hostname
=> 0 );
my
$content
;
my
$url
=
$TREASURY_DIRECT_URL
;
if
(0) {
my
$response
=
$ua
->request(GET
$url
);
if
(!
$response
->is_success) {
$info
{
$_
,
'errormsg'
} =
'Error contacting URL'
for
@symbols
;
return
wantarray
() ?
%info
: \
%info
;
}
$content
=
$response
->content;
}
elsif
(0) {
my
$post_data
= [
'priceDate.month'
=>
$m
,
'priceDate.day'
=>
$d
,
'priceDate.year'
=>
$y
,
'submit'
=>
'Show Prices'
,
];
my
$request
= POST(
$url
,
$post_data
);
my
$resp
=
$ua
->request(
$request
);
if
(
$resp
->is_success) {
$content
=
$resp
->decoded_content;
}
else
{
$info
{
$_
,
'errormsg'
} =
'Error contacting URL'
for
@symbols
;
return
wantarray
() ?
%info
: \
%info
;
}
}
else
{
my
$data
=
'priceDate.month='
.
$m
.
'&priceDate.day='
.
$d
.
'&priceDate.year='
.
$y
.
'&submit=Show+Prices'
;
$content
= `wget --
no
-check-certificate --post-data=
'$data'
$url
-O - 2>/dev/null`;
}
return
if
$content
=~ /Submitted date must be equal to/;
return
if
$content
=~ /No data
for
selected date range/;
my
(
$date
,
$isodate
);
if
(
$content
=~ /Prices For:\s+(\w+)\s+(\d+),\s+(\d+)/) {
my
@months
=
qw/ Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec /
;
my
%months
;
@months
{
@months
} = 1..12;
my
(
$year
,
$month
,
$day
) = ($3,
$months
{$1}, $2);
$date
=
sprintf
"%02d/%02d/%04d"
,
$month
,
$day
,
$year
;
$isodate
=
sprintf
"%04d-%02d-%02d"
,
$year
,
$month
,
$day
;
}
my
$te
= new HTML::TableExtract();
$te
->parse(
$content
);
unless
(
$te
->first_table_found()) {
$info
{
$_
,
'errormsg'
} =
'Parse error'
for
@symbols
;
return
wantarray
() ?
%info
: \
%info
;
}
my
%bonds
;
for
my
$ts
(
$te
->table_states) {
for
my
$row
(
$ts
->rows) {
$bonds
{
$row
->[0]} = {
rate
=>
$row
->[2],
maturity
=>
$row
->[3],
bid
=>
$row
->[5],
ask
=>
$row
->[6],
};
}
}
return
unless
keys
(
%bonds
) > 1;
for
my
$symbol
(
@symbols
) {
$info
{
$symbol
,
'method'
} =
'treasurydirect'
;
$info
{
$symbol
,
'symbol'
} =
$symbol
;
$info
{
$symbol
,
'source'
} =
$TREASURY_DIRECT_URL
;
if
(
exists
$bonds
{
$symbol
}) {
$info
{
$symbol
,
'success'
} = 1;
$info
{
$symbol
,
'currency'
} =
'USD'
;
$info
{
$symbol
,
$_
} =
$bonds
{
$symbol
}{
$_
}
for
keys
%{
$bonds
{
$symbol
}};
$info
{
$symbol
,
'price'
} =
sprintf
(
"%.2f"
, 0.5*(
$info
{
$symbol
,
'bid'
} +
$info
{
$symbol
,
'ask'
}));
$info
{
$symbol
,
'date'
} =
$date
if
defined
$date
;
$info
{
$symbol
,
'isodate'
} =
$isodate
if
defined
$isodate
;
}
else
{
$info
{
$symbol
,
'errormsg'
} =
'no match'
;
}
}
return
wantarray
() ?
%info
: \
%info
;
}
1;