Dukascopy
 
 
Wiki JStore Search Login

Calculating our own pivot and S/R
 Post subject: Calculating our own pivot and S/R Post rating: 0   New post Posted: Tue 12 May, 2015, 13:41 
User avatar

User rating: 0
Joined: Mon 08 Dec, 2014, 19:48
Posts: 18
Location: CanadaCanada
I have been browsing a lot on this site and googling.. without success
I am trying to find a way to get this calculation

DP = (H + L + C) /3
s1 = DP - (H - DP)
s2 = DP - (H - L)
s3 = L - (H - L)
r1 = DP + (DP - L)
r2 = DP + (H - L)
r3 = H + (H - L)

does this ring the bell?

thanks !


 
 Post subject: Re: Calculating our own pivot and S/R Post rating: 0   New post Posted: Tue 12 May, 2015, 17:40 
User avatar

User rating: 94
Joined: Mon 06 Feb, 2012, 12:22
Posts: 357
Location: Portugal, Castelo Branco
Hi

Here is the standard code of pivot indicator:

/**
 * Copyright 2009 Dukascopy (Suisse) SA. All rights reserved.
 * DUKASCOPY PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

package com.dukascopy.indicators;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.GeneralPath;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;

import com.dukascopy.api.Filter;
import com.dukascopy.api.IBar;
import com.dukascopy.api.Period;
import com.dukascopy.api.indicators.BooleanOptInputDescription;
import com.dukascopy.api.indicators.IDrawingIndicator;
import com.dukascopy.api.indicators.IIndicator;
import com.dukascopy.api.indicators.IIndicatorContext;
import com.dukascopy.api.indicators.IIndicatorDrawingSupport;
import com.dukascopy.api.indicators.IndicatorInfo;
import com.dukascopy.api.indicators.IndicatorResult;
import com.dukascopy.api.indicators.InputParameterInfo;
import com.dukascopy.api.indicators.OptInputParameterInfo;
import com.dukascopy.api.indicators.OutputParameterInfo;
import com.dukascopy.api.indicators.OutputParameterInfo.DrawingStyle;
import com.dukascopy.api.indicators.OutputParameterInfo.Type;
import com.dukascopy.api.indicators.PeriodListDescription;

/**
 * Created by: S.Vishnyakov
 * Date: Oct 21, 2009
 * Time: 1:59:16 PM
 */
public class PivotIndicator implements IIndicator, IDrawingIndicator {
   
   protected static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
   static {
      DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT 0"));
   }

    private IndicatorInfo indicatorInfo;
    private InputParameterInfo[] inputParameterInfos;
    private OutputParameterInfo[] outputParameterInfos;
    private OptInputParameterInfo[] optInputParameterInfos;
   
    private IBar[][] inputs = new IBar[2][];
   
    private double[][] outputs = new double[14][];
    private PivotLevel[] finishedCalculationOutputs, drawingOutputs;
    private InputParameterInfo dailyInput;
    private DecimalFormat decimalFormat;
   
    private final GeneralPath generalPath = new GeneralPath();
    private List<Point> tmpHandlesPoints = new ArrayList<Point>();
   
    private boolean showHistoricalLevels = false;
   
    private IIndicatorContext context;
   
    private int maxDistanceBetweenTwoSeparators;
    private int lastCalculatedOutputSize = Integer.MIN_VALUE;
   
    private List<Period> periods = new ArrayList<Period>();
   
    private class PivotLevel {
       private long barTime;
       private double[] values = new double[13];
       private long timeOnChart = -1;
       
      private int x = -1;
       
      public long getBarTime() {
         return barTime;
      }
      public void setBarTime(long time) {
         this.barTime = time;
      }
      public double[] getValues() {
         return values;
      }
      
      public int getX() {
         return x;
      }
      public void setX(int x) {
         this.x = x;
      }
      
      public void setTimeOnChart(long timeOnChart) {
         this.timeOnChart = timeOnChart;
      }
      
      public long getTime(){
         return timeOnChart <= 0 ? barTime : timeOnChart;
      }
    }   
   
