package org.cryptocoinpartners.schema; import java.math.BigDecimal; import javax.annotation.Nullable; import javax.persistence.Cacheable; import javax.persistence.Entity; import javax.persistence.Index; import javax.persistence.PostPersist; import javax.persistence.Table; import javax.persistence.Transient; import org.cryptocoinpartners.schema.dao.TradeDao; import org.cryptocoinpartners.util.EM; import org.cryptocoinpartners.util.Visitor; import org.joda.time.Instant; import org.joda.time.Interval; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; import com.google.inject.Inject; import com.google.inject.assistedinject.Assisted; import com.google.inject.assistedinject.AssistedInject; /** * Trade represents a single known transaction of a Market * * @author Tim Olson */ @Entity @Cacheable @Table(indexes = { @Index(columnList = "time"), @Index(columnList = "timeReceived"), @Index(columnList = "market"), @Index(columnList = "market,time"), @Index(columnList = "market,remoteKey") }) public class Trade extends PriceData { @Inject protected TradeDao tradeDao; private static final DateTimeFormatter FORMAT = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss"); // private static final SimpleDateFormat FORMAT = new SimpleDateFormat("dd.MM.yyyy kk:mm:ss"); private static final String SEPARATOR = ","; public <T> T queryZeroOne(Class<T> resultType, String queryStr, Object... params) { // em = createEntityManager(); return tradeDao.queryZeroOne(resultType, queryStr, params); } @Override @Transient public TradeDao getDao() { return tradeDao; } public static Trade fromDoubles(Market market, Instant time, @Nullable String remoteKey, double price, double volume) { long priceCount = Math.round(price / market.getPriceBasis()); long volumeCount = Math.round(volume / market.getVolumeBasis()); return new Trade(market, time, remoteKey, priceCount, volumeCount); } public static Trade fromDoubles(Market market, Instant time, Instant timeRecieved, @Nullable String remoteKey, double price, double volume) { long priceCount = Math.round(price / market.getPriceBasis()); long volumeCount = Math.round(volume / market.getVolumeBasis()); return new Trade(market, time, timeRecieved, remoteKey, priceCount, volumeCount); } @Override public void persit() { tradeDao.persist(this); } @Override public EntityBase refresh() { return tradeDao.refresh(this); } /** * @param market what Market was traded * @param time when the trade originally occured * @param remoteKey the unique key assigned by the market data provider to this trade. helps prevent duplication of market data * @param priceCount the trade price as a count of "pips," where the size of the pip is the market's priceBasis() * @param volumeCount the trade price as a count of "pips," where the size of the pip is the market's volumeBasis() * @return */ @AssistedInject public Trade(@Assisted Market market, @Assisted Instant time, @Assisted @Nullable String remoteKey, @Assisted("tradePrice") double price, @Assisted("tradeVolume") double volume) { this(market, time, remoteKey, Math.round(price / market.getPriceBasis()), Math.round(volume / market.getVolumeBasis())); } @AssistedInject public Trade(@Assisted Market market, @Assisted("tradeTime") Instant time, @Assisted("timeRecieved") Instant timeRecieved, @Assisted @Nullable String remoteKey, @Assisted("tradePrice") double price, @Assisted("tradeVolume") double volume) { this(market, time, timeRecieved, remoteKey, Math.round(price / market.getPriceBasis()), Math.round(volume / market.getVolumeBasis())); } @AssistedInject public Trade(@Assisted Market market, @Assisted Instant time, @Assisted @Nullable String remoteKey, @Assisted("tradePriceCount") long priceCount, @Assisted("tradeVolumeCount") long volumeCount) { super(time, remoteKey, market, priceCount, volumeCount); } @AssistedInject public Trade(@Assisted Market market, @Assisted("tradeTime") Instant time, @Assisted("tradeTimeRecieved") Instant timeRecieved, @Assisted @Nullable String remoteKey, @Assisted("tradePriceCount") long priceCount, @Assisted("tradeVolumeCount") long volumeCount) { super(time, timeRecieved, remoteKey, market, priceCount, volumeCount); } @AssistedInject public Trade(@Assisted Market market, @Assisted Instant time, @Assisted @Nullable String remoteKey, @Assisted("tradePrice") BigDecimal price, @Assisted("tradeVolume") BigDecimal volume) { super(time, remoteKey, market, price, volume); } public static void find(Interval timeInterval, Visitor<Trade> visitor) { EM.queryEach(Trade.class, visitor, "select t from Trade t where time > ?1 and time < ?2", timeInterval.getStartMillis(), timeInterval.getEndMillis()); } public static void forAll(Visitor<Trade> visitor) { EM.queryEach(Trade.class, visitor, "select t from Trade t"); } @PostPersist private void postPersist() { detach(); } @Override public String toString() { return "time=" + (getTime() != null ? (FORMAT.print(getTime())) : "") + SEPARATOR + "Market=" + getMarket() + SEPARATOR + "Price=" + getPriceAsDouble() + SEPARATOR + "Volume=" + getVolumeAsDouble(); } public Trade() { } // JPA only @Override public void detach() { // tradeDao.detach(this); } @Override public void merge() { tradeDao.merge(this); // TODO Auto-generated method stub } @Override public void delete() { // TODO Auto-generated method stub } }