1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package com.nickokiss.investor.functioncalc;
22
23 import java.math.BigDecimal;
24
25 import com.nickokiss.investor.calc.MathCalc;
26 import com.nickokiss.investor.function.Function;
27 import com.nickokiss.investor.util.Range;
28 import com.nickokiss.investor.util.TkFinConstructionException;
29
30
31
32
33
34
35 public class Div2FunctionCalc implements FunctionCalc {
36
37 private MathCalc mathCalc = new MathCalc();
38 private long iterationsLimit = 10000;
39
40 public Range getParameterRange(BigDecimal value, Function function, BigDecimal maxSize) throws TkFinConstructionException {
41 Range initialRange = getInitialRange(value, function, mathCalc.ZERO);
42 return getParameterRange(value, function, maxSize, initialRange);
43 }
44
45 public Range getInitialRange(BigDecimal value, Function function, BigDecimal startPoint) throws TkFinConstructionException {
46 BigDecimal valueAtStartPoint = function.getValue(startPoint);
47 int directionToValue = valueAtStartPoint.compareTo(value);
48 int directionRight = valueAtStartPoint.compareTo(function.getValue(startPoint.add(mathCalc.ONE)));
49 BigDecimal end = startPoint;
50 BigDecimal start = startPoint;
51 if (directionToValue == directionRight) {
52 end = moveTillDirectionChange(value, function, startPoint, directionToValue, 1);
53 } else {
54 start = moveTillDirectionChange(value, function, startPoint, directionToValue, -1);
55 }
56 return new Range(start, end);
57 }
58
59 private BigDecimal moveTillDirectionChange(BigDecimal value, Function function, BigDecimal point, int direction, int dir)
60 throws TkFinConstructionException {
61 BigDecimal stepIncrementalFactor = mathCalc.TWO;
62 BigDecimal step = mathCalc.ONE.multiply(new BigDecimal(dir));
63 int actDirection = direction;
64 BigDecimal newPoint = point;
65 while (actDirection == direction) {
66 newPoint = point.add(step);
67 actDirection = function.getValue(newPoint).compareTo(value);
68 step = step.multiply(stepIncrementalFactor);
69 }
70 return newPoint;
71 }
72
73 public Range getParameterRange(BigDecimal value, Function function, BigDecimal maxSize, Range initialRange)
74 throws TkFinConstructionException {
75 int directionFromTop = value.compareTo(function.getValue(initialRange.getStart()));
76 int directionFromBottom = value.compareTo(function.getValue(initialRange.getEnd()));
77 if (directionFromTop == directionFromBottom) {
78 throw new TkFinConstructionException("value out of range");
79 }
80 Range range = new Range(initialRange);
81 int i = 0;
82 while (maxSize.compareTo(range.getSize()) < 0) {
83 int direction = value.compareTo(function.getValue(range.getMiddle()));
84 if (direction == directionFromTop) {
85 range = range.getUpperHalf();
86 } else {
87 range = range.getLowerHalf();
88 }
89 if (i++ > iterationsLimit) {
90 throw new TkFinConstructionException("can't calculate the value: Iterations limit exceeded (" + iterationsLimit + ")");
91 }
92 }
93 return range;
94 }
95
96 public BigDecimal getParameterForValue(BigDecimal value, Function function, int scale) throws TkFinConstructionException {
97 BigDecimal maxSize = mathCalc.getUnit(scale);
98 Range range = getParameterRange(value, function, maxSize);
99 return range.getMiddle();
100 }
101
102 public void setIterationsLimit(long iterationsLimit) {
103 this.iterationsLimit = iterationsLimit;
104 }
105
106 }