FadeTheMoveStrategy { public void analysePrices() { for (Map.Entry<TradeableInstrument<T>, Cache<DateTime, MarketDataPayLoad<T>>> entry : instrumentRecentPricesCache .entrySet()) { SortedMap<DateTime, MarketDataPayLoad<T>> sortedByDate = ImmutableSortedMap .copyOf(entry.getValue().asMap()); if (sortedByDate.isEmpty()) { continue; } Double pipJump = calculatePipJump(sortedByDate.values(), entry.getKey()); Double absPipJump = Math.abs(pipJump); if (absPipJump >= this.pipJumpCutOffCalculator.calculatePipJumpCutOff(entry.getKey())) { MarketDataPayLoad<T> lastPayLoad = sortedByDate.get(sortedByDate.lastKey()); Double pip = this.instrumentService.getPipForInstrument(entry.getKey()); double takeProfitPrice; double limitPrice; TradingSignal signal = null; if (Math.signum(pipJump) > 0) { signal = TradingSignal.SHORT; limitPrice = lastPayLoad.getBidPrice() + tradingConfig.getFadeTheMoveDistanceToTrade() * pip; takeProfitPrice = limitPrice - tradingConfig.getFadeTheMovePipsDesired() * pip; } else { signal = TradingSignal.LONG; limitPrice = lastPayLoad.getAskPrice() - tradingConfig.getFadeTheMoveDistanceToTrade() * pip; takeProfitPrice = limitPrice + tradingConfig.getFadeTheMovePipsDesired() * pip; } this.orderQueue.offer(new TradingDecision<T>(entry.getKey(), signal, takeProfitPrice, 0.0, limitPrice, TradingDecision.SRCDECISION.FADE_THE_MOVE)); entry.getValue().asMap() .clear(); } } } FadeTheMoveStrategy(Collection<TradeableInstrument<T>> instruments); @PostConstruct void init(); @Subscribe @AllowConcurrentEvents void handleMarketDataEvent(MarketDataPayLoad<T> marketDataPayLoad); void analysePrices();  }
@SuppressWarnings("unchecked") @Test public void analysePricesTest() throws Exception { TradingConfig tradingConfig = mock(TradingConfig.class); PipJumpCutOffCalculator<String> pipCalculator = mock(PipJumpCutOffCalculator.class); when(tradingConfig.getFadeTheMoveDistanceToTrade()).thenReturn(25); when(tradingConfig.getFadeTheMovePipsDesired()).thenReturn(10); when(tradingConfig.getFadeTheMovePriceExpiry()).thenReturn(15); BlockingQueue<TradingDecision<String>> orderQueue = new LinkedBlockingQueue<TradingDecision<String>>(); TradeableInstrument<String> eurusd = new TradeableInstrument<String>("EUR_USD"); TradeableInstrument<String> audchf = new TradeableInstrument<String>("AUD_CHF"); when(pipCalculator.calculatePipJumpCutOff(eq(eurusd))).thenReturn(45.0); when(pipCalculator.calculatePipJumpCutOff(eq(audchf))).thenReturn(29.0); FadeTheMoveStrategy<String> strategy = new FadeTheMoveStrategy<String>(Lists.newArrayList(eurusd, audchf)); InstrumentService<String> instrumentService = mock(InstrumentService.class); when(instrumentService.getPipForInstrument(any(TradeableInstrument.class))).thenReturn(0.0001); strategy.tradingConfig = tradingConfig; strategy.orderQueue = orderQueue; strategy.instrumentService = instrumentService; strategy.pipJumpCutOffCalculator = pipCalculator; strategy.init(); final double[] eurusdPrices = { 1.1345, 1.1341, 1.1339, 1.1338, 1.1333, 1.1332, 1.1331, 1.1330, 1.1328, 1.1325, 1.1324, 1.1322, 1.1320, 1.1317, 1.1316, 1.1314, 1.1311, 1.1309, 1.1310, 1.1313, 1.1308, 1.1305, 1.1302, 1.1300, 1.1298, 1.1296, 1.1293 }; DateTime eventStarteurusd = DateTime.now().minusMinutes(10); for (double price : eurusdPrices) { eventStarteurusd = eventStarteurusd.plusSeconds(5); strategy.handleMarketDataEvent( new MarketDataPayLoad<String>(eurusd, price - TradingAppTestConstants.precision, price + TradingAppTestConstants.precision, eventStarteurusd)); } final double[] audchfPrices = { 0.7069, 0.7070, 0.7073, 0.7076, 0.7077, 0.7078, 0.708, 0.7082, 0.7084, 0.7085, 0.7086, 0.7089, 0.7091, 0.7093, 0.7094, 0.7098, 0.71, 0.7102, 0.7105, 0.7104, 0.7103, 0.7105, 0.7109, 0.7111, 0.7112, 0.7115, 0.7118 }; DateTime eventStartaudchf = DateTime.now().minusMinutes(10); for (double price : audchfPrices) { eventStartaudchf = eventStartaudchf.plusSeconds(5); strategy.handleMarketDataEvent( new MarketDataPayLoad<String>(audchf, price - TradingAppTestConstants.precision, price + TradingAppTestConstants.precision, eventStartaudchf)); } strategy.analysePrices(); for (int i = 1; i <= 2; i++) { TradingDecision<String> decision = orderQueue.take(); assertEquals(TradingDecision.SRCDECISION.FADE_THE_MOVE, decision.getTradeSource()); if (eurusd.equals(decision.getInstrument())) { assertEquals(TradingSignal.LONG, decision.getSignal()); assertEquals(1.1269, decision.getLimitPrice(), TradingAppTestConstants.precision); assertEquals(1.1279, decision.getTakeProfitPrice(), TradingAppTestConstants.precision); assertEquals(eurusd, decision.getInstrument()); } else { assertEquals(TradingSignal.SHORT, decision.getSignal()); assertEquals(audchf, decision.getInstrument()); assertEquals(0.7142, decision.getLimitPrice(), TradingAppTestConstants.precision); assertEquals(0.7132, decision.getTakeProfitPrice(), TradingAppTestConstants.precision); } } }