Hello Support,
I am looking to develop a strategy component, which will move a stop (akin to trailing stop) after x bars. I am working with the below strategy, please note that I take multiple positions.
Can you suggest a code snippet to count bars since (each) position opening, and then adjust the stop?
package com.pixelka.forex;
import java.util.*;
import com.dukascopy.api.IEngine.OrderCommand;
import com.dukascopy.api.*;
import com.dukascopy.api.IIndicators.AppliedPrice;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.TimeZone;
import com.dukascopy.api.IIndicators.AppliedPrice;
import com.dukascopy.api.indicators.IIndicator;
public class MasterRSImultipos implements IStrategy {
private IOrder order;
private IContext context = null;
private IEngine engine = null;
private IChart chart = null;
private IHistory history = null;
private IIndicators indicators = null;
private IConsole console = null;
public double volume = 0.01;
public int profitLimit;
public int lossLimit;
public double bidPrice;
public double askPrice;
public double accountEquity;
public int tradeDate;
public Instrument instrument;
//@Configurable("trigger up")
public double triggerUp = 0.03;
//@Configurable("trigger down")
public double triggerDown = 0.03;
@Configurable("Period")
public Period selectedPeriod = Period.THIRTY_MINS;
// @Configurable("SMA Period")
public int SMAPeriod = 50;
@Configurable("Take Profit")
public int takeProfit = 1000;
@Configurable("Stop Loss")
public int stopLoss = 1000;
//@Configurable("Take Profit2")
public int TP2 = 19;
//@Configurable("Stop Loss2")
public int SL2 = 18;
//@Configurable("VaR in percentage")
public double VaR = 0.05;
//@Configurable("VaR Multiplier")
public int VaRMultiplier = 2;
//@Configurable("Start Equity")
public double startEquity = 10000;
//@Configurable("Maximum Duraration Mon thru Thu (Hr)")
public double MaxDuration = 250;
private int counter = 0;
public double MaxDurationMills = 0;
//@Configurable("Maximum Volume (million)")
public double MaxVol = 10;
@Configurable("RSI period")
public int rsiPeriod = 16;
@Configurable("RSI Over bought")
public double rsiOB = 76;
@Configurable("RSI Over Sold")
public double rsiOS = 22;
@Configurable("Filter")
public Filter filter = Filter.ALL_FLATS;
@Configurable("Applied price")
public AppliedPrice appliedPrice = AppliedPrice.CLOSE;
@Configurable("Maximum Open Positions")
public int maxpos = 5;
public void onStart(IContext context) throws JFException {
this.context = context;
engine = context.getEngine();
indicators = context.getIndicators();
history = context.getHistory();
console = context.getConsole();
indicators = context.getIndicators();
instrument = Instrument.EURUSD;
Set subscribedInstruments = new HashSet();
subscribedInstruments.add(Instrument.EURUSD);
context.setSubscribedInstruments(subscribedInstruments);
}
public void onStop() throws JFException {
}
public void onTick(Instrument instrument, ITick tick) throws JFException {
/* if (!isActive(order)) {
if(order != null) {
print(order.getLabel(), order.getState(), "closed sl/tp", "long" );
}
order = null;
} else if(order.equals(IOrder.State.CREATED)) {
return;
}*/
}
// DETECTION OF LONG OR SHORT TRADE
protected int islong(Instrument instrument) throws JFException {
int counter = 0;
for (IOrder order : engine.getOrders(instrument)) {
if (order.isLong()) {
counter++;
}
}
return counter;
}
// OPEN POSITION COUNTER
protected int positionsTotal(Instrument instrument) throws JFException {
int counter = 0;
for (IOrder order : engine.getOrders(instrument)) {
if (order.getState() == IOrder.State.FILLED) {
counter++;
}
}
return counter;
}
protected String getLabel(Instrument instrument) {
String label = instrument.name();
label = label + (counter++);
label = label.toUpperCase();
return label;
}
public void onBar(Instrument instrument, Period period, IBar askbar, IBar bidbar) throws JFException {
if( (instrument != this.instrument) || (askbar.getVolume() == 0) ) return;
if(period == selectedPeriod ){
profitLimit = takeProfit;
lossLimit = stopLoss;
if (!isActive(order)) {
if(order != null) {
print(order.getLabel(), order.getState(), "closed sl/tp", "long" );
}
order = null;
} else if(order.equals(IOrder.State.CREATED)) {
return;
}
// VOLUME SETTINGS
volume = 0.01;
// TRADE ENTRY PARAMETERS
double openPrice = bidbar.getOpen();
askPrice = askbar.getClose();
bidPrice = bidbar.getClose();
long time = new java.util.Date().getTime();
double rsi1 = indicators.rsi(instrument, selectedPeriod, OfferSide.ASK, appliedPrice, rsiPeriod, 1);
double rsi2 = indicators.rsi(instrument, selectedPeriod, OfferSide.ASK, appliedPrice, rsiPeriod, 2);
if (positionsTotal(instrument) < maxpos) {
if (rsi2 < rsiOS && rsi1 >= rsiOS) {
buy(instrument, engine, profitLimit, lossLimit, volume);
}
if (rsi2 < rsiOB && rsi1 >= rsiOB) {
sell(instrument, engine, profitLimit, lossLimit, volume);
}
} // closes position == 0
// CLOSING POSITION
for (IOrder orderInMarket : engine.getOrders()) {
if (orderInMarket.getState() == IOrder.State.FILLED) {
if ((rsi2 < rsiOB && rsi1 >= rsiOB) && orderInMarket.isLong()) {
orderInMarket.close();}
else if((rsi2 > rsiOS && rsi1 <= rsiOS) && !orderInMarket.isLong()) {
orderInMarket.close();}
}
}
} // closes select period
} // closes onBar
public void onMessage(IMessage message) throws JFException {
if (message != null && message.getType() == IMessage.Type.ORDER_CLOSE_OK) {
IOrder lastOne = message.getOrder();
double profitsLoss = lastOne.getProfitLossInPips();
console.getOut().println("Order : "+lastOne.getLabel()+ " "+ lastOne.getOrderCommand()+ " Pips: "+profitsLoss);
print(message);
}
}
// TRADE EXECUTION MECHANICS
@Override
public void onAccount(IAccount account) throws JFException {
accountEquity = account.getEquity() ;
}
public void sell(Instrument instrument, IEngine engine, int takeProfitPipLevel, int endLossPipLevel, double volumeParam) throws JFException {
engine.submitOrder(getLabel(instrument), instrument, IEngine.OrderCommand.SELL, volumeParam, 0, 3, bidPrice
+ instrument.getPipValue() *endLossPipLevel, bidPrice - instrument.getPipValue() * takeProfitPipLevel);
}
public void buy(Instrument instrument, IEngine engine, int takeProfitPipLevel, int endLossPipLevel, double volumeParam) throws JFException {
engine.submitOrder(getLabel(instrument), instrument, IEngine.OrderCommand.BUY, volumeParam, 0, 3, askPrice
- instrument.getPipValue() * endLossPipLevel, askPrice + instrument.getPipValue() * takeProfitPipLevel);
}
private void closeOrder(IOrder order) throws JFException {
if (order != null && isActive(order)) {
order.close();
}
}
private boolean isActive(IOrder order) throws JFException {
if (order != null && order.getState() != IOrder.State.CLOSED && order.getState() != IOrder.State.CANCELED) {
return true;
}
return false;
}
/**************** 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));
}
}