    public void onStart(IIndicatorContext context) {
       this.context = context;
       
        indicatorInfo = new IndicatorInfo("PIVOT", "Pivot", "Overlap Studies", true, false, true, 2, 2, 14);
        indicatorInfo.setSparseIndicator(true);
        indicatorInfo.setRecalculateAll(true);
       
        dailyInput = new InputParameterInfo("Input data", InputParameterInfo.Type.BAR);
        dailyInput.setPeriod(Period.DAILY);
        dailyInput.setFilter(Filter.WEEKENDS);       
        inputParameterInfos = new InputParameterInfo[] {
           new InputParameterInfo("Main Input data", InputParameterInfo.Type.BAR),
            dailyInput
        };

        for (Period p : Period.values()){
           if (p.isTickBasedPeriod() || p.equals(Period.ONE_YEAR)){
              continue;
           }
           periods.add(p);
        }
       
        optInputParameterInfos = new OptInputParameterInfo[] {
              new OptInputParameterInfo("Period", OptInputParameterInfo.Type.OTHER,
                    new PeriodListDescription(Period.DAILY, periods.toArray(new Period[periods.size()]))),
              new OptInputParameterInfo("Show historical levels", OptInputParameterInfo.Type.OTHER, new BooleanOptInputDescription(showHistoricalLevels))
        };

        outputParameterInfos = new OutputParameterInfo[] {
           createOutputParameterInfo("Central Point (P)", OutputParameterInfo.Type.DOUBLE, OutputParameterInfo.DrawingStyle.LEVEL_LINE, true),
           createOutputParameterInfo("Resistance (R1)", OutputParameterInfo.Type.DOUBLE, OutputParameterInfo.DrawingStyle.LEVEL_LINE, true),
           createOutputParameterInfo("Support (S1)", OutputParameterInfo.Type.DOUBLE, OutputParameterInfo.DrawingStyle.LEVEL_LINE, true),
           createOutputParameterInfo("Resistance (R2)", OutputParameterInfo.Type.DOUBLE, OutputParameterInfo.DrawingStyle.LEVEL_LINE, true),
           createOutputParameterInfo("Support (S2)", OutputParameterInfo.Type.DOUBLE, OutputParameterInfo.DrawingStyle.LEVEL_LINE, true),
           createOutputParameterInfo("Resistance (R3)", OutputParameterInfo.Type.DOUBLE, OutputParameterInfo.DrawingStyle.LEVEL_LINE, true),
           createOutputParameterInfo("Support (S3)", OutputParameterInfo.Type.DOUBLE, OutputParameterInfo.DrawingStyle.LEVEL_LINE, true),           
           createOutputParameterInfo("Mid Point P-R1", OutputParameterInfo.Type.DOUBLE, OutputParameterInfo.DrawingStyle.LEVEL_LINE, false),
           createOutputParameterInfo("Mid Point P-S1", OutputParameterInfo.Type.DOUBLE, OutputParameterInfo.DrawingStyle.LEVEL_LINE, false),
           createOutputParameterInfo("Mid Point R1-R2", OutputParameterInfo.Type.DOUBLE, OutputParameterInfo.DrawingStyle.LEVEL_LINE, false),
           createOutputParameterInfo("Mid Point S1-S2", OutputParameterInfo.Type.DOUBLE, OutputParameterInfo.DrawingStyle.LEVEL_LINE, false),
           createOutputParameterInfo("Mid Point R2-R3", OutputParameterInfo.Type.DOUBLE, OutputParameterInfo.DrawingStyle.LEVEL_LINE, false),
           createOutputParameterInfo("Mid Point S2-S3", OutputParameterInfo.Type.DOUBLE, OutputParameterInfo.DrawingStyle.LEVEL_LINE, false),
           createOutputParameterInfo("Separators", OutputParameterInfo.Type.DOUBLE, OutputParameterInfo.DrawingStyle.LEVEL_LINE, true),
        };
       
        decimalFormat = new DecimalFormat("0.00000");
    }
   
    private OutputParameterInfo createOutputParameterInfo(String name, Type type, DrawingStyle drawingStyle, final boolean showOutput) {
       return new OutputParameterInfo(name, type, drawingStyle, false){{
         setDrawnByIndicator(true);
         setShowOutput(showOutput);
      }};
    }

    public IndicatorResult calculate(int startIndex, int endIndex) {
       resetOutputs(outputs);
       
       if (startIndex > endIndex) {
          return new IndicatorResult(0, 0);
       }

       IndicatorResult result = new IndicatorResult(startIndex, endIndex - startIndex + 1);
        if(inputs[0] == null) {
            return result;
        }
       
       int leftIndexForIndicatorPeriod = getLeftBarIndexForIndicatorPeriod(startIndex) - 1;
       int rightIndexForIndicatorPeriod = getRightBarIndexForIndicatorPeriod(endIndex);
       
       if (leftIndexForIndicatorPeriod < 0) {
          leftIndexForIndicatorPeriod = 0;
       }
       if (rightIndexForIndicatorPeriod < 0) {
          rightIndexForIndicatorPeriod = inputs[1].length - 1;
       }
       
       if (leftIndexForIndicatorPeriod < 0 || rightIndexForIndicatorPeriod < 0) {
          /**
           * Not enough data for calculations
           */
          return result;
       }
       else {
          IBar previousBar = null;
          
          PivotLevel[] innerOutputs = new PivotLevel[rightIndexForIndicatorPeriod - leftIndexForIndicatorPeriod + 1];
          
          for (int i = leftIndexForIndicatorPeriod; i <= rightIndexForIndicatorPeriod; i++) {
             IBar currentBar = inputs[1][i];
             
             if (previousBar != null) {
                int chartPeriodBarIndex = i - leftIndexForIndicatorPeriod;
                
                if (innerOutputs[chartPeriodBarIndex] == null) {
                   innerOutputs[chartPeriodBarIndex] = new PivotLevel();
                }
                
                calculateAndSetupPivotValue(innerOutputs, chartPeriodBarIndex, previousBar, currentBar);                
             }
             previousBar = currentBar;
          }
          
          fillOutput(innerOutputs);
          
          lastCalculatedOutputSize = endIndex - startIndex + 1;
          
          synchronized(this) {
             finishedCalculationOutputs = innerOutputs;
          }
          
          return result;
       }
    }
   
