App-Chart

 view release on metacpan or  search on metacpan

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

  while (my ($lo, $hi) = $iter->()) {
    ### do: "$method $lo, $hi"
    $self->$method ($lo, $hi);

    foreach my $array (@arrays) {
      $self->{'fill_high'} = App::Chart::max_maybe ($self->{'fill_high'},
                                                   @{$array}[$lo .. $hi]);
      $self->{'fill_low'} = App::Chart::min_maybe ($self->{'fill_low'},
                                                  @{$array}[$lo .. $hi]);
    }
    ### merge to: $got_set->as_string
  }
}

sub range {
  my ($self, $lo, $hi, @array_names) = @_;
  ### Series range: "$lo $hi of @array_names"
  $lo = max ($lo, 0);
  if ($hi < $lo) { return; }    # eg. lo==-5 hi==-1, no data before 0
  $self->fill ($lo, $hi);
  my $arrays_hash = $self->{'arrays'}; # hash
  if (! @array_names) {
    @array_names = $self->range_default_names;
  }
  my @arefs = @{$arrays_hash}{@array_names}; # hash slice

  require List::MoreUtils;
  return List::MoreUtils::minmax
    (grep {defined} map { @{$_}[$lo .. $hi] } @arefs);
}
sub range_default_names {
  my ($self) = @_;
  return keys %{$self->{'arrays'}};  # all arrays
}

sub linestyle {
  my ($self, $newval) = @_;
  if (@_ >= 2) {
    $self->{'linestyle'} = $newval;
  } elsif ($self->{'linestyle'}) {
    return $self->{'linestyle'};
  } else {
    return $self->default_linestyle;
  }
}
sub linestyle_class {
  my ($self) = @_;
  my $linestyle = $self->linestyle // return undef;
  return "App::Chart::Gtk2::LineStyle::$linestyle";
}

# Return (LOWER UPPER) which is a suggested initial Y-axis page range to
# show for dates LO to HI.  This is for use both with
# App::Chart::Series::OHLCVI and also any other series type without its own
# specific style.
#
# As described in "Main Window" in the manual, the aim is to scale according
# to apparent volatility, so that daily range or daily close-to-close change
# are some modest fraction of the initial page.  In particular if the series
# is just going sideways it's not zoomed out to try to fill the whole
# screen.  The absolute price level is not used, so say bond prices which
# hover near 100 still get scaled out to make typical daily changes of 0.1
# or whatever visible.
#
sub initial_range {
  my ($self, $lo, $hi) = @_;
  ### Series initial_range: "$lo to $hi   $self"
  $lo = max ($lo, 0);
  $hi = max ($hi, 0);
  $self->fill ($lo, $hi);
  my $highs = $self->array('highs') // [];
  my $lows  = $self->array('lows') // $highs;
  my $values = $self->values_array;
  my @diffs = ();

  my $timebase = $self->timebase;
  my $latest;
  if ($self->units eq 'price'
      && (my $symbol = $self->symbol)) {
    $latest = defined $symbol && App::Chart::Latest->get($symbol);
  }
  if ($latest
      && defined $latest->{'high'}
      && defined $latest->{'low'}
      && defined (my $last_iso = $latest->{'last_date'})) {
    my $last_t = $timebase->from_iso_floor ($last_iso);
    if ($last_t >= $lo && $last_t <= $hi) {
      push @diffs, $latest->{'high'} - $latest->{'low'};
    }
  }

  # high to low ranges in ohlcv
  if ($highs != $lows) {
    foreach my $i ($lo .. $hi) {
      if (defined $highs->[$i] && defined $lows->[$i]) {
        my $diff = CORE::abs ($highs->[$i] - $lows->[$i]);
        if ($diff != 0) {
          push @diffs, $diff;
        }
      }
    }
  }

  # ENHANCE-ME: look at all parts of a multi-line like macd, bollinger,
  # guppy, etc
  #     (if (= 2 (array-rank array))
  # 	# macd, not quite right
  # 	(set! array (make-shared-array-column array 0)))

  # close to close ranges
  {
    my $prev;
    foreach my $i ($lo .. $hi) {
      my $value = $values->[$i];
      if (! defined $value) { next; }

      if (defined $prev) {
        my $diff = CORE::abs ($value - $prev);
        if ($diff != 0) {
          push @diffs, $diff;
        }



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