/******************************************************************************* * myTwitter - Example how to integrate Twitter services on JForex platform. * * * * With this strategy you will automatically send order events information and * * also you can send your personal "tweets". You can modify it to send any * * information you want. * * * * For more information about, read my article about it at Dukascopy Library * * * * Developped by Dukascopy Community member JLongo * ******************************************************************************/ package myJForex.strategies; import com.dukascopy.api.Configurable; import com.dukascopy.api.IAccount; import com.dukascopy.api.IBar; import com.dukascopy.api.IConsole; import com.dukascopy.api.IContext; import com.dukascopy.api.IEngine; import com.dukascopy.api.IHistory; import com.dukascopy.api.IIndicators; import com.dukascopy.api.IMessage; import com.dukascopy.api.IOrder; import com.dukascopy.api.IStrategy; import com.dukascopy.api.ITick; import com.dukascopy.api.Instrument; import com.dukascopy.api.JFException; import com.dukascopy.api.Library; import com.dukascopy.api.Period; import com.dukascopy.api.RequiresFullAccess; import java.awt.KeyEventDispatcher; import java.awt.KeyboardFocusManager; import java.awt.event.KeyEvent; import java.text.DecimalFormat; import java.util.Calendar; import java.util.TimeZone; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JOptionPane; import twitter4j.Twitter; import twitter4j.TwitterException; import twitter4j.TwitterFactory; import twitter4j.auth.AccessToken; // We need access outside default JForex directories @RequiresFullAccess /* * Change the text bellow between quotation marks with your path and library * name to math the file structure of your system where you placed the library. * * You can get this library at http://twitter4j.org/en/index.html */ @Library("P:/Recursos/twitter/lib/twitter4j-core-3.0.3.jar") public class myJFTweets implements IStrategy { // Base objects creation private IContext myContext; private IHistory myHistory; private IConsole myConsole; private IIndicators myIndicators; private IAccount myAccount; private IEngine myEngine; /* * TWITTER VARIABLES */ /* * Twitter "keys" that allows the program to interact with Twitter services * without the need to do logins. * To get this "keys" you need to access the following url * https://dev.twitter.com/apps/ * and proceed with the steps provided on my article * IMPORTANT NOTE: Do not make public this keys ! */ private final String OAUTH_CONSUMER_KEY = "**********************"; private final String OAUTH_CONSUMER_SECRET = "*****************************************"; private final String OAUTH_ACCESS_TOKEN = "**************************************************"; private final String OAUTH_ACCESS_TOKEN_SECRET = "*****************************************"; private Twitter myTwitter; // Configurable variables @Configurable("Message prefix") public String myPrefix = ""; @Configurable("Send instrument:") public boolean mySendInstrument = true; @Configurable("Send direction:") public boolean mySendDirection = true; @Configurable("Send Amount:") public boolean mySendAmount = false; @Configurable("Send take profit:") public boolean mySendTP = false; @Configurable("Send stop loss:") public boolean mySendSL = false; @Configurable("Send pips P/L:") public boolean mySendPLPips = true; @Configurable("Send P/L value:") public boolean mySendPLValue = false; @Configurable("Send % P/L") public boolean mySendPercentage = false; // other variables // code to execute when CTRL+T is pressed KeyEventDispatcher myKeysEvents = new KeyEventDispatcher() { @Override public boolean dispatchKeyEvent(KeyEvent e) { if (e.getID() == KeyEvent.KEY_PRESSED){ if (e.getKeyCode() == KeyEvent.VK_T && e.isControlDown()){ String tweet; tweet = (String) JOptionPane.showInputDialog(null, "Write the Tweet! 10 chars min. and 140 chars max.", "Free form Tweet", JOptionPane.PLAIN_MESSAGE); if (tweet.length() > 9){ mySendTweet(tweet); } e.consume(); } return false; } return false; } }; @Override public void onStart(IContext context) throws JFException { // Base objects initialization myContext = context; myHistory = myContext.getHistory(); myConsole = myContext.getConsole(); myIndicators = myContext.getIndicators(); myAccount = myContext.getAccount(); myEngine = myContext.getEngine(); // Twitter initialization TwitterFactory myTwitterFactory = new TwitterFactory(); myTwitter = myTwitterFactory.getInstance(); myTwitter.setOAuthConsumer(OAUTH_CONSUMER_KEY, OAUTH_CONSUMER_SECRET); AccessToken myAccessToken = new AccessToken(OAUTH_ACCESS_TOKEN, OAUTH_ACCESS_TOKEN_SECRET); myTwitter.setOAuthAccessToken(myAccessToken); // add key events controler KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(myKeysEvents); } @Override public void onTick(Instrument instrument, ITick tick) throws JFException { } @Override public void onBar(Instrument instrument, Period period, IBar askBar, IBar bidBar) throws JFException { } @Override public void onMessage(IMessage message) throws JFException { // examples of sent tweets with all fields settings checked // on create order // prefix ID=xxxxxxxxx CREATED@20130510-10:53 Instr.=EURUSD BUY@1.23456 SL@1.23456 TP@1.23456 $=1.000.000 // on order filled // prefix ID=xxxxxxxxx FILLED@20130510-10:53 Instr.=EURUSD SELL@1.23456 SL@1.23456 TP@1.23456 $=1.000.000 // on order closed // prefix ID=xxxxxxxxx FILLED@20130510-10:53 CLOSED@20130510-10:53 Instr.=EURUSD SELL@1.23456 P/L#=-1000 P/L$=1.000.000,00 %=-100.00 String tweet = myPrefix; if (message.getType() == IMessage.Type.ORDER_SUBMIT_OK){ IOrder order = message.getOrder(); tweet += " ID=" + order.getId(); tweet += " CREATED@" + myGetTime(order.getCreationTime()); if(mySendInstrument){ tweet += " Instr.=" + order.getInstrument().name(); } if (mySendDirection){ tweet += " " + order.getOrderCommand().name() + "@"; tweet += order.getOpenPrice(); } if (mySendSL){ tweet += " SL@" + order.getStopLossPrice(); } if (mySendTP){ tweet += " TP@" + order.getTakeProfitPrice(); } if (mySendAmount){ tweet += " $=" + order.getAmount(); } mySendTweet(tweet); } if (message.getType() == IMessage.Type.ORDER_FILL_OK){ IOrder order = message.getOrder(); tweet += " ID=" + order.getId(); tweet += " FILLED@" + myGetTime(order.getFillTime()); if(mySendInstrument){ tweet += " Instr.=" + order.getInstrument().name(); } if (mySendDirection){ tweet += " " + order.getOrderCommand().name() + "@"; tweet += order.getOpenPrice(); } if (mySendSL){ tweet += " SL@" + order.getStopLossPrice(); } if (mySendTP){ tweet += " TP@" + order.getTakeProfitPrice(); } if (mySendAmount){ tweet += " $=" + order.getAmount(); } mySendTweet(tweet); } if (message.getType() == IMessage.Type.ORDER_CLOSE_OK){ IOrder order = message.getOrder(); tweet += " ID=" + order.getId(); tweet += " FILLED@" + myGetTime(order.getFillTime()); tweet += " CLOSED@" + myGetTime(order.getCloseTime()); if(mySendInstrument){ tweet += " Instr.=" + order.getInstrument().name(); } if (mySendDirection){ tweet += " " + order.getOrderCommand().name() + "@"; tweet += order.getOpenPrice() + "/" + order.getClosePrice(); } if (mySendPLPips){ tweet += " P/L#=" + order.getProfitLossInPips(); } if (mySendPLValue){ tweet += " P/L$=" + order.getProfitLossInAccountCurrency(); } if (mySendPercentage){ DecimalFormat myDf = new DecimalFormat("###.##"); double equity = myAccount.getEquity(); double percentage = (order.getProfitLossInAccountCurrency() / equity) * 100.0; tweet += " %=" + myDf.format(percentage); } mySendTweet(tweet); } } @Override public void onAccount(IAccount account) throws JFException { } @Override public void onStop() throws JFException { // Important ! remove the keyboard dispatcher. KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventDispatcher(myKeysEvents); } private void mySendTweet(String tweet){ // tweets can only have 140 chars maximum, remove the excess if (tweet.length() > 140){ tweet = tweet.substring(0, 139); } try { myTwitter.updateStatus(tweet); } catch (TwitterException ex) { Logger.getLogger(myJFTweets.class.getName()).log(Level.SEVERE, null, ex); } } private String myGetTime(long time) { Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); cal.setTimeInMillis(time); String resultTime = ""; resultTime += cal.get(Calendar.YEAR); String month = "0" + (Calendar.MONTH + 1); resultTime += month.substring(month.length() - 2, month.length()); String day = "0" + Calendar.DAY_OF_MONTH; resultTime += day.substring(day.length() -2, day.length()) + "-"; String hour = "0" + cal.get(Calendar.HOUR_OF_DAY); resultTime += hour.substring(hour.length() - 2, hour.length()) + ":"; String minute = "0" + cal.get(Calendar.MINUTE); resultTime += minute.substring(minute.length() - 2, minute.length()); return resultTime; } }