    private void fillOutput(PivotLevel[] innerOutputs){
        if(inputs[0] == null) {
            return;
        }

       for (int i = 1; i < innerOutputs.length; i++){
          
          int currentInputIndex = getTimeIndex(innerOutputs[i].getBarTime(), inputs[0]);
            if(currentInputIndex < 0) {
                // if time of first input is after start of last innerOutput
                for (int j = 0; j < indicatorInfo.getNumberOfOutputs() - 1; j++) {
                    for (int k = 0; k < outputs[0].length; k++) {
                        outputs[j][k] = innerOutputs[innerOutputs.length - 1].getValues()[j];
                    }

                }

            } else {
                if (currentInputIndex < outputs[0].length){
                    outputs[indicatorInfo.getNumberOfOutputs() - 1][currentInputIndex] = 0;
                    innerOutputs[i].setTimeOnChart(inputs[0][currentInputIndex].getTime());

                    for (int j = 0; j < indicatorInfo.getNumberOfOutputs() - 1; j++) {
                        outputs[j][currentInputIndex] = innerOutputs[i].getValues()[j];

                        PivotLevel prevPivotLevel = innerOutputs[i - 1];
                        int prevInputIndex = prevPivotLevel == null ? -1 : getTimeIndex(prevPivotLevel.getBarTime(), inputs[0]);
                        if (prevInputIndex > -1 && prevInputIndex < outputs[j].length){
                            for (int k = prevInputIndex + 1; k < currentInputIndex; k++){
                                outputs[j][k] = prevPivotLevel.getValues()[j];
                            }
                        }

                        if (i == innerOutputs.length - 1){
                            for (int k = currentInputIndex + 1; k < outputs[0].length; k++){
                                outputs[j][k] = innerOutputs[i].getValues()[j];
                            }
                        }
                    }
                }
            }
       }
    }
   
    private void resetOutputs(double[][] outputs) {
       if (outputs != null) {
          for (double[] otpts : outputs) {
             if (otpts != null) {
                for (int i = 0; i < otpts.length; i++) {
                   otpts[i] = Double.NaN;
                }
             }
          }
       }
    }
   
    private void calculateAndSetupPivotValue(
          PivotLevel[] innerOutputs,          
          int chartPeriodBarIndex,
          IBar previousBar,
          IBar currentBar
    ) {
       // P
       double p = (previousBar.getClose() + previousBar.getHigh() + previousBar.getLow())/3;
       double r1 = 2 * p - previousBar.getLow();
       double s1 = 2 * p - previousBar.getHigh();
       double r2 = p + previousBar.getHigh() - previousBar.getLow();
       double s2 = p - previousBar.getHigh() + previousBar.getLow();
       double r3 = previousBar.getHigh() + 2 * (p - previousBar.getLow());
       double s3 = previousBar.getLow() - 2 * (previousBar.getHigh() - p);
       
       innerOutputs[chartPeriodBarIndex].getValues()[0] = p;
       // R1
       innerOutputs[chartPeriodBarIndex].getValues()[1] = r1;
       // S1
       innerOutputs[chartPeriodBarIndex].getValues()[2] = s1;
       // R2
       innerOutputs[chartPeriodBarIndex].getValues()[3] = r2;
       // S2
       innerOutputs[chartPeriodBarIndex].getValues()[4] = s2;
       // R3
       innerOutputs[chartPeriodBarIndex].getValues()[5] = r3;
       // S3
       innerOutputs[chartPeriodBarIndex].getValues()[6] = s3;
       
       //Mid Points
       //P-R1
       innerOutputs[chartPeriodBarIndex].getValues()[7] = p + (r1 - p) / 2;
       //P-S1
       innerOutputs[chartPeriodBarIndex].getValues()[8] = p - (p - s1) / 2;
       //R1-R2
       innerOutputs[chartPeriodBarIndex].getValues()[9] = r1 + (r2 - r1) / 2;
       //S1-S2
       innerOutputs[chartPeriodBarIndex].getValues()[10] = s2 + (s1 - s2) / 2;
       //R2-R3
       innerOutputs[chartPeriodBarIndex].getValues()[11] = r2 + (r3 - r2) / 2;
       //S2-S3
       innerOutputs[chartPeriodBarIndex].getValues()[12] = s3 + (s2 - s3) / 2;
       
       innerOutputs[chartPeriodBarIndex].setBarTime(currentBar.getTime());
    }
   
