App-finquotehist
view release on metacpan or search on metacpan
lib/App/finquotehist.pm view on Meta::CPAN
package App::finquotehist;
our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
our $DATE = '2019-11-29'; # DATE
our $DIST = 'App-finquotehist'; # DIST
our $VERSION = '0.002'; # VERSION
use 5.010001;
use strict;
use warnings;
use Log::ger;
our %SPEC;
my $sch_date = [
'date*', {
'x.perl.coerce_to' => 'DateTime',
'x.perl.coerce_rules' => ['From_str::natural'],
},
];
$SPEC{finquotehist} = {
v => 1.1,
summary => 'Fetch historical stock quotes',
args => {
action => {
schema => 'str*',
description => <<'_',
Choose what action to perform. The default is 'fetch_quotes'. Other actions include:
* 'fetch_splits' - Fetch splits.
* 'fetch_dividends' - Fetch dividends.
* 'list_engines' - List available engines (backends).
_
default => 'fetch_quotes',
cmdline_aliases => {
l => {is_flag=>1, summary => 'Shortcut for --action list_engines', code => sub { $_[0]{action} = 'list_engines' }},
},
},
symbols => {
'x.name.is_plural' => 1,
'x.name.singular' => 'symbol',
schema => ['array*', of=>'str*', min_len=>1],
pos => 0,
greedy => 1,
},
from => {
schema => $sch_date,
tags => ['category:filtering'],
},
to => {
schema => $sch_date,
tags => ['category:filtering'],
},
engines => {
'x.name.is_plural' => 1,
'x.name.singular' => 'engine',
schema => ['array*', of=>'perl::modname*'],
default => ['Yahoo', 'Google'],
element_completion => sub {
require Complete::Module;
my %args = @_;
my $ans = Complete::Module::complete_module(
word => $args{word},
ns_prefix => 'Finance::QuoteHist',
);
[grep {$_ !~ /\A(Generic)\z/} @$ans];
},
cmdline_aliases => {
e => {},
},
},
},
examples => [
{
summary => 'List available engines (backends)',
argv => [qw/-l/],
test => 0,
'x.doc.show_result' => 0,
},
{
summary => 'Fetch historical quote (by default 1 year) for a few NASDAQ stocks',
argv => [qw/AAPL AMZN MSFT/],
test => 0,
'x.doc.show_result' => 0,
},
{
summary => 'Fetch quotes for a few Indonesian stocks, for a certain date range',
argv => [qw/--from 2018-01-01 --to 2018-09-07 BBCA.JK BBRI.JK TLKM.JK/],
test => 0,
'x.doc.show_result' => 0,
},
{
summary => 'Fetch quotes for a stock, from 3 years ago',
argv => ['--from', '3 years ago', 'AAPL'],
test => 0,
'x.doc.show_result' => 0,
},
{
summary => 'Fetch splits for a few Indonesian stocks',
argv => [qw/--action fetch_splits BBCA.JK BBRI.JK TLKM.JK/],
test => 0,
'x.doc.show_result' => 0,
},
],
};
sub finquotehist {
my %args = @_;
my $action = $args{action} // 'fetch';
if ($action eq 'list_engines') {
require PERLANCAR::Module::List;
my $mods = PERLANCAR::Module::List::list_modules(
"Finance::QuoteHist::", {list_modules=>1, recurse=>1});
return [200, "OK", [
grep {!/\A(Generic)\z/}
map {my $x = $_; $x =~ s/\AFinance::QuoteHist:://; $x}
sort keys %$mods]];
} elsif ($action eq 'fetch_quotes' || $action eq 'fetch_splits' || $action eq 'fetch_dividends') {
require DateTime;
require Finance::QuoteHist;
return [400, "Please specify one or more symbols"]
unless $args{symbols} && @{ $args{symbols} };
my $from = $args{from} // DateTime->today->subtract(years=>1);
my $to = $args{to} // DateTime->today;
my $q = Finance::QuoteHist->new(
lineup => [map {"Finance::QuoteHist::$_"} @{ $args{engines} }],
symbols => $args{symbols},
start_date => $from->strftime("%m/%d/%Y"),
end_date => $to ->strftime("%m/%d/%Y"),
);
my @rows;
my @rows0;
if ($action eq 'fetch_quotes' ) { @rows0 = $q->quotes }
elsif ($action eq 'fetch_splits' ) { @rows0 = $q->splits }
elsif ($action eq 'fetch_dividends') { @rows0 = $q->dividends }
my $fields;
for my $row0 (@rows0) {
my $row;
if ($action eq 'fetch_quotes') {
$fields //= [qw/symbol date open high low close volume adjclose/];
$row = {
symbol => $row0->[0],
date => $row0->[1],
open => $row0->[2],
high => $row0->[3],
low => $row0->[4],
close => $row0->[5],
volume => $row0->[6],
adjclose => $row0->[7],
};
} elsif ($action eq 'fetch_splits') {
$fields //= [qw/symbol date post pre/];
$row = {
symbol => $row0->[0],
date => $row0->[1],
post => $row0->[2],
pre => $row0->[3],
};
} elsif ($action eq 'fetch_dividends') {
$fields //= [qw/symbol date dividend/];
$row = {
symbol => $row0->[0],
date => $row0->[1],
dividend => $row0->[2],
};
}
push @rows, $row;
}
[200, "OK", \@rows, {'table.fields' => $fields}];
} else {
return [400, "Unknown action"];
}
}
1;
# ABSTRACT: Fetch historical stock quotes
__END__
=pod
=encoding UTF-8
=head1 NAME
( run in 1.452 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )