package org.ripple.power.hft;
import java.util.LinkedList;
import java.util.List;
import org.ripple.power.collection.ArrayUtils;
import org.ripple.power.txns.data.Candle;
import com.tictactec.ta.lib.Core;
import com.tictactec.ta.lib.MInteger;
public class AnalysisData {
public static int getCash(int cash, int leverage, int max) {
if (cash < 0) {
return 0;
} else if (cash > max) {
cash = max;
}
if (leverage > max) {
leverage = max;
} else if (leverage < 0) {
leverage = max;
}
cash = (cash * leverage) - ((cash * leverage) / 50);
if (cash > max) {
cash = max;
}
return cash;
}
public static int getQuantity(int maxCash, double price,
int traderPercentage, int maxQuantity) {
if (maxCash == 0) {
return ((maxQuantity * traderPercentage) / 100);
}
else if (price == 0.0) {
return ((maxQuantity * traderPercentage) / 100);
}
else if (maxQuantity == 0) {
return ((int) (maxCash / price));
}
else if (traderPercentage < 0) {
traderPercentage = 0;
} else if (traderPercentage > 100) {
traderPercentage = 100;
}
return ((int) (maxCash / price) <= ((maxQuantity * traderPercentage) / 100)) ? ((int) (maxCash / price))
: ((maxQuantity * traderPercentage) / 100);
}
private static double pdf(double x) {
return Math.exp(-x * x / 2) / Math.sqrt(2 * Math.PI);
}
public static double cdf(double z) {
if (z < -15.0) {
return 0.0;
} else if (z > 15.0) {
return 1.0;
}
double sum = 0.0, term = z;
for (int i = 3; sum + term != sum; i += 2) {
sum = sum + term;
term = term * z * z / i;
}
return 0.5 + sum * pdf(z);
}
public static double dcdf(double z) {
double epislon = 0.00001;
return (cdf(z - epislon) - cdf(z + epislon))
/ ((z - epislon) - (z + epislon));
}
public static Double createEMA(java.util.List<Double> values, int period) {
if (period <= 0) {
throw new IllegalArgumentException("period must be greater than 0");
}
final int size = values.size();
final Core core = new Core();
final int allocationSize = size - core.emaLookback(period);
if (allocationSize <= 0) {
return null;
}
final double[] output = new double[allocationSize];
final MInteger outBegIdx = new MInteger();
final MInteger outNbElement = new MInteger();
double[] _values = ArrayUtils
.toPrimitive(values.toArray(new Double[0]));
core.ema(0, values.size() - 1, _values, period, outBegIdx,
outNbElement, output);
return output[outNbElement.value - 1];
}
public static Double createMFI(List<Double> highs, List<Double> lows,
List<Double> closes, List<Long> volumes, int period) {
if (period <= 0) {
throw new IllegalArgumentException("period must be greater than 0");
}
if (highs.size() != lows.size() || highs.size() != closes.size()
|| highs.size() != volumes.size()) {
throw new IllegalArgumentException("input list must be same size");
}
final int size = highs.size();
final Core core = new Core();
final int allocationSize = size - core.mfiLookback(period);
if (allocationSize <= 0) {
return null;
}
final double[] output = new double[allocationSize];
final MInteger outBegIdx = new MInteger();
final MInteger outNbElement = new MInteger();
double[] _highs = ArrayUtils.toPrimitive(highs.toArray(new Double[0]));
double[] _lows = ArrayUtils.toPrimitive(lows.toArray(new Double[0]));
double[] _closes = ArrayUtils
.toPrimitive(closes.toArray(new Double[0]));
long[] _volumes = ArrayUtils.toPrimitive(volumes.toArray(new Long[0]));
double[] dv = new double[_volumes.length];
for (int i = 0; i < dv.length; i++) {
dv[i] = _volumes[i];
}
core.mfi(0, _highs.length - 1, _highs, _lows, _closes, dv, period,
outBegIdx, outNbElement, output);
return output[outNbElement.value - 1];
}
public static Double createRSI(List<Double> values, int period) {
if (period <= 0) {
throw new IllegalArgumentException("period must be greater than 0");
}
final int size = values.size();
final Core core = new Core();
final int allocationSize = size - core.rsiLookback(period);
if (allocationSize <= 0) {
return null;
}
final double[] output = new double[allocationSize];
final MInteger outBegIdx = new MInteger();
final MInteger outNbElement = new MInteger();
double[] _values = ArrayUtils
.toPrimitive(values.toArray(new Double[0]));
core.rsi(0, values.size() - 1, _values, period, outBegIdx,
outNbElement, output);
return output[outNbElement.value - 1];
}
public static double getTypicalPrice(double high, double low, double last) {
return (high + low + last) / 3.0d;
}
public static double getTypicalPrice(Candle candle) {
return (candle.high + candle.low + candle.close) / 3.0d;
}
public static MACD.Result createMACDFix(List<Double> values, int period) {
if (period <= 0) {
throw new IllegalArgumentException("period must be greater than 0");
}
final int size = values.size();
final Core core = new Core();
final int allocationSize = size - core.macdFixLookback(period);
if (allocationSize <= 0) {
return null;
}
final double[] outMACD = new double[allocationSize];
final double[] outMACDSignal = new double[allocationSize];
final double[] outMACDHist = new double[allocationSize];
final MInteger outBegIdx = new MInteger();
final MInteger outNbElement = new MInteger();
double[] _values = ArrayUtils
.toPrimitive(values.toArray(new Double[0]));
core.macdFix(0, values.size() - 1, _values, period, outBegIdx,
outNbElement, outMACD, outMACDSignal, outMACDHist);
return MACD.Result.newInstance(outMACD[outNbElement.value - 1],
outMACDSignal[outNbElement.value - 1],
outMACDHist[outNbElement.value - 1]);
}
public static double MILLISECONDS_PER_YEAR = 1000 * 60 * 60 * 24 * 365;
public static double convertTimeToExpiry(long aTimeToExpiry) {
return aTimeToExpiry / MILLISECONDS_PER_YEAR;
}
public static double getd1(double aUnderlyingPrice, double aStrikePrice,
double aAnnualRate, double aVolatility, double myTimeToExpiry) {
return (Math.log(aUnderlyingPrice / aStrikePrice) + (aAnnualRate + aVolatility
* aVolatility / 2)
* myTimeToExpiry)
/ (aVolatility * Math.sqrt(myTimeToExpiry));
}
public static double getd2(double aVolatility, double myTimeToExpiry,
double d1) {
return d1 - aVolatility * Math.sqrt(myTimeToExpiry);
}
public static double getCallOptionPrice(double aUnderlyingPrice,
double aStrikePrice, double aAnnualRate, double aVolatility,
long aTimeToExpiry) {
double myTimeToExpiry = convertTimeToExpiry(aTimeToExpiry);
double d1 = getd1(aUnderlyingPrice, aStrikePrice, aAnnualRate,
aVolatility, myTimeToExpiry);
double d2 = getd2(aVolatility, myTimeToExpiry, d1);
return aUnderlyingPrice * AnalysisData.cdf(d1) - aStrikePrice
* Math.exp(-aAnnualRate * myTimeToExpiry)
* AnalysisData.cdf(d2);
}
public static double getPutOptionPrice(double aUnderlyingPrice,
double aStrikePrice, double aAnnualRate, double aVolatility,
long aTimeToExpiry) {
double myTimeToExpiry = convertTimeToExpiry(aTimeToExpiry);
double d1 = getd1(aUnderlyingPrice, aStrikePrice, aAnnualRate,
aVolatility, myTimeToExpiry);
double d2 = getd2(aVolatility, myTimeToExpiry, d1);
return (1 - AnalysisData.cdf(d2)) * aStrikePrice
* Math.exp(-aAnnualRate * myTimeToExpiry)
- (1 - AnalysisData.cdf(d1)) * aUnderlyingPrice;
}
public static double getCallDelta(double aUnderlyingPrice,
double aStrikePrice, double aAnnualRate, double aVolatility,
long aTimeToExpiry) {
double myTimeToExpiry = convertTimeToExpiry(aTimeToExpiry);
double d1 = getd1(aUnderlyingPrice, aStrikePrice, aAnnualRate,
aVolatility, myTimeToExpiry);
return AnalysisData.cdf(d1);
}
public static double getPutDelta(double aUnderlyingPrice,
double aStrikePrice, double aAnnualRate, double aVolatility,
long aTimeToExpiry) {
return getCallDelta(aUnderlyingPrice, aStrikePrice, aAnnualRate,
aVolatility, aTimeToExpiry) - 1;
}
public static double getGamma(double aUnderlyingPrice,
double aStrikePrice, double aAnnualRate, double aVolatility,
long aTimeToExpiry) {
double myTimeToExpiry = convertTimeToExpiry(aTimeToExpiry);
double d1 = getd1(aUnderlyingPrice, aStrikePrice, aAnnualRate,
aVolatility, myTimeToExpiry);
return AnalysisData.dcdf(d1)
/ (aUnderlyingPrice * aVolatility * Math.sqrt(myTimeToExpiry));
}
public static double getVega(double aUnderlyingPrice, double aStrikePrice,
double aAnnualRate, double aVolatility, long aTimeToExpiry) {
double myTimeToExpiry = convertTimeToExpiry(aTimeToExpiry);
double d1 = getd1(aUnderlyingPrice, aStrikePrice, aAnnualRate,
aVolatility, myTimeToExpiry);
return AnalysisData.dcdf(d1) * aUnderlyingPrice
* Math.sqrt(myTimeToExpiry);
}
public static double getCallTheta(double aUnderlyingPrice,
double aStrikePrice, double aAnnualRate, double aVolatility,
long aTimeToExpiry) {
double myTimeToExpiry = convertTimeToExpiry(aTimeToExpiry);
double d1 = getd1(aUnderlyingPrice, aStrikePrice, aAnnualRate,
aVolatility, myTimeToExpiry);
double d2 = getd2(aVolatility, myTimeToExpiry, d1);
double firstTerm = -aUnderlyingPrice * AnalysisData.dcdf(d1)
* aVolatility / ((2 * Math.sqrt(myTimeToExpiry)));
double secondTerm = aAnnualRate * aStrikePrice
* Math.exp(-aAnnualRate * myTimeToExpiry)
* AnalysisData.cdf(d2);
return firstTerm - secondTerm;
}
public static double getPutTheta(double aUnderlyingPrice,
double aStrikePrice, double aAnnualRate, double aVolatility,
long aTimeToExpiry) {
double myTimeToExpiry = convertTimeToExpiry(aTimeToExpiry);
double d1 = getd1(aUnderlyingPrice, aStrikePrice, aAnnualRate,
aVolatility, myTimeToExpiry);
double d2 = getd2(aVolatility, myTimeToExpiry, d1);
double firstTerm = -aUnderlyingPrice * AnalysisData.dcdf(d1)
* aVolatility / ((2 * Math.sqrt(myTimeToExpiry)));
double secondTerm = aAnnualRate * aStrikePrice
* Math.exp(-aAnnualRate * myTimeToExpiry)
* AnalysisData.cdf(-d2);
return firstTerm + secondTerm;
}
public static double getCallRho(double aUnderlyingPrice,
double aStrikePrice, double aAnnualRate, double aVolatility,
long aTimeToExpiry) {
double myTimeToExpiry = convertTimeToExpiry(aTimeToExpiry);
double d1 = getd1(aUnderlyingPrice, aStrikePrice, aAnnualRate,
aVolatility, myTimeToExpiry);
double d2 = getd2(aVolatility, myTimeToExpiry, d1);
return aStrikePrice * myTimeToExpiry
* Math.exp(-aAnnualRate * myTimeToExpiry)
* AnalysisData.cdf(d2);
}
public static double getPutRho(double aUnderlyingPrice,
double aStrikePrice, double aAnnualRate, double aVolatility,
long aTimeToExpiry) {
double myTimeToExpiry = convertTimeToExpiry(aTimeToExpiry);
double d1 = getd1(aUnderlyingPrice, aStrikePrice, aAnnualRate,
aVolatility, myTimeToExpiry);
double d2 = getd2(aVolatility, myTimeToExpiry, d1);
return -aStrikePrice * myTimeToExpiry
* Math.exp(-aAnnualRate * myTimeToExpiry)
* AnalysisData.cdf(-d2);
}
public static List<Integer> negativeWeightCycle(double[][] adjacenyMatrix,
int source) throws IllegalArgumentException {
if (adjacenyMatrix.length == 0
|| adjacenyMatrix.length != adjacenyMatrix[0].length) {
throw new IllegalArgumentException(
"Adjaceny Matrix is not a square matrix!");
}
int[] predecessors = new int[adjacenyMatrix.length];
double[] distance = new double[adjacenyMatrix.length];
double[][] logValMat = createLogValueMatrix(adjacenyMatrix);
for (int j = 0; j < adjacenyMatrix.length; j++) {
distance[j] = Double.MAX_VALUE;
}
distance[source] = 0;
for (int i = 0; i < logValMat.length - 1; i++) {
relaxEdges(logValMat, distance, predecessors);
}
return findNegativeWeightCycle(logValMat, distance, predecessors);
}
private static double[][] createLogValueMatrix(double[][] adjacenyMatrix) {
double[][] logValMat = adjacenyMatrix.clone();
for (int i = 0; i < adjacenyMatrix.length; i++) {
for (int j = 0; j < adjacenyMatrix[0].length; j++) {
double weight = adjacenyMatrix[i][j];
if (weight > 0) {
logValMat[i][j] = -Math.log(weight);
} else {
logValMat[i][j] = Double.MAX_VALUE;
}
}
}
return logValMat;
}
private static void relaxEdges(double[][] logValMat, double[] distance,
int[] predecessors) {
for (int v = 0; v < logValMat.length; v++) {
for (int j = 0; j < logValMat.length; j++) {
double weight = logValMat[v][j];
if (weight < Double.MAX_VALUE) {
if (weight + distance[v] < distance[j]) {
distance[j] = distance[v] + weight;
predecessors[j] = v;
}
}
}
}
}
private static List<Integer> findNegativeWeightCycle(double[][] logValMat,
double[] distance, int[] predecessors) {
for (int v = 0; v < logValMat.length; v++) {
for (int j = 0; j < logValMat[0].length; j++) {
double weight = logValMat[v][j];
if (weight < Double.MAX_VALUE) {
if (weight + distance[v] < distance[j]) {
predecessors[j] = v;
return createCycleFromPredecessors(predecessors, j);
}
}
}
}
return new LinkedList<Integer>();
}
public static List<Integer> createCycleFromPredecessors(int[] predecessors,
int end) {
LinkedList<Integer> path = new LinkedList<>();
boolean[] visited = new boolean[predecessors.length];
int current = end;
while (true) {
if (visited[current]) {
LinkedList<Integer> cycle = new LinkedList<Integer>();
cycle.addFirst(current);
for (Integer item : path) {
cycle.add(item);
if (item.intValue() == current) {
break;
}
}
return cycle;
}
path.addFirst(current);
visited[current] = true;
current = predecessors[current];
}
}
}