App-Chart

 view release on metacpan or  search on metacpan

lib/App/Chart/Download.pm  view on Meta::CPAN

    return __x('{symbol} no data at all, marked historical',
               symbol => $symbol);
  }
  my $days = iso_timestamp_days_ago ($date, $last_download_timestamp);
  if ($days > 21) {
    return __x('{symbol} no data for {days} days, marked historical',
               days => $days,
               symbol => $symbol);
  }
  return undef;
}

sub iso_timestamp_days_ago {
  my ($iso, $prev_timestamp) = @_;
  my ($prev_year,$prev_month,$prev_day) = timestamp_to_ymdhms($prev_timestamp);
  return Date::Calc::Delta_Days (App::Chart::iso_to_ymd($iso),
                                 $prev_year, $prev_month, $prev_day);
}

sub consider_latest_from_daily {
  my ($h) = @_;
  my $dbh = App::Chart::DBI->instance;
  my %latest_changed;
  my $timestamp;

  my $database_symbols_hash = App::Chart::Database::database_symbols_hash();

  # find the newest and second newest data record of each symbol
  my %data_newest;
  my %data_second;
  foreach my $data (@{$h->{'data'}}) {
    my $symbol = $data->{'symbol'};
    if ($data->{'date'} ge ($data_newest{$symbol}->{'date'} // '')) {
      $data_second{$symbol} = $data_newest{$symbol};
      $data_newest{$symbol} = $data;
    } elsif ($data->{'date'} ge ($data_second{$symbol}->{'date'} // '')) {
      $data_second{$symbol} = $data;
    }
  }

  foreach my $symbol (keys %data_newest) {
    my $newest = $data_newest{$symbol};
    my $date = $newest->{'date'};

    # For symbols in the database, if newest daily is >= latest quote then
    # delete that quote in order to prefer the daily data in the database.
    if (exists $database_symbols_hash->{$symbol}) {
      my $latest_delete_sth = $dbh->prepare_cached
        ('DELETE FROM latest WHERE symbol=? AND quote_date < ?');
      if ($latest_delete_sth->execute ($symbol, $date)) {
        $latest_changed{$symbol} = 1;
      }
      next;
    }

    # For symbols not in the database, if the newest daily is >= latest quote
    # then replace that quote with the daily.
    #
    # Times in the latest record are not considered, so it's possible a
    # quote taken after close of trading will be deleted or overwritten.
    # Would want something in the latest to say it's after the close ...

    my $latest_get_sth = $dbh->prepare_cached
      ('SELECT last_date, name FROM latest WHERE symbol=?');
    my ($last_date, $name, $dividend)
      = $dbh->selectrow_array ($latest_get_sth, undef, $symbol);
    if (defined $last_date && $last_date gt $date) { next; }

    # "name" from the daily, or retain name from existing latest record.
    $name = $h->{'names'}->{$symbol} // $name;

    # "dividend" from existing latest record retained, but only if same date.
    unless (defined $last_date && $last_date eq $date) {
      undef $dividend;
    }

    # change by difference from second newest daily, if have one
    my $change = undef;
    if (defined(my $second_close = $data_second{$symbol}->{'close'})) {
      $change = App::Chart::decimal_sub ($newest->{'close'}, $second_close);
    }

    $timestamp ||= timestamp_now();

    my $latest_set_sth = $dbh->prepare_cached
      ('INSERT OR REPLACE INTO latest
        (symbol, name, currency, exchange, dividend,
         last_date, open, high, low, last, change, volume,
         source, fetch_timestamp)
        VALUES (?,?,?,?,?, ?,?,?,?,?,?,?, ?,?)');
    $latest_set_sth->execute
      ($symbol,
       $name,
       $h->{'currencies'}->{$symbol},
       $h->{'exchanges'}->{$symbol},
       $dividend,
       #
       $newest->{'date'},
       $newest->{'open'},
       $newest->{'high'},
       $newest->{'low'},
       $newest->{'close'},
       $change,
       $newest->{'volume'},
       #
       $h->{'source'},
       $timestamp);
    $latest_changed{$symbol} = 1;
  }

  foreach my $dividend (@{$h->{'dividends'}}) {
    my $latest_dividend_sth = $dbh->prepare_cached
      ('UPDATE latest SET dividend=? WHERE symbol=? AND last_date=?');
    my $symbol = $dividend->{'symbol'};
    if ($latest_dividend_sth->execute ($dividend->{'amount'},
                                       $symbol,
                                       $dividend->{'ex_date'})) {
      $latest_changed{$symbol} = 1;
    }
  }



( run in 0.477 second using v1.01-cache-2.11-cpan-d7a12ab2c7f )