Hi Support,
I have amended a strategy posted earlier on the board. I want to achieve the following:
1. for existing manually placed orders (multiple orders, multiple currency pairs)
2. each with an existing stop loss and take profit
3. If the market price moves to x pips from TP, then
4. move TP 5 pips further in the money and move SL to Y pips from the market price
I tried the strategy on demo account and it appeared to work fine, however it doesnt work on live remote run.
Your help is much appreciated!
package jforex.strategies;
import com.dukascopy.api.*;
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.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.indicators.IIndicator;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.TimeZone;
public class TrailingStopv2 implements IStrategy {
private IEngine engine;
private IConsole console;
private int counter = 0;
@Configurable("trigger pips")
public int triggerPips = 5;
@Configurable("SL pips")
public int slPips = 30;
@Override
public void onStart(IContext context) throws JFException {
this.console = context.getConsole();
this.engine = context.getEngine();
}
@Override
public void onBar(Instrument instrument, Period period, IBar askBar, IBar bidBar) throws JFException {
}
public void onTick(Instrument instrument, ITick tick) throws JFException {
for(IOrder order : engine.getOrders(instrument)) {
updateTrailingStopLoss(tick, order, triggerPips, slPips);
}
}
private boolean isActive(IOrder order) throws JFException {
if (order != null && order.getState() != IOrder.State.CLOSED && order.getState() != IOrder.State.CANCELED) {
return true;
}
return false;
}
private double getPipPrice(double pips, Instrument instr) {
return pips * instr.getPipValue();
}
private String getLabel(Instrument instrument) {
String label = instrument.name();
label = label + (counter++);
label = label.toUpperCase();
return label;
}
public boolean updateTrailingStopLoss(ITick tick, IOrder pOrder, double pTriggerPips, double pStopLossPips) throws JFException {
boolean triggered = false;
if ( pTriggerPips > 0 && pStopLossPips > 0 &&
pOrder != null && pOrder.getState() == IOrder.State.FILLED) {
Instrument instr = pOrder.getInstrument();
double newStop;
double newTP;
double openPrice = pOrder.getOpenPrice();
double currentStopLoss = pOrder.getStopLossPrice();
double currentTakeProfit = pOrder.getTakeProfitPrice();
// (START) trailing stop loss is activated
if (pOrder.isLong()) { // long side order
if ( tick.getBid() > currentStopLoss + getPipPrice(pStopLossPips, instr) &&
tick.getBid() > currentTakeProfit - getPipPrice(pTriggerPips, instr)) {
// trailing stop loss
newStop = tick.getBid() - getPipPrice(pStopLossPips, instr);
newStop = getRoundedPrice(newStop, instr);
newTP = tick.getBid() + getPipPrice(pTriggerPips + 5, instr);
newTP = getRoundedPrice(newTP, instr);
if (currentStopLoss != newStop) {
pOrder.setStopLossPrice(newStop);
triggered = true;
}
if (currentTakeProfit + getPipPrice(1, instr)<= newTP) {
pOrder.setTakeProfitPrice(newTP);
}
}
} else { // short side order
if ( tick.getAsk() < currentStopLoss - getPipPrice(pStopLossPips, instr) &&
tick.getAsk() < currentTakeProfit + getPipPrice(pTriggerPips, instr)) {
// trailing stop loss
newStop = tick.getAsk() + getPipPrice(pStopLossPips, instr);
newStop = getRoundedPrice(newStop, instr);
newTP = tick.getBid() - getPipPrice(pTriggerPips + 5, instr);
newTP = getRoundedPrice(newTP, instr);
if (currentStopLoss != newStop) {
pOrder.setStopLossPrice(newStop);
triggered = true;
}
if (currentTakeProfit - getPipPrice(1, instr)>= newTP) {
pOrder.setTakeProfitPrice(newTP);
}
}
}
}
return triggered;
}
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();
}
public void onMessage(IMessage message) throws JFException {
print(message);
}
public void onAccount(IAccount account) throws JFException {
}
public void onStop() throws JFException {
}
/**************** debug print functions ***********************/
private void print(Object... o) {
for (Object ob : o) {
//console.getOut().print(ob + " ");
if (ob instanceof Double) {
print2(toStr((Double) ob));
} else if (ob instanceof double[]) {
print((double[]) ob);
} else if (ob instanceof double[]) {
print((double[][]) ob);
} else if (ob instanceof Long) {
print2(toStr((Long) ob));
} else if (ob instanceof IBar) {
print2(toStr((IBar) ob));
} else {
print2(ob);
}
print2(" ");
}
console.getOut().println();
}
private void print(Object o) {
console.getOut().println(o);
}
private void print2(Object o) {
console.getOut().print(o);
}
private void print(double d) {
print(toStr(d));
}
private void print(double[] arr) {
print(toStr(arr));
}
private void print(double[][] arr) {
print(toStr(arr));
}
private void print(IBar bar) {
print(toStr(bar));
}
private void printIndicatorInfos(IIndicator ind) {
for (int i = 0; i < ind.getIndicatorInfo().getNumberOfInputs(); i++) {
print(ind.getIndicatorInfo().getName() + " Input " + ind.getInputParameterInfo(i).getName() + " " + ind.getInputParameterInfo(i).getType());
}
for (int i = 0; i < ind.getIndicatorInfo().getNumberOfOptionalInputs(); i++) {
print(ind.getIndicatorInfo().getName() + " Opt Input " + ind.getOptInputParameterInfo(i).getName() + " " + ind.getOptInputParameterInfo(i).getType());
}
for (int i = 0; i < ind.getIndicatorInfo().getNumberOfOutputs(); i++) {
print(ind.getIndicatorInfo().getName() + " Output " + ind.getOutputParameterInfo(i).getName() + " " + ind.getOutputParameterInfo(i).getType());
}
console.getOut().println();
}
public static String toStr(double[] arr) {
String str = "";
for (int r = 0; r < arr.length; r++) {
str += "[" + r + "] " + (new DecimalFormat("#.#######")).format(arr[r]) + "; ";
}
return str;
}
public static String toStr(double[][] arr) {
String str = "";
if (arr == null) {
return "null";
}
for (int r = 0; r < arr.length; r++) {
for (int c = 0; c < arr[r].length; c++) {
str += "[" + r + "][" + c + "] " + (new DecimalFormat("#.#######")).format(arr[r][c]);
}
str += "; ";
}
return str;
}
public String toStr(double d) {
return (new DecimalFormat("#.#######")).format(d);
}
public String toStr(Long time) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") {
{
setTimeZone(TimeZone.getTimeZone("GMT"));
}
};
return sdf.format(time);
}
private String toStr(IBar bar) {
return toStr(bar.getTime()) + " O:" + bar.getOpen() + " C:" + bar.getClose() + " H:" + bar.getHigh() + " L:" + bar.getLow();
}
private void printTime(Long time) {
console.getOut().println(toStr(time));
}
}