package org.cryptocoinpartners.schema; import java.math.BigDecimal; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; import java.util.concurrent.CopyOnWriteArrayList; import javax.annotation.Nullable; import javax.persistence.Basic; import javax.persistence.Cacheable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Index; import javax.persistence.Inheritance; import javax.persistence.InheritanceType; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.NamedAttributeNode; import javax.persistence.NamedEntityGraph; import javax.persistence.NamedEntityGraphs; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; import javax.persistence.OneToMany; import javax.persistence.OrderBy; import javax.persistence.PostPersist; import javax.persistence.Table; import javax.persistence.Transient; import org.apache.commons.lang.NotImplementedException; import org.cryptocoinpartners.enumeration.ExecutionInstruction; import org.cryptocoinpartners.enumeration.FillType; import org.cryptocoinpartners.enumeration.PositionEffect; import org.cryptocoinpartners.enumeration.TransactionType; import org.cryptocoinpartners.schema.dao.Dao; import org.cryptocoinpartners.schema.dao.FillJpaDao; import org.cryptocoinpartners.schema.dao.OrderDao; import org.cryptocoinpartners.util.EM; import org.cryptocoinpartners.util.FeesUtil; import org.hibernate.Hibernate; import org.hibernate.annotations.Type; import org.joda.time.Instant; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.inject.Inject; /** * This is the base class for GeneralOrder and SpecificOrder. To create orders, see OrderBuilder or BaseStrategy.order * * @author Mike Olson * @author Tim Olson */ @Entity @Cacheable @Table(name = "\"Order\"", indexes = { @Index(columnList = "fillType"), @Index(columnList = "portfolio"), @Index(columnList = "market"), @Index(columnList = "parentFill"), @Index(columnList = "parentOrder") }) //, @Index(columnList = "portfolio") }) // This is required because ORDER is a SQL keyword and must be escaped @Inheritance(strategy = InheritanceType.SINGLE_TABLE) @SuppressWarnings({ "JpaDataSourceORMInspection", "UnusedDeclaration" }) @NamedQueries({ @NamedQuery(name = "Order.findOrder", query = "select o from Order o where id =?1") }) // @NamedEntityGraphs({ // @NamedEntityGraph(name = "orderWithParentFill", attributeNodes = { @NamedAttributeNode(value = "parentFill", subgraph = "orderWithParentFillDetails") }, subgraphs = { @NamedSubgraph(name = "orderWithParentFillDetails", attributeNodes = { @NamedAttributeNode("children") }) }), @NamedEntityGraph(name = "orderWithFills", attributeNodes = { @NamedAttributeNode(value = "fills") }), @NamedEntityGraph(name = "orderWithTransactions", attributeNodes = { @NamedAttributeNode(value = "transactions") }), @NamedEntityGraph(name = "orderWithChildOrders", attributeNodes = { @NamedAttributeNode(value = "orderChildren") }) //@NamedSubgraph(name = "fills", attributeNodes = @NamedAttributeNode(value = "fills", subgraph = "order")) //,@NamedSubgraph(name = "order", attributeNodes = @NamedAttributeNode("order")) }) public abstract class Order extends Event { @Inject protected OrderDao orderDao; @Inject protected FillJpaDao fillDao; protected static Logger log = LoggerFactory.getLogger("org.cryptocoinpartners.order"); protected static final DateTimeFormatter FORMAT = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss"); private static Object lock = new Object(); // private static final SimpleDateFormat FORMAT = new SimpleDateFormat("dd.MM.yyyy kk:mm:ss"); protected static final String SEPARATOR = ","; @ManyToOne(optional = true) @JoinColumn(name = "parentOrder") //, cascade = { CascadeType.MERGE, CascadeType.REFRESH }) //@Transient public Order getParentOrder() { return parentOrder; } //@ManyToOne(optional = true) // @Transient @Nullable @ManyToOne(optional = true) //, cascade = { CascadeType.MERGE }) //cascade = { CascadeType.ALL }) @JoinColumn(name = "parentFill") public Fill getParentFill() { return parentFill; } @Transient public abstract boolean isBid(); @Transient public boolean isAsk() { return !isBid(); } @Transient public TransactionType getTransactionType() { if (isBid()) return TransactionType.BUY; else return TransactionType.SELL; } @ManyToOne(optional = false) //@Transient public Portfolio getPortfolio() { return portfolio; } @Transient public Amount getForcastedCommission() { if (commission == null) setForcastedCommission(FeesUtil.getCommission(this)); return commission; } @Transient public Amount getForcastedMargin() { if (margin == null) setForcastedMargin(FeesUtil.getMargin(this)); return margin; } @Nullable @Column(insertable = false, updatable = false) @Transient public abstract Amount getLimitPrice(); @Nullable @Column(insertable = false, updatable = false) @Transient public abstract Amount getMarketPrice(); public abstract Order withLimitPrice(String price); public abstract Order withMarketPrice(String price); public abstract Order withLimitPrice(BigDecimal price); public abstract Order withMarketPrice(BigDecimal price); public abstract Order withLimitPrice(DiscreteAmount price); public abstract Order withMarketPrice(DiscreteAmount price); @ManyToOne(optional = true) @JoinColumn(insertable = false, updatable = false) public abstract Market getMarket(); @Nullable @Column(insertable = false, updatable = false) @Transient public abstract Amount getStopAmount(); @Nullable @Column(insertable = false, updatable = false) @Transient public abstract Amount getTargetAmount(); @Nullable @Column(insertable = false, updatable = false) @Transient public abstract Amount getStopPrice(); @Nullable @Column(insertable = false, updatable = false) @Transient public abstract Amount getTargetPrice(); @Nullable @Column(insertable = false, updatable = false) @Transient public abstract Amount getTrailingStopPrice(); @Column(insertable = false, updatable = false) @Transient public abstract Amount getVolume(); @Transient public abstract Amount getUnfilledVolume(); public abstract void setStopAmount(DecimalAmount stopAmount); public abstract void setTargetAmount(DecimalAmount targetAmount); public abstract void setStopPrice(DecimalAmount stopPrice); public abstract void setTargetPrice(DecimalAmount targetPrice); public abstract void setTrailingStopPrice(DecimalAmount trailingStopPrice); public abstract void setMarket(Market market); public void setPositionEffect(PositionEffect positionEffect) { this.positionEffect = positionEffect; } public void setExecutionInstruction(ExecutionInstruction executionInstruction) { this.executionInstruction = executionInstruction; } public void setParentOrder(Order order) { this.parentOrder = order; } public void setParentFill(Fill fill) { this.parentFill = fill; } public FillType getFillType() { return fillType; } public PositionEffect getPositionEffect() { return positionEffect; } public ExecutionInstruction getExecutionInstruction() { return executionInstruction; } public String getComment() { return comment; } public enum MarginType { USE_MARGIN, // trade up to the limit of credit in the quote fungible CASH_ONLY, // do not trade more than the available cash-on-hand (quote fungible) } public MarginType getMarginType() { return marginType; } public Instant getExpiration() { return expiration; } public boolean getPanicForce() { return force; } public boolean setPanicForce() { return force; } public boolean isEmulation() { return emulation; } // @Transient @Nullable @OneToMany //(cascade = CascadeType.PERSIST) //, mappedBy = "order") (mappedBy = "order") //, fetch = FetchType.EAGER) //, cascade = CascadeType.MERGE) //, fetch = FetchType.LAZY) // @OrderBy @OrderBy // @OrderColumn(name = "time") // @OrderColumn(name = "id") //, fetch = FetchType.EAGER) //, cascade = { CascadeType.MERGE, CascadeType.REFRESH }) public List<Fill> getFills() { // if (fills == null) // System.out.println("test"); return fills; // } } void getAllFillsByParentOrder(Order parentOrder, List allChildren) { for (Order child : parentOrder.getOrderChildren()) { allChildren.addAll(child.getFills()); getAllFillsByParentOrder(child, allChildren); } } public void loadAllChildOrdersByParentOrder(Order parentOrder, Map<Order, Order> orders, Map<Fill, Fill> fills) { Map withFillsHints = new HashMap(); Map withTransHints = new HashMap(); Map withChildrenHints = new HashMap(); // Map orderHints = new HashMap(); // UUID portfolioID = EM.queryOne(UUID.class, queryStr, portfolioName); withFillsHints.put("javax.persistence.fetchgraph", "orderWithFills"); withTransHints.put("javax.persistence.fetchgraph", "orderWithTransactions"); withChildrenHints.put("javax.persistence.fetchgraph", "orderWithChildOrders"); Order orderWithFills; Order orderWithChildren; Order orderWithTransactions; // so for each fill in the open position we need to load the whole order tree // getorder, then get all childe orders, then for each child, load child orders, so on and so forth. // load all child orders, and theri child ordres // load all parent orders and thier parent orders // need to laod all parent fills, their child orders, and their children // get a list of all orders in the tree then load // orderId = fill.getOrder().getId(); // if (parentOrder.getParentFill() != null) { // parentOrder.getParentFill().loadAllChildOrdersByFill(parentOrder.getParentFill(), orders, fills); // } // if (parentOrder.getParentOrder() != null) // parentOrder.getParentOrder().loadAllChildOrdersByParentOrder(parentOrder.getParentOrder()); try { orderWithFills = EM.namedQueryZeroOne(Order.class, "Order.findOrder", withFillsHints, parentOrder.getId()); orderWithChildren = EM.namedQueryZeroOne(Order.class, "Order.findOrder", withChildrenHints, parentOrder.getId()); orderWithTransactions = EM.namedQueryZeroOne(Order.class, "Order.findOrder", withTransHints, parentOrder.getId()); } catch (Error | Exception ex) { log.error("Order:loadAllChildOrdersByParentOrdere unable to get order for orderID: " + parentOrder.getId()); return; } if (orderWithFills != null && orderWithFills.getFills() != null && Hibernate.isInitialized(orderWithFills.getFills()) && orderWithFills.getId().equals(parentOrder.getId())) { int index = 0; for (Fill fill : orderWithFills.getFills()) { if (fill.getPortfolio().equals(parentOrder.getPortfolio())) fill.setPortfolio(parentOrder.getPortfolio()); if (!fills.containsKey(fill)) { fills.put(fill, fill); fill.loadAllChildOrdersByFill(fill, orders, fills); } else orderWithFills.getFills().set(index, fills.get(fill)); index++; } parentOrder.setFills(orderWithFills.getFills()); } else parentOrder.setFills(new CopyOnWriteArrayList<Fill>()); if (orderWithTransactions != null && orderWithTransactions.getTransactions() != null && Hibernate.isInitialized(orderWithTransactions.getTransactions()) && orderWithTransactions.getId().equals(parentOrder.getId())) { for (Transaction transaction : orderWithTransactions.getTransactions()) { if (transaction.getPortfolio().equals(parentOrder.getPortfolio())) transaction.setPortfolio(parentOrder.getPortfolio()); // if (transaction.getOrder().equals(parentOrder)) //child = parentOrder; // continue; if (!orders.containsKey(transaction.getOrder())) { orders.put(transaction.getOrder(), transaction.getOrder()); transaction.getOrder().loadAllChildOrdersByParentOrder(transaction.getOrder(), orders, fills); } else transaction.setOrder(orders.get(transaction.getOrder())); } parentOrder.setTransactions(orderWithTransactions.getTransactions()); } else parentOrder.setTransactions(new CopyOnWriteArrayList<Transaction>()); if (orderWithChildren != null && orderWithChildren.getOrderChildren() != null && Hibernate.isInitialized(orderWithChildren.getOrderChildren()) && orderWithChildren.getId().equals(parentOrder.getId())) { int index = 0; for (Order order : orderWithChildren.getOrderChildren()) { if (order.getPortfolio().equals(parentOrder.getPortfolio())) order.setPortfolio(parentOrder.getPortfolio()); if (order.equals(parentOrder)) //child = parentOrder; continue; if (!orders.containsKey(order)) { orders.put(order, order); System.out.println("loading child orders for: " + order.getId()); order.loadAllChildOrdersByParentOrder(order, orders, fills); } else orderWithChildren.getOrderChildren().set(index, orders.get(order)); index++; } parentOrder.setOrderChildren(orderWithChildren.getOrderChildren()); } else parentOrder.setOrderChildren(new CopyOnWriteArrayList<Order>()); if (orders.containsKey(getParentOrder())) setParentOrder(orders.get(getParentOrder())); if (fills.containsKey(getParentFill())) setParentFill(fills.get(getParentFill())); } void getAllGeneralOrderByParentOrder(Order paretnOrder, Collection allChildren) { for (Order child : paretnOrder.getOrderChildren()) { if (child instanceof GeneralOrder) allChildren.add(child); getAllGeneralOrderByParentOrder(child, allChildren); } } void getAllSpecificOrderByParentOrder(Order parentOrder, Collection allChildren) { for (Order child : parentOrder.getOrderChildren()) { if (child instanceof SpecificOrder) allChildren.add(child); getAllSpecificOrderByParentOrder(child, allChildren); } } // @Nullable //@OneToMany(cascade = CascadeType.PERSIST, mappedBy = "order") //, orphanRemoval = true, cascade = CascadeType.REMOVE) //, fetch = FetchType.LAZY) //@OrderBy // @OrderColumn(name = "id") //, fetch = FetchType.EAGER) //, cascade = { CascadeType.MERGE, CascadeType.REFRESH }) // @Transient @Nullable @OneToMany //(cascade = CascadeType.PERSIST) //, mappedBy = "order") (mappedBy = "order", orphanRemoval = true) //, cascade = CascadeType.MERGE) //, fetch = FetchType.LAZY) // @OrderBy @OrderBy public List<OrderUpdate> getOrderUpdates() { return orderUpdates; // } } public Order withTargetPrice(String price) { if (this.fillType == (FillType.STOP_LIMIT) || this.fillType == (FillType.STOP_LOSS) || this.fillType == (FillType.TRAILING_STOP_LIMIT)) { this.setTargetPrice(DecimalAmount.of(price)); return this; } throw new NotImplementedException(); } public Order withFillType(FillType fillType) { this.setFillType(fillType); return this; } public Order withParentFill(Fill fill) { if (fill != null) { fill.addChildOrder(this); this.setParentFill(fill); } return this; } public Order withTargetPrice(BigDecimal price) { if (getFillType() == (FillType.STOP_LIMIT) || getFillType() == (FillType.STOP_LOSS) || getFillType() == (FillType.TRAILING_STOP_LIMIT)) { this.setTargetPrice(DecimalAmount.of(price)); return this; } throw new NotImplementedException(); } public Order withStopPrice(String price) { if (getFillType() == (FillType.STOP_LIMIT) || getFillType() == (FillType.STOP_LOSS) || getFillType() == (FillType.TRAILING_STOP_LIMIT)) { this.setStopAmount(DecimalAmount.of(price)); return this; } throw new NotImplementedException(); } public Order withStopPrice(BigDecimal price) { if (getFillType() == (FillType.STOP_LIMIT) || getFillType() == (FillType.STOP_LOSS) || getFillType() == (FillType.TRAILING_STOP_LIMIT)) { this.setStopPrice(DecimalAmount.of(price)); return this; } throw new NotImplementedException(); } public Order withStopAmount(BigDecimal price) { if (getFillType() == (FillType.STOP_LIMIT) || getFillType() == (FillType.STOP_LOSS) || getFillType() == (FillType.TRAILING_STOP_LIMIT)) { this.setStopAmount(DecimalAmount.of(price)); return this; } throw new NotImplementedException(); } public Order withTargetAmount(BigDecimal price) { this.setTargetAmount(DecimalAmount.of(price)); return this; } public Order withTimeToLive(long timeToLive) { this.setTimeToLive(timeToLive); return this; } public Order withTrailingStopPrice(BigDecimal price, BigDecimal trailingStopPrice) { if (getFillType() == (FillType.STOP_LIMIT) || getFillType() == (FillType.STOP_LOSS) || getFillType() == (FillType.TRAILING_STOP_LIMIT)) { this.setStopAmount(DecimalAmount.of(price)); this.setTrailingStopPrice(DecimalAmount.of(trailingStopPrice)); return this; } throw new NotImplementedException(); } public Order withTrailingStopPrice(String price, String trailingStopPrice) { if (this.fillType == (FillType.STOP_LIMIT) || getFillType() == (FillType.STOP_LOSS) || getFillType() == (FillType.TRAILING_STOP_LIMIT)) { this.setStopAmount(DecimalAmount.of(price)); this.setTrailingStopPrice(DecimalAmount.of(trailingStopPrice)); return this; } throw new NotImplementedException(); } public Order withComment(String comment) { this.setComment(comment); return this; } public Order withPositionEffect(PositionEffect positionEffect) { this.setPositionEffect(positionEffect); return this; } public Order withExecutionInstruction(ExecutionInstruction executionInstruction) { this.setExecutionInstruction(executionInstruction); return this; } @Nullable //@OneToMany(mappedBy = "order") //, orphanRemoval = true, cascade = CascadeType.REMOVE) //@OrderBy // @OrderColumn(name = "id") //, cascade = { CascadeType.MERGE, CascadeType.REFRESH }) // @Transient @OneToMany //(cascade = CascadeType.PERSIST) //, mappedBy = "order") (mappedBy = "order", orphanRemoval = true) //, fetch = FetchType.EAGER) //, cascade = CascadeType.MERGE) //, fetch = FetchType.LAZY) @OrderBy public List<Transaction> getTransactions() { if (transactions == null) transactions = new CopyOnWriteArrayList<Transaction>(); // synchronized (lock) { return transactions; // } } @Override public synchronized void merge() { // synchronized (persistanceLock) { try { orderDao.merge(this); //if (duplicate == null || duplicate.isEmpty()) } catch (Exception | Error ex) { System.out.println("Unable to perform request in " + this.getClass().getSimpleName() + ":merge, full stack trace follows:" + ex); // ex.printStackTrace(); } } public <T> T find() { // synchronized (persistanceLock) { try { return (T) orderDao.find(Order.class, this.getId()); //if (duplicate == null || duplicate.isEmpty()) } catch (Exception | Error ex) { return null; //System.out.println("Unable to perform request in " + this.getClass().getSimpleName() + ":find, full stack trace follows:" + ex); // ex.printStackTrace(); } // return null; } @PostPersist private void postPersist() { // detach(); } // @PrePersist private void prePersist() { if (getDao() != null) { Portfolio orderPortfolio = null; Order orderParent = null; Fill fillParent = null; UUID parentOrderId = null; if (getPortfolio() != null) { orderPortfolio = (getDao().find(Portfolio.class, getPortfolio().getId())); // positionId = (fillDao.queryZeroOne(UUID.class, "select p.id from Position p where p.id=?1", position.getId())); if (orderPortfolio == null) getDao().persist(getPortfolio()); // portfolio.merge(); } // if (parentOrder != null) { // orderParent = (orderDao.find(Order.class, parentOrder.getId())); // positionId = (fillDao.queryZeroOne(UUID.class, "select p.id from Position p where p.id=?1", position.getId())); // if (orderParent == null) // orderDao.persist(orderParent); // } if (getParentFill() != null) { fillParent = (getDao().find(Fill.class, getParentFill().getId())); // positionId = (fillDao.queryZeroOne(UUID.class, "select p.id from Position p where p.id=?1", position.getId())); if (fillParent == null) getDao().persist(getParentFill()); // parentFill.merge(); } if (getParentOrder() != null) { orderParent = (getDao().find(Order.class, getParentOrder().getId())); // positionId = (fillDao.queryZeroOne(UUID.class, "select p.id from Position p where p.id=?1", position.getId())); if (orderParent == null) getDao().persist(getParentOrder()); // parentFill.merge(); } } // if (portfolio != null) { // portfolioId = (orderDao == null) ? (EM.queryZeroOne(UUID.class, "select p.id from Portfolio p where p.id=?1", portfolio.getId())) : (orderDao // .queryZeroOne(UUID.class, "select p.id from Portfolio p where p.id=?1", portfolio.getId())); // if (portfolioId == null) // portfolio.persit(); // } // // if (parentOrder != null) { // parentOrderId = (orderDao == null) ? (EM.queryZeroOne(UUID.class, "select o.id from Order o where o.id=?1", parentOrder.getId())) : (orderDao // .queryZeroOne(UUID.class, "select o.id from Order o where o.id=?1", parentOrder.getId())); // // if (parentOrderId == null) // parentOrder.persit(); // } //detach(); } @Override public void detach() { orderDao.detach(this); } @Override @Transient public Dao getDao() { return orderDao; } @Override public EntityBase refresh() { return orderDao.refresh(this); } @Override public synchronized void persit() { // synchronized (persistanceLock) { // if (this.hasFills()) { // for (Fill fill : this.getFills()) //PersistUtil.merge(fill); //} //if (this.hasFills()) { // for (Fill fill : getFills()) { // if (this.parentOrder != null) // parentOrder.persit(); // if (this.parentFill != null) // parentFill.persit(); // PersistUtil.insert(this); // PersistUtil.find(this); // List<Order> duplicate = orderDao.queryList(Order.class, "select o from Order o where o=?1", this); //List<Order> duplicate = null; // EntityBase entity = PersistUtil.find(this); try { orderDao.persist(this); //if (duplicate == null || duplicate.isEmpty()) } catch (Exception | Error ex) { System.out.println("Unable to perform request in " + this.getClass().getSimpleName() + ":persist, full stack trace follows:" + ex); // ex.printStackTrace(); } //else // orderDao.merge(this); // PersistUtil.insert(this); // else // PersistUtil.merge(this); // } // Iterator<Fill> itf = getFills().iterator(); //while (itf.hasNext()) { // // for (Fill pos : getFills()) { // Fill fill = itf.next(); //fillDao.persist(fill); // fill.persit(); // } } @Transient public Transaction getReservation() { for (Transaction tran : getTransactions()) { if (tran.getType() == (TransactionType.BUY_RESERVATION) || tran.getType() == (TransactionType.SELL_RESERVATION)) { return tran; } } return null; } @Transient public synchronized void removeTransaction(Transaction transaction) { getTransactions().remove(transaction); transaction.setOrder(null); } public synchronized void removeChildOrder(Order child) { getOrderChildren().remove(child); child.setParentOrder(null); } public synchronized void removeFill(Fill fill) { getFills().remove(fill); fill.setOrder(null); } public synchronized void removeOrderUpdate(OrderUpdate orderUpdate) { getOrderUpdates().remove(orderUpdate); orderUpdate.setOrder(null); } public synchronized void removeChildOrders() { getOrderChildren().clear(); } public synchronized void removeTransactions() { getTransactions().clear(); } @Nullable @OneToMany(mappedBy = "parentOrder") //, fetch = FetchType.EAGER) //(orphanRemoval = true, cascade = CascadeType.REMOVE) // @OrderBy // @OrderColumn(name = "id") // @Transient public List<Order> getOrderChildren() { // synchronized (lock) { return children; // } } public synchronized void addFill(Fill fill) { if (!getFills().contains(fill)) getFills().add(fill); } public synchronized void addOrderUpdate(OrderUpdate orderUpdate) { getOrderUpdates().add(orderUpdate); } public synchronized void addTransaction(Transaction transaction) { if (!getTransactions().contains(transaction)) getTransactions().add(transaction); } public synchronized void addChildOrder(Order order) { if (!getOrderChildren().contains(order)) getOrderChildren().add(order); } @Transient public boolean hasFills() { return !getFills().isEmpty(); } @Transient public boolean hasChildren() { return !getOrderChildren().isEmpty(); } @Transient public abstract boolean isFilled(); @Transient public DecimalAmount getAverageFillPrice() { if (!hasFills()) return DecimalAmount.ZERO; BigDecimal sumProduct = BigDecimal.ZERO; BigDecimal volume = BigDecimal.ZERO; List<Fill> fills = getFills(); for (Fill fill : fills) { BigDecimal priceBd = fill.getPrice().asBigDecimal(); BigDecimal volumeBd = fill.getVolume().asBigDecimal(); sumProduct = sumProduct.add(priceBd.multiply(volumeBd)); volume = volume.add(volumeBd); } return (sumProduct.equals(BigDecimal.ZERO)) ? DecimalAmount.ZERO : new DecimalAmount(sumProduct.divide(volume, Amount.mc)); } protected Order() { } protected Order(Instant time) { super(time); } protected void setFills(List<Fill> fills) { this.fills = fills; } protected void setOrderUpdates(List<OrderUpdate> orderUpdates) { this.orderUpdates = orderUpdates; } protected void setTransactions(List<Transaction> transactions) { this.transactions = transactions; } public void setFillType(FillType fillType) { this.fillType = fillType; } public void setComment(String comment) { this.comment = comment; } protected void setMarginType(MarginType marginType) { this.marginType = marginType; } protected void setForcastedCommission(Amount commission) { this.commission = commission; } protected void setForcastedMargin(Amount margin) { this.margin = margin; } protected void setExpiration(Instant expiration) { this.expiration = expiration; } protected void setPanicForce(boolean force) { this.force = force; } protected void setEmulation(boolean emulation) { this.emulation = emulation; } public void setPortfolio(Portfolio portfolio) { this.portfolio = portfolio; } @Type(type = "org.jadira.usertype.dateandtime.joda.PersistentInstantAsMillisLong") @Basic(optional = true) public Instant getEntryTime() { return entryTime; } public void setEntryTime(Instant time) { this.entryTime = time; } @Basic(optional = true) public long getTimeToLive() { return timeToLive; } @Transient public Instant getExpiryTime() { if (getTimeToLive() != 0) return getTime().plus(getTimeToLive()); else return null; } public void setTimeToLive(long time) { this.timeToLive = time; } protected void setOrderChildren(List<Order> children) { this.children = children; } protected List<Order> children; protected Instant entryTime; protected long timeToLive; protected Portfolio portfolio; protected List<Fill> fills; protected List<OrderUpdate> orderUpdates; protected List<Transaction> transactions; protected FillType fillType; protected MarginType marginType; protected Amount commission; protected Amount margin; protected String comment; protected PositionEffect positionEffect; protected Instant expiration; protected ExecutionInstruction executionInstruction; protected boolean force; // allow this order to override various types of panic protected boolean emulation; // ("allow order type emulation" [default, true] or "only use exchange's native functionality") protected Order parentOrder; protected Fill parentFill; }