// Copyright 2015 Ivan Popivanov // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package net.tradelib.functors; public class ZigZag { private double deviation = 3; private int n = 21; private int count = 0; private Sma returns; private int age = 0; private double correction = 0; private double target = 0; private double anchor = 0; private int trend = 0; private double prevPrice = 0; // The interface public int getAge() { return age; } public double getCorrection() { return correction; } public int getTrend() { return trend; } public double getTarget() { return target; } public ZigZag(int n, double deviation) { this.n = n; this.deviation = deviation; this.returns = new Sma(n); } public void add(double price) { if(count > 0) { returns.add(Math.abs(price/prevPrice - 1)); } if(count >= n) { double newTarget = returns.last()*deviation; if(count == n) { target = newTarget; anchor = price; } else { if(trend == 1) { double pct = 1 - price/anchor; boolean newTrend = pct > target; if(newTrend) { age = 0; correction = 0; target = newTarget; trend = -1; anchor = price; } else { ++age; if(price >= anchor) { correction = 0; target = newTarget; anchor = price; } else { correction = 1 - pct/target; } } } else if(trend == -1) { double pct = price/anchor - 1; boolean newTrend = pct > target; if(newTrend) { age = 0; correction = 1; target = newTarget; trend = 1; anchor = price; } else { ++age; if(price <= anchor) { correction = 0; target = newTarget; anchor = price; } else { correction = pct/target; } } } else { // No trend, the initial state if((price/anchor - 1) > target) { trend = 1; target = newTarget; anchor = price; } else if((1 - price/anchor) > target) { trend = -1; target = newTarget; anchor = price; } } } } ++count; prevPrice = price; } }