PERL calculate and output ratio adjusted time series ( OHLC ) from two input files [closed]
I wish to merge two one minute time series files with PERL and adjusting the input data to output a ratio adjusted time series.
I am having troubles with reading two files at the same time and designing the control (loop?) architecture.
I need to able to read one line from FileA and one line from fileB and compare the date and time values. From there will either calculate the adjusted time series.
my $cntA = 1 ;
my $cntB = 1 ;
if ($cntA == 1 ) {
unlink ("$rATS");
#open files
open(FA, $fileA) or die "Error opening data file: $fileA $!\n";
open(FB, $fileB) or die "Error opening data file: $fileB $!\n";
open(MYOUTFILE, ">> $rATS") || die("unable to open $fileName");
#header
print MYOUTFILE "Date,Time,Open,High,Low,Close\n";
}
=item
#possible controlling loop
foreach my $SymA (@filesA){
foreach my $SumB (@filesB){
print "$filesASym $filesBSym\n";
=cut
while (<FA>) {
my @fieldsA = split /,/,$_;
#if ($fieldsA[0] != $DateA) { $closeYA = $CloseA ;}
my $DateA = $fieldsA[0] ;
my $TimeA = $fieldsA[1] ;
my $OpenA = $fieldsA[2] ;
my $HighA = $fieldsA[3] ;
my $LowA = $fieldsA[4] ;
my $CloseA = $fieldsA[5] ;
my $VolumeA = $fieldsA[6] ;
my $OpenIntA = $fieldsA[7] ;
my $lineNumA = $. ;
print "line num A: $lineNumA\n\n";
$cntA++;
last if $cntA != 0 ;
}
while (<FB>) {
my @fieldsB = split /,/,$_;
#if ($fieldsB[0] != $DateB) { $closeYB = $CloseB ;}
my $DateB = $fieldsB[0] ;
my $TimeB = $fieldsB[1] ;
my $OpenB = $fieldsB[2] ;
my $HighB = $fieldsB[3] ;
my $LowB = $fieldsB[4] ;
my $CloseB = $fieldsB[5] ;
my $VolumeB = $fieldsB[6] ;
my $OpenIntB = $fieldsB[7] ;
$cntB++;
last if $cntB != 0 ;
}
close(FA) || die("unable to close $fileA") ;
close(FB) || die("unable to close $fileB") ;
close(MYOUTFILE) || die("unable to close $fileName") ;
=item
sub ratio ($$) {
my $rat开发者_Python百科ioAB;
if ($_[0] > $_[1]) { $ratioAB = eval { $_[1] / $_[0]; } ; } warn $@ if $@ ;
if ($_[0] <= $_[0]) { $ratioAB = eval { $_[0] / $_[1]; } ; } warn $@ if $@ ;
return sprintf("%.2f", $ratioAB) ;
}
sub calcOHLC {
if ($closeYA > $closeYB) {
$open = sprintf("%.2f",$ratio * $openA - $openB);
$close = sprintf("%.2f",$ratio * $closeA - $closeB);
$high = sprintf("%.2f",$ratio * $highA - $highB);
$low = sprintf("%.2f",$ratio * $lowA - $lowB);
}
if ($closeYA <= $closeYB ) {
$open = sprintf("%.2f",$openA - $ratio * $openB);
$close = sprintf("%.2f",$closeA - $ratio * $closeB);
$high = sprintf("%.2f",$highA - $ratio * $highB);
$low = sprintf("%.2f",$lowA - $ratio * $lowB);
}
return undef;
}
sub outputFile{
print MYOUTFILE "$Date" . "," . "$Time" . "," . "$Open" . "," . "$High" . "," . "$Low" . "," . "$Close" . "\n";
}
=cut
Sample Data:
CVX File:
1/28/2011 957 94.21 94.21 94 94 83424 1357498
1/28/2011 958 94.02 94.11 94.02 94.1 41351 1398849
1/28/2011 959 94.1 94.11 94.06 94.1 27715 1426564
1/28/2011 1000 94.1 94.11 94.06 94.1 27715 1426564
1/28/2011 1001 94.18 94.2 94.04 94.07 61584 1523943
1/28/2011 1002 94.07 94.2 94.04 94.06 67352 1591295
1/28/2011 1003 94.07 94.2 94.04 94.06 67352 1591295
1/28/2011 1004 94.09 94.16 94.02 94.12 42852 1684278
XOM File:
1/28/2011 957 79.59 79.59 79.53 79.55 78759 1997094
1/28/2011 958 79.59 79.59 79.53 79.55 78759 1997094
1/28/2011 959 79.62 79.64 79.58 79.58 77559 2107813
1/28/2011 1000 79.58 79.6 79.58 79.6 87640 2195453
1/28/2011 1001 79.6 79.61 79.54 79.55 88442 2283895
1/28/2011 1002 79.6 79.61 79.54 79.55 88442 2283895
1/28/2011 1003 79.57 79.59 79.55 79.57 54073 2408315
1/28/2011 1004 79.57 79.58 79.5 79.52 118655 2526970
ratio as of 1/27/2011 = 79.88/94.75 = .84
since CVX is higher XOM/CVX
(CVX * .84) - XOM for output on 1/28/2011
Output file
Date time open high low close
1/28/2011 957 -0.45 -0.45 -0.57 -0.59
1/28/2011 958 -0.61 -0.54 -0.55 -0.51
1/28/2011 959 -0.58 -0.59 -0.57 -0.54
1/28/2011 1000 -0.54 -0.55 -0.57 -0.56
1/28/2011 1001 -0.49 -0.48 -0.55 -0.53
1/28/2011 1002 -0.58 -0.48 -0.55 -0.54
1/28/2011 1003 -0.55 -0.46 -0.56 -0.56
1/28/2011 1004 -0.53 -0.49 -0.52 -0.46
It's a little bit unclear what you mean by "in order to process fileA and fileB and have both a line from each to calc, yet keep some sort of master loop iterating".
if you mean that you wish to advance in 2 files in parallel, you can do it fairly easily - keep 1 loop, and read 1 line from each file per iteration. My code below is a bit vague since I don't know what you want to do
my ($done, $done_with_A, $done_with_B, $lineA, $lineB) = (0, 0, 0);
while (!$done_with_A || !$done_with_B) {
if (!$done_with_A) {
$lineA = <FA>;
}
if (!$done_with_B) {
$lineB = <FB>;
}
($done_with_A, $done_with_B) = are_we_done($lineA, $lineB);
# $lineA, $lineB are undef when the files are done.
process($lineA, $lineB);
}
If you need to be able to possibly process several lines from fileA for 1 line for fileB (or vice versa), its a bit more complicated - you accumulate lines in buffers:
my ($done, $read_from_A, $read_from_B, $done_with_A, $done_with_B, $lineA, $lineB) = (0, 1, 1, 0, 0);
my (@buffer_A, @buffer_B);
while (!$done_with_A || !$done_with_B) {
if (!$done_with_A && $need_to_read_from_A) {
$lineA = <FA>;
}
if (!$done_with_B && $need_to_read_from_B) {
$lineB = <FB>;
}
($done_with_A, $done_with_B) = are_we_done($lineA, $lineB);
# $lineA, $lineB are undef when the files are done.
if ( need_more_lines_from_A($lineA, $lineB) ) {
$read_from_A = 1;
$read_from_B = 0; # $lineB stays the same
push @buffer_A, $lineA;
next;
}
if ( need_more_lines_from_B($lineA, $lineB) ) {
$read_from_A = 0; # $lineA stays the same
$read_from_B = 1;
push @buffer_B, $lineB;
next;
}
push @buffer_A, $lineA;
push @buffer_B, $lineB;
process(@buffer_A, @buffer_A);
@buffer_B = (); @buffer_B = (); # Reset the buffers
$read_from_A = 0; $read_from_B = 0; # Read next batch.
}
精彩评论