# Copyright 2008, 2009, 2010, 2011 Kevin Ryde # This file is part of Chart. # # Chart is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License as published by the Free Software # Foundation; either version 3, or (at your option) any later version. # # Chart is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along # with Chart. If not, see . package GT::DB::Chart; use 5.010; use strict; use warnings; use Carp; use List::Util; # don't "use base" since GT::DB as of 2010 doesn't have a $VERSION and # base.pm will warn and assign $GT::DB::VERSION=-1 use GT::DB; our @ISA = ('GT::DB'); use GT::Prices; use GT::Conf; use GT::DateTime; # uncomment this to run the ### lines #use Smart::Comments; our $VERSION = 246; # extra appended to GT::Prices elements giving the tdate etc corresponding # to the $DATE element our $DATE_T = List::Util::max ($OPEN, $HIGH, $LOW, $CLOSE, $VOLUME, $DATE) + 1; sub new { my ($class, $series, $hi) = @_; return bless { series => $series, hi => $hi, }, $class; } sub disconnect { my ($self) = @_; if (App::Chart::DBI->can('disconnect')) { # if loaded App::Chart::DBI->disconnect; } } sub has_code { my ($self, $symbol) = @_; ### GT-DB-Chart has_code(): $symbol require App::Chart::Database; return App::Chart::Database->symbol_exists ($symbol); } sub get_db_name { my ($self, $symbol) = @_; ### GT-DB-Chart get_db_name(): $symbol require App::Chart::Database; return App::Chart::Database->symbol_name ($symbol); } my %timeframe_to_class = ($WEEK => 'Weeks', $MONTH => 'Months', $YEAR => 'Years'); sub get_prices { my ($self, $symbol, $timeframe) = @_; return $self->get_last_prices ($symbol, -1, $timeframe); } sub get_last_prices { my ($self, $symbol, $limit, $timeframe) = @_; ### GT-DB-Chart get_last_prices(): $symbol ### $limit ### $timeframe $timeframe ||= $DAY; my $prices = GT::Prices->new; $prices->set_timeframe ($timeframe); if ($timeframe < $DAY) { ### no intraday data return $prices; } if ($limit == 0) { return $prices; } my $series = $self->{'series'} || do { require App::Chart::Series::Database; App::Chart::Series::Database->new ($symbol); }; if ($timeframe != $DAY) { # can leave this to GT::Tools too, maybe my $class = $timeframe_to_class{$timeframe} or croak __PACKAGE__.": unrecognised timeframe $timeframe"; $series = $series->collapse ($class); } my $hi = $self->{'hi'} // $series->hi; my $lo; if ($limit == -1) { $lo = 0; # all data } else { # the newest $limit many values $lo = $series->find_before ($hi, $limit-1); } $series->fill ($lo, $hi); my $opens = $series->array('opens') || []; my $highs = $series->array('highs') || []; my $lows = $series->array('lows') || []; my $closes = $series->array('closes') || $series->values_array; my $volumes = $series->array('volumes') || []; my $timebase = $series->timebase; foreach my $t ($lo .. $hi) { $closes->[$t] // next; my @elem; $elem[$DATE_T] = $t; $elem[$OPEN] = $opens->[$t] || $closes->[$t]; $elem[$HIGH] = $highs->[$t] || $closes->[$t]; $elem[$LOW] = $lows->[$t] || $closes->[$t]; $elem[$CLOSE] = $closes->[$t]; $elem[$VOLUME] = $volumes->[$t] || 0; $elem[$DATE] = $timebase->to_iso($t); $prices->add_prices (\@elem); # added in ascending date order } return $prices; } 1; __END__ =for stopwords GeniusTrader Ryde =head1 NAME GT::DB::Chart - GeniusTrader access to data from Chart =head1 SYNOPSIS use GT::DB::Chart; my $db = GT::DB::Chart->new; my $prices = $db->get_prices ('BHP.AX', $GT::Prices::DAYS); =head1 DESCRIPTION This is a C module giving access to the Chart database from GeniusTrader scripts and calculations. =head1 FUNCTIONS =over 4 =item C<< $db = GT::DB::Chart->new() >> Create and return a new C object to retrieve data from the Chart database (F<~/Chart/database.sqdb>). =item C<< $db->disconnect() >> Disconnect from the Chart database. =item C<< $prices = $db->get_prices ($symbol, $timeframe) >> =item C<< $prices = $db->get_last_prices ($symbol, $limit, $timeframe) >> Create and return a C object with the data for C<$symbol> in the given C<$timeframe> increments. C<$timeframe> can be C<$DAYS>, C<$WEEKS>, C<$MONTHS> or C<$YEARS>. C returns all available data for C<$symbol>, C returns only the most recent C<$limit> many values (or as many as available). For example to get the last 250 trading days, my $prices = $db->get_last_prices ('GM', 250, $GT::Prices::DAYS); =item C<< $str = $db->get_db_name ($symbol) >> Return the company name for the stock C<$symbol>, or C if unknown. For most applications use C<< $db->get_name() >> instead (see C), since it tries your F<~/.gt/sharenames> file if nothing from C. =back =head1 SEE ALSO L, L L =head1 HOME PAGE L =head1 LICENCE Copyright 2008, 2009, 2010, 2011 Kevin Ryde Chart is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. Chart is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Chart; see the file F. Failing that, see L. =cut