    private int getTimeIndex(long time, IBar[] source) {
       if (source == null) {
          return -1;
       }

       int curIndex = 0;
       int upto = source.length;
      
       while (curIndex < upto) {
           int midIndex = (curIndex + upto) / 2;
           int nextToMidIndex = midIndex + 1;
          
           IBar midBar = source[midIndex];
           IBar nextToMidBar = nextToMidIndex >= 0 && nextToMidIndex < source.length ? source[nextToMidIndex] : null;
                     
           if (midBar.getTime() == time) {
              return midIndex;
           }
           else if (nextToMidBar != null && midBar.getTime() < time && time <= nextToMidBar.getTime()){
              if (time == nextToMidBar.getTime()){
                 return nextToMidIndex;
              }
              else {
                 if (Math.abs(midBar.getTime() - time) < context.getFeedDescriptor().getPeriod().getInterval()){
                    return midIndex;
                 }
                 else {
                    return nextToMidIndex;
                 }
              }
           }
           else if (time < midBar.getTime()) {
               upto = midIndex;
           }
           else if (time > midBar.getTime()) {
              curIndex = midIndex + 1;
           }
       }
      
       return -1;
   }
   
    private int getRightBarIndexForIndicatorPeriod(int index) {
       int result = -1;
        if(inputs[0] == null) {
            return -1;
        }

        if (index >= 0 && index < inputs[0].length) {
          IBar bar = inputs[0][index];
          if (bar != null) {
             long time = bar.getTime();
             result = getTimeOrAfterTimeIndex(time, inputs[1]);
          }
       }
       
        return result;
    }
 
   private int getLeftBarIndexForIndicatorPeriod(int index) {
       int result = -1;
        if(inputs[0] == null) {
            return -1;
        }
       
       if (index >= 0 && index < inputs[0].length) {
          IBar bar = inputs[0][index];
          if (bar != null) {
             long time = bar.getTime();
             result = getTimeOrBeforeTimeIndex(time, inputs[1]);
          }
       }
       
        return result;
    }
   
    private int getTimeOrAfterTimeIndex(long time, IBar[] source) {
       if (source == null) {
          return -1;
       }

       int curIndex = 0;
       int upto = source.length;
      
       while (curIndex < upto) {
           int midIndex = (curIndex + upto) / 2;
           int nextToMidIndex = midIndex + 1;
          
           IBar midBar = source[midIndex];
           IBar nextToMidBar = nextToMidIndex >= 0 && nextToMidIndex < source.length ? source[nextToMidIndex] : null;
                     
           if (midBar.getTime() == time) {
              return midIndex;
           }
           else if (nextToMidBar != null && midBar.getTime() < time && time <= nextToMidBar.getTime()) {
              return nextToMidIndex;
           }
           else if (time < midBar.getTime()) {
               upto = midIndex;
           }
           else if (time > midBar.getTime()) {
              curIndex = midIndex + 1;
           }
       }

      return -1;
   }

   private int getTimeOrBeforeTimeIndex(long time, IBar[] source) {
       if (source == null) {
          return -1;
       }

       int curIndex = 0;
       int upto = source.length;
      
       while (curIndex < upto) {
           int midIndex = (curIndex + upto) / 2;
           int previousToMidIndex = midIndex - 1;
          
           IBar midBar = source[midIndex];
           IBar previousToMidBar = previousToMidIndex >= 0 && previousToMidIndex < source.length ? source[previousToMidIndex] : null;
          
           if (midBar.getTime() == time) {
              return midIndex;
           }
           else if (previousToMidBar != null && previousToMidBar.getTime() <= time && time < midBar.getTime()) {
              return previousToMidIndex;
           }
           else if (time < midBar.getTime()) {
               upto = midIndex;
           }
           else if (time > midBar.getTime()) {
              curIndex = midIndex + 1;
           }
       }

      return -1;
   }

    public IndicatorInfo getIndicatorInfo() {
        return indicatorInfo;
    }

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

