TradeEventHandler implements EventHandler<JSONObject, TradeEventPayLoad>,
		EmailContentGenerator<JSONObject>, EventPayLoadToTweet<JSONObject, TradeEventPayLoad> { @Override public String toTweet(TradeEventPayLoad payLoad) { if (!tradeEventsSupported.contains(payLoad.getEvent())) { return null; } final JSONObject jsonPayLoad = payLoad.getPayLoad(); final String instrument = jsonPayLoad.get(OandaJsonKeys.instrument).toString(); final String instrumentAsHashtag = OandaUtils.oandaToHashTagCcy(instrument); final long tradeUnits = (Long) jsonPayLoad.get(OandaJsonKeys.units); final double price = ((Number) jsonPayLoad.get(OandaJsonKeys.price)).doubleValue(); final long origTransactionId = (Long) jsonPayLoad.get(OandaJsonKeys.tradeId); final long accountId = (Long) jsonPayLoad.get(OandaJsonKeys.accountId); Transaction<Long, Long, String> origTransaction = this.transactionDataProvider.getTransaction( origTransactionId, accountId); if (origTransaction == null) { String side = jsonPayLoad.get(OandaJsonKeys.side).toString(); TradingSignal signal = OandaUtils.toTradingSignal(side); return String.format("Closed %s %d units of %s@%2.5f.", signal.flip().name(), tradeUnits, instrumentAsHashtag, price); } double pips = 0; if (origTransaction.getSide() == TradingSignal.LONG) { pips = (price - origTransaction.getPrice()) / this.instrumentService.getPipForInstrument(new TradeableInstrument<String>(instrument)); } else { pips = (origTransaction.getPrice() - price) / this.instrumentService.getPipForInstrument(new TradeableInstrument<String>(instrument)); } return String.format("Closed %s %d units of %s@%2.5f for %3.1f pips.", origTransaction.getSide().name(), tradeUnits, instrumentAsHashtag, price, pips); } TradeEventHandler(TradeInfoService<Long, String, Long> tradeInfoService,
			TransactionDataProvider<Long, Long, String> transactionDataProvider,
			InstrumentService<String> instrumentService); @Override @Subscribe @AllowConcurrentEvents void handleEvent(TradeEventPayLoad payLoad); @Override EmailPayLoad generate(EventPayLoad<JSONObject> payLoad); @Override String toTweet(TradeEventPayLoad payLoad);  }
@SuppressWarnings("unchecked") @Test public void payLoadToTweet() { JSONObject jsonPayLoad = mock(JSONObject.class); TradeableInstrument<String> eurchf = new TradeableInstrument<String>("EUR_CHF"); TradeEventPayLoad payLoad = new TradeEventPayLoad(TradeEvents.TAKE_PROFIT_FILLED, jsonPayLoad); when(jsonPayLoad.get(OandaJsonKeys.instrument)).thenReturn(eurchf.getInstrument()); when(jsonPayLoad.get(OandaJsonKeys.units)).thenReturn(200l); when(jsonPayLoad.get(OandaJsonKeys.price)).thenReturn(1.10325); when(jsonPayLoad.get(OandaJsonKeys.tradeId)).thenReturn(OandaTestConstants.tradeId); when(jsonPayLoad.get(OandaJsonKeys.accountId)).thenReturn(OandaTestConstants.accountId); TransactionDataProvider<Long, Long, String> transactionDataProvider = mock(TransactionDataProvider.class); Transaction<Long, Long, String> transaction = mock(Transaction.class); when(transactionDataProvider.getTransaction(OandaTestConstants.tradeId, OandaTestConstants.accountId)) .thenReturn(transaction); when(transaction.getSide()).thenReturn(TradingSignal.SHORT); when(transaction.getPrice()).thenReturn(1.11); InstrumentService<String> instrumentService = mock(InstrumentService.class); when(instrumentService.getPipForInstrument(eq(eurchf))).thenReturn(0.0001); TradeEventHandler eventHandler = new TradeEventHandler(null, transactionDataProvider, instrumentService); String tweet = eventHandler.toTweet(payLoad); assertNotNull(tweet); assertEquals("Closed SHORT 200 units of #EURCHF@1.10325 for 67.5 pips.", tweet); transaction = mock(Transaction.class); when(transactionDataProvider.getTransaction(OandaTestConstants.tradeId, OandaTestConstants.accountId)) .thenReturn(transaction); when(transaction.getSide()).thenReturn(TradingSignal.SHORT); when(transaction.getPrice()).thenReturn(1.10); tweet = eventHandler.toTweet(payLoad); assertNotNull(tweet); assertEquals("Closed SHORT 200 units of #EURCHF@1.10325 for -32.5 pips.", tweet); transaction = mock(Transaction.class); when(transactionDataProvider.getTransaction(OandaTestConstants.tradeId, OandaTestConstants.accountId)) .thenReturn(transaction); when(transaction.getSide()).thenReturn(TradingSignal.LONG); when(transaction.getPrice()).thenReturn(1.10); tweet = eventHandler.toTweet(payLoad); assertNotNull(tweet); assertEquals("Closed LONG 200 units of #EURCHF@1.10325 for 32.5 pips.", tweet); transaction = mock(Transaction.class); when(transactionDataProvider.getTransaction(OandaTestConstants.tradeId, OandaTestConstants.accountId)) .thenReturn(transaction); when(transaction.getSide()).thenReturn(TradingSignal.LONG); when(transaction.getPrice()).thenReturn(1.11); tweet = eventHandler.toTweet(payLoad); assertNotNull(tweet); assertEquals("Closed LONG 200 units of #EURCHF@1.10325 for -67.5 pips.", tweet); when(transactionDataProvider.getTransaction(OandaTestConstants.tradeId, OandaTestConstants.accountId)) .thenReturn(null); when(jsonPayLoad.get(OandaJsonKeys.side)).thenReturn("sell"); tweet = eventHandler.toTweet(payLoad); assertNotNull(tweet); assertEquals("Closed LONG 200 units of #EURCHF@1.10325.", tweet); TradeEventPayLoad payload2 = new TradeEventPayLoad(TradeEvents.MIGRATE_TRADE_CLOSE, jsonPayLoad); assertNull(eventHandler.toTweet(payload2)); }