package dailyBot.model;
import java.util.Calendar;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.TimeZone;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import dailyBot.control.DailyLog;
import dailyBot.control.DailyUtils;
import dailyBot.control.connection.SqlConnection;
public enum Pair
{
EURUSD(10000), USDJPY(100), GBPUSD(10000), USDCHF(10000), EURCHF(EURUSD, USDCHF, 10000), AUDUSD(10000), USDCAD(
10000), NZDUSD(10000), EURJPY(EURUSD, USDJPY, 100), GBPJPY(100), CHFJPY(USDCHF, USDJPY, 100), GBPCHF(GBPUSD,
USDCHF, 10000), EURAUD(EURUSD, AUDUSD, 10000), AUDJPY(AUDUSD, USDJPY, 100), ALL(0);
private transient final Pair fatherA;
private transient final Pair fatherB;
private transient final int multiplier;
private transient double currentBid = 0;
private transient double currentAsk = 0;
private transient double currentSSI = 0;
private transient double high = Double.NEGATIVE_INFINITY;
private transient double low = Double.POSITIVE_INFINITY;
private transient double open = Double.NEGATIVE_INFINITY;
private transient Calendar date = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
private final transient AtomicLong pairUpdateCounter = new AtomicLong();
private transient final LinkedList <StrategySignal> signals = new LinkedList <StrategySignal>();
private transient static String message = "";
private transient static int startNumber = 0;
private transient final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock(true);
private transient final Lock read = readWriteLock.readLock();
private transient final Lock write = DailyUtils.getSafeWriteLock(readWriteLock);
private transient final ReentrantReadWriteLock readWriteLockB = new ReentrantReadWriteLock(true);
private transient final Lock readB = readWriteLockB.readLock();
private transient final Lock writeB = DailyUtils.getSafeWriteLock(readWriteLockB);
private Pair(int multiplier)
{
fatherA = this;
fatherB = this;
this.multiplier = multiplier;
}
private Pair(Pair fatherA, Pair fatherB, int multiplier)
{
this.fatherA = fatherA;
this.fatherB = fatherB;
this.multiplier = multiplier;
}
public int pairMultiplier()
{
return multiplier;
}
public Pair pairFatherA()
{
return fatherA;
}
public Pair pairFatherB()
{
return fatherB;
}
public boolean isCorrect(double price)
{
if(multiplier == 100)
return price >= 10;
else
return price < 10;
}
public int differenceInPips(double priceA, double priceB, boolean buy)
{
double currentPrice = priceA;
double difference = buy ? currentPrice - priceB : priceB - currentPrice;
return (int) Math.round(Math.max(-1000000d, Math.min(1000000d, (difference) * multiplier)));
}
public int differenceInPips(double priceB, boolean buy)
{
double currentPrice = getCurrentPrice(buy);
double difference = buy ? currentPrice - priceB : priceB - currentPrice;
return (int) Math.round(Math.max(-1000000d, Math.min(1000000d, (difference) * multiplier)));
}
public void changeBidAsk(double bid, double ask)
{
String errorMessage = null;
boolean zeroBid = false;
write.lock();
try
{
zeroBid = currentBid == 0;
if(zeroBid)
{
if(isCorrect(bid) && isCorrect(ask) && pairSpread(bid, ask, this) <= 75)
{
currentBid = bid;
currentAsk = ask;
double[] initialData = SqlConnection.getPairData(this, date);
low = initialData[0];
high = initialData[1];
open = initialData[2];
message += "\nInicializando par " + toString() + ", bid nuevo: " + bid + ", ask nuevo: " + ask;
}
else
errorMessage = "Error en Par inicializando " + toString() + ", bid anterior: " + currentBid
+ ", bid nuevo: " + bid + ", ask anterior: " + currentAsk + ", ask nuevo: " + ask;
startNumber++;
}
else
{
if(Math.abs(differenceInPips(bid, true)) <= 200 && Math.abs(differenceInPips(ask, false)) <= 200
&& pairSpread(bid, ask, this) <= 75)
{
currentBid = bid;
currentAsk = ask;
}
else
{
errorMessage = "Error en par " + toString() + ", bid anterior: " + currentBid + ", bid nuevo: "
+ bid + ", ask anterior: " + currentAsk + ", ask nuevo: " + ask;
}
}
}
finally
{
write.unlock();
}
if(zeroBid && startNumber >= values().length - 1)
DailyLog.logInfo(message);
if(errorMessage != null)
DailyLog.logError(errorMessage);
}
public double getPriceMinus(double priceA, int pips, boolean buy)
{
double currentPrice = priceA;
double pipsD = pips;
pipsD /= multiplier;
if(buy)
return currentPrice - pipsD;
else
return currentPrice + pipsD;
}
public double getCurrentPriceMinus(int pips, boolean buy)
{
double currentPrice = getCurrentPrice(buy);
double pipsD = pips;
pipsD /= multiplier;
if(buy)
return currentPrice - pipsD;
else
return currentPrice + pipsD;
}
public double getCurrentPrice(boolean buy)
{
read.lock();
try
{
return buy ? currentBid : currentAsk;
}
finally
{
read.unlock();
}
}
public void changeSSI(double ssi)
{
write.lock();
try
{
currentSSI = ssi;
}
finally
{
write.unlock();
}
}
public double pairSSI()
{
read.lock();
try
{
return currentSSI;
}
finally
{
read.unlock();
}
}
private int getProfitInPips(StrategySignal s)
{
double currentPrice = getCurrentPrice(s.isBuy());
double difference = s.isBuy() ? currentPrice - s.getEntryPrice() : s.getEntryPrice() - currentPrice;
return (int) Math.round((difference) * multiplier);
}
public void addSignal(StrategySignal signal)
{
writeB.lock();
try
{
if(!signals.contains(signal))
signals.add(signal);
}
finally
{
writeB.unlock();
}
}
public void deleteSignal(StrategySignal signal)
{
writeB.lock();
try
{
for(Iterator <StrategySignal> it = signals.iterator(); it.hasNext();)
if(signal == it.next())
it.remove();
}
finally
{
writeB.unlock();
}
}
public void processSignals()
{
if(this == ALL)
return;
writeB.lock();
try
{
if(Math.abs(getCurrentPrice(true) - 0.0d) < 10e-4d || Math.abs(getCurrentPrice(false) - 0.0d) < 10e-4d)
return;
for(StrategySignal signal : signals)
{
signal.setLow(Math.min(signal.getLow(), getProfitInPips(signal)));
signal.setHigh(Math.max(signal.getHigh(), getProfitInPips(signal)));
}
low = Math.min(low, getCurrentPrice(true));
high = Math.max(high, getCurrentPrice(true));
if(open == Double.NEGATIVE_INFINITY)
open = getCurrentPrice(true);
Calendar current = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
int day = current.get(Calendar.DAY_OF_MONTH);
if(day != date.get(Calendar.DAY_OF_MONTH))
closeDay();
else if((pairUpdateCounter.incrementAndGet() % 600) == 0)
SqlConnection.addPairData(this, open, getCurrentPrice(true), low, high);
}
finally
{
writeB.unlock();
}
}
public void closeDay()
{
writeB.lock();
try
{
high = getCurrentPrice(true);
low = getCurrentPrice(true);
open = getCurrentPrice(true);
date = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
}
finally
{
writeB.unlock();
}
}
public String checkSignals()
{
readB.lock();
try
{
String debug = "";
for(StrategySignal s : signals)
debug += s.getStrategyId().toString() + " " + s.getPair().toString() + " " + s.getEntryPrice() + " "
+ s.isBuy() + " " + s.getLow() + " " + s.getHigh() + "\n";
return debug;
}
finally
{
readB.unlock();
}
}
public int pairSpread()
{
double currentBid = 0;
double currentAsk = 0;
read.lock();
try
{
currentBid = this.currentBid;
currentAsk = this.currentAsk;
}
finally
{
read.unlock();
}
return pairSpread(currentBid, currentAsk, this);
}
public static int pairSpread(double bid, double ask, Pair pair)
{
double difference = ask - bid;
return (int) Math.round((difference) * pair.multiplier);
}
public static Pair stringToPair(String string)
{
for(Pair pair : values())
if(string.equals(pair.toString()))
return pair;
return ALL;
}
public static Pair parsePair(String content)
{
Pair answer = null;
for(Pair pair : values())
if(pair != ALL && content.contains(pair.toString()))
answer = pair;
return answer;
}
public boolean equals(Pair par)
{
if(par == ALL)
return true;
return super.equals(par);
}
}