package QuoteDB;
###########################################
# Store and retrieve historical quotes 
# Mike Schilli, 2002 (m@perlmeister.com)
###########################################
use warnings;
use strict qw(vars subs);

use Date::Calc qw(Add_Delta_Days 
                  check_date);
use Finance::QuoteHist;
use DB_File;
use POSIX;

our $VERSION = "1.0";
our %QUOTES = ();

###########################################
sub import {
###########################################
    my($class, $filename) = @_;

    tie %QUOTES, "DB_File", $filename, 
        O_CREAT, 0644;

    my $callerpkg = caller(0);
    *{"$callerpkg\::quote"} = *quote;

    1;
}

END { untie %QUOTES; }

###########################################
sub quote {
###########################################
    my($symbol, $year, $month, $day) = @_;

    if(!exists $QUOTES{$symbol}) {
        print "Updating ...\n";
        db_update($symbol);
    }

    return latest_price($symbol, $year, 
                        $month, $day);
}

###########################################
sub db_update {
###########################################
    my($sym) = @_;

    my $q = Finance::QuoteHist->new(
        symbols    => [$sym],
        start_date => '12/20/1994',
        end_date   => 'today');

    $QUOTES{$sym}++;

    foreach my $row ($q->quote_get()) {
        my ($stock, $date, $open, $high, 
            $low, $close, $volume) = @$row;
        my($year, $month, $day) = 
            map { sprintf "%d", $_ } 
            split(m#/#, $date);
        $QUOTES{"$sym,$year,$month,$day"} = 
                                    $close;
    }
}

###########################################
sub latest_price {
###########################################
    my($symbol, $year, $month, $day) = @_;

    my @try = ($year, $month, $day);

    my $maxtries = 10;

    while($maxtries--) {
        while(!check_date($year, $month, 
                          $day)) {
            $day--;
        }
        my $key = 
              "$symbol,$year,$month,$day";
        if(exists($QUOTES{$key})) {
            return $QUOTES{$key};
        }
    } continue {
        ($year, $month, $day) = 
            Add_Delta_Days($year, $month, 
                           $day, -1);
    }

    die "Can't find date (@try)";
}

1;
