Created
July 1, 2020 14:37
-
-
Save nickmitchko/45189a7e2ac9269fbb1a5a3c8b795d00 to your computer and use it in GitHub Desktop.
HeikinAshi Candle Implementation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.nmitchko.storage.Candles; | |
import com.nmitchko.storage.Candle; | |
import com.nmitchko.storage.Candles.enums.CandleDirection; | |
import com.nmitchko.storage.Candles.enums.CandlePeriod; | |
import com.nmitchko.storage.Candles.enums.CandleType; | |
import org.ta4j.core.Bar; | |
import java.sql.Timestamp; | |
/** | |
* HeikinAski Candle used for better trend analysis | |
*/ | |
public class HeikinAshiCandle implements Candle { | |
/** | |
* The Heikin Ashi high for the candle, not the exchange high | |
* MAX(exchange high, HA-Open, HA-Close) | |
*/ | |
public double high; | |
/** | |
* The Heikin Ashi open | |
* [HA-open t-1 + HA-Close t-1) / 2 | |
*/ | |
public double open; | |
/** | |
* The Heikin Ashi close | |
* [open + high + low + close) /4 | |
*/ | |
public double close; | |
/** | |
* Volume for this candle (same as exchange candle) | |
*/ | |
public double volume; | |
/** | |
* SQL timestamp of the candle close | |
*/ | |
public Timestamp closeTime; | |
/** | |
* Period of the candle, set via enum | |
*/ | |
public CandlePeriod candlePeriod; | |
/** | |
* Direction of the candle | |
*/ | |
public CandleDirection candleDirection; | |
/** | |
* The Heikin Ashi low for the candle, not the exchange low | |
* MIN(exchange low, HA-Open, HA-close) | |
*/ | |
private double low; | |
public HeikinAshiCandle(Timestamp closeTime, double high, double low, double open, double close, double volume) { | |
this.closeTime = closeTime; | |
this.high = high; | |
this.low = low; | |
this.open = open; | |
this.close = close; | |
this.volume = volume; | |
} | |
public HeikinAshiCandle(Bar ta4jBar) { | |
this.closeTime = new Timestamp(ta4jBar.getEndTime().toLocalDateTime().getNano()); | |
this.high = ta4jBar.getHighPrice().doubleValue(); | |
this.low = ta4jBar.getLowPrice().doubleValue(); | |
this.open = ta4jBar.getOpenPrice().doubleValue(); | |
this.close = ta4jBar.getClosePrice().doubleValue(); | |
this.candleDirection = (this.close > this.open) ? CandleDirection.UP : CandleDirection.DOWN; | |
this.volume = ta4jBar.getVolume().doubleValue(); | |
} | |
public HeikinAshiCandle(HeikinAshiCandle previous, Candle candle) { | |
if (previous == null) { | |
throw new NullPointerException("Previous candle cannot be null. Pass the exchange candle for first period."); | |
} | |
this.open = this.calculateOpen(previous); | |
this.close = this.calculateClose(candle.getOpen(), candle.getHigh(), candle.getLow(), candle.getClose()); | |
this.high = this.calculateHigh(candle.getHigh()); | |
this.low = this.calculateLow(candle.getLow()); | |
this.candleDirection = (this.close > this.open) ? CandleDirection.UP : CandleDirection.DOWN; | |
this.closeTime = new Timestamp(candle.getCandleCloseTime().getTime()); | |
this.volume = candle.getVolume(); | |
} | |
/** | |
* @param previous Previous candle, should not be null, for starting period pass the exchange | |
* candle. | |
*/ | |
public HeikinAshiCandle(HeikinAshiCandle previous, Timestamp closeTime, double high, double low, double open, double close, double volume) { | |
if (previous == null) { | |
throw new NullPointerException("Previous candle cannot be null. Pass the exchange candle for first period."); | |
} | |
this.open = this.calculateOpen(previous); | |
this.close = this.calculateClose(open, high, low, close); | |
this.high = this.calculateHigh(high); | |
this.low = this.calculateLow(low); | |
this.candleDirection = (this.close > this.open) ? CandleDirection.UP : CandleDirection.DOWN; | |
this.closeTime = closeTime; | |
this.volume = volume; | |
} | |
private double calculateClose(double open, double high, double low, double close) { | |
return (open + high + low + close) / 4; | |
} | |
private double calculateHigh(double high) { | |
return Double.max(Double.max(high, this.open), this.close); | |
} | |
private double calculateLow(double low) { | |
return Double.min(Double.min(low, this.open), this.close); | |
} | |
private double calculateOpen(HeikinAshiCandle previous) { | |
return (previous.getOpen() + previous.getClose()) * 0.5; | |
} | |
/** | |
* @return Returns the candle time of close | |
*/ | |
@Override | |
public Timestamp getCandleCloseTime() { | |
return this.closeTime; | |
} | |
/** | |
* @return Returns whether the candle was positive or negative (green or red) | |
* When close greater than open, return up, else down | |
*/ | |
@Override | |
public CandleDirection getCandleDirection() { | |
return this.candleDirection; | |
} | |
/** | |
* @return Returns the candle period as an enum | |
*/ | |
@Override | |
public CandlePeriod getCandlePeriod() { | |
if (this.candlePeriod == null) { | |
throw new NullPointerException("You need to set a candle period!"); | |
} | |
return this.candlePeriod; | |
} | |
/** | |
* @param period the period this candle represents in a timeframe enum | |
*/ | |
@Override | |
public void setCandlePeriod(CandlePeriod period) { | |
this.candlePeriod = period; | |
} | |
/** | |
* @return Returns the close of the candle | |
*/ | |
@Override | |
public double getClose() { | |
return this.close; | |
} | |
/** | |
* @return Returns the high of the candle | |
*/ | |
@Override | |
public double getHigh() { | |
return this.high; | |
} | |
/** | |
* @return Returns the low of the candle period | |
*/ | |
@Override | |
public double getLow() { | |
return this.low; | |
} | |
/** | |
* @return Returns the Open of the candle period | |
*/ | |
@Override | |
public double getOpen() { | |
return this.open; | |
} | |
/** | |
* @return Candle type for this candle instance | |
*/ | |
@Override | |
public CandleType getType() { | |
return CandleType.HEIKINASHI; | |
} | |
/** | |
* @return returns the volume for this candle | |
*/ | |
@Override | |
public double getVolume() { | |
return this.volume; | |
} | |
@Override | |
public String toString() { | |
return "HeikinAshiCandle{" + | |
"high=" + high + | |
", low=" + low + | |
", open=" + open + | |
", close=" + close + | |
", volume=" + volume + | |
", closeTime=" + closeTime + | |
", candlePeriod=" + candlePeriod + | |
", candleDirection=" + candleDirection + | |
'}'; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment