/* ===========================================================
* TradeManager : a application to trade strategies for the Java(tm) platform
* ===========================================================
*
* (C) Copyright 2011-2011, by Simon Allen and Contributors.
*
* Project Info: org.trade
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* [Java is a trademark or registered trademark of Oracle, Inc.
* in the United States and other countries.]
*
* (C) Copyright 2011-2011, by Simon Allen and Contributors.
*
* Original Author: Simon Allen;
* Contributor(s): -;
*
* Changes
* -------
*
*/
package org.trade.persistent;
import java.math.BigDecimal;
import java.time.ZonedDateTime;
import java.util.Hashtable;
import java.util.List;
import javax.persistence.OptimisticLockException;
import org.trade.core.dao.Aspect;
import org.trade.core.dao.AspectHome;
import org.trade.core.dao.Aspects;
import org.trade.core.util.CoreUtils;
import org.trade.core.util.TradingCalendar;
import org.trade.core.valuetype.Money;
import org.trade.dictionary.valuetype.Action;
import org.trade.dictionary.valuetype.OrderStatus;
import org.trade.dictionary.valuetype.Side;
import org.trade.dictionary.valuetype.TradestrategyStatus;
import org.trade.persistent.dao.Account;
import org.trade.persistent.dao.AccountHome;
import org.trade.persistent.dao.Candle;
import org.trade.persistent.dao.CandleHome;
import org.trade.persistent.dao.CodeType;
import org.trade.persistent.dao.CodeTypeHome;
import org.trade.persistent.dao.Contract;
import org.trade.persistent.dao.ContractHome;
import org.trade.persistent.dao.Portfolio;
import org.trade.persistent.dao.PortfolioHome;
import org.trade.persistent.dao.Rule;
import org.trade.persistent.dao.RuleHome;
import org.trade.persistent.dao.Strategy;
import org.trade.persistent.dao.StrategyHome;
import org.trade.persistent.dao.TradeOrder;
import org.trade.persistent.dao.TradeOrderHome;
import org.trade.persistent.dao.TradeOrderfill;
import org.trade.persistent.dao.TradeOrderfillHome;
import org.trade.persistent.dao.TradePosition;
import org.trade.persistent.dao.TradePositionHome;
import org.trade.persistent.dao.TradelogHome;
import org.trade.persistent.dao.TradelogReport;
import org.trade.persistent.dao.Tradestrategy;
import org.trade.persistent.dao.TradestrategyHome;
import org.trade.persistent.dao.TradestrategyLite;
import org.trade.persistent.dao.TradestrategyOrders;
import org.trade.persistent.dao.Tradingday;
import org.trade.persistent.dao.TradingdayHome;
import org.trade.persistent.dao.Tradingdays;
import org.trade.strategy.data.CandleSeries;
import org.trade.strategy.data.candle.CandleItem;
/**
*/
public class TradePersistentModel implements PersistentModel {
private CodeTypeHome m_codeTypeHome = null;
private ContractHome m_contractHome = null;
private StrategyHome m_strategyHome = null;
private TradingdayHome m_tradingdayHome = null;
private TradeOrderHome m_tradeOrderHome = null;
private TradeOrderfillHome m_tradeOrderfillHome = null;
private TradePositionHome m_tradePositionHome = null;
private TradelogHome m_tradelogHome = null;
private AccountHome m_accountHome = null;
private PortfolioHome m_portfolioHome = null;
private TradestrategyHome m_tradestrategyHome = null;
private CandleHome m_candleHome = null;
private AspectHome m_aspectHome = null;
private RuleHome m_ruleHome = null;
private static final int SCALE_5 = 5;
private static final int SCALE_2 = 2;
public TradePersistentModel() {
m_codeTypeHome = new CodeTypeHome();
m_contractHome = new ContractHome();
m_strategyHome = new StrategyHome();
m_tradingdayHome = new TradingdayHome();
m_tradeOrderHome = new TradeOrderHome();
m_tradeOrderfillHome = new TradeOrderfillHome();
m_tradePositionHome = new TradePositionHome();
m_tradelogHome = new TradelogHome();
m_accountHome = new AccountHome();
m_portfolioHome = new PortfolioHome();
m_tradestrategyHome = new TradestrategyHome();
m_candleHome = new CandleHome();
m_aspectHome = new AspectHome();
m_ruleHome = new RuleHome();
}
/**
* Method findTradelogReport.
*
* @param portfolio
* Portfolio
* @param start
* ZonedDateTime
* @param end
* ZonedDateTime
* @param filter
* boolean
* @param symbol
* String
* @param winLossAmount
* BigDecimal
* @return TradelogReport
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#findTradelogReport(Account,
* Date, Date, boolean)
*/
public TradelogReport findTradelogReport(final Portfolio portfolio, ZonedDateTime start, ZonedDateTime end,
boolean filter, String symbol, BigDecimal winLossAmount) throws PersistentModelException {
return m_tradelogHome.findByTradelogReport(portfolio, start, end, filter, symbol, winLossAmount);
}
/**
* Method findAccountById.
*
* @param id
* Integer
* @return Account
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#findAccountById(Integer)
*/
public Account findAccountById(final Integer id) throws PersistentModelException {
Account instance = m_accountHome.findById(id);
if (null == instance)
throw new PersistentModelException("Account not found for id: " + id);
return instance;
}
/**
* Method findAccountByNumber.
*
* @param accountNumber
* String
* @return Account
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#findAccountByNumber(String)
*/
public Account findAccountByNumber(String accountNumber) throws PersistentModelException {
return m_accountHome.findByAccountNumber(accountNumber);
}
/**
* Method findTradingdayById.
*
* @param id
* Integer
* @return Tradingday
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#findTradingdayById(Integer)
*/
public Tradingday findTradingdayById(final Integer id) throws PersistentModelException {
Tradingday instance = m_tradingdayHome.findTradingdayById(id);
if (null == instance)
throw new PersistentModelException("Tradingday not found for id: " + id);
return instance;
}
/**
* Method findTradingdayByOpenDate.
*
* @param openDate
* ZonedDateTime
* @param closeDate
* ZonedDateTime
*
* @return Tradingday
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#findTradingdayByOpenDate(Date)
*/
public Tradingday findTradingdayByOpenCloseDate(final ZonedDateTime openDate, final ZonedDateTime closeDate)
throws PersistentModelException {
return m_tradingdayHome.findByOpenCloseDate(openDate, closeDate);
}
/**
* Method findContractById.
*
* @param id
* Integer
* @return Contract
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#findContractById(Integer)
*/
public Contract findContractById(final Integer id) throws PersistentModelException {
Contract instance = m_contractHome.findById(id);
if (null == instance)
throw new PersistentModelException("Contract not found for id: " + id);
return instance;
}
/**
* Method findTradeOrderById.
*
* @param id
* Integer
* @return TradeOrder
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#findContractById(Integer)
*/
public TradeOrder findTradeOrderById(final Integer id) throws PersistentModelException {
TradeOrder instance = m_tradeOrderHome.findById(id);
if (null == instance)
throw new PersistentModelException("Contract not found for id: " + id);
return instance;
}
/**
* Method findContractByUniqueKey.
*
* @param SECType
* String
* @param symbol
* String
* @param exchange
* String
* @param currency
* String
* @return Contract
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#findContractByUniqueKey(String,
* String, String, String)
*/
public Contract findContractByUniqueKey(String SECType, String symbol, String exchange, String currency,
ZonedDateTime expiry) throws PersistentModelException {
return m_contractHome.findByUniqueKey(SECType, symbol, exchange, currency, expiry);
}
/**
* Method findTradestrategyById.
*
* @param tradestrategy
* Tradestrategy
* @return Tradestrategy
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#findTradestrategyById(Tradestrategy)
*/
public Tradestrategy findTradestrategyById(final Tradestrategy tradestrategy) throws PersistentModelException {
if (null == tradestrategy.getIdTradeStrategy())
throw new PersistentModelException(
"Please save Tradestrategy for symbol: " + tradestrategy.getContract().getSymbol());
Tradestrategy instance = m_tradestrategyHome.findById(tradestrategy.getIdTradeStrategy());
if (null == instance)
throw new PersistentModelException("Tradestrategy not found for id: " + tradestrategy.getIdTradeStrategy());
instance.setStrategyData(tradestrategy.getStrategyData());
return instance;
}
/**
* Method refreshPositionOrdersByTradestrategyId.
*
* @param positionOrders
* PositionOrders
*
* @return PositionOrders
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#findPositionOrdersById(Integer)
*/
public TradestrategyOrders refreshPositionOrdersByTradestrategyId(final TradestrategyOrders positionOrders)
throws PersistentModelException {
Integer version = m_tradestrategyHome.findVersionById(positionOrders.getIdTradeStrategy());
if (positionOrders.getVersion().equals(version)) {
return positionOrders;
} else {
TradestrategyOrders instance = m_tradestrategyHome
.findPositionOrdersByTradestrategyId(positionOrders.getIdTradeStrategy());
if (null == instance)
throw new PersistentModelException(
"Tradestrategy not found for id: " + positionOrders.getIdTradeStrategy());
return instance;
}
}
/**
* Method findPositionOrdersByTradestrategyId.
*
* @param idTradestrategy
* Integer
*
* @return PositionOrders
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#findPositionOrdersById(Integer)
*/
public TradestrategyOrders findPositionOrdersByTradestrategyId(final Integer idTradestrategy)
throws PersistentModelException {
TradestrategyOrders instance = m_tradestrategyHome.findPositionOrdersByTradestrategyId(idTradestrategy);
if (null == instance)
throw new PersistentModelException("Tradestrategy not found for id: " + idTradestrategy);
return instance;
}
/**
* Method findTradestrategyById.
*
* @param id
* Integer
* @return Tradestrategy
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#findTradestrategyById(Integer)
*/
public Tradestrategy findTradestrategyById(final Integer id) throws PersistentModelException {
Tradestrategy instance = m_tradestrategyHome.findById(id);
if (null == instance)
throw new PersistentModelException("Tradestrategy not found for id: " + id);
return instance;
}
/**
* Method existTradestrategyById.
*
* @param id
* Integer
* @return boolean
* @see org.trade.persistent.PersistentModel#existTradestrategyById(Integer)
*/
public boolean existTradestrategyById(final Integer id) {
Tradestrategy instance = m_tradestrategyHome.findById(id);
if (null == instance)
return false;
return true;
}
/**
* Method findTradestrategyLiteById.
*
* @param id
* Integer
* @return TradestrategyLite
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#findTradestrategyById(Integer)
*/
public TradestrategyLite findTradestrategyLiteById(final Integer id) throws PersistentModelException {
TradestrategyLite instance = m_tradestrategyHome.findTradestrategyLiteById(id);
if (null == instance)
throw new PersistentModelException("TradestrategyLite not found for id: " + id);
return instance;
}
/**
* Method findTradePositionById.
*
* @param id
* Integer
* @return TradePosition
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#findTradeById(Integer)
*/
public TradePosition findTradePositionById(final Integer id) throws PersistentModelException {
TradePosition instance = m_tradePositionHome.findById(id);
if (null == instance)
throw new PersistentModelException("TradePosition not found for id: " + id);
return instance;
}
/**
* Method findPortfolioById.
*
* @param id
* Integer
* @return Portfolio
* @throws PersistentModelException
*/
public Portfolio findPortfolioById(final Integer id) throws PersistentModelException {
Portfolio instance = m_portfolioHome.findById(id);
if (null == instance)
throw new PersistentModelException("Portfolio not found for id: " + id);
return instance;
}
/**
* Method findPortfolioByName.
*
* @param name
* String
* @return Portfolio
* @throws PersistentModelException
*/
public Portfolio findPortfolioByName(String name) throws PersistentModelException {
return m_portfolioHome.findByName(name);
}
/**
* Method findPortfolioDefault.
*
* @return Portfolio
* @throws PersistentModelException
*/
public Portfolio findPortfolioDefault() throws PersistentModelException {
return m_portfolioHome.findDefault();
}
/**
* Method resetDefaultPortfolio.
*
* @param transientInstance
* Portfolio
* @throws PersistentModelException
*/
public void resetDefaultPortfolio(final Portfolio transientInstance) throws PersistentModelException {
try {
m_portfolioHome.resetDefaultPortfolio(transientInstance);
} catch (OptimisticLockException ex1) {
throw new PersistentModelException("Error setting default portfolio. Please refresh before save.");
} catch (Exception e) {
throw new PersistentModelException(
"Error saving Portfolio: " + transientInstance.getName() + "\n Msg: " + e.getMessage());
}
}
/**
* Method persistPortfolio.
*
* @param instance
* Portfolio
* @throws PersistentModelException
*/
public Portfolio persistPortfolio(final Portfolio instance) throws PersistentModelException {
try {
return m_portfolioHome.persistPortfolio(instance);
} catch (Exception ex) {
throw new PersistentModelException("Error saving PortfolioAccount: " + ex.getMessage());
}
}
/**
* Method findAllTradestrategies.
*
* @return List<Tradestrategy>
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#findAllTradestrategies()
*/
public List<Tradestrategy> findAllTradestrategies() throws PersistentModelException {
return m_tradestrategyHome.findAll();
}
/**
* Method findTradestrategyByUniqueKeys.
*
* @param open
* ZonedDateTime
* @param strategy
* String
* @param idContract
* Integer
* @param portfolioName
* String
* @return Tradestrategy
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#findTradestrategyByUniqueKeys(Date,
* String, Integer, String)
*/
public Tradestrategy findTradestrategyByUniqueKeys(final ZonedDateTime open, final String strategy,
final Integer idContract, final String portfolioName) throws PersistentModelException {
return m_tradestrategyHome.findTradestrategyByUniqueKeys(open, strategy, idContract, portfolioName);
}
/**
* Method findTradestrategyDistinctByDateRange.
*
* @param fromOpen
* ZonedDateTime
* @param toOpen
* ZonedDateTime
* @return List<Tradestrategy>
*/
public List<Tradestrategy> findTradestrategyDistinctByDateRange(final ZonedDateTime fromOpen,
final ZonedDateTime toOpen) {
return m_tradestrategyHome.findTradestrategyDistinctByDateRange(fromOpen, toOpen);
}
/**
* Method findTradestrategyContractDistinctByDateRange.
*
* @param fromOpen
* ZonedDateTime
* @param toOpen
* ZonedDateTime
* @return List<Tradestrategy>
*/
public List<Tradestrategy> findTradestrategyContractDistinctByDateRange(final ZonedDateTime fromOpen,
final ZonedDateTime toOpen) {
return m_tradestrategyHome.findTradestrategyContractDistinctByDateRange(fromOpen, toOpen);
}
/**
* Method removeTradingdayTrades.
*
* @param transientInstance
* Tradingday
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#removeTradingdayTrades(Tradingday)
*/
public void removeTradingdayTradeOrders(final Tradingday transientInstance) throws PersistentModelException {
for (Tradestrategy tradestrategy : transientInstance.getTradestrategies()) {
this.removeTradestrategyTradeOrders(tradestrategy);
}
}
/**
* Method removeTradestrategyTradeOrders.
*
* @param transientInstance
* Tradestrategy
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#removeTradestrategyTrades(Tradestrategy)
*/
public void removeTradestrategyTradeOrders(final Tradestrategy tradestrategy) throws PersistentModelException {
try {
/*
* Refresh the trade strategy as orders across tradePosition could
* have been deleted if this is a bulk delete of tradestrategies.
*/
Tradestrategy transientInstance = m_tradestrategyHome.findById(tradestrategy.getIdTradeStrategy());
transientInstance.setStatus(null);
m_aspectHome.persist(transientInstance);
Hashtable<Integer, TradePosition> tradePositions = new Hashtable<Integer, TradePosition>();
for (TradeOrder tradeOrder : transientInstance.getTradeOrders()) {
if (tradeOrder.hasTradePosition())
tradePositions.put(tradeOrder.getTradePosition().getIdTradePosition(),
tradeOrder.getTradePosition());
if (null != tradeOrder.getIdTradeOrder()) {
m_aspectHome.remove(tradeOrder);
}
}
for (TradePosition tradePosition : tradePositions.values()) {
tradePosition = this.findTradePositionById(tradePosition.getIdTradePosition());
/*
* Remove the open trade position from contract if this is a
* tradePosition to be deleted.
*/
if (tradePosition.equals(transientInstance.getContract().getTradePosition())) {
transientInstance.getContract().setTradePosition(null);
m_aspectHome.persist(transientInstance.getContract());
}
m_aspectHome.remove(tradePosition);
}
transientInstance.getTradeOrders().clear();
} catch (OptimisticLockException ex1) {
throw new PersistentModelException(
"Error removing Tradestrategy TradePositions. Please refresh before remove.");
} catch (Exception ex) {
throw new PersistentModelException("Error removing Tradestrategy TradePositions: "
+ tradestrategy.getContract().getSymbol() + "\n Msg: " + ex.getMessage());
}
}
/**
* Method findTradeOrderByKey.
*
* @param orderKey
* Integer
* @return TradeOrder
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#findTradeOrderByKey(Integer)
*/
public TradeOrder findTradeOrderByKey(final Integer orderKey) throws PersistentModelException {
return m_tradeOrderHome.findTradeOrderByKey(orderKey);
}
/**
* Method findTradeOrderfillByExecId.
*
* @param execId
* String
* @return TradeOrderfill
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#findTradeOrderfillByExecId(String)
*/
public TradeOrderfill findTradeOrderfillByExecId(String execId) throws PersistentModelException {
return m_tradeOrderfillHome.findOrderFillByExecId(execId);
}
/**
* Method findTradeOrderByMaxKey.
*
* @return Integer
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#findTradeOrderByMaxKey()
*/
public Integer findTradeOrderByMaxKey() throws PersistentModelException {
return m_tradeOrderHome.findTradeOrderByMaxKey();
}
/**
* Method findTradingdaysByDateRange.
*
* @param startDate
* ZonedDateTime
* @param endDate
* ZonedDateTime
* @return Tradingdays
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#findTradingdaysByDateRange(Date,
* Date)
*/
public Tradingdays findTradingdaysByDateRange(final ZonedDateTime startDate, final ZonedDateTime endDate)
throws PersistentModelException {
return m_tradingdayHome.findTradingdaysByDateRange(startDate, endDate);
}
/**
* Method findCandlesByContractDateRangeBarSize.
*
* @param idContract
* Integer
* @param startDate
* Date
* @param endDate
* Date
* @param barSize
* Integer
* @return List<Candle>
* @throws PersistentModelException
*/
public List<Candle> findCandlesByContractDateRangeBarSize(final Integer idContract, final ZonedDateTime startDate,
final ZonedDateTime endDate, final Integer barSize) throws PersistentModelException {
return m_candleHome.findCandlesByContractDateRangeBarSize(idContract, startDate, endDate, barSize);
}
/**
* Method findCandleCount.
*
* @param idTradingday
* Integer
* @param idContract
* Integer
* @return Long
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#findCandleCount(Integer,
* Integer)
*/
public Long findCandleCount(final Integer idTradingday, final Integer idContract) throws PersistentModelException {
return m_candleHome.findCandleCount(idTradingday, idContract);
}
/**
* Method persistContract.
*
* @param transientInstance
* Contract
* @return Contract
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#persistContract(Contract)
*/
public Contract persistContract(final Contract transientInstance) throws PersistentModelException {
try {
if (null == transientInstance.getIdContract()) {
Contract currentContract = m_contractHome.findByUniqueKey(transientInstance.getSecType(),
transientInstance.getSymbol(), transientInstance.getExchange(), transientInstance.getCurrency(),
transientInstance.getExpiry());
if (null != currentContract) {
transientInstance.setIdContract(currentContract.getIdContract());
}
}
return m_aspectHome.persist(transientInstance, true);
} catch (OptimisticLockException ex1) {
throw new PersistentModelException("Error saving Contract please refresh before save.");
} catch (Exception e) {
throw new PersistentModelException(
"Error saving Contract: " + transientInstance.getSymbol() + "\n Msg: " + e.getMessage());
}
}
/**
* Method persistCandleSeries.
*
* @param candleSeries
* CandleSeries
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#persistCandleSeries(CandleSeries)
*/
public void persistCandleSeries(final CandleSeries candleSeries) throws PersistentModelException {
try {
/*
* This can happen when an indicator is a contract that has never
* been used.
*/
if (null == candleSeries.getContract().getIdContract()) {
Contract contract = this.persistContract(candleSeries.getContract());
candleSeries.getContract().setIdContract(contract.getIdContract());
candleSeries.getContract().setVersion(contract.getVersion());
}
m_candleHome.persistCandleSeries(candleSeries);
} catch (OptimisticLockException ex1) {
throw new PersistentModelException("Error saving CandleSeries please refresh before save.");
} catch (Exception e) {
throw new PersistentModelException(
"Error saving CandleSeries: " + candleSeries.getDescription() + "\n Msg: " + e.getMessage());
}
}
/**
* Method persistCandleItem.
*
* @param candle
* Candle
* @return Candle
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#persistCandleItem(CandleItem)
*/
public Candle persistCandle(final Candle candle) throws PersistentModelException {
try {
synchronized (candle) {
if (null == candle.getTradingday().getIdTradingDay()) {
Tradingday tradingday = this.findTradingdayByOpenCloseDate(candle.getTradingday().getOpen(),
candle.getTradingday().getClose());
if (null == tradingday) {
tradingday = m_aspectHome.persist(candle.getTradingday());
}
candle.setTradingday(tradingday);
}
if (null == candle.getIdCandle()) {
Candle currCandle = m_candleHome.findByUniqueKey(candle.getTradingday().getIdTradingDay(),
candle.getContract().getIdContract(), candle.getStartPeriod(), candle.getEndPeriod(),
candle.getBarSize());
/*
* Candle exists set the id and version so we can merge the
* incoming candle.
*/
if (null != currCandle) {
candle.setIdCandle(currCandle.getIdCandle());
candle.setVersion(currCandle.getVersion());
}
}
Candle item = m_aspectHome.persist(candle);
candle.setVersion(item.getVersion());
return item;
}
} catch (OptimisticLockException ex1) {
throw new PersistentModelException("Error saving Candle please refresh before save.");
} catch (Exception e) {
throw new PersistentModelException(
"Error saving CandleItem: " + candle.getOpen() + "\n Msg: " + e.getMessage());
}
}
/**
* Method persistTradingday.
*
* @param transientInstance
* Tradingday
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#persistTradingday(Tradingday)
*/
public void persistTradingday(final Tradingday transientInstance) throws PersistentModelException {
try {
m_tradingdayHome.persist(transientInstance);
} catch (OptimisticLockException ex1) {
throw new PersistentModelException("Error saving Tradingday please refresh before save.");
} catch (Exception e) {
throw new PersistentModelException(
"Error saving Tradingday: " + transientInstance.getOpen() + "\n Msg: " + e.getMessage());
}
}
/**
* Method persistTradeOrder.
*
* @param tradeOrder
* TradeOrder
* @return TradeOrder
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#persistTradeOrder(TradeOrder)
*/
public synchronized TradeOrder persistTradeOrder(final TradeOrder tradeOrder) throws PersistentModelException {
try {
if (null == tradeOrder.getOrderKey()) {
throw new PersistentModelException("Order key cannot be null.");
}
/*
* This is a new order set the status to UNSUBMIT
*/
if (null == tradeOrder.getIdTradeOrder() && null == tradeOrder.getStatus()) {
tradeOrder.setStatus(OrderStatus.UNSUBMIT);
}
if (!tradeOrder.getIsFilled()
&& CoreUtils.nullSafeComparator(tradeOrder.getQuantity(), tradeOrder.getFilledQuantity()) == 0) {
tradeOrder.setIsFilled(true);
tradeOrder.setStatus(OrderStatus.FILLED);
}
/*
* If a partial filled order is cancelled mark the order as filled.
*/
if (OrderStatus.CANCELLED.equals(tradeOrder.getStatus()) && !tradeOrder.getIsFilled()
&& CoreUtils.nullSafeComparator(tradeOrder.getFilledQuantity(), new Integer(0)) == 1) {
tradeOrder.setIsFilled(true);
tradeOrder.setStatus(OrderStatus.FILLED);
}
Integer tradestrategyId = null;
if (null == tradeOrder.getTradestrategyId()) {
tradestrategyId = tradeOrder.getTradestrategy().getIdTradeStrategy();
tradeOrder.setTradestrategyId(this.findTradestrategyLiteById(tradestrategyId));
} else {
tradestrategyId = tradeOrder.getTradestrategyId().getIdTradeStrategy();
}
/*
* If the filled qty is > 0 and we have no TradePosition then create
* one.
*/
TradePosition tradePosition = null;
TradestrategyOrders tradestrategyOrders = null;
if (!tradeOrder.hasTradePosition()) {
if (CoreUtils.nullSafeComparator(tradeOrder.getFilledQuantity(), new Integer(0)) == 1) {
tradestrategyOrders = this.findPositionOrdersByTradestrategyId(tradestrategyId);
if (tradestrategyOrders.hasOpenTradePosition()) {
tradePosition = this.findTradePositionById(
tradestrategyOrders.getContract().getTradePosition().getIdTradePosition());
if (!tradePosition.containsTradeOrder(tradeOrder)) {
tradePosition.addTradeOrder(tradeOrder);
}
} else {
/*
* Note Order status can be fired before execDetails
* this could result in a new tradeposition. OrderStatus
* does not contain the filled date so we must set it
* here.
*/
ZonedDateTime positionOpenDate = tradeOrder.getFilledDate();
if (null == positionOpenDate) {
positionOpenDate = TradingCalendar.getDateTimeNowMarketTimeZone();
}
tradePosition = new TradePosition(tradestrategyOrders.getContract(), positionOpenDate,
(Action.BUY.equals(tradeOrder.getAction()) ? Side.BOT : Side.SLD));
tradeOrder.setIsOpenPosition(true);
tradestrategyOrders.setStatus(TradestrategyStatus.OPEN);
tradestrategyOrders.setLastUpdateDate(TradingCalendar.getDateTimeNowMarketTimeZone());
this.persistAspect(tradestrategyOrders);
tradePosition.addTradeOrder(tradeOrder);
tradePosition = this.persistAspect(tradePosition);
}
tradeOrder.setTradePosition(tradePosition);
} else {
/*
* If the order has not been filled and it has no
* TradePosition this is the first order that has just been
* update.
*/
return this.persistAspect(tradeOrder);
}
} else {
tradePosition = this.findTradePositionById(tradeOrder.getTradePosition().getIdTradePosition());
tradeOrder.setTradePosition(tradePosition);
}
boolean allOrdersCancelled = true;
int totalBuyQuantity = 0;
int totalSellQuantity = 0;
double totalCommission = 0;
double totalBuyValue = 0;
double totalSellValue = 0;
for (TradeOrder order : tradePosition.getTradeOrders()) {
if (order.getOrderKey().equals(tradeOrder.getOrderKey())) {
order = tradeOrder;
}
/*
* If all orders are cancelled and not filled then we need to
* update the tradestrategy status to cancelled.
*/
if (!OrderStatus.CANCELLED.equals(order.getStatus())) {
allOrdersCancelled = false;
}
if (null != order.getFilledQuantity()) {
if (Action.BUY.equals(order.getAction())) {
totalBuyQuantity = totalBuyQuantity + order.getFilledQuantity();
totalBuyValue = totalBuyValue + (order.getAverageFilledPrice().doubleValue()
* order.getFilledQuantity().doubleValue());
} else {
totalSellQuantity = totalSellQuantity + order.getFilledQuantity();
totalSellValue = totalSellValue + (order.getAverageFilledPrice().doubleValue()
* order.getFilledQuantity().doubleValue());
}
if (null != order.getCommission()) {
totalCommission = totalCommission + order.getCommission().doubleValue();
}
}
}
/*
* totalFilledQuantity has changed for the trade update the trade
* values.
*/
Money comms = new Money(totalCommission);
if (CoreUtils.nullSafeComparator(new Integer(totalBuyQuantity), tradePosition.getTotalBuyQuantity()) != 0
|| CoreUtils.nullSafeComparator(new Integer(totalSellQuantity),
tradePosition.getTotalSellQuantity()) != 0) {
int openQuantity = totalBuyQuantity - totalSellQuantity;
tradePosition.setOpenQuantity(openQuantity);
tradePosition.setTotalBuyQuantity(totalBuyQuantity);
tradePosition.setTotalBuyValue(
(new BigDecimal(totalBuyValue)).setScale(SCALE_5, BigDecimal.ROUND_HALF_EVEN));
tradePosition.setTotalSellQuantity(totalSellQuantity);
tradePosition.setTotalSellValue(
(new BigDecimal(totalSellValue)).setScale(SCALE_5, BigDecimal.ROUND_HALF_EVEN));
tradePosition.setTotalNetValue(
(new BigDecimal(totalSellValue - totalBuyValue)).setScale(SCALE_5, BigDecimal.ROUND_HALF_EVEN));
tradePosition.setTotalCommission(comms.getBigDecimalValue());
if (openQuantity > 0) {
tradePosition.setSide(Side.BOT);
}
if (openQuantity < 0) {
tradePosition.setSide(Side.SLD);
}
/*
* Position should be closed if openQuantity = 0
*/
if (tradePosition.equals(tradePosition.getContract().getTradePosition())) {
if (openQuantity == 0) {
tradePosition.setPositionCloseDate(tradeOrder.getFilledDate());
tradePosition.getContract().setTradePosition(null);
this.persistAspect(tradePosition.getContract());
}
} else {
tradePosition.getContract().setTradePosition(tradePosition);
this.persistAspect(tradePosition.getContract());
}
// Partial fills case.
if (null == tradestrategyOrders) {
tradestrategyOrders = this.findPositionOrdersByTradestrategyId(tradestrategyId);
}
if (!tradePosition.isOpen() && !TradestrategyStatus.CLOSED.equals(tradestrategyOrders.getStatus())) {
/*
* Now update all the tradestrategies as there could be many
* if the position is across multiple days.
*/
for (TradeOrder item : tradePosition.getTradeOrders()) {
if (!item.getTradestrategyId().getIdTradeStrategy()
.equals(tradestrategyOrders.getIdTradeStrategy())) {
item.getTradestrategyId().setStatus(TradestrategyStatus.CLOSED);
item.getTradestrategyId().setLastUpdateDate(TradingCalendar.getDateTimeNowMarketTimeZone());
this.persistAspect(item.getTradestrategyId());
}
}
tradestrategyOrders.setStatus(TradestrategyStatus.CLOSED);
tradestrategyOrders.setLastUpdateDate(TradingCalendar.getDateTimeNowMarketTimeZone());
this.persistAspect(tradestrategyOrders);
}
tradePosition.setLastUpdateDate(TradingCalendar.getDateTimeNowMarketTimeZone());
tradePosition = this.persistAspect(tradePosition);
} else {
if (allOrdersCancelled) {
if (null == tradestrategyOrders) {
tradestrategyOrders = this.findPositionOrdersByTradestrategyId(tradestrategyId);
}
if (!TradestrategyStatus.CANCELLED.equals(tradestrategyOrders.getStatus())) {
if (null == tradestrategyOrders.getStatus()) {
tradestrategyOrders.setStatus(TradestrategyStatus.CANCELLED);
tradestrategyOrders.setLastUpdateDate(TradingCalendar.getDateTimeNowMarketTimeZone());
this.persistAspect(tradestrategyOrders);
}
}
}
/*
* If the commissions (note these are updated by the orderState
* event after the order may have been filled) have changed
* update the trade.
*/
if (CoreUtils.nullSafeComparator(comms.getBigDecimalValue(), tradePosition.getTotalCommission()) == 1) {
tradePosition.setTotalCommission(comms.getBigDecimalValue());
tradePosition.setLastUpdateDate(TradingCalendar.getDateTimeNowMarketTimeZone());
tradePosition = this.persistAspect(tradePosition);
}
}
return this.persistAspect(tradeOrder);
} catch (OptimisticLockException ex1) {
throw new PersistentModelException("Error saving TradeOrder please refresh before save.");
} catch (Exception e) {
throw new PersistentModelException(
"Error saving TradeOrder: " + tradeOrder.getOrderKey() + "\n Msg: " + e.getMessage());
}
}
/**
* Method persistTradeOrderfill.
*
* @param tradeOrder
* TradeOrder
* @return TradeOrder
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#persistTradeOrderfill(TradeOrder)
*/
public synchronized TradeOrder persistTradeOrderfill(final TradeOrder tradeOrder) throws PersistentModelException {
try {
ZonedDateTime filledDate = null;
double filledValue = 0;
double commission = 0;
int filledQuantity = 0;
for (TradeOrderfill tradeOrderfill : tradeOrder.getTradeOrderfills()) {
if (null != tradeOrderfill.getCommission())
commission = commission + tradeOrderfill.getCommission().doubleValue();
filledQuantity = filledQuantity + tradeOrderfill.getQuantity();
filledValue = filledValue + (tradeOrderfill.getPrice().doubleValue() * tradeOrderfill.getQuantity());
if (null == filledDate)
filledDate = tradeOrderfill.getTime();
if (filledDate.isBefore(tradeOrderfill.getTime()))
filledDate = tradeOrderfill.getTime();
}
if (filledQuantity > 0) {
BigDecimal avgFillPrice = (new BigDecimal(filledValue / filledQuantity)).setScale(SCALE_5,
BigDecimal.ROUND_HALF_EVEN);
BigDecimal commissionAmount = (new BigDecimal(commission)).setScale(SCALE_2,
BigDecimal.ROUND_HALF_EVEN);
/*
* If filled qty is greater than current filled qty set the new
* value. Note openOrder can update the filled order quantity
* before the orderFills have arrived.
*/
if (CoreUtils.nullSafeComparator(new Integer(filledQuantity), tradeOrder.getFilledQuantity()) == 1) {
tradeOrder.setAverageFilledPrice(avgFillPrice);
tradeOrder.setFilledQuantity(filledQuantity);
tradeOrder.setFilledDate(filledDate);
/*
* If the commission amount is greater than the TradeOrder
* commission set this amount. Note tradeOrder commission
* can be set via the commissionReport event i.e each
* execution or by the openOrder event.
*/
if (CoreUtils.nullSafeComparator(commissionAmount, tradeOrder.getCommission()) == 1)
tradeOrder.setCommission(commissionAmount);
tradeOrder.setLastUpdateDate(TradingCalendar.getDateTimeNowMarketTimeZone());
}
}
return persistTradeOrder(tradeOrder);
} catch (OptimisticLockException ex1) {
throw new PersistentModelException("Error saving TradeOrderfill please refresh before save.");
} catch (Exception e) {
throw new PersistentModelException(
"Error saving TradeOrderfill: " + tradeOrder.getOrderKey() + "\n Msg: " + e.getMessage());
}
}
/**
* Method findRuleById.
*
* @param id
* Integer
* @return Rule
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#findRuleById(Integer)
*/
public Rule findRuleById(final Integer id) throws PersistentModelException {
Rule instance = m_ruleHome.findById(id);
if (null == instance)
throw new PersistentModelException("Rule not found for Id: " + id);
return instance;
}
/**
* Method findRuleByMaxVersion.
*
* @param strategy
* Strategy
* @return Integer
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#findRuleByMaxVersion(Strategy)
*/
public Integer findRuleByMaxVersion(final Strategy strategy) throws PersistentModelException {
return m_ruleHome.findByMaxVersion(strategy);
}
/**
* Method findStrategyById.
*
* @param id
* Integer
* @return Strategy
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#findStrategyById(Integer)
*/
public Strategy findStrategyById(final Integer id) throws PersistentModelException {
Strategy instance = m_strategyHome.findById(id);
if (null == instance)
throw new PersistentModelException("Strategy not found for Id: " + id);
return instance;
}
/**
* Method findStrategyByName.
*
* @param name
* String
* @return Strategy
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#findStrategyByName(String)
*/
public Strategy findStrategyByName(String name) throws PersistentModelException {
return m_strategyHome.findByName(name);
}
/**
* Method findStrategies.
*
* @return List<Strategy>
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#findStrategies()
*/
public List<Strategy> findStrategies() throws PersistentModelException {
return m_strategyHome.findAll();
}
/**
* Method findAspectsByClassName.
*
* @param aspectClassName
* String
* @return Aspects
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#findAspectsByClassName(String)
*/
public Aspects findAspectsByClassName(String aspectClassName) throws PersistentModelException {
try {
if ("org.trade.persistent.dao.Strategy".equals(aspectClassName)) {
/*
* Relationship Strategy -> IndicatorSeries is LAZY so we need
* to call size() on Rule/IndicatorSeries.
*/
List<Strategy> items = m_strategyHome.findAll();
Aspects aspects = new Aspects();
for (Object item : items) {
aspects.add((Aspect) item);
}
aspects.setDirty(false);
return aspects;
} else if ("org.trade.persistent.dao.Portfolio".equals(aspectClassName)) {
/*
* Relationship Portfolio -> PortfilioAccount iis LAZY so we
* need to call size() on PortfolioAccount.
*/
List<Portfolio> items = m_portfolioHome.findAll();
Aspects aspects = new Aspects();
for (Object item : items) {
aspects.add((Aspect) item);
}
aspects.setDirty(false);
return aspects;
} else {
return m_aspectHome.findByClassName(aspectClassName);
}
} catch (Exception ex) {
throw new PersistentModelException("Error finding Aspects: " + ex.getMessage());
}
}
/**
* Method findAspectsByClassNameFieldName.
*
* @param className
* String
* @param fieldname
* String
* @param value
* String
* @return Aspects
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#findAspectsByClassNameFieldName(String,
* String, String)
*/
public Aspects findAspectsByClassNameFieldName(String className, String fieldname, String value)
throws PersistentModelException {
try {
return m_aspectHome.findByClassNameFieldName(className, fieldname, value);
} catch (Exception ex) {
throw new PersistentModelException("Error finding Aspects: " + ex.getMessage());
}
}
/**
* Method findAspectById.
*
* @param transientInstance
* Aspect
* @return Aspect
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#findAspectById(Aspect)
*/
public Aspect findAspectById(final Aspect aspect) throws PersistentModelException {
Aspect instance = m_aspectHome.findById(aspect);
if (null == instance)
throw new PersistentModelException("Aspect not found for Id: " + aspect.getId());
return instance;
}
/**
* Method persistAspect.
*
* @param transientInstance
* Aspect
* @return Aspect
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#persistAspect(Aspect)
*/
public <T extends Aspect> T persistAspect(final T transientInstance) throws PersistentModelException {
try {
return m_aspectHome.persist(transientInstance);
} catch (OptimisticLockException ex1) {
throw new PersistentModelException(
"Error saving " + transientInstance.getClass().getSimpleName() + " please refresh before save.");
} catch (Exception ex) {
throw new PersistentModelException(
"Error saving " + transientInstance.getClass().getSimpleName() + " : " + ex.getMessage());
}
}
/**
* Method persistAspect.
*
* @param aspect
* Aspect
* @param overrideVersion
* boolean
* @return Aspect
* @throws PersistentModelException
*
* @see org.trade.persistent.PersistentModel#persistAspect(Aspect)
*/
public <T extends Aspect> T persistAspect(final T transientInstance, boolean overrideVersion)
throws PersistentModelException {
try {
return m_aspectHome.persist(transientInstance, overrideVersion);
} catch (OptimisticLockException ex1) {
throw new PersistentModelException(
"Error saving " + transientInstance.getClass().getSimpleName() + " please refresh before save.");
} catch (Exception e) {
throw new PersistentModelException(
"Error saving " + transientInstance.getClass().getSimpleName() + " : " + e.getMessage());
}
};
/**
* Method removeAspect.
*
* @param transientInstance
* Aspect
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#removeAspect(Aspect)
*/
public void removeAspect(final Aspect transientInstance) throws PersistentModelException {
try {
m_aspectHome.remove(transientInstance);
} catch (OptimisticLockException ex1) {
throw new PersistentModelException(
"Error removing " + transientInstance.getClass().getSimpleName() + " please refresh before save.");
} catch (Exception e) {
throw new PersistentModelException(
"Error removing " + transientInstance.getClass().getSimpleName() + " : " + e.getMessage());
}
}
/**
* Method reassignStrategy.
*
* @param fromStrategy
* Strategy
* @param toStrategy
* Strategy
* @param tradingday
* Tradingday
* @throws PersistentModelException
* @see org.trade.persistent.PersistentModel#reassignStrategy(Strategy,
* Strategy, Tradingday)
*/
public void reassignStrategy(final Strategy fromStrategy, final Strategy toStrategy, final Tradingday tradingday)
throws PersistentModelException {
try {
for (Tradestrategy item : tradingday.getTradestrategies()) {
if (item.getStrategy().getIdStrategy().equals(fromStrategy.getIdStrategy())) {
item.setStrategy(toStrategy);
item.setDirty(true);
item.setStrategyData(null);
m_aspectHome.persist(item);
}
}
} catch (Exception ex) {
throw new PersistentModelException("Error reassign Strategy: " + ex.getMessage());
}
}
/**
* Method findCodeTypeByNameType.
*
* @param name
* String
* @param type
* String
* @return CodeType
* @throws PersistentModelException
*/
public CodeType findCodeTypeByNameType(String name, String type) throws PersistentModelException {
try {
return m_codeTypeHome.findByNameAndType(name, type);
} catch (Exception ex) {
throw new PersistentModelException("Error finding CodeType: " + ex.getMessage());
}
}
}