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