Finance-QuoteHist

 view release on metacpan or  search on metacpan

lib/Finance/QuoteHist/Yahoo.pm  view on Meta::CPAN

#  --compressed


# https://query1.finance.yahoo.com/v7/finance/download/IBM?period1=1495391410&period2=1498069810&interval=1d&events=history&crumb=bB6k340lPXt
# https://query1.finance.yahoo.com/v7/finance/download/IBM?period1=993096000&period2=1498017600&interval=1wk&events=history&crumb=bB6k340lPXt
# https://query1.finance.yahoo.com/v7/finance/download/IBM?period1=993096000&period2=1498017600&interval=1mo&events=history&crumb=bB6k340lPXt
#
# Dividends:
# https://query1.finance.yahoo.com/v7/finance/download/IBM?period1=993096000&period2=1498017600&interval=1d&events=div&crumb=bB6k340lPXt
#
# Splits:
# https://query1.finance.yahoo.com/v7/finance/download/NKE?period1=993096000&period2=1498017600&interval=1d&events=split&crumb=bB6k340lPXt

sub new {
  my $that = shift;
  my $class = ref($that) || $that;
  my %parms = @_;

  $parms{parse_mode} = 'json';
  $parms{ua_params} ||= {};
  $parms{ua_params}{cookie_jar} ||= {};

  my $self = __PACKAGE__->SUPER::new(%parms);
  bless $self, $class;

  # set initial cookie (the cookie crumbs are hashed out of this)
  # https://finance.yahoo.com/quote/IBM/history
  my $ticker = $parms{symbols};
  $ticker = $ticker->[0] if ref $ticker eq 'ARRAY';
  my $html = $self->fetch("https://finance.yahoo.com/quote/$ticker/history");

  # extract the cookie crumb
  my %crumbs;
  for my $c ($html =~ /"crumb"\s*:\s*"([^"]+)"/g) {
    next if $c =~ /[{}]/;
    $c =~ s/\\u002F/\//;
    ++$crumbs{$c};
  }
  my $crumb = '';
  my $max = 0;
  for my $c (keys %crumbs) {
    if ($crumbs{$c} >= $max) {
      $crumb = $c;
      $max = $crumbs{$c};
    }
  }

  $self->{crumb} = $crumb;

  $self;
}

sub granularities { qw( daily weekly monthly ) }

sub url_maker {
  my($self, %parms) = @_;
  my $target_mode = $parms{target_mode} || $self->target_mode;
  my $parse_mode = $parms{parse_mode} || $self->parse_mode;

  # *always* block unknown target mode and parse mode combinations for
  # cascade to work properly!
  return undef unless $target_mode eq 'quote' ||
                      $target_mode eq 'split' ||
                      $target_mode eq 'dividend';

  $parse_mode = "json";

  my $granularity = lc($parms{granularity} || $self->granularity);
  my $grain = 'd';
  $granularity =~ /^\s*(\w)/;
  $grain = $1 if $1 eq 'w' || $1 eq 'm';
  my($ticker, $start_date, $end_date) =
    @parms{qw(symbol start_date end_date)};
  $start_date ||= $self->start_date;
  $end_date   ||= $self->end_date;
  if ($start_date && $end_date && $start_date gt $end_date) {
    ($start_date, $end_date) = ($end_date, $start_date);
  }

  #my $host = "query1.finance.yahoo.com";
  #my $base_url = "https://$host/v7/finance/download/$ticker?";
  
  # https://query2.finance.yahoo.com/v8/finance/chart/TLSA?
  #   formatted=true
  #   crumb=l92p7dftYe%2F
  #   lang=en-US
  #   region=US
  #   includeAdjustedClose=true
  #   interval=1d
  #   period1=1455840000
  #   period2=1613692800
  #   events=div%7Csplit
  #   useYfid=true
  #   corsDomain=finance.yahoo.com

  my $host = "query2.finance.yahoo.com";
  my $base_url = "https://$host/v8/finance/chart/$ticker?";
  my @base_parms;
  if ($start_date) {
    my($y, $m, $d) = $self->ymd($start_date);
    my $ts = Date_SecsSince1970($m, $d, $y, 0, 0, 0);
    push(@base_parms, "period1=$ts");
  }
  if ($end_date) {
    my($y, $m, $d) = $self->ymd($end_date);
    my $ts = Date_SecsSince1970($m, $d, $y, 0, 0, 0);
    $ts += 24*60*60;
    push(@base_parms, "period2=$ts");
  }

  my $interval = "1d";
  if ($grain eq 'w') {
    $interval = "1wk";
  }
  elsif ($grain eq 'm') {
    $interval = "1mo";
  }
  push(@base_parms, "interval=$interval");

  if ($target_mode eq "quote") {
    push(@base_parms, "events=history");



( run in 0.418 second using v1.01-cache-2.11-cpan-9581c071862 )