our $join1 = Triceps::LookupJoin->new( name => "join1", leftFromLabel => $tRate->getOutputLabel(), leftFields => [ "ccy1", "ccy2", "rate/rate1" ], rightTable => $tRate, rightIdxPath => [ "byCcy1" ], rightFields => [ "ccy2/ccy3", "rate/rate2" ], byLeft => [ "ccy2/ccy1" ], isLeft => 0, ); # would die by itself on an error our $join2 = Triceps::LookupJoin->new( name => "join2", leftFromLabel => $join1->getOutputLabel(), rightTable => $tRate, rightIdxPath => [ "byCcy1", "byCcy12" ], rightFields => [ "rate/rate3" ], byLeft => [ "ccy3/ccy1", "ccy1/ccy2" ], isLeft => 0, ); # would die by itself on an error # now compute the resulting circular rate and filter the profitable loops our $rtResult = Triceps::RowType->new( $join2->getResultRowType()->getdef(), looprate => "float64", ) or die "$!"; my $lbResult = $uArb->makeDummyLabel($rtResult, "lbResult"); my $lbCompute = $uArb->makeLabel($join2->getResultRowType(), "lbCompute", undef, sub { my ($label, $rowop) = @_; my $row = $rowop->getRow(); my $ccy1 = $row->get("ccy1"); my $ccy2 = $row->get("ccy2"); my $ccy3 = $row->get("ccy3"); my $rate1 = $row->get("rate1"); my $rate2 = $row->get("rate2"); my $rate3 = $row->get("rate3"); my $looprate = $rate1 * $rate2 * $rate3; # now build the row in normalized order of currencies print("____Order before: $ccy1, $ccy2, $ccy3\n"); my $result; if ($ccy2 lt $ccy3) { if ($ccy2 lt $ccy1) { # rotate left $result = $lbResult->makeRowopHash($rowop->getOpcode(), ccy1 => $ccy2, ccy2 => $ccy3, ccy3 => $ccy1, rate1 => $rate2, rate2 => $rate3, rate3 => $rate1, looprate => $looprate, ) or die "$!"; } } else { if ($ccy3 lt $ccy1) { # rotate right $result = $lbResult->makeRowopHash($rowop->getOpcode(), ccy1 => $ccy3, ccy2 => $ccy1, ccy3 => $ccy2, rate1 => $rate3, rate2 => $rate1, rate3 => $rate2, looprate => $looprate, ) or die "$!"; } } if (!defined $result) { # use the straight order $result = $lbResult->makeRowopHash($rowop->getOpcode(), ccy1 => $ccy1, ccy2 => $ccy2, ccy3 => $ccy3, rate1 => $rate1, rate2 => $rate2, rate3 => $rate3, looprate => $looprate, ) or die "$!"; } if ($looprate > 1) { $uArb->call($result); } else { print("__", $result->printP(), "\n"); # for debugging } }) or die "$!"; $join2->getOutputLabel()->chain($lbCompute) or die "$!";
It produces the exact same result as the version with the manual loops, with the only minor difference of the field order in the result rows.
And, in retrospect, I should have probably made a function for the row rotation, so that I would not have to copy that code here.
Well, it works the same as the version with the loops and maybe even looks a little bit neater, but in practice it's much harder to write, debug and understand.
No comments:
Post a Comment