    public int getLookback() {
        return 0;
    }

    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) {
          Period period;
           if (value instanceof Integer){
              period = mapToPredefPeriodOrdinal((Integer)value);
           }
           else {
                period = (Period)value;
           }                 
           
          if (! periods.contains(period)){
              throw new IllegalArgumentException("Period not supported");
           }
                     
           dailyInput.setPeriod(period);
       }
       else if (index == 1) {
          showHistoricalLevels = Boolean.valueOf(String.valueOf(value)).booleanValue();
       }
    }

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

   @Override
   public Point drawOutput(
         Graphics g,
         int outputIdx,
         Object values,
         Color color,
         Stroke stroke,
         IIndicatorDrawingSupport indicatorDrawingSupport,
         List<Shape> shapes,
         Map<Color, List<Point>> handles
   ) {
      doDrawOutput(g, outputIdx, values, color, stroke, indicatorDrawingSupport, shapes, handles);
      return null;
   }
   
   private void doDrawOutput(
         Graphics g,
         int outputIdx,
         Object values,
         Color color,
         Stroke stroke,
         IIndicatorDrawingSupport indicatorDrawingSupport,
         List<Shape> shapes,
         Map<Color, List<Point>> handles
   ) {
      synchronized(this) {
         drawingOutputs = finishedCalculationOutputs;
      }
      
      if (drawingOutputs == null) {
         return;
      }

      tmpHandlesPoints.clear();
      
      if (values != null && stroke != null) {
         double[] output = (double[]) values;
         
         if (output.length != lastCalculatedOutputSize) {
            /*
             * This means that data was changed, but not calculated yet - can not draw yet
             */
            return;
         }
         
         Graphics2D g2 = (Graphics2D) g;
         generalPath.reset();
         g2.setColor(color);
         g2.setStroke(stroke);
         
         IBar[] chartData = inputs[0];
         int si = 0, ei = drawingOutputs.length - 1;
         int firstCandleIndex = indicatorDrawingSupport.getIndexOfFirstCandleOnScreen();
         int lastCandleIndex = firstCandleIndex + indicatorDrawingSupport.getNumberOfCandlesOnScreen() - 1;
         
         if (firstCandleIndex <= chartData.length && lastCandleIndex < chartData.length){
            
            if (drawingOutputs[ei] != null && drawingOutputsOutOfScope(chartData, firstCandleIndex, drawingOutputs)){
               si = drawingOutputs.length > 1 ? ei - 1 : ei;
            }
            else {
            
               IBar siBar = firstCandleIndex > 0 ?  chartData[firstCandleIndex - 1] : chartData[firstCandleIndex];         
               IBar eiBar = lastCandleIndex < chartData.length - 1 ? chartData[lastCandleIndex + 1] : chartData[lastCandleIndex];
               
               si = drawingOutputs.length - 1;
               while (si > 0){
                  if (drawingOutputs[si] == null){
                     si--;
                     continue;
                  }
                  
                  if (drawingOutputs[si].getTime() >= siBar.getTime()){
                     si--;
                  }
                  else {
                     break;
                  }
               }
               
               ei = si;
               while (ei < drawingOutputs.length - 1){
                  if (drawingOutputs[ei] == null){
                     ei++;
                     continue;
                  }
                  
                  if (drawingOutputs[ei].getTime() <= eiBar.getTime()){
                     ei++;
                  }
                  else {
                     break;
                  }
               }
            }
         }
         
         if (outputIdx == getFirstEnabledOutputIndex()){
            maxDistanceBetweenTwoSeparators = calculateMaxDistanceBetweenTwoSeparators(drawingOutputs, indicatorDrawingSupport, si, ei);
         }
      
         int fontSize = calculateFontSize(maxDistanceBetweenTwoSeparators, (int)indicatorDrawingSupport.getCandleWidthInPixels());
         boolean drawValues = canDrawValues(fontSize);
         
         if (outputIdx == 13) {
            if (drawValues) {
               drawSeparators(
                     drawingOutputs,
                     indicatorDrawingSupport,
                     generalPath,
                     maxDistanceBetweenTwoSeparators,
                     si,
                     ei
               );
            }
         }
         else {
            drawPivotLevels(
                  g2,
                  outputIdx,
                  drawingOutputs,
                  indicatorDrawingSupport,
                  generalPath,
                  fontSize,
                  drawValues,
                  maxDistanceBetweenTwoSeparators,
                  si,
                  ei
            );
         }
         
         g2.draw(generalPath);
         
         shapes.add((Shape) generalPath.clone()); // cloning path, so when checking for intersection each indicator has its own path
         handles.put(color, new ArrayList<Point>(tmpHandlesPoints));
      }
   }

   private void drawSeparators(
         PivotLevel[] innerOutputs,
         IIndicatorDrawingSupport indicatorDrawingSupport,
         GeneralPath generalPath,
         int maxDistanceBetweenTwoSeparators,
         int si,
         int ei
   ) {
      if (innerOutputs == null) {
         return;
      }
      
      int maxWidth = indicatorDrawingSupport.getChartWidth() + maxDistanceBetweenTwoSeparators;
      int maxHeight = indicatorDrawingSupport.getChartHeight();
      
      Integer lastSeparatorX = null;
      
      for (int i = ei; i >= si; i--) {   
         if(innerOutputs[i] == null){
            continue;
         }
         int x = innerOutputs[i].getX() == -1 ? indicatorDrawingSupport.getXForTime(innerOutputs[i].getTime()) : innerOutputs[i].getX();
         
         if (lastSeparatorX == null) {
            lastSeparatorX = new Integer(x);
         }
         
         if (x < 0) {
            /*
             * Drawing is from right to left
             * Stop drawing if we are out of screen
             */
            break;
         }
         
         drawSeparator(
               generalPath,
               x,
               maxWidth,
               maxHeight
         );
         
         if (!showHistoricalLevels) {
            /*
             * Don't draw separators further if the user doesn't want them
             */
            break;
         }
      }
      
      if (indicatorDrawingSupport.isTimeAggregatedPeriod()) {
          drawSeparator(
                generalPath,
                (lastSeparatorX == null ? 0 : lastSeparatorX.intValue()) + maxDistanceBetweenTwoSeparators,
                maxWidth,
                maxHeight
          );
       }

   }

   private int calculateMaxDistanceBetweenTwoSeparators(
         PivotLevel[] innerOutputs,
         IIndicatorDrawingSupport indicatorDrawingSupport,
         int si, int ei
   ) {
      int maxDistance = Integer.MIN_VALUE;
      
      if (innerOutputs == null) {
         return maxDistance;
      }
      
      int previousX = -1;
      
      for (int i = si; i <= ei; i++) {
         if (innerOutputs[i] == null){
            continue;
         }
         
         int x = indicatorDrawingSupport.getXForTime(innerOutputs[i].getTime());
         innerOutputs[i].setX(x);
         
         if (i > si && previousX != -1) {
            if (x != previousX) {
               int distance = Math.abs(x - previousX);
               
               if (maxDistance < distance) {
                  maxDistance = distance;
               }
            }
            if (!showHistoricalLevels){
               int lastInnerOutputIndex = innerOutputs.length - 1;
               if (innerOutputs[lastInnerOutputIndex] != null){
                  innerOutputs[lastInnerOutputIndex].setX(indicatorDrawingSupport.getXForTime(innerOutputs[lastInnerOutputIndex].getTime()));
               }
               break;
            }
         }
         previousX = x;
      }
      return maxDistance;
   }

   private void drawPivotLevels(
         Graphics2D g2,
         int outputIdx,
         PivotLevel[] innerOutputs,
         IIndicatorDrawingSupport indicatorDrawingSupport,
         GeneralPath generalPath,
         int fontSize,
         boolean drawValues,
         int maxDistanceBetweenTwoSeparators,
         int si,
         int ei
   ) {
      g2.setFont(new Font(g2.getFont().getName(), g2.getFont().getStyle(), fontSize));
      
      int maxX = indicatorDrawingSupport.getChartWidth() + maxDistanceBetweenTwoSeparators; //JFOREX-2432
      int minX = -maxDistanceBetweenTwoSeparators;
      
      Integer previousX = null;
      
      for (int i = ei; i >= si; i--) {
         if (innerOutputs[i] == null){
            continue;
         }
         
         double d = innerOutputs[i].getValues()[outputIdx];
         
         int x = innerOutputs[i].getX() == -1 ? indicatorDrawingSupport.getXForTime(innerOutputs[i].getTime()) : innerOutputs[i].getX();
         int y = (int)indicatorDrawingSupport.getYForValue(d);
         
         if (previousX == null) {
             if (indicatorDrawingSupport.isTimeAggregatedPeriod()) {
                 previousX = new Integer(x + maxDistanceBetweenTwoSeparators);
             } else {
                 previousX = indicatorDrawingSupport.getChartWidth();
             }
         }
         
         if (
                 (y >= 0 && y <= indicatorDrawingSupport.getChartHeight()) &&
                 ! (previousX < 0 && x < 0) &&
                 ! (previousX > indicatorDrawingSupport.getChartWidth() && x > indicatorDrawingSupport.getChartWidth()) &&
               (
                       (minX <= previousX.intValue() && previousX.intValue() <= maxX) ||
                       (minX <= x && x <= maxX)
               )
         ) {
             previousX = Math.max(0, previousX);
             previousX = Math.min(indicatorDrawingSupport.getChartWidth(), previousX);
             x = Math.max(0, x);
             x = Math.min(indicatorDrawingSupport.getChartWidth(), x);
            
            generalPath.moveTo(previousX.intValue(), y);
            generalPath.lineTo(x, y);
            
            if (drawValues) {
               String valueStr = decimalFormat.format(d);
               String lineCode = getLineCodeText(outputIdx);
               String result = lineCode + ": " + valueStr;
               
               int lineCodeX = x + 1;
               int distance = Math.abs(x - previousX.intValue());
               int newFontSize = calculateFontSize(distance, (int)indicatorDrawingSupport.getCandleWidthInPixels());
               boolean canDrawValues = this.canDrawValues(newFontSize);
               
               if (canDrawValues) {
                  if (newFontSize != fontSize) {
                     fontSize = newFontSize;
                     g2.setFont(new Font(g2.getFont().getName(), g2.getFont().getStyle(), fontSize));
                  }
                  g2.drawString(result, lineCodeX, y - 2);
               }
            }
            
            if (!showHistoricalLevels) {
               break;
            }
         }
         else if (y < 0 || y > indicatorDrawingSupport.getChartHeight() ||
                    (previousX < 0 && x < 0) ||
                    (previousX > indicatorDrawingSupport.getChartWidth() && x > indicatorDrawingSupport.getChartWidth()) ||
               x > maxX ||
               previousX.intValue() > maxX
         ) {
            /*
             *   the last actual period is out of screen => don't draw anything if showHistoricalLevels is disabled
             */            
            if (!showHistoricalLevels) {
               break;
            }
         }
         
         previousX = Integer.valueOf(x);
      }
   }
   
   private boolean canDrawValues(int fontSize) {
      final int MIN_FONT_SIZE = 4;
      
      if (fontSize <= MIN_FONT_SIZE) {
         return false;
      }
      return true;
   }

   private int calculateFontSize(
         int spaceBetweenTwoSeparators,
         int candleWidthInPixels
   ) {
      
      final int MAX_FONT_SIZE = 12;
      final int DIVISION_COEF = 7;
      
      spaceBetweenTwoSeparators /= DIVISION_COEF;
      spaceBetweenTwoSeparators = spaceBetweenTwoSeparators < 0 ? candleWidthInPixels : spaceBetweenTwoSeparators;
      
      return spaceBetweenTwoSeparators > MAX_FONT_SIZE ? MAX_FONT_SIZE : spaceBetweenTwoSeparators;
   }

   private void drawSeparator(
         GeneralPath generalPath,
         int x,
         int maxWidth,
         int maxHeight
   ) {
      if (0 <= x && x <= maxWidth) {
         generalPath.moveTo(x, 0);
         generalPath.lineTo(x, maxHeight);
         
         tmpHandlesPoints.add(new Point(x, 5));
         tmpHandlesPoints.add(new Point(x, maxHeight/2));
         tmpHandlesPoints.add(new Point(x, maxHeight - 5));
      }
   }

   private String getLineCodeText(int outputIdx) {
      String lineCode = "";
      switch (outputIdx) {
         case 0 : lineCode = "P"; break;
         case 1 : lineCode = "R1"; break;
         case 2 : lineCode = "S1"; break;
         case 3 : lineCode = "R2"; break;
         case 4 : lineCode = "S2"; break;
         case 5 : lineCode = "R3"; break;
         case 6 : lineCode = "S3"; break;
         case 7 : lineCode = "P-R1"; break;
         case 8 : lineCode = "P-S1"; break;
         case 9 : lineCode = "R1-R2"; break;
         case 10 : lineCode = "S1-S2"; break;
         case 11 : lineCode = "R2-R3"; break;
         case 12 : lineCode = "S2-S3"; break;
         default: throw new IllegalArgumentException("Illegal outputIdx - " + outputIdx);
      }
      return lineCode;
   }
   
   private int getFirstEnabledOutputIndex(){
      for (int i = 0; i < getIndicatorInfo().getNumberOfOutputs(); i++){
         if (outputParameterInfos[i].isShowOutput()) {
            return i;
         }
      }
      return -1;
   }
   
   protected boolean drawingOutputsOutOfScope(IBar[] chartData, int firstCandleIndex, PivotLevel[] drawingOutputs){
      boolean res = chartData[firstCandleIndex].getTime() > drawingOutputs[drawingOutputs.length - 1].getTime();
      
      return res;
   }
   private static Period mapToPredefPeriodOrdinal(int oldPeriod){
      Period res;
      
      switch (oldPeriod) {
      case 0:
         res = Period.ONE_MIN;
         break;
      case 1:
         res = Period.FIVE_MINS;
         break;
      case 2:
         res = Period.TEN_MINS;
         break;
      case 3:
         res = Period.FIFTEEN_MINS;
         break;
      case 4:
         res = Period.THIRTY_MINS;
         break;
      case 5:
         res = Period.ONE_HOUR;
         break;
      case 6:
         res = Period.FOUR_HOURS;
         break;
      case 7:
         res = Period.DAILY;
         break;
      case 8:
         res = Period.WEEKLY;
         break;
      case 9:
         res = Period.MONTHLY;
         break;

      default:
         res = Period.DAILY;
      }
      
      return res;
   }
}


