diff --git a/src/main/java/com/after_sunrise/cryptocurrency/cryptotrader/service/estimator/CompositeEstimator.java b/src/main/java/com/after_sunrise/cryptocurrency/cryptotrader/service/estimator/CompositeEstimator.java index a3395c84..4c56ce2f 100644 --- a/src/main/java/com/after_sunrise/cryptocurrency/cryptotrader/service/estimator/CompositeEstimator.java +++ b/src/main/java/com/after_sunrise/cryptocurrency/cryptotrader/service/estimator/CompositeEstimator.java @@ -5,18 +5,17 @@ import com.after_sunrise.cryptocurrency.cryptotrader.framework.Request; import com.google.common.annotations.VisibleForTesting; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import java.math.BigDecimal; -import java.util.AbstractMap; import java.util.List; -import java.util.Map; +import java.util.Objects; import java.util.function.BiFunction; import java.util.function.BinaryOperator; -import java.util.stream.Collectors; import java.util.stream.Stream; -import static java.math.BigDecimal.ONE; +import static java.math.BigDecimal.*; import static java.math.RoundingMode.HALF_UP; /** @@ -25,11 +24,6 @@ */ public class CompositeEstimator extends AbstractEstimator { - private static final Map> OPERATORS = Stream.of( - new AbstractMap.SimpleEntry<>('*', (BinaryOperator) BigDecimal::multiply), - new AbstractMap.SimpleEntry<>('/', (BinaryOperator) (o1, o2) -> o1.divide(o2, SCALE, HALF_UP)) - ).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - static final CompositeEstimator INSTANCE = new CompositeEstimator(); private CompositeEstimator() { @@ -51,9 +45,9 @@ Estimation estimate(Context context, Request request, BiFunction operator = OPERATORS.get(site.charAt(0)); + char operation = site.charAt(0); + + BinaryOperator operator = null; + + if ('+' == operation) { + operator = BigDecimal::add; + } + + if ('-' == operation) { + operator = BigDecimal::subtract; + } + + if ('*' == operation) { + operator = BigDecimal::multiply; + } + + if ('/' == operation) { + operator = (o1, o2) -> o1.divide(o2, SCALE, HALF_UP); + } - if (operator == null) { + if ('@' != operation && operator == null) { return BAIL; } @@ -79,13 +91,31 @@ Estimation estimate(Context context, Request request, BiFunction function = mock(BiFunction.class); @@ -89,21 +90,42 @@ public void testCompositeEstimator_EstimateComposite() { return b.price(new BigDecimal("0.4")).confidence(new BigDecimal("0.6")).build(); } + if ("d".equals(r.getSite()) && "5".equals(r.getInstrument())) { + return b.price(new BigDecimal("0.5")).confidence(new BigDecimal("0.5")).build(); + } + return null; }).when(function).apply(same(context), any()); CompositeEstimator target = CompositeEstimator.INSTANCE; - // Price = 1 * 0.1 / 0.2 / 0.3 * 0.4 = 0.66666666666... - // Confidence = 0.9 * 0.8 * 0.7 * 0.6 = 0.3024 + // Multiplied Price = 1 * 0.1 / 0.2 / 0.3 * 0.4 = 0.66666666666... + // Average Price = (0.666666 + 0.5) / 2 + // Confidence = [(0.9 * 0.8 * 0.7 * 0.6) + 0.5] / 2 = 0.7 Estimator.Estimation result = target.estimate(context, request, function); - assertEquals(result.getPrice(), new BigDecimal("0.66666666668")); - assertEquals(result.getConfidence(), new BigDecimal("0.3024")); + assertEquals(result.getPrice(), new BigDecimal("0.5833333333")); + assertEquals(result.getConfidence(), new BigDecimal("0.4012000000")); + + // Composite Only + composites.clear(); + composites.add(new Composite("*a", "1")); + composites.add(new Composite("/b", "2")); + result = target.estimate(context, request, function); + assertEquals(result.getPrice(), new BigDecimal("0.5000000000")); + assertEquals(result.getConfidence(), new BigDecimal("0.7200000000")); + + // Average Only + composites.clear(); + composites.add(new Composite("@c", "4")); + composites.add(new Composite("@d", "5")); + result = target.estimate(context, request, function); + assertEquals(result.getPrice(), new BigDecimal("0.4500000000")); + assertEquals(result.getConfidence(), new BigDecimal("0.5500000000")); // Unknown Operator ('@') composites.clear(); - composites.add(new Composite("@a", "1")); + composites.add(new Composite("%a", "1")); result = target.estimate(context, request, function); assertEquals(result.getPrice(), null); assertEquals(result.getConfidence(), new BigDecimal("0"));