package jforex; import java.util.*; import java.math.*; import com.dukascopy.api.*; public class RizHedge implements IStrategy { @Configurable("") public String Comment = "RizHedge"; @Configurable("") public int Gap1 = 50; @Configurable("") public int TP1 = 50; @Configurable("") public double LotMultiplier1=2; @Configurable("") public int Set1Orders = 4; @Configurable("") public int Gap2 = 50; @Configurable("") public int TP2 = 50; @Configurable("") public double LotMultiplier2=2; @Configurable("") public int Set2Orders = 4; @Configurable("") public int Gap3 = 50; @Configurable("") public int TP3 = 50; @Configurable("") public double LotMultiplier3=2; @Configurable("") public int Levels = 15; @Configurable("") public double LotSize=0.001; @Configurable("") public double LotAdjuster=33; @Configurable("") public int MAPeriod=100; @Configurable("") public boolean StopTrading=false; @Configurable("") public double PerCurrencyMargin=10000; protected static Map pairs = new HashMap(); static { pairs.put(Currency.getInstance("AUD"), Instrument.AUDUSD); pairs.put(Currency.getInstance("CAD"), Instrument.USDCAD); pairs.put(Currency.getInstance("CHF"), Instrument.USDCHF); pairs.put(Currency.getInstance("DKK"), Instrument.USDDKK); pairs.put(Currency.getInstance("EUR"), Instrument.EURUSD); pairs.put(Currency.getInstance("GBP"), Instrument.GBPUSD); pairs.put(Currency.getInstance("HKD"), Instrument.USDHKD); pairs.put(Currency.getInstance("JPY"), Instrument.USDJPY); pairs.put(Currency.getInstance("MXN"), Instrument.USDMXN); pairs.put(Currency.getInstance("NOK"), Instrument.USDNOK); pairs.put(Currency.getInstance("NZD"), Instrument.NZDUSD); pairs.put(Currency.getInstance("SEK"), Instrument.USDSEK); pairs.put(Currency.getInstance("SGD"), Instrument.USDSGD); pairs.put(Currency.getInstance("TRY"), Instrument.USDTRY); } private IEngine engine; private IConsole console; private IHistory history; private IContext context; private IIndicators indicators; private IUserInterface userInterface; private int SellOrders,BuyOrders,SellStopOrders,BuyStopOrders,SellLimitOrders,BuyLimitOrders,PendingOrders,LimitOrders,StopOrders,MarketOrders,TotalOrders; private double lastActiveTP,totalProfit,closedOrders; static private Map maxDD,cycleDD,maxInitLot,maxDDPer,maxLevels,lastTotalProfit; static private Map subscribedCurrencies; static private Map> mOrders; static private double overAllMaxDD,overAllMaxDDPer; private double equity,openEquity,availEquity; private Currency accountCurrency; private IChart chart; private String commentStr; public void onStart(IContext context) throws JFException { this.engine = context.getEngine(); this.console = context.getConsole(); this.history = context.getHistory(); this.context = context; this.indicators = context.getIndicators(); this.userInterface = context.getUserInterface(); overAllMaxDD=0; overAllMaxDDPer=0; openEquity = 0; maxDD = new HashMap(); cycleDD = new HashMap(); maxInitLot=new HashMap(); maxDDPer=new HashMap(); maxLevels=new HashMap(); lastTotalProfit=new HashMap(); mOrders=new HashMap>(); subscribedCurrencies = new HashMap(); for(Instrument inst:Instrument.values()){ try{ if (history.getLastTick(inst)==null) continue; } catch (Exception e){ continue; } subscribedCurrencies.put(inst,0.0); maxDD.put(inst,0.0); cycleDD.put(inst,0.0); maxInitLot.put(inst,0.0); maxDDPer.put(inst,0.0); maxLevels.put(inst,0.0); lastTotalProfit.put(inst,0.0); mOrders.put(Comment + "_" + inst,null); } } public void onAccount(IAccount account) throws JFException { double totalSum = PerCurrencyMargin * subscribedCurrencies.size(); availEquity = account.getEquity(); equity = (availEquity/totalSum)*PerCurrencyMargin; accountCurrency = account.getCurrency(); } public void onMessage(IMessage message) throws JFException { } public void onStop() throws JFException { for(Instrument inst:subscribedCurrencies.keySet()){ console.getOut().println(inst.toString() + " : Maximum Draw Down: $" + maxDD.get(inst)); console.getOut().println(inst.toString() + " : Maximum Draw Down: " + round(maxDDPer.get(inst)*100,2) + " %"); console.getOut().println(inst.toString() + " : Maximum Initial Lot: " + maxInitLot.get(inst)); console.getOut().println(inst.toString() + " : Maximum Levels Used: " + maxLevels.get(inst)); } console.getOut().println("Over All Draw Down: $" + overAllMaxDD); console.getOut().println("Over All Draw Down: " + round(overAllMaxDDPer*100,2) + "%"); console.getOut().println("Final Equity: $" + availEquity); } public void onTick(Instrument instrument, ITick tick) throws JFException { List orders = checkOpenOrders(instrument); chart = context.getChart(instrument); commentStr = ""; if (MarketOrders==0 && PendingOrders==0){ //no orders on right so place a buystop and buy limit if (StopTrading) return; //Stop Trading is on so do not open any more trades. openEquity = equity; IEngine.OrderCommand openType; if (isBuySignal(instrument)) {openType=IEngine.OrderCommand.BUY;print ("Buy Signal",instrument);} else if (isSellSignal(instrument)) {openType=IEngine.OrderCommand.SELL;print ("Sell Signal",instrument);} else {return;} cycleDD.put(instrument, new Double(0.0)); //reset the cycle drawdown if (getLotSize()>maxInitLot.get(instrument).doubleValue()) maxInitLot.put(instrument,getLotSize()); IOrder MainOrder = engine.submitOrder(getLabel(instrument)+"1",instrument,openType,getLotSize(),0,0,0,0); MainOrder.waitForUpdate(30000); print ("Main Order " + MainOrder.getState() + " at: " + MainOrder.getOpenPrice() + " dir: " + MainOrder.getOrderCommand(),instrument); mOrders.put(Comment + "_" + instrument,null); //reset the orders list. } else{ if (closedOrders>0){ //an order has closed this means all existing orders should close String labels=""; double totLots=0; for (IOrder ord:orders){ IOrder.State ordState = ord.getState(); if (ordState!=IOrder.State.CANCELED && ordState!=IOrder.State.CLOSED){ try {print ("Closing orders because of cycle close: " + ord.getLabel() + " Lots = " + ord.getRequestedAmount(),instrument);ord.close();} catch (Exception e){ } } } /*if (equity0){ if (MarketOrders==1){ IOrder ord = orders.get(0); if (ord.getTakeProfitPrice()==0){ double openTP =0; if (ord.getOrderCommand()==IEngine.OrderCommand.BUY){ openTP = ord.getOpenPrice() + (TP1*instrument.getPipValue()); } if (ord.getOrderCommand()==IEngine.OrderCommand.SELL){ openTP = ord.getOpenPrice() - (TP1*instrument.getPipValue()); } if (ord.getState() == IOrder.State.FILLED){ openTP = roundToHalfPip(openTP,instrument); print ("Setting Main Order Take Profit to: " + openTP + " TP in pips is: " + (Math.abs(openTP-ord.getOpenPrice())),instrument); ord.setTakeProfitPrice(openTP); ord.waitForUpdate(30000); } return; } } int i = TotalOrders +1; double Gap,TP,LotMultiplier,limitPrice=0,limitTP=0; if (i<=Set1Orders){Gap = Gap1;TP = TP1;LotMultiplier = LotMultiplier1;print ("using set 1",instrument);} else if (i<=(Set1Orders+Set2Orders)){Gap = Gap2;TP = TP2;LotMultiplier = LotMultiplier2;print ("using set 2",instrument);} else{Gap = Gap3;TP = TP3;LotMultiplier = LotMultiplier3;print ("using set 3",instrument);} IOrder lastOrder=null; //Synchronization of TP might be required for(IOrder ord:orders){ lastOrder = ord; if(ord.getOrderCommand()==IEngine.OrderCommand.BUY || ord.getOrderCommand()==IEngine.OrderCommand.SELL) { if (ord.getTakeProfitPrice()!=lastActiveTP){ print ("Changing Take Profit for Order: " + ord.getLabel() + " to " + lastActiveTP + " tp gap = " + Math.abs(ord.getOpenPrice() - lastActiveTP),instrument); ord.setTakeProfitPrice(lastActiveTP); ord.waitForUpdate(30000); } } } IEngine.OrderCommand signal = lastOrder.getOrderCommand(); IEngine.OrderCommand limitType=null; if (signal==IEngine.OrderCommand.BUY){ limitPrice = lastOrder.getOpenPrice()-(Gap*instrument.getPipValue()); limitTP = limitPrice + (TP*instrument.getPipValue()); limitType = IEngine.OrderCommand.BUYLIMIT; } else if (signal==IEngine.OrderCommand.SELL){ limitPrice = lastOrder.getOpenPrice()+(Gap*instrument.getPipValue()); limitTP = limitPrice - (TP*instrument.getPipValue()); limitType = IEngine.OrderCommand.SELLLIMIT; } double lot = lastOrder.getRequestedAmount() * LotMultiplier; //lot = round(lot,4); //if (lot<=lastOrder.getRequestedAmount()) lot= round(lot + 0.0005,4); //while ((lot%0.0005)>0.0) {lot= round(lot + 0.0001,4);if ((lot%0.0005)==0.0)break;} limitPrice = roundToHalfPip(limitPrice,instrument); limitTP = roundToHalfPip(limitTP,instrument); IOrder pendingOrder = engine.submitOrder(getLabel(instrument)+i,instrument,limitType,lot,limitPrice,10,0,limitTP); pendingOrder.waitForUpdate(30000); print ("Pending order "+ pendingOrder.getState() + " with lots = " + lot + " price at: " + limitPrice + " TP = " + limitTP + " dir = " + limitType,instrument); orders.add(pendingOrder); mOrders.put(Comment + "_" + instrument,orders); } } if (MarketOrders>maxLevels.get(instrument).doubleValue()){ maxLevels.put(instrument,new Double(MarketOrders)); } if (totalProfit checkOpenOrders(Instrument instrument) throws JFException{ SellOrders=0; BuyOrders=0; SellStopOrders=0; BuyStopOrders=0; SellLimitOrders=0; BuyLimitOrders=0; PendingOrders=0; LimitOrders=0; StopOrders=0; MarketOrders=0; TotalOrders=0; lastActiveTP=0; totalProfit=0; closedOrders=0; if (mOrders.get(Comment + "_" + instrument)==null){ //No Orders for this currency and comment exist reload all orders for this comment + instrument List ordersAll = engine.getOrders(instrument); List orders = new ArrayList(); for(IOrder ord:ordersAll){ String label = ord.getLabel(); if (label.length()0) mOrders.put(Comment + "_" + instrument,orders); else mOrders.put(Comment + "_" + instrument,null); } List orders = mOrders.get(Comment + "_" + instrument); if (orders==null) return (orders); if (orders.size()==0) return(orders); //Remove orders which don't belong to this Strategy for (IOrder ord:orders){ IEngine.OrderCommand ordCommand = ord.getOrderCommand(); IOrder.State ordState = ord.getState(); if (ordState==IOrder.State.CLOSED) closedOrders = closedOrders + 1; if (ordCommand==IEngine.OrderCommand.BUY){ BuyOrders = BuyOrders + 1; MarketOrders = MarketOrders + 1; TotalOrders = TotalOrders + 1; lastActiveTP = ord.getTakeProfitPrice(); totalProfit = totalProfit + calculateProfitLoss(ord); } else if (ordCommand==IEngine.OrderCommand.SELL){ SellOrders = SellOrders + 1; MarketOrders = MarketOrders + 1; TotalOrders = TotalOrders + 1; lastActiveTP = ord.getTakeProfitPrice(); totalProfit = totalProfit + calculateProfitLoss(ord); } else if (ordCommand==IEngine.OrderCommand.SELLSTOP){ SellStopOrders = SellStopOrders + 1; PendingOrders = PendingOrders + 1; StopOrders = StopOrders + 1; TotalOrders = TotalOrders + 1; } else if (ordCommand==IEngine.OrderCommand.BUYSTOP){ BuyStopOrders = BuyStopOrders + 1; PendingOrders = PendingOrders + 1; StopOrders = StopOrders + 1; TotalOrders = TotalOrders + 1; } else if (ordCommand==IEngine.OrderCommand.SELLLIMIT){ SellLimitOrders = SellLimitOrders + 1; PendingOrders = PendingOrders + 1; LimitOrders = LimitOrders + 1; TotalOrders = TotalOrders + 1; } else if (ordCommand==IEngine.OrderCommand.BUYLIMIT){ BuyLimitOrders = BuyLimitOrders + 1; PendingOrders = PendingOrders + 1; LimitOrders = LimitOrders + 1; TotalOrders = TotalOrders + 1; } } return (orders); } private boolean isBuySignal(Instrument instrument) throws JFException{ double ma15_0 = indicators.ma(instrument,Period.FIFTEEN_MINS,OfferSide.BID,IIndicators.AppliedPrice.CLOSE,MAPeriod,IIndicators.MaType.SMA,0); double ma15_1 = indicators.ma(instrument,Period.FIFTEEN_MINS,OfferSide.BID,IIndicators.AppliedPrice.CLOSE,MAPeriod,IIndicators.MaType.SMA,1); double ma60_0 = indicators.ma(instrument,Period.ONE_HOUR,OfferSide.BID,IIndicators.AppliedPrice.CLOSE,MAPeriod,IIndicators.MaType.SMA,0); double ma60_1 = indicators.ma(instrument,Period.ONE_HOUR,OfferSide.BID,IIndicators.AppliedPrice.CLOSE,MAPeriod,IIndicators.MaType.SMA,1); double ma1440_0 = indicators.ma(instrument,Period.DAILY,OfferSide.BID,IIndicators.AppliedPrice.CLOSE,MAPeriod,IIndicators.MaType.SMA,0); double ma1440_1 = indicators.ma(instrument,Period.DAILY,OfferSide.BID,IIndicators.AppliedPrice.CLOSE,MAPeriod,IIndicators.MaType.SMA,1); IBar dailyBar = history.getBar(instrument,Period.DAILY,OfferSide.BID,0); ITick lastTick = history.getLastTick(instrument); double barSize = dailyBar.getHigh()-dailyBar.getLow(); double barQuarter = barSize/4; double upperLevel = dailyBar.getHigh()-barQuarter; double lowerLevel = dailyBar.getLow()-barQuarter; //if (lastTick.getBid()<=lowerLevel || lastTick.getBid()>=upperLevel) {log ("Price is beyond acceptable daily range");return(false);} //if (ma15_0<=ma15_1) return (false); //if (ma60_0<=ma60_1) return (false); if (ma1440_0<=ma1440_1) return (false); return(true); } private boolean isSellSignal(Instrument instrument) throws JFException{ double ma15_0 = indicators.ma(instrument,Period.FIFTEEN_MINS,OfferSide.BID,IIndicators.AppliedPrice.CLOSE,MAPeriod,IIndicators.MaType.SMA,0); double ma15_1 = indicators.ma(instrument,Period.FIFTEEN_MINS,OfferSide.BID,IIndicators.AppliedPrice.CLOSE,MAPeriod,IIndicators.MaType.SMA,1); double ma60_0 = indicators.ma(instrument,Period.ONE_HOUR,OfferSide.BID,IIndicators.AppliedPrice.CLOSE,MAPeriod,IIndicators.MaType.SMA,0); double ma60_1 = indicators.ma(instrument,Period.ONE_HOUR,OfferSide.BID,IIndicators.AppliedPrice.CLOSE,MAPeriod,IIndicators.MaType.SMA,1); double ma1440_0 = indicators.ma(instrument,Period.DAILY,OfferSide.BID,IIndicators.AppliedPrice.CLOSE,MAPeriod,IIndicators.MaType.SMA,0); double ma1440_1 = indicators.ma(instrument,Period.DAILY,OfferSide.BID,IIndicators.AppliedPrice.CLOSE,MAPeriod,IIndicators.MaType.SMA,1); IBar dailyBar = history.getBar(instrument,Period.DAILY,OfferSide.BID,0); ITick lastTick = history.getLastTick(instrument); double barSize = dailyBar.getHigh()-dailyBar.getLow(); double barQuarter = barSize/4; double upperLevel = dailyBar.getHigh()-barQuarter; double lowerLevel = dailyBar.getLow()-barQuarter; //if (lastTick.getBid()<=lowerLevel || lastTick.getBid()>=upperLevel) {log ("Price is beyond acceptable daily range");return(false);} //if (ma15_0>=ma15_1) return (false); //if (ma60_0>=ma60_1) return (false); if (ma1440_0>=ma1440_1) return (false); return(true); } private String getLabel(Instrument instrument){ return (Comment + instrument.toString().replace("/","") + (new Date()).getTime()); } private double getLotSize(){ if (LotAdjuster==0) return (LotSize); double Contracts, Factor, Lotsize,LotMultiplier; LotMultiplier = LotMultiplier1; Contracts = (equity/10000); Factor = (Math.pow(LotMultiplier,Levels)-LotMultiplier) / (LotMultiplier - 1); Lotsize = (LotAdjuster*(Contracts/(1.0 + Factor))); Lotsize = Lotsize /10; //Dukascopy adjustment factor //Lotsize = round(Lotsize,3); if (Lotsize<0.001) Lotsize = 0.001; //LotSize = round(LotSize,4); //while ((LotSize%0.0005)>0.0) {LotSize+=0.0001;if ((LotSize%0.0005)==0.0)break;} return (Lotsize); } public static double round(double d, int decimalPlace){ BigDecimal bd = new BigDecimal(Double.toString(d)); bd = bd.setScale(decimalPlace,BigDecimal.ROUND_HALF_UP); return bd.doubleValue(); } private void log (String comment){ commentStr = commentStr + comment + "\n"; } private void print (String comment,Instrument inst){ console.getOut().println(Comment + " : " + inst.toString() + " : " + comment); } private double calculateProfitLoss(IOrder order) throws JFException { double closePrice; if (order.getState() == IOrder.State.CLOSED) { closePrice = order.getClosePrice(); } else { ITick tick = history.getLastTick(order.getInstrument()); if (order.getOrderCommand().isLong()) { closePrice = tick.getBid(); } else { closePrice = tick.getAsk(); } } BigDecimal profLossInSecondaryCCY; if (order.getOrderCommand().isLong()) { profLossInSecondaryCCY = BigDecimal.valueOf(closePrice).subtract(BigDecimal.valueOf(order.getOpenPrice())) .multiply(BigDecimal.valueOf(order.getAmount()).multiply(BigDecimal.valueOf(1000000))).setScale(2, BigDecimal.ROUND_HALF_EVEN); } else { profLossInSecondaryCCY = BigDecimal.valueOf(order.getOpenPrice()).subtract(BigDecimal.valueOf(closePrice)) .multiply(BigDecimal.valueOf(order.getAmount()).multiply(BigDecimal.valueOf(1000000))).setScale(2, BigDecimal.ROUND_HALF_EVEN); } OfferSide side = order.getOrderCommand().isLong() ? OfferSide.ASK : OfferSide.BID; BigDecimal convertedProfLoss = convert(profLossInSecondaryCCY, order.getInstrument().getSecondaryCurrency(), accountCurrency, side).setScale(2, BigDecimal.ROUND_HALF_EVEN); return convertedProfLoss.doubleValue(); } public BigDecimal convert(BigDecimal amount, Currency sourceCurrency, Currency targetCurrency, OfferSide side) throws JFException { if (targetCurrency.equals(sourceCurrency)) { return amount; } BigDecimal dollarValue; if (sourceCurrency.equals(Instrument.EURUSD.getSecondaryCurrency())) { dollarValue = amount; } else { Instrument helperSourceCurrencyPair = pairs.get(sourceCurrency); if (helperSourceCurrencyPair == null) { throw new IllegalArgumentException("No currency pair found for " + sourceCurrency); } BigDecimal helperSourceCurrencyPrice = getLastPrice(helperSourceCurrencyPair, side); if (null == helperSourceCurrencyPrice) return null; dollarValue = helperSourceCurrencyPair.toString().indexOf("USD") == 0 ? amount.divide(helperSourceCurrencyPrice, 2, RoundingMode.HALF_EVEN) : amount.multiply(helperSourceCurrencyPrice).setScale(2, RoundingMode.HALF_EVEN); } if (targetCurrency.equals(Instrument.EURUSD.getSecondaryCurrency())) { return dollarValue; } Instrument pair = pairs.get(targetCurrency); BigDecimal price = getLastPrice(pair, side); if (null == price) return null; BigDecimal result = pair.toString().indexOf("USD") == 0 ? dollarValue.multiply(price).setScale(2, RoundingMode.HALF_EVEN) : dollarValue.divide(price, 2, RoundingMode.HALF_EVEN); return result; } protected BigDecimal getLastPrice(Instrument pair, OfferSide side) throws JFException { ITick tick = history.getLastTick(pair); if (tick == null) { return null; } if (side == OfferSide.BID) { return BigDecimal.valueOf(tick.getBid()); } else { return BigDecimal.valueOf(tick.getAsk()); } } public void onBar(Instrument instrument, Period period, IBar askBar, IBar bidBar) throws JFException { } public static double roundToHalfPip(double d,Instrument inst){ double pipScale = (inst.getPipValue()/10) * 5; //converts 0.0001 to 0.00005 double roundedNum = round((d/pipScale),0) * pipScale; return (roundedNum); } }