Find the code
// P
       double p = (previousBar.getClose() + previousBar.getHigh() + previousBar.getLow())/3;
       double r1 = 2 * p - previousBar.getLow();
       double s1 = 2 * p - previousBar.getHigh();
       double r2 = p + previousBar.getHigh() - previousBar.getLow();
       double s2 = p - previousBar.getHigh() + previousBar.getLow();
       double r3 = previousBar.getHigh() + 2 * (p - previousBar.getLow());
       double s3 = previousBar.getLow() - 2 * (previousBar.getHigh() - p);


and change it to meet your needs, compile and test it.

I hope that helps

Regards

JL


 
 Post subject: Re: Calculating our own pivot and S/R Post rating: 0   New post Posted: Tue 12 May, 2015, 18:06 
User avatar

User rating: 0
Joined: Mon 08 Dec, 2014, 19:48
Posts: 18
Location: CanadaCanada
that's very nice much appreciated. I don't understand how to do this properly but i will search and try to learn that.
that's funny, I see where you are from and I just reading diverse recipes about Bacalhau... been trying to find a wonderful similar dish but not with cod... I know that's not really the place :)
cheers and thank, I'll look into the "how to" about the indicator and let you know


 
 Post subject: Re: Calculating our own pivot and S/R Post rating: 0   New post Posted: Tue 12 May, 2015, 18:50 
