perlでローソク足

ta-nuki2016-04-24

ググったけども日本語の記事がなかったので。
最初はなぜかgnuplotで描こうとしていたのですが、gnuplotは対話式であるため、スクリプトでガンガン描けないため方針転換。
cpanmで落としてきたGD::Graph::candlesticksを使用。下記のサンプルコードは、マイクロソフトを例に取っているところまで含めてほぼコピペ。
データは米Yahoo!financeから落としたものを想定。

#!/usr/bin/perl

use strict;
use warnings FATAL => 'all';
use GD::Graph::candlesticks;

no warnings 'redefine';

 my (@date, @kabu_data, $max_price, $min_price);
 open(MSFT,"<","MSFT\.csv") or die("Cannt open MSFT\.csv!\n");
 while(<MSFT>){
  if(($_ =~ /^[0-9][0-9][0-9][0-9]\-/)&&($_ =~ /\,/)){
   $_ =~ s/\n//;
   my @date_data = split(/\,/,$_);
   push(@date,$date_data[0]);
   push(@kabu_data,[@date_data[1..4]]);
   $max_price = $date_data[2];
   $min_price = $date_data[3];
   last;
  }
 }
 while(<MSFT>){
  if(($_ =~ /^[0-9][0-9][0-9][0-9]\-/)&&($_ =~ /\,/)){
   $_ =~ s/\n//;
   my @date_data = split(/\,/,$_);
   unshift(@date,$date_data[0]);
   unshift(@kabu_data,[@date_data[1..4]]);
   if($date_data[2] > $max_price){
	$max_price = $date_data[2];
   }
   if($min_price > $date_data[3]){
	$min_price = $date_data[3];
   }
  }
 }
 close(MSFT);
 my $graph = GD::Graph::candlesticks->new(800, 400);
   $graph->set( 
      x_labels_vertical => 1,
      x_label           => 'Trade Date',
      y_label           => 'US $',
      title             => "NASDAQ:MSFT",
      transparent       => 0,
      candlestick_width => 7,
      dclrs             => [qw(blue)],
      y_min_value       => $min_price -0.2,
      y_max_value       => $max_price +0.2,
      y_number_format   => '%0.2f',
   ) or warn $graph->error;

 my $data_candlesticks = [
   [ @date ],       # date
   [ @kabu_data ], # candlesticks
  ];
 my $gd = $graph->plot($data_candlesticks) or die $graph->error;
 open my $dump, ">", "candlesticks_example.png" or die $!;
 print $dump $gd->png;
 close $dump;
 exit;

出力サンプルはこの記事の右上。小さくてすまぬ。先週末にかなり下落したもよう。


GD::Graph::mixedを使って他のグラフとも重ね合わせられた。
下記の例は、当方で年移動平均を計算済み、かつ、米Yahoo!とは時系列が逆のデータを使用しているのであしからず。

#!/usr/bin/perl

use strict;
use warnings FATAL => 'all';
use GD::Graph::candlesticks;

no warnings 'redefine';

 my (@date, @kabu_data, @year_ave, $max_price, $min_price);
 open(TWTR,"<","TWTR\.csv") or die("Cannt open TWTR\.csv!\n");
 while(<TWTR>){
  if(($_ =~ /^[0-9][0-9][0-9][0-9]\-/)&&($_ =~ /\,/)){
   $_ =~ s/\n//;
   my @date_data = split(/\,/,$_);
   push(@date,$date_data[0]);
   push(@kabu_data,[@date_data[1..4]]);
   push(@year_ave,$date_data[10]);
   $max_price = $date_data[2];
   $min_price = $date_data[3];
   last;
  }
 }
 while(<TWTR>){
  if(($_ =~ /^[0-9][0-9][0-9][0-9]\-/)&&($_ =~ /\,/)){
   $_ =~ s/\n//;
   my @date_data = split(/\,/,$_);
   push(@date,$date_data[0]);
   push(@kabu_data,[@date_data[1..4]]);
   push(@year_ave,$date_data[10]);
   if($date_data[2] > $max_price){
	$max_price = $date_data[2];
   }
   if($min_price > $date_data[3]){
	$min_price = $date_data[3];
   }
  }
 }
 close(TWTR);
 my $graph = GD::Graph::mixed->new(3600, 600);
   $graph->set( 
      x_labels_vertical => 1,
      x_label           => 'Trade Date',
      y_label           => 'US $',
      title             => "NASDAQ:TWTR",
      transparent       => 0,
      types             => [ qw(candlesticks lines) ],
      dclrs             => [qw(blue red)],
      fgclr            => "dgray",
      y_min_value       => $min_price -0.2,
      y_max_value       => $max_price +0.2,
      y_number_format   => '%0.2f',
   ) or warn $graph->error;

 my $graph_data = [
   [ @date ],       # date
   [ @kabu_data ], # candlesticks
   [ @year_ave ], # lines
  ];
 my $gd = $graph->plot($graph_data) or die $graph->error;
 open my $dump, ">", "candlesticks_example.png" or die $!;
 print $dump $gd->png;
 close $dump;
 exit;

なお、この程度のチャートは日本のYahoo!ファイナンスで見れる罠。