JForex Example: Not letting profit turn to losses with a breakeven stop

While the dual-timeframe trading setup and much of the algorithm in my contest strategy are for competition only (read: not for use with real money) as I've warned numerous times, some of the risk management techniques used there are really what I use in real life. This being one of them. There's a saying in trading that "never let profits turns into losses." That is exactly the motivation behind this JForex code snippet. The following source code are excerpts from my Dukascopy JForex contest's July strategy. The complete source code file is available in that link. Back to this concept of not letting profits turn to losses. This is a matter of balancing between giving room for your trade to reach its potential and limiting your drawdown. If you're too careful, you may find yourself being whipsawed out before a price move can materialize. If you keep your leash too loose though, well, you may watch your profits turn into losses. The way I intrepret the saying is that once your trade is profitable enough, you shouldn't let it slip back into a loss. I implement the above statement in my automated strategy as follows. Note that everything goes in the onTick() method so that it watches your position on every tick. The line numbers correspond to the complete source code of my automated strategy. [java firstline="177"] boolean isLong; double open, stop, diff, newStop; for (IOrder order : engine.getOrders(instrument)) { if (order.getState() == IOrder.State.FILLED) { [/java] [java firstline="191"] isLong = order.isLong(); open = order.getOpenPrice(); stop = order.getStopLossPrice(); diff = (open - stop); // ********* BREAKEVEN *********************** if (isLong && diff > 0 && tick.getBid() > (open + diff)) { order.close(roundLot(order.getAmount() * beRatio)); // close a portion newStop = open + instrument.getPipValue() * LOCKPIP; order.setStopLossPrice(newStop); print(order.getLabel() + ": Moved STOP to breakeven"); } else if (!isLong && diff \< 0 && tick.getAsk() \< (open + diff)) { order.close(roundLot(order.getAmount() * beRatio)); newStop = open - (instrument.getPipValue() * LOCKPIP); order.setStopLossPrice(newStop); print(order.getLabel() + ": Moved STOP to breakeven"); } [/java] What this does is that it will partially exit a position and move the stop to breakeven once the price is equidistantly positive from your initial stop loss. For example, if my stop loss is 100 pips, then once the position is 100 pips in profit, it will exit partially and set the new stop to breakeven. Update: This is now integrated into the JFUtil open source project.

JForex StopManager 1.0

I am building my real JForex automated trading system one feature at a time. The idea is to automate some of my most fundamental trading techniques on JForex so that I can trade forex semi-automatically on Dukascopy. I am starting off here with a simple stop management strategy. In a nutshell, once the market price moves in your favour equidistant from your original stop loss, this strategy moves the stop to breakeven. For example, if I go long EURUSD at 1.3500 with a stop at 1.3400 (100 pips stop). Then if the price breaks above 1.3600 (100 pips profit), the strategy moves the stop to breakeven. This is a simplistic implementation of the saying that "never let profits turn into losses". You can download the source code here and the executable strategy here. Note that these files are made available through Dropbox. Update: This logic is now integrated into the JFUtil open source project. You can also see a list of my latest JForex articles here. [java] /* StopManager.java version 1.0 Copyright 2010 Quantisan.com Move stops to breakeven when equidistance to original stop loss */ package jforex; import com.dukascopy.api.*; public class StopManager implements IStrategy { private IEngine engine; private IConsole console; private IContext context; @Configurable("Lock-in Pips for Breakeven") public int lockPip = 3; @Configurable("Move stop to breakeven?") public boolean moveBE = true; public void onStart(IContext context) throws JFException { this.engine = context.getEngine(); this.console = context.getConsole(); this.context = context; } public void onAccount(IAccount account) throws JFException { } public void onMessage(IMessage message) throws JFException { } public void onStop() throws JFException { } public void onTick(Instrument instrument, ITick tick) throws JFException { for (IOrder order : engine.getOrders(instrument)) { if (order.getState() == IOrder.State.FILLED) { boolean isLong; double open, stop, diff, newStop; String label = order.getLabel(); IChart chart; isLong = order.isLong(); open = order.getOpenPrice(); stop = order.getStopLossPrice(); diff = open - stop; // stop loss distance if (isLong) { // long side order if (moveBE && diff > 0 && tick.getBid() > (open + diff)) { // make it breakeven trade + lock in a few pips newStop = open + instrument.getPipValue() * lockPip; order.setStopLossPrice(newStop); console.getOut().println(label + ": Moved stop to breakeven"); chart = this.context.getChart(instrument); chart.draw(label + "_BE", IChart.Type.SIGNAL_UP, tick.getTime(), newStop); } } else { // short side order // Move to breakeven if (moveBE && diff \< 0 && tick.getAsk() \< (open + diff)) { // diff is negative // make it breakeven trade + lock in a few pips newStop = open - (instrument.getPipValue() * lockPip); order.setStopLossPrice(newStop); console.getOut().println(label + ": Moved stop to breakeven"); chart = this.context.getChart(instrument); chart.draw(label + "_BE", IChart.Type.SIGNAL_DOWN, tick.getTime(), newStop); } } } } } public void onBar(Instrument instrument, Period period, IBar askBar, IBar bidBar) throws JFException { } } [/java]