Hi,
I have found a strategy here in the forum that move SL to BE and start trailing stop at predefined pips. I have been looking for a strategy that also close half position when SL is moved to BE. Can not find one that do all in one. Could that function be added to this strategy?
package jforex.strategies;
import com.dukascopy.api.Configurable;
import com.dukascopy.api.IAccount;
import com.dukascopy.api.IBar;
import com.dukascopy.api.IChart;
import com.dukascopy.api.IConsole;
import com.dukascopy.api.IContext;
import com.dukascopy.api.IEngine.OrderCommand;
import com.dukascopy.api.IEngine;
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.Period;
import com.dukascopy.api.drawings.ISignalDownChartObject;
import com.dukascopy.api.drawings.ISignalUpChartObject;
import java.math.BigDecimal;
import java.math.RoundingMode;
public class StopManager implements IStrategy {
private IEngine engine;
private IConsole console;
private IContext context;
@Configurable("Lock-in Pips for Breakeven (SLBE)")
public int lockPip = 3;
@Configurable("Stoploss Break Even Trigger (SLBET)")
public int triggerPips = 80;
@Configurable("Move stop to breakeven?")
public boolean moveBE = true;
@Configurable("Trailing stop loss?")
public boolean doTrailingSL = true;
@Configurable("Trailing stop loss trigger pips")
public double trailingSLTrig = 1;
@Configurable("Trailing stop loss pips")
public double trailingSL = 5;
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 {
console.getOut().println(message);
}
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, newStop;
String label = order.getLabel();
IChart chart;
open = order.getOpenPrice();
if (order.isLong()) { // long side order
if (moveBE && tick.getBid() > (open + toPrice(instrument, triggerPips))) {
// make it breakeven trade + lock in a few pips
newStop = open + toPrice(instrument, lockPip);
order.setStopLossPrice(newStop);
console.getOut().println(label + ": Moved stop to breakeven");
chart = this.context.getChart(instrument);
drawUp(label + "_BE_UP", tick.getTime(), newStop, chart);
}
} else { // short side order
// Move to breakeven
if (moveBE && tick.getAsk() < (open - toPrice(instrument, triggerPips))) { // diff is negative
// make it breakeven trade + lock in a few pips
newStop = open - toPrice(instrument, lockPip);
order.setStopLossPrice(newStop);
console.getOut().println(label + ": Moved stop to breakeven");
chart = this.context.getChart(instrument);
drawDown(label + "_BE_DOWN", tick.getTime(), newStop, chart);
}
}
if (doTrailingSL) {
newStop = updateTrailingStopLoss(tick, order, trailingSLTrig, trailingSL);
if(newStop > 0) {
if (order.isLong()) {
chart = this.context.getChart(instrument);
drawUp(label + "_TS_UP", tick.getTime(), newStop, chart);
} else {
chart = this.context.getChart(instrument);
drawDown(label + "_TS_DOWN", tick.getTime(), newStop, chart);
}
}
}
}
}
}
ISignalUpChartObject upArrow = null;
ISignalDownChartObject downArrow = null;
private void drawUp(String label, long time, double newStop, IChart chart) {
if(chart != null) {
if(upArrow == null) {
upArrow = chart.getChartObjectFactory().createSignalUp(label, time, newStop);
chart.addToMainChart(upArrow);
} else {
upArrow.move(time, newStop);
}
}
}
private void drawDown(String label, long time, double newStop, IChart chart) {
if(chart != null) {
if(downArrow == null) {
downArrow = chart.getChartObjectFactory().createSignalDown(label, time, newStop);
chart.addToMainChart(downArrow);
} else {
downArrow.move(time, newStop);
}
}
}
private double toPrice(Instrument instr, int pips) {
return instr.getPipValue() * pips;
}
public void onBar(Instrument instrument, Period period, IBar askBar, IBar bidBar) throws JFException {
}
// sets stop loss to "tick.getAsk - pStopLossPips" if price is higher than "pOrder.getOpenPrice() + pTriggerPips"
public double updateTrailingStopLoss(ITick tick, IOrder pOrder, double pTriggerPips, double pStopLossPips) throws JFException {
if (pStopLossPips > 0 && pOrder != null && pOrder.getState() == IOrder.State.FILLED) {
Instrument instr = pOrder.getInstrument();
double newStop;
double openPrice = pOrder.getOpenPrice();
double currentStopLoss = pOrder.getStopLossPrice();
// (START) trailing stop loss is activated when price is higher than oper price + trailingTrigger pips
// (TRAILING STOP) if price moves further up (for BUY order), stop loss is updated to stopLossPips
if (pOrder.isLong()) { // long side order
if ((currentStopLoss == 0.0 || tick.getBid() > currentStopLoss + getPipPrice(pStopLossPips, instr))
&& tick.getBid() > openPrice + getPipPrice(pTriggerPips, instr)) {
// trailing stop loss
newStop = tick.getBid() - getPipPrice(pStopLossPips, instr);
newStop = getRoundedPrice(newStop, instr);
if (currentStopLoss != newStop) {
pOrder.setStopLossPrice(newStop);
return newStop;
}
}
} else { // short side order
if ((currentStopLoss == 0.0 || tick.getAsk() < currentStopLoss - getPipPrice(pStopLossPips, instr))
&& tick.getAsk() < openPrice - getPipPrice(pTriggerPips, instr)) {
// trailing stop loss
newStop = tick.getAsk() + getPipPrice(pStopLossPips, instr);
newStop = getRoundedPrice(newStop, instr);
if (currentStopLoss != newStop) {
pOrder.setStopLossPrice(newStop);
return newStop;
}
}
}
}
return 0.0;
}
private double getRoundedPrice(double price, Instrument instr) {
BigDecimal bd = new BigDecimal(price);
bd = bd.setScale(instr.getPipScale() + 1, RoundingMode.HALF_UP);
return bd.doubleValue();
}
private double getRoundedPipCount(double pips) {
BigDecimal bd = new BigDecimal(pips);
bd = bd.setScale(1, RoundingMode.HALF_UP);
return bd.doubleValue();
}
private double getPipPrice(double pips, Instrument instr) {
return pips * instr.getPipValue();
}
}