/* 
 *   interinvest1000
 *   
 *   Autor: Ricardo Pereira
 *   
 *   Skype: pereira_ricardo
 *   
 *   Email: interinvest1000@gmail.com
 *   
 *   VPA - Volume Price Analysis
 *  
 *  
 */

package jforex;

import java.util.*;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import com.dukascopy.api.indicators.*;
import com.dukascopy.api.IBar;
import com.dukascopy.api.ITick;
import com.dukascopy.api.Instrument;
import com.dukascopy.api.IHistory;
import java.awt.Color;
import java.util.List;
import com.dukascopy.api.Period;
import com.dukascopy.api.JFException;
import com.dukascopy.api.OfferSide;
import com.dukascopy.api.IConsole;


class customBar
{
    public double high = 0;
    public double low = 9999999;
    public double open = 0;
    public double close = 0;
    public double volume = 0;  
 };
 
public class volClimax implements IIndicator {
    private IndicatorInfo indicatorInfo;
    private InputParameterInfo[] inputParameterInfos;
    private OptInputParameterInfo[] optInputParameterInfos;
    private OutputParameterInfo[] outputParameterInfos;
    private IBar[][] inputs = new IBar[1][];
    private int timePeriod = 30;
    private Period[] periods = new Period[11];
    private int timePeriodLong = 500;
    private int customPeriod = 0;
    private double percMin = 0;
    private double volumVolat = 0;
    private double valMin = 0;
    private double[][] outputs = new double[6][];
    private IHistory history;
    private IIndicatorContext theContext;
    private IConsole console;

    private int volType = 0;
    

    
    public void onStart(IIndicatorContext context) {
         this.history = context.getHistory();
         this.console = context.getConsole();
         this.theContext = context ;

          int[] volValues = new int[2];
          String[] volNames = new String[2];
          volValues[0] = 0;
          volNames[0] = "Volume";
          volValues[1] = 1;
          volNames[1] = "RangeVol";


            
        indicatorInfo = new IndicatorInfo("volClimax", "Climax do Volume 3", "My indicators",
                false, false, false, 1, 5, 5);
        inputParameterInfos = new InputParameterInfo[] {new InputParameterInfo("Input data", InputParameterInfo.Type.BAR)
        
        

        };
        optInputParameterInfos = new OptInputParameterInfo[] {

               new OptInputParameterInfo("Climax Period", OptInputParameterInfo.Type.OTHER,new IntegerRangeDescription(10, 1, 2000, 1)), 
               new OptInputParameterInfo("Bar Size", OptInputParameterInfo.Type.OTHER,new IntegerRangeDescription(1, 0, 9000, 1)),
               new OptInputParameterInfo("Perc Min", OptInputParameterInfo.Type.OTHER,new IntegerRangeDescription(0, 0,100, 1)),
               new OptInputParameterInfo("Val Min", OptInputParameterInfo.Type.OTHER,new DoubleRangeDescription(0, 0,10000, 0.01,2)),
               new OptInputParameterInfo("Volume Type", OptInputParameterInfo.Type.OTHER, new IntegerListDescription(0 , volValues, volNames)),
                     
        
         };
         
       
       

        outputParameterInfos = new OutputParameterInfo[] {
              new OutputParameterInfo("Normal", OutputParameterInfo.Type.DOUBLE,OutputParameterInfo.DrawingStyle.HISTOGRAM){{setColor(Color.LIGHT_GRAY);}},
              new OutputParameterInfo("Rising Bull", OutputParameterInfo.Type.DOUBLE,OutputParameterInfo.DrawingStyle.HISTOGRAM){{setColor(Color.GREEN);}},
              new OutputParameterInfo("Rising Bear", OutputParameterInfo.Type.DOUBLE,OutputParameterInfo.DrawingStyle.HISTOGRAM){{setColor(Color.RED);}},
              new OutputParameterInfo("Climax Bull", OutputParameterInfo.Type.DOUBLE,OutputParameterInfo.DrawingStyle.HISTOGRAM){{setColor(Color.BLUE);}},
              new OutputParameterInfo("Climax Bear", OutputParameterInfo.Type.DOUBLE,OutputParameterInfo.DrawingStyle.HISTOGRAM){{setColor(Color.MAGENTA);}},

            
            };
    }
    