User avatar

User rating: 0
Joined: Mon 08 Dec, 2014, 19:48
Posts: 18
Location: CanadaCanada
OK I think I found out what to change. thanks again

but when I compile, I got an error line 45 : 17:43:11 The public type PivotIndicator must be defined in its own file

which seems normal as this is no longer a public class indicator, what should be the syntax to change this?


"public class PivotIndicator implements IIndicator, IDrawingIndicator {"


 
 Post subject: Re: Calculating our own pivot and S/R Post rating: 0   New post Posted: Tue 12 May, 2015, 23:27 
User avatar

User rating: 94
Joined: Mon 06 Feb, 2012, 12:22
Posts: 357
Location: Portugal, Castelo Branco
Hi

Sorry, i do not know you don't have some basic knowledge of Java.

You need to create a file with the name of the class with the extension '.java'

That means if you have this code:

public class PivotIndicator implements IIndicator, IDrawingIndicator { .....


You need to save the file with the name 'PivotIndicator.java'

If you want to name it other way, for example 'MyPivotPoints.java' you need to change the class name on the source to this name

...
public class MyPivotPoints implements IIndicator, IDrawingIndicator {
.....



I hope it will be clear enought.

Regards

JL


 
 Post subject: Re: Calculating our own pivot and S/R Post rating: 0   New post Posted: Wed 13 May, 2015, 00:43 
User avatar

User rating: 0
Joined: Mon 08 Dec, 2014, 19:48
Posts: 18
Location: CanadaCanada
thank you so much JLongo, your help is highly appreciated, never felt so close

compilation seems fine
but now I got: 23:36:29 Cannot enable indicator, another indicator with name [PIVOT] already registered in the system

tried to save under another name, like bobfile (and replacing as well in the file) saving is OK but same message
tried also to save in the "indicators" folder and also elsewhere

same error message

after compilation the file changes suffix? from .java to .jfx ?


 
 Post subject: Re: Calculating our own pivot and S/R Post rating: 0   New post Posted: Wed 13 May, 2015, 09:18 
User avatar

User rating: 94
Joined: Mon 06 Feb, 2012, 12:22
Posts: 357
Location: Portugal, Castelo Branco
Hi

Sorry, i forgot to inform you to change the name of indicator at this line:

indicatorInfo = new IndicatorInfo("PIVOT", "Pivot", "Overlap Studies", true, false, true, 2, 2, 14);


In this case you need to change the "PIVOT" and "Pivot" to other name to avoid conflict with the pivot indicator that exits on JForex.

The .jfx file is the generated file by compiling java file and is the one that JForex runs (to run, you only need this file).


Regards

JL


 
 Post subject: Re: Calculating our own pivot and S/R Post rating: 0   New post Posted: Wed 13 May, 2015, 11:45 
User avatar

User rating: 0
Joined: Mon 08 Dec, 2014, 19:48
Posts: 18
Location: CanadaCanada
Jose,

It worked so easily! I still need to verify calculations but I now know how to define my own pivot and S/R

Jose, you have a gift for explaining things simply!

thank you so much for helping.

I am no expert in Dukascopy, I tend to get lost as they propose so many stuff, contects...TV...community .... BUT please let me know if I can leave a feedback or something.

Be in touch, enjoy your wonderful country, traveled there 4 years ago and loved the strengh and independance of the people (not to mention, culture, beaches and food...)

cheers


 
 Post subject: Re: Calculating our own pivot and S/R Post rating: 0   New post Posted: Wed 13 May, 2015, 17:16 
User avatar

User rating: 94
Joined: Mon 06 Feb, 2012, 12:22
Posts: 357
Location: Portugal, Castelo Branco
Hi

I'm pleased that i was capable to help you. Just say if you need anything more.

Also, i'm glad to know your opinion about my country :)

Regards

JL


 
 Post subject: Re: Calculating our own pivot and S/R Post rating: 0   New post Posted: Thu 14 May, 2015, 00:40 
User avatar

User rating: 94
Joined: Mon 06 Feb, 2012, 12:22
Posts: 357
Location: Portugal, Castelo Branco
Hi

Only now i have some time to analize your pivot points formulas (i'm curious about the ring bell :) ). The only ones that differ from standard pivot indicator is s3 and r3.

Just for information i place a file with some formulas i found on internet if you feel some interest in try/study them.

Regards

JL


Attachments:
Pivot Points Formulas.pdf [108.65 KiB]
Downloaded 191 times
DISCLAIMER: Dukascopy Bank SA's waiver of responsability - Documents, data or information available on this webpage may be posted by third parties without Dukascopy Bank SA being obliged to make any control on their content. Anyone accessing this webpage and downloading or otherwise making use of any document, data or information found on this webpage shall do it on his/her own risks without any recourse against Dukascopy Bank SA in relation thereto or for any consequences arising to him/her or any third party from the use and/or reliance on any document, data or information found on this webpage.
 

Jump to:  

  © 1998-2024 Dukascopy® Bank SA
On-line Currency forex trading with Swiss Forex Broker - ECN Forex Brokerage,
Managed Forex Accounts, introducing forex brokers, Currency Forex Data Feed and News
Currency Forex Trading Platform provided on-line by Dukascopy.com