package jforex_november;

import com.dukascopy.api.*;
import java.util.*;

public class linnux_Nov implements IStrategy {  
  
    private IContext context = null;
    private IEngine engine = null;
    private IChart chart = null;
    private IHistory history = null;
    private IIndicators indicators = null;
    private IConsole console = null;
    
    private int profitLimit;
    private int lossLimit;
    private double bidPrice;
    private double askPrice;
    private double accountEquity;
    public double Risk = 0.1; 
    
    private static final int Slippage = 5; //in pips
    public boolean breakeven = true;
    public double breakpoint = 10.5; //20.5
    private int trailingStop = 60;//60
    public boolean tradeAllowed=true;
    public boolean loggingEnabled = false;
    
    private double myTotalPositiveProfit = 0.0;
    private boolean closedOrder = false;
    
    public Instrument myInstrument = Instrument.EURUSD;
    public Period myPeriod = Period.ONE_MIN;
  
    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();
    }

    // count opened positions
    protected int positionsTotal(Instrument myInstrument) throws JFException 
    {
        int counter = 0;
        for (IOrder order : engine.getOrders(myInstrument)) {
            if (order.getState() == IOrder.State.FILLED) {
                counter++;
            }
        }
        return counter;
    }

    protected String getLabel(Instrument myInstrument)
    {
        String label = myInstrument.name();        
        long time = new java.util.Date().getTime();
        label = label.substring(0, 2) + label.substring(3, 5);
        label = label + time;
        label = label.toLowerCase();
        return label;
    }

    public void onBar(Instrument instrument, Period period, IBar askbar, IBar bidbar) throws JFException 
    {
        double Un = Risk * accountEquity / 1000;
        double lots = 0.25 * Math.round(Un); 
           
		if(period == myPeriod && instrument == myInstrument) 
		{       
        	profitLimit = 150;//150
        	lossLimit = 55;//55
        	tradeAllowed = true;
       
			if (askbar.getVolume() == 0) return;
      
			double openPrice = bidbar.getOpen();
             
            askPrice = askbar.getClose();
            bidPrice = bidbar.getClose();
                      
            double sma50 = this.indicators.ema(myInstrument, myPeriod, OfferSide.BID, IIndicators.AppliedPrice.CLOSE, 50, 0);
            double sma100 = this.indicators.ema(myInstrument, myPeriod, OfferSide.BID, IIndicators.AppliedPrice.CLOSE, 100, 0);
            double sma200 = this.indicators.ema(myInstrument, myPeriod, OfferSide.BID, IIndicators.AppliedPrice.CLOSE, 200, 0);  
           
          	double [] bands = this.indicators.bbands(myInstrument,
                myPeriod,
                OfferSide.BID,
                IIndicators.AppliedPrice.CLOSE,
                20,
                2,
                2,
                IIndicators.MaType.EMA,
                0);
                
            double adx = this.indicators.adx(myInstrument, myPeriod, OfferSide.BID, 14, 1);
          
			if (positionsTotal(myInstrument) == 0) 
			{                 
                if (adx > 35 && bidPrice > bands[0]  && openPrice < bands[0] && bidPrice > sma50
                	&& bidPrice > sma100 && bidPrice > sma200) 
                {                    
                 buy(myInstrument, engine, profitLimit, lossLimit, lots);                  
                }
                
                else  if (adx > 35 && bidPrice < bands[2] && openPrice > bands[2]  && bidPrice < sma50
                		&& bidPrice < sma100 && bidPrice < sma200) 
                {   
                   sell(myInstrument, engine, profitLimit, lossLimit, lots);
                }             
        	}                      
    	}
    }

	public void onMessage(IMessage message) throws JFException 
  	{  
        IOrder myOrder = message.getOrder();
              
        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); 
            
            if (profitsLoss>0){myTotalPositiveProfit += profitsLoss;}      
        }
	}
     

    @Override
	public void onAccount(IAccount account) throws JFException 
   	{      
      accountEquity = account.getEquity();
      
      //if (accountEquity > 150000) volume = 0.01;
   	}
   	
    public void sell(Instrument myInstrument, IEngine engine, int takeProfitPipLevel, int endLossPipLevel, double volumeParam)  throws JFException 
    {
        
        engine.submitOrder("MyOrder", myInstrument, IEngine.OrderCommand.SELL, volumeParam, 0, Slippage, bidPrice
                        + myInstrument.getPipValue() *endLossPipLevel, bidPrice - myInstrument.getPipValue() * takeProfitPipLevel);
	} 
     
     public void buy(Instrument myInstrument, IEngine engine, int takeProfitPipLevel, int endLossPipLevel, double volumeParam)  throws JFException 
     {
        
         engine.submitOrder("MyOrder", myInstrument, IEngine.OrderCommand.BUY, volumeParam, 0, Slippage, askPrice
                        - myInstrument.getPipValue() * endLossPipLevel, askPrice + myInstrument.getPipValue() * takeProfitPipLevel);
     }     
     
     // *****  Order Management - TrailingStop *****

    public void myTrailingStop(Instrument myInstrument, int vTrailingStop, ITick tick) throws JFException {
    
        if (engine.getOrder("MyOrder")== null) return;
           // trailing stop if order is a sell order
              if(engine.getOrder("MyOrder").isLong()){
                     // if order is a buy do the following
                     if(breakeven==true){
                         
                         if((tick.getAsk()-(5*breakpoint*myInstrument.getPipValue()))>(engine.getOrder("MyOrder").getOpenPrice())) {
                         engine.getOrder("MyOrder").setStopLossPrice(engine.getOrder("MyOrder").getOpenPrice()+breakpoint*myInstrument.getPipValue());
                         breakeven=false;
                        }
                        
                     }
                     else{
                         double vStop=tick.getAsk()-(myInstrument.getPipValue()*trailingStop);
                     // check if current stop loss is less than the trailing stop, if yes traling stop is the new stoploss
                          
                        if(engine.getOrder("MyOrder").getStopLossPrice()<vStop-2*myInstrument.getPipValue()) {
                             engine.getOrder("MyOrder").setStopLossPrice(vStop);
                        }
                    }
              }
              else{
                  
                  if(breakeven==true){
                         if(tick.getBid()+(5*breakpoint*myInstrument.getPipValue())<engine.getOrder("MyOrder").getOpenPrice()) {
                         engine.getOrder("MyOrder").setStopLossPrice(engine.getOrder("MyOrder").getOpenPrice()-myInstrument.getPipValue()*breakpoint);                           
                         breakeven=false;
                        }                        
                                
                    }
                    else{
                        double vStop=myInstrument.getPipValue()*trailingStop+tick.getBid();
                    // check if current stoploss is over the trailing stop loss, if yes set a new stop with trailing stop value
                        if(engine.getOrder("MyOrder").getStopLossPrice()>vStop+2*myInstrument.getPipValue()) {
                            engine.getOrder("MyOrder").setStopLossPrice(vStop);
                        }
                    }
            }
    }
       

	public void onTick(Instrument myInstrument, ITick tick) throws JFException 
	{	    
            if(positionsTotal(myInstrument) == 1)
            {
                myTrailingStop(myInstrument, this.trailingStop, tick);
            } 
    }
    
    public void print(String string) {

        if (loggingEnabled) console.getOut().println(string);        
    }
    
    public void closeOrder(Instrument myInstrument) throws JFException {

        for (IOrder order : engine.getOrders(myInstrument)) {
            if (order.getState() == IOrder.State.FILLED && positionsTotal(myInstrument)>1) {
            
                // Rule 6.3, profit per trade cannot be > 25% of total wins
                if (order.getProfitLossInUSD() > myTotalPositiveProfit*0.225) 
                {
                   order.close();
                   print(order.getLabel() + ": CLOSED for Rule 6.3");
                }
              }
        }     
    }
     
    public void onStop() throws JFException {}
}