    public void calcHistory(IBar currentBar, int x,int pos) throws JFException {
       
        long to = currentBar.getTime();
        long from =  history.getTimeForNBarsBack(theContext.getPeriod(), to, (timePeriod *  customPeriod)); 
       
 
      //  console.getOut().println(hora.format(from) + "/" + hora.format(to) + "/" + hora.format(currentBar.getTime()));
        
        customBar _listBar[] = new customBar[timePeriod+1];
        List<IBar> listBars = new ArrayList<IBar>();
        int t = 0;
         for (int i = inputs[0].length - 1; i >= 0;i--) {
            IBar testBar = inputs[0][i];
            
            
            
            if (testBar.getTime() <= to) {
               
                listBars.add(testBar);
                t = t + 1;
            }
            
            if (t >= timePeriod *  customPeriod)
                break;
  
         }
    
     
   
        int cont = 0;
        int contPer = 0;

   
        _listBar[0] = new customBar();
        _listBar[0].close = currentBar.getClose();        
        
        double lastOpen = 0;

     for (int i = 0;i < listBars.size();i++) {
            IBar processBar = listBars.get(i);
        
            
            _listBar[cont].volume = _listBar[cont].volume + processBar.getVolume();               
            _listBar[cont].high = Math.max(_listBar[cont].high,processBar.getHigh()); 
            _listBar[cont].low = Math.min(_listBar[cont].low,processBar.getLow());   
                                                
            contPer++;
               
            lastOpen = processBar.getOpen();
            if (contPer == customPeriod) {

                _listBar[cont].open = processBar.getOpen();
         
                // Nova iteracao
                
                {
                
             
                    cont ++;
                    _listBar[cont] = new customBar();
                    
                    contPer = 0;
                    _listBar[cont].close = processBar.getClose();
               
                }
                
            }
        }
        
        
           
        
        if (_listBar[0].open == 0) 
            _listBar[cont].open = lastOpen;


        double av = 0;
        double tempv2 = 0;
        double HiValue2 = 0;
        double fator = 0;
        double av2 = 0;
        double value2 = 0;
        double perc = 0;
        double range = (_listBar[0].high - _listBar[0].low);
      
        value2 = _listBar[0].volume * range; 


        if (_listBar[0].high - _listBar[0].low > 0) {
            
            fator = Math.abs((_listBar[0].open - _listBar[0].close) / (_listBar[0].high - _listBar[0].low) / customPeriod); 
            perc = Math.abs((_listBar[0].open - _listBar[0].close) / (_listBar[0].high - _listBar[0].low)) * 100;
        }
  
        if (volType == 0)
           range = 1;

        outputs[0][pos] =  _listBar[0].volume * range / customPeriod;
       
        for (int i = 0;i < timePeriod; i++) {
              try {
            
                 av += _listBar[i].volume;
                         
                 tempv2 = _listBar[i].volume *  (_listBar[i].high - _listBar[i].low); 
                    if (tempv2 >= HiValue2) 
                       HiValue2 = tempv2;    
                         } catch (NumberFormatException error) {

                console.getErr().println(error.getMessage());
                
                } finally {
           
       }

      }
     
 
         av = av / timePeriod;

         if (perc > percMin &&  _listBar[0].volume * fator * range > valMin) {
         
             if (_listBar[0].volume >=  av * 1.5) {
                    
                if (_listBar[0].close > _listBar[0].open) 
                   outputs[3][pos] = _listBar[0].volume * fator * range;
    
                if (_listBar[0].close < _listBar[0].open) 
                   outputs[4][pos] = _listBar[0].volume * fator * range;
             }
             else
             if ((value2 >= HiValue2) || (_listBar[0].volume >= av * 2)) {
                  if (_listBar[0].close > _listBar[0].open) 
                       outputs[1][pos] = _listBar[0].volume * fator * range;
        
                    if (_listBar[0].close < _listBar[0].open) 
                       outputs[2][pos] = _listBar[0].volume * fator * range;
              }
         }
          


           
    }

    public IndicatorResult calculate(int startIndex, int endIndex) {
        
       
        //calculating startIndex taking into account lookback value
        if (startIndex - getLookback() < 0) {
            startIndex -= startIndex - getLookback();
        }
        int i, j;
       
   
        for (i = startIndex, j = 0; i <= endIndex; i++, j++) {

             try {
         
                calcHistory(inputs[0][i],i,j);
             } 
             catch(Exception e) {}
             
    
            
        }      
        return new IndicatorResult(startIndex, j);
    }

    public IndicatorInfo getIndicatorInfo() {
        return indicatorInfo;
    }

    public InputParameterInfo getInputParameterInfo(int index) {
        if (index <= inputParameterInfos.length) {
            return inputParameterInfos[index];
        }
        return null;
    }

    public int getLookback() {
        return 1000;
    }

    public int getLookforward() {
        return 0;
    }

    public OptInputParameterInfo getOptInputParameterInfo(int index) {
        if (index <= optInputParameterInfos.length) {
            return optInputParameterInfos[index];
        }
        return null;
    }

    public OutputParameterInfo getOutputParameterInfo(int index) {
        if (index <= outputParameterInfos.length) {
            return outputParameterInfos[index];
        }
        return null;
    }

    public void setInputParameter(int index, Object array) {
        inputs[index] = (IBar[]) array;
    }

    public void setOptInputParameter(int index, Object value) {
        

                     
        if (index == 0)
           timePeriod = (Integer) value;
           
           
        if (index == 1) 
           customPeriod = (Integer) value;

            
        if (index == 2)
           percMin= (Integer) value;
           
        if (index == 3)
           valMin= (Double) value;
           
           
       if (index == 4)
          volType = (Integer) value;
    }

    public void setOutputParameter(int index, Object array) {
        outputs[index] = (double[]) array;
    }
}