package org.ripple.power.hft;
import java.util.Calendar;
import java.util.List;
import org.ripple.power.RippleSeedAddress;
import org.ripple.power.config.LSystem;
import org.ripple.power.txns.RippleBackendsAPI;
import org.ripple.power.txns.Updateable;
import org.ripple.power.txns.data.Ask;
import org.ripple.power.txns.data.Bid;
import org.ripple.power.txns.data.Candle;
import org.ripple.power.txns.data.Offer;
import org.ripple.power.txns.data.OffersResponse;
import org.ripple.power.txns.data.Take;
import org.ripple.power.utils.DateUtils;
import com.ripple.core.coretypes.RippleDate;
public abstract class TraderBase implements ITrader {
protected double MIN_WALL_VOLUME = 100.0;
protected final int ZOMBIE_CHECK = 10;
protected int _minInterval = 8000;
protected int _maxInterval = 20000;
final double MIN_AVG_VOLUME = 400.0;
final double MAX_AVG_VOLUME = 3000.0;
final int MIN_TRADES = 2;
final int MAX_TRADES = 10;
private boolean _killSignal;
protected int _intervalMs;
protected boolean _cleanup;
protected BotLog _log;
protected RippleBackendsAPI _rippleApi;
protected RippleSeedAddress _seed;
protected BOT_SET _set;
protected Take _pay;
protected Take _get;
protected int query_limit = 15;
public TraderBase(RippleBackendsAPI api, RippleSeedAddress seed,
BOT_SET set, BotLog log) {
this._rippleApi = api;
this._seed = seed;
this._set = set;
this._log = log;
}
@Override
public void startTrading() {
do {
try {
check();
LSystem.sleep(_intervalMs);
} catch (Exception ex) {
}
} while (!_killSignal);
}
@Override
public void kill() {
_killSignal = true;
}
protected abstract void check();
protected void log(String message, Object... args) {
if (_log != null) {
_log.mes(message, args);
}
}
public void cleanupZombies(final String address, final long buyOrderId,
final long sellOrderId, final Updateable update) {
_rippleApi.getActiveOrders(address, new Updateable() {
@Override
public void action(Object o) {
if (o != null && o instanceof OffersResponse) {
OffersResponse offers = (OffersResponse) o;
if (offers == null || offers.result == null) {
return;
}
for (Offer offer : offers.result.offers) {
if (String.valueOf(offer.getPrice()).contains("12345"))
log("Cleanup: Order ID=" + offer.seq
+ " not a zombie, possibly manual");
else if (-1 != buyOrderId && buyOrderId == offer.seq)
log("Cleanup: Order ID=" + offer.seq
+ " not a zombie, our BUY order");
else if (-1 != sellOrderId && sellOrderId == offer.seq)
log("Cleanup: Order ID=" + offer.seq
+ " not a zombie, our SELL order");
else {
log("Identified %s zombie order with ID=%s (%s XRP for %s %s). Trying to cancel...",
offer.getType(), offer.seq,
offer.getAmountXrp(), offer.getPrice(),
offer.getCurrency());
if (_rippleApi.cancelSynOrder(_seed, offer.seq)) {
log("... success");
} else {
log("... failed. Maybe next time");
}
}
}
}
if (update != null) {
update.action(null);
}
}
});
}
public float getMadness(List<Candle> candles) {
if (candles == null || candles.size() == 0) {
return 0.0f;
}
Candle last5mCandle = candles.get(candles.size() - 1);
long startTime = last5mCandle.getStartTime().getTime();
Calendar time = DateUtils.getUTCCalendar();
time.setTime(RippleDate.now());
time.set(Calendar.MINUTE, -10);
if (startTime < time.getTimeInMillis()) {
return 0.0f;
}
if (last5mCandle.isPartial()) {
if (candles.size() > 1) {
Candle beforeLast = candles.get(candles.size() - 2);
last5mCandle = new Candle();
last5mCandle.startTime = beforeLast.startTime;
last5mCandle.count = beforeLast.count + last5mCandle.count;
last5mCandle.baseVolume = beforeLast.baseVolume
+ last5mCandle.count;
}
}
float intenseCoef;
if (last5mCandle.count < MIN_TRADES) {
intenseCoef = 0.0f;
} else if (last5mCandle.count >= MAX_TRADES) {
intenseCoef = 1.0f;
} else {
intenseCoef = (float) (last5mCandle.count - MIN_TRADES)
/ (MAX_TRADES - MIN_TRADES);
}
float volumeCoef;
double avgVolume = last5mCandle.baseVolume / last5mCandle.count;
if (avgVolume < MIN_AVG_VOLUME) {
volumeCoef = 0.0f;
} else if (avgVolume >= MAX_AVG_VOLUME) {
volumeCoef = 1.0f;
} else {
volumeCoef = (float) ((avgVolume - MIN_AVG_VOLUME) / (MAX_AVG_VOLUME - MIN_AVG_VOLUME));
}
return (intenseCoef + volumeCoef) / 2;
}
protected float getSumAVGBuyPrice(List<Bid> bids) {
double sumVolume = 0.0f;
int count = 0;
for (Bid bid : bids) {
double price = bid.getPrice();
if (bid.getAmount() > MIN_WALL_VOLUME) {
sumVolume += price;
count++;
}
}
return Float.valueOf(LSystem.getNumberShort(String.valueOf(sumVolume
/ count)));
}
protected float getSumAVGSellPrice(List<Ask> asks) {
double sumVolume = 0.0f;
int count = 0;
for (Ask ask : asks) {
double price = ask.getPrice();
if (ask.getAmount() > MIN_WALL_VOLUME) {
sumVolume += price;
count++;
}
}
return Float.valueOf(LSystem.getNumberShort(String.valueOf(sumVolume
/ count)));
}
protected float getSumAVGBuyAmount(List<Bid> bids) {
double sumVolume = 0.0f;
int count = 0;
for (Bid bid : bids) {
double amount = bid.getAmount();
if (amount > MIN_WALL_VOLUME) {
sumVolume += amount;
count++;
}
}
return Float.valueOf(LSystem.getNumberShort(String.valueOf(sumVolume
/ count)));
}
protected float getSumAVGSellAmount(List<Ask> asks) {
double sumVolume = 0.0f;
int count = 0;
for (Ask ask : asks) {
double amount = ask.getAmount();
if (amount > MIN_WALL_VOLUME) {
sumVolume += amount;
count++;
}
}
return Float.valueOf(LSystem.getNumberShort(String.valueOf(sumVolume
/ count)